diff --git a/Makefile b/Makefile index 33b737f8a..1e7df4211 100644 --- a/Makefile +++ b/Makefile @@ -114,9 +114,6 @@ help: @echo " supported boards are ($(BL_BOARDS))" @echo @echo " [Simulation]" - @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_win32 - Build OpenPilot simulation firmware for" @echo " Windows using mingw and msys" @echo " sim_win32_clean - Delete all build output for the win32 simulation" @@ -230,7 +227,7 @@ openocd_install: openocd_clean $(V1) mkdir -p "$(OPENOCD_DIR)" $(V1) ( \ cd $(OPENOCD_BUILD_DIR)/openocd-0.5.0 ; \ - ./configure --prefix="$(OPENOCD_DIR)" --enable-ft2232_libftdi --enable-buspirate; \ + ./configure --prefix="$(OPENOCD_DIR)" --enable-ft2232_libftdi ; \ $(MAKE) --silent ; \ $(MAKE) --silent install ; \ ) @@ -633,12 +630,13 @@ all_$(1)_clean: $$(addsuffix _clean, $$(filter bu_$(1), $$(BU_TARGETS))) all_$(1)_clean: $$(addsuffix _clean, $$(filter ef_$(1), $$(EF_TARGETS))) endef -ALL_BOARDS := coptercontrol pipxtreme revolution +ALL_BOARDS := coptercontrol pipxtreme revolution simposix # Friendly names of each board (used to find source tree) coptercontrol_friendly := CopterControl pipxtreme_friendly := PipXtreme revolution_friendly := Revolution +simposix_friendly := SimPosix # Start out assuming that we'll build fw, bl and bu for all boards FW_BOARDS := $(ALL_BOARDS) @@ -692,14 +690,6 @@ $(foreach board, $(ALL_BOARDS), $(eval $(call BL_TEMPLATE,$(board),$($(board)_fr # Expand the entire-flash rules $(foreach board, $(ALL_BOARDS), $(eval $(call EF_TEMPLATE,$(board),$($(board)_friendly)))) -.PHONY: sim_posix -sim_posix: sim_posix_elf - -sim_posix_%: uavobjects_flight - $(V1) mkdir -p $(BUILD_DIR)/sitl_posix - $(V1) $(MAKE) --no-print-directory \ - -C $(ROOT_DIR)/flight/OpenPilot --file=$(ROOT_DIR)/flight/OpenPilot/Makefile.posix $* - .PHONY: sim_win32 sim_win32: sim_win32_exe diff --git a/flight/Bootloaders/BootloaderUpdater/main.c b/flight/Bootloaders/BootloaderUpdater/main.c index 0d475a395..b7348dac4 100644 --- a/flight/Bootloaders/BootloaderUpdater/main.c +++ b/flight/Bootloaders/BootloaderUpdater/main.c @@ -28,12 +28,13 @@ /* Bootloader Includes */ #include #include +#include "pios_board_info.h" #define MAX_WRI_RETRYS 3 /* Prototype of PIOS_Board_Init() function */ extern void PIOS_Board_Init(void); extern void FLASH_Download(); -void error(void); +void error(int); /* The ADDRESSES of the _binary_* symbols are the important * data. This is non-intuitive for _binary_size where you @@ -50,12 +51,40 @@ int main() { PIOS_SYS_Init(); PIOS_Board_Init(); + PIOS_LED_On(PIOS_LED_HEARTBEAT); + PIOS_DELAY_WaitmS(3000); + PIOS_LED_Off(PIOS_LED_HEARTBEAT); /// Self overwrite check uint32_t base_address = SCB->VTOR; if ((0x08000000 + embedded_image_size) > base_address) - error(); + error(PIOS_LED_HEARTBEAT); /// + + /* + * Make sure the bootloader we're carrying is for the same + * board type and board revision as the one we're running on. + * + * Assume the bootloader in flash and the bootloader contained in + * the updater both carry a board_info_blob at the end of the image. + */ + + /* Calculate how far the board_info_blob is from the beginning of the bootloader */ + uint32_t board_info_blob_offset = (uint32_t)&pios_board_info_blob - (uint32_t)0x08000000; + + /* Use the same offset into our embedded bootloader image */ + struct pios_board_info * new_board_info_blob = (struct pios_board_info *) + ((uint32_t)embedded_image_start + board_info_blob_offset); + + /* Compare the two board info blobs to make sure they're for the same HW revision */ + if ((pios_board_info_blob.magic != new_board_info_blob->magic) || + (pios_board_info_blob.board_type != new_board_info_blob->board_type) || + (pios_board_info_blob.board_rev != new_board_info_blob->board_rev)) { + error(PIOS_LED_HEARTBEAT); + } + + /* Embedded bootloader looks like it's the right one for this HW, proceed... */ + FLASH_Unlock(); /// Bootloader memory space erase @@ -79,7 +108,7 @@ int main() { } if (fail == true) - error(); + error(PIOS_LED_HEARTBEAT); /// @@ -87,6 +116,7 @@ int main() { /// Bootloader programing for (uint32_t offset = 0; offset < embedded_image_size/sizeof(uint32_t); ++offset) { bool result = false; + PIOS_LED_Toggle(PIOS_LED_HEARTBEAT); for (uint8_t retry = 0; retry < MAX_WRI_RETRYS; ++retry) { if (result == false) { result = (FLASH_ProgramWord(0x08000000 + (offset * 4), embedded_image_start[offset]) @@ -94,9 +124,15 @@ int main() { } } if (result == false) - error(); + error(PIOS_LED_HEARTBEAT); } /// + for (uint8_t x = 0; x < 3; ++x) { + PIOS_LED_On(PIOS_LED_HEARTBEAT); + PIOS_DELAY_WaitmS(1000); + PIOS_LED_Off(PIOS_LED_HEARTBEAT); + PIOS_DELAY_WaitmS(1000); + } /// Invalidate the bootloader updater so we won't run /// the update again on the next power cycle. @@ -109,7 +145,11 @@ int main() { } -void error(void) { +void error(int led) { for (;;) { + PIOS_LED_On(led); + PIOS_DELAY_WaitmS(500); + PIOS_LED_Off(led); + PIOS_DELAY_WaitmS(500); } } diff --git a/flight/Bootloaders/BootloaderUpdater/pios_board.c b/flight/Bootloaders/BootloaderUpdater/pios_board.c index 93973b470..0b7cb9efc 100644 --- a/flight/Bootloaders/BootloaderUpdater/pios_board.c +++ b/flight/Bootloaders/BootloaderUpdater/pios_board.c @@ -35,6 +35,8 @@ #include void PIOS_Board_Init(void) { + const struct pios_board_info * bdinfo = &pios_board_info_blob; + /* Enable Prefetch Buffer */ FLASH_PrefetchBufferCmd(FLASH_PrefetchBuffer_Enable); @@ -42,8 +44,15 @@ void PIOS_Board_Init(void) { FLASH_SetLatency(FLASH_Latency_2); /* Delay system */ - PIOS_DELAY_Init(); - + PIOS_DELAY_Init(); + + /* LEDs */ +#if defined(PIOS_INCLUDE_LED) + const struct pios_led_cfg * led_cfg = PIOS_BOARD_HW_DEFS_GetLedCfg(bdinfo->board_rev); + PIOS_Assert(led_cfg); + PIOS_LED_Init(led_cfg); +#endif /* PIOS_INCLUDE_LED */ + /* Initialize the PiOS library */ PIOS_GPIO_Init(); } diff --git a/flight/Bootloaders/CopterControl/Makefile b/flight/Bootloaders/CopterControl/Makefile index d52541791..8c22d37a7 100644 --- a/flight/Bootloaders/CopterControl/Makefile +++ b/flight/Bootloaders/CopterControl/Makefile @@ -115,6 +115,7 @@ SRC += $(PIOSSTM32F10X)/pios_usb_hid_istr.c SRC += $(PIOSSTM32F10X)/pios_usb_hid_pwr.c SRC += $(OPSYSTEM)/pios_usb_board_data.c SRC += $(PIOSCOMMON)/pios_usb_desc_hid_only.c +SRC += $(PIOSCOMMON)/pios_usb_util.c ## PIOS Hardware (Common) SRC += $(PIOSCOMMON)/pios_board_info.c diff --git a/flight/Bootloaders/CopterControl/inc/pios_usb_board_data.h b/flight/Bootloaders/CopterControl/inc/pios_usb_board_data.h index f1accee17..addb24f19 100644 --- a/flight/Bootloaders/CopterControl/inc/pios_usb_board_data.h +++ b/flight/Bootloaders/CopterControl/inc/pios_usb_board_data.h @@ -39,6 +39,7 @@ #define PIOS_USB_BOARD_PRODUCT_ID USB_PRODUCT_ID_COPTERCONTROL #define PIOS_USB_BOARD_DEVICE_VER USB_OP_DEVICE_VER(USB_OP_BOARD_ID_COPTERCONTROL, USB_OP_BOARD_MODE_BL) +#define PIOS_USB_BOARD_SN_SUFFIX "+BL" /* * The bootloader uses a simplified report structure diff --git a/flight/Bootloaders/CopterControl/main.c b/flight/Bootloaders/CopterControl/main.c index 9aaa31787..77c02f18b 100644 --- a/flight/Bootloaders/CopterControl/main.c +++ b/flight/Bootloaders/CopterControl/main.c @@ -74,7 +74,7 @@ int main() { PIOS_Board_Init(); PIOS_IAP_Init(); - USB_connected = PIOS_USB_CheckAvailable(0); + USB_connected = PIOS_USB_CableConnected(0); if (PIOS_IAP_CheckRequest() == TRUE) { PIOS_DELAY_WaitmS(1000); diff --git a/flight/Bootloaders/CopterControl/pios_board.c b/flight/Bootloaders/CopterControl/pios_board.c index 844670a6e..4104c4028 100644 --- a/flight/Bootloaders/CopterControl/pios_board.c +++ b/flight/Bootloaders/CopterControl/pios_board.c @@ -62,17 +62,9 @@ void PIOS_Board_Init(void) { const struct pios_board_info * bdinfo = &pios_board_info_blob; #if defined(PIOS_INCLUDE_LED) - switch(bdinfo->board_rev) { - case 0x01: // Revision 1 - PIOS_LED_Init(&pios_led_cfg_cc); - break; - case 0x02: // Revision 2 - GPIO_PinRemapConfig(GPIO_Remap_SWJ_JTAGDisable, ENABLE); - PIOS_LED_Init(&pios_led_cfg_cc3d); - break; - default: - PIOS_Assert(0); - } + const struct pios_led_cfg * led_cfg = PIOS_BOARD_HW_DEFS_GetLedCfg(bdinfo->board_rev); + PIOS_Assert(led_cfg); + PIOS_LED_Init(led_cfg); #endif /* PIOS_INCLUDE_LED */ #if defined(PIOS_INCLUDE_USB) @@ -84,10 +76,10 @@ void PIOS_Board_Init(void) { uint32_t pios_usb_id; switch(bdinfo->board_rev) { - case 0x01: // Revision 1 + case BOARD_REVISION_CC: PIOS_USB_Init(&pios_usb_id, &pios_usb_main_cfg_cc); break; - case 0x02: // Revision 2 + case BOARD_REVISION_CC3D: PIOS_USB_Init(&pios_usb_id, &pios_usb_main_cfg_cc3d); break; default: diff --git a/flight/Bootloaders/CopterControl/pios_usb_board_data.c b/flight/Bootloaders/CopterControl/pios_usb_board_data.c index 4f02ce424..1993320d4 100644 --- a/flight/Bootloaders/CopterControl/pios_usb_board_data.c +++ b/flight/Bootloaders/CopterControl/pios_usb_board_data.c @@ -31,6 +31,7 @@ #include "pios_usb_board_data.h" /* struct usb_*, USB_* */ #include "pios_sys.h" /* PIOS_SYS_SerialNumberGet */ #include "pios_usbhook.h" /* PIOS_USBHOOK_* */ +#include "pios_usb_util.h" /* PIOS_USB_UTIL_AsciiToUtf8 */ static const uint8_t usb_product_id[28] = { sizeof(usb_product_id), @@ -50,40 +51,15 @@ static const uint8_t usb_product_id[28] = { 'l', 0, }; -static uint8_t usb_serial_number[52] = { +static uint8_t usb_serial_number[2 + PIOS_SYS_SERIAL_NUM_ASCII_LEN*2 + (sizeof(PIOS_USB_BOARD_SN_SUFFIX)-1)*2] = { sizeof(usb_serial_number), USB_DESC_TYPE_STRING, - 0, 0, - 0, 0, - 0, 0, - 0, 0, - 0, 0, - 0, 0, - 0, 0, - 0, 0, - 0, 0, - 0, 0, - 0, 0, - 0, 0, - 0, 0, - 0, 0, - 0, 0, - 0, 0, - 0, 0, - 0, 0, - 0, 0, - 0, 0, - 0, 0, - 0, 0, - 0, 0, - 0, 0, - 0, 0 }; static const struct usb_string_langid usb_lang_id = { .bLength = sizeof(usb_lang_id), .bDescriptorType = USB_DESC_TYPE_STRING, - .bLangID = htousbs(USB_LANGID_ENGLISH_UK), + .bLangID = htousbs(USB_LANGID_ENGLISH_US), }; static const uint8_t usb_vendor_id[28] = { @@ -107,11 +83,13 @@ static const uint8_t usb_vendor_id[28] = { int32_t PIOS_USB_BOARD_DATA_Init(void) { /* Load device serial number into serial number string */ - uint8_t sn[25]; + uint8_t sn[PIOS_SYS_SERIAL_NUM_ASCII_LEN + 1]; PIOS_SYS_SerialNumberGet((char *)sn); - for (uint8_t i = 0; sn[i] != '\0' && (2 * i) < usb_serial_number[0]; i++) { - usb_serial_number[2 + 2 * i] = sn[i]; - } + + /* Concatenate the device serial number and the appropriate suffix ("+BL" or "+FW") into the USB serial number */ + uint8_t * utf8 = &(usb_serial_number[2]); + utf8 = PIOS_USB_UTIL_AsciiToUtf8(utf8, sn, PIOS_SYS_SERIAL_NUM_ASCII_LEN); + utf8 = PIOS_USB_UTIL_AsciiToUtf8(utf8, (uint8_t *)PIOS_USB_BOARD_SN_SUFFIX, sizeof(PIOS_USB_BOARD_SN_SUFFIX)-1); PIOS_USBHOOK_RegisterString(USB_STRING_DESC_PRODUCT, (uint8_t *)&usb_product_id, sizeof(usb_product_id)); PIOS_USBHOOK_RegisterString(USB_STRING_DESC_SERIAL, (uint8_t *)&usb_serial_number, sizeof(usb_serial_number)); diff --git a/flight/Bootloaders/PipXtreme/Makefile b/flight/Bootloaders/PipXtreme/Makefile index 8711ccbd9..5747a0511 100644 --- a/flight/Bootloaders/PipXtreme/Makefile +++ b/flight/Bootloaders/PipXtreme/Makefile @@ -86,6 +86,7 @@ RTOSDIR = $(APPLIBDIR)/FreeRTOS RTOSSRCDIR = $(RTOSDIR)/Source RTOSINCDIR = $(RTOSSRCDIR)/include DOXYGENDIR = ../Doc/Doxygen +HWDEFSINC = ../../board_hw_defs/$(BOARD_NAME) # List C source files here. (C dependencies are automatically generated.) # use file-extension c for "c-only"-files @@ -114,12 +115,11 @@ SRC += $(PIOSSTM32F10X)/pios_usb_hid_istr.c SRC += $(PIOSSTM32F10X)/pios_usb_hid_pwr.c SRC += $(OPSYSTEM)/pios_usb_board_data.c SRC += $(PIOSCOMMON)/pios_usb_desc_hid_only.c +SRC += $(PIOSCOMMON)/pios_usb_util.c ## PIOS Hardware (Common) SRC += $(PIOSCOMMON)/pios_board_info.c SRC += $(PIOSCOMMON)/pios_com_msg.c -SRC += $(PIOSCOMMON)/pios_bl_helper.c -SRC += $(PIOSCOMMON)/pios_iap.c SRC += $(PIOSCOMMON)/printf-stdarg.c ## Libraries for flight calculations @@ -200,8 +200,7 @@ EXTRAINCDIRS += $(MSDDIR) EXTRAINCDIRS += $(RTOSINCDIR) EXTRAINCDIRS += $(APPLIBDIR) EXTRAINCDIRS += $(RTOSSRCDIR)/portable/GCC/ARM_CM3 - - +EXTRAINCDIRS += $(HWDEFSINC) # List any extra directories to look for library files here. # Also add directories where the linker should search for diff --git a/flight/Bootloaders/PipXtreme/inc/pios_usb_board_data.h b/flight/Bootloaders/PipXtreme/inc/pios_usb_board_data.h index 2e35f2fa4..f959c0e03 100644 --- a/flight/Bootloaders/PipXtreme/inc/pios_usb_board_data.h +++ b/flight/Bootloaders/PipXtreme/inc/pios_usb_board_data.h @@ -39,6 +39,7 @@ #define PIOS_USB_BOARD_PRODUCT_ID USB_PRODUCT_ID_PIPXTREME #define PIOS_USB_BOARD_DEVICE_VER USB_OP_DEVICE_VER(USB_OP_BOARD_ID_PIPXTREME, USB_OP_BOARD_MODE_BL) +#define PIOS_USB_BOARD_SN_SUFFIX "+BL" /* * The bootloader uses a simplified report structure diff --git a/flight/Bootloaders/PipXtreme/pios_board.c b/flight/Bootloaders/PipXtreme/pios_board.c index 60ec1db76..893dc35f9 100644 --- a/flight/Bootloaders/PipXtreme/pios_board.c +++ b/flight/Bootloaders/PipXtreme/pios_board.c @@ -23,97 +23,9 @@ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ +#include "board_hw_defs.c" #include -#if defined(PIOS_INCLUDE_LED) - -#include -static const struct pios_led pios_leds[] = { - [PIOS_LED_USB] = { - .pin = { - .gpio = GPIOA, - .init = { - .GPIO_Pin = GPIO_Pin_3, - .GPIO_Mode = GPIO_Mode_Out_PP, - .GPIO_Speed = GPIO_Speed_50MHz, - }, - }, - }, - [PIOS_LED_LINK] = { - .pin = { - .gpio = GPIOB, - .init = { - .GPIO_Pin = GPIO_Pin_5, - .GPIO_Mode = GPIO_Mode_Out_PP, - .GPIO_Speed = GPIO_Speed_50MHz, - }, - }, - }, - [PIOS_LED_RX] = { - .pin = { - .gpio = GPIOB, - .init = { - .GPIO_Pin = GPIO_Pin_6, - .GPIO_Mode = GPIO_Mode_Out_PP, - .GPIO_Speed = GPIO_Speed_50MHz, - }, - }, - }, - [PIOS_LED_TX] = { - .pin = { - .gpio = GPIOB, - .init = { - .GPIO_Pin = GPIO_Pin_7, - .GPIO_Mode = GPIO_Mode_Out_PP, - .GPIO_Speed = GPIO_Speed_50MHz, - }, - }, - }, -}; - -static const struct pios_led_cfg pios_led_cfg = { - .leds = pios_leds, - .num_leds = NELEMENTS(pios_leds), -}; - -#endif /* PIOS_INCLUDE_LED */ - -#if defined(PIOS_INCLUDE_COM_MSG) - -#include - -#endif /* PIOS_INCLUDE_COM_MSG */ - -#if defined(PIOS_INCLUDE_USB) -#include "pios_usb_priv.h" - -static const struct pios_usb_cfg pios_usb_main_cfg = { - .irq = { - .init = { - .NVIC_IRQChannel = USB_LP_CAN1_RX0_IRQn, - .NVIC_IRQChannelPreemptionPriority = PIOS_IRQ_PRIO_LOW, - .NVIC_IRQChannelSubPriority = 0, - .NVIC_IRQChannelCmd = ENABLE, - }, - }, -}; - -#include "pios_usb_board_data_priv.h" -#include "pios_usb_desc_hid_only_priv.h" - -#endif /* PIOS_INCLUDE_USB */ - -#if defined(PIOS_INCLUDE_USB_HID) -#include - -const struct pios_usb_hid_cfg pios_usb_hid_cfg = { - .data_if = 0, - .data_rx_ep = 1, - .data_tx_ep = 1, -}; - -#endif /* PIOS_INCLUDE_USB_HID */ - uint32_t pios_com_telem_usb_id; /** @@ -139,6 +51,10 @@ void PIOS_Board_Init(void) { /* Initialize the PiOS library */ PIOS_GPIO_Init(); +#if defined(PIOS_INCLUDE_LED) + PIOS_LED_Init(&pios_led_cfg); +#endif /* PIOS_INCLUDE_LED */ + #if defined(PIOS_INCLUDE_USB) /* Initialize board specific USB data */ PIOS_USB_BOARD_DATA_Init(); diff --git a/flight/Bootloaders/PipXtreme/pios_usb_board_data.c b/flight/Bootloaders/PipXtreme/pios_usb_board_data.c index 3e41e5ac9..c2e0c8762 100644 --- a/flight/Bootloaders/PipXtreme/pios_usb_board_data.c +++ b/flight/Bootloaders/PipXtreme/pios_usb_board_data.c @@ -31,6 +31,7 @@ #include "pios_usb_board_data.h" /* struct usb_*, USB_* */ #include "pios_sys.h" /* PIOS_SYS_SerialNumberGet */ #include "pios_usbhook.h" /* PIOS_USBHOOK_* */ +#include "pios_usb_util.h" /* PIOS_USB_UTIL_AsciiToUtf8 */ static const uint8_t usb_product_id[20] = { sizeof(usb_product_id), @@ -46,40 +47,15 @@ static const uint8_t usb_product_id[20] = { 'e', 0, }; -static uint8_t usb_serial_number[52] = { +static uint8_t usb_serial_number[2 + PIOS_SYS_SERIAL_NUM_ASCII_LEN*2 + (sizeof(PIOS_USB_BOARD_SN_SUFFIX)-1)*2] = { sizeof(usb_serial_number), USB_DESC_TYPE_STRING, - 0, 0, - 0, 0, - 0, 0, - 0, 0, - 0, 0, - 0, 0, - 0, 0, - 0, 0, - 0, 0, - 0, 0, - 0, 0, - 0, 0, - 0, 0, - 0, 0, - 0, 0, - 0, 0, - 0, 0, - 0, 0, - 0, 0, - 0, 0, - 0, 0, - 0, 0, - 0, 0, - 0, 0, - 0, 0 }; static const struct usb_string_langid usb_lang_id = { .bLength = sizeof(usb_lang_id), .bDescriptorType = USB_DESC_TYPE_STRING, - .bLangID = htousbs(USB_LANGID_ENGLISH_UK), + .bLangID = htousbs(USB_LANGID_ENGLISH_US), }; static const uint8_t usb_vendor_id[28] = { @@ -103,11 +79,13 @@ static const uint8_t usb_vendor_id[28] = { int32_t PIOS_USB_BOARD_DATA_Init(void) { /* Load device serial number into serial number string */ - uint8_t sn[25]; + uint8_t sn[PIOS_SYS_SERIAL_NUM_ASCII_LEN + 1]; PIOS_SYS_SerialNumberGet((char *)sn); - for (uint8_t i = 0; sn[i] != '\0' && (2 * i) < usb_serial_number[0]; i++) { - usb_serial_number[2 + 2 * i] = sn[i]; - } + + /* Concatenate the device serial number and the appropriate suffix ("+BL" or "+FW") into the USB serial number */ + uint8_t * utf8 = &(usb_serial_number[2]); + utf8 = PIOS_USB_UTIL_AsciiToUtf8(utf8, sn, PIOS_SYS_SERIAL_NUM_ASCII_LEN); + utf8 = PIOS_USB_UTIL_AsciiToUtf8(utf8, (uint8_t *)PIOS_USB_BOARD_SN_SUFFIX, sizeof(PIOS_USB_BOARD_SN_SUFFIX)-1); PIOS_USBHOOK_RegisterString(USB_STRING_DESC_PRODUCT, (uint8_t *)&usb_product_id, sizeof(usb_product_id)); PIOS_USBHOOK_RegisterString(USB_STRING_DESC_SERIAL, (uint8_t *)&usb_serial_number, sizeof(usb_serial_number)); diff --git a/flight/CopterControl/Makefile b/flight/CopterControl/Makefile index 7de345bb1..82334e56a 100644 --- a/flight/CopterControl/Makefile +++ b/flight/CopterControl/Makefile @@ -243,6 +243,7 @@ SRC += $(PIOSSTM32F10X)/pios_usb_hid_pwr.c SRC += $(OPSYSTEM)/pios_usb_board_data.c SRC += $(PIOSCOMMON)/pios_usb_desc_hid_cdc.c SRC += $(PIOSCOMMON)/pios_usb_desc_hid_only.c +SRC += $(PIOSCOMMON)/pios_usb_util.c ## PIOS Hardware (Common) SRC += $(PIOSCOMMON)/pios_crc.c diff --git a/flight/CopterControl/System/inc/pios_usb_board_data.h b/flight/CopterControl/System/inc/pios_usb_board_data.h index 9907a4934..2dcb5f845 100644 --- a/flight/CopterControl/System/inc/pios_usb_board_data.h +++ b/flight/CopterControl/System/inc/pios_usb_board_data.h @@ -41,5 +41,6 @@ #define PIOS_USB_BOARD_PRODUCT_ID USB_PRODUCT_ID_COPTERCONTROL #define PIOS_USB_BOARD_DEVICE_VER USB_OP_DEVICE_VER(USB_OP_BOARD_ID_COPTERCONTROL, USB_OP_BOARD_MODE_FW) +#define PIOS_USB_BOARD_SN_SUFFIX "+FW" #endif /* PIOS_USB_BOARD_DATA_H */ diff --git a/flight/CopterControl/System/pios_board.c b/flight/CopterControl/System/pios_board.c index 78e316cb5..2db478a07 100644 --- a/flight/CopterControl/System/pios_board.c +++ b/flight/CopterControl/System/pios_board.c @@ -156,29 +156,21 @@ void PIOS_Board_Init(void) { const struct pios_board_info * bdinfo = &pios_board_info_blob; #if defined(PIOS_INCLUDE_LED) - switch(bdinfo->board_rev) { - case 0x01: // Revision 1 - PIOS_LED_Init(&pios_led_cfg_cc); - break; - case 0x02: // Revision 2 - GPIO_PinRemapConfig(GPIO_Remap_SWJ_JTAGDisable, ENABLE); - PIOS_LED_Init(&pios_led_cfg_cc3d); - break; - default: - PIOS_Assert(0); - } + const struct pios_led_cfg * led_cfg = PIOS_BOARD_HW_DEFS_GetLedCfg(bdinfo->board_rev); + PIOS_Assert(led_cfg); + PIOS_LED_Init(led_cfg); #endif /* PIOS_INCLUDE_LED */ #if defined(PIOS_INCLUDE_SPI) /* Set up the SPI interface to the serial flash */ switch(bdinfo->board_rev) { - case 0x01: // Revision 1 + case BOARD_REVISION_CC: if (PIOS_SPI_Init(&pios_spi_flash_accel_id, &pios_spi_flash_accel_cfg_cc)) { PIOS_Assert(0); } break; - case 0x02: // Revision 2 + case BOARD_REVISION_CC3D: if (PIOS_SPI_Init(&pios_spi_flash_accel_id, &pios_spi_flash_accel_cfg_cc3d)) { PIOS_Assert(0); } @@ -190,11 +182,11 @@ void PIOS_Board_Init(void) { #endif switch(bdinfo->board_rev) { - case 0x01: // Revision 1 + case BOARD_REVISION_CC: PIOS_Flash_Jedec_Init(pios_spi_flash_accel_id, 1, &flash_w25x_cfg); PIOS_FLASHFS_Init(&flashfs_w25x_cfg); break; - case 0x02: // Revision 2 + case BOARD_REVISION_CC3D: PIOS_Flash_Jedec_Init(pios_spi_flash_accel_id, 0, &flash_m25p_cfg); PIOS_FLASHFS_Init(&flashfs_m25p_cfg); break; @@ -246,40 +238,31 @@ void PIOS_Board_Init(void) { /* Initialize board specific USB data */ PIOS_USB_BOARD_DATA_Init(); + /* Flags to determine if various USB interfaces are advertised */ bool usb_hid_present = false; bool usb_cdc_present = false; - uint8_t hwsettings_usb_devicetype; - HwSettingsUSB_DeviceTypeGet(&hwsettings_usb_devicetype); - - switch (hwsettings_usb_devicetype) { - case HWSETTINGS_USB_DEVICETYPE_HIDONLY: - if (PIOS_USB_DESC_HID_ONLY_Init()) { - PIOS_Assert(0); - } - usb_hid_present = true; - break; - case HWSETTINGS_USB_DEVICETYPE_HIDVCP: - if (PIOS_USB_DESC_HID_CDC_Init()) { - PIOS_Assert(0); - } - usb_hid_present = true; - usb_cdc_present = true; - break; - case HWSETTINGS_USB_DEVICETYPE_VCPONLY: - break; - default: +#if defined(PIOS_INCLUDE_USB_CDC) + if (PIOS_USB_DESC_HID_CDC_Init()) { PIOS_Assert(0); } + usb_hid_present = true; + usb_cdc_present = true; +#else + if (PIOS_USB_DESC_HID_ONLY_Init()) { + PIOS_Assert(0); + } + usb_hid_present = true; +#endif uint32_t pios_usb_id; switch(bdinfo->board_rev) { - case 0x01: // Revision 1 + case BOARD_REVISION_CC: PIOS_USB_Init(&pios_usb_id, &pios_usb_main_cfg_cc); break; - case 0x02: // Revision 2 + case BOARD_REVISION_CC3D: PIOS_USB_Init(&pios_usb_id, &pios_usb_main_cfg_cc3d); break; default: @@ -699,7 +682,7 @@ void PIOS_Board_Init(void) { #endif /* PIOS_DEBUG_ENABLE_DEBUG_PINS */ switch(bdinfo->board_rev) { - case 0x01: + case BOARD_REVISION_CC: // Revision 1 with invensense gyros, start the ADC #if defined(PIOS_INCLUDE_ADC) PIOS_ADC_Init(&pios_adc_cfg); @@ -708,7 +691,7 @@ void PIOS_Board_Init(void) { PIOS_ADXL345_Init(pios_spi_flash_accel_id, 0); #endif break; - case 0x02: + case BOARD_REVISION_CC3D: // Revision 2 with L3GD20 gyros, start a SPI interface and connect to it GPIO_PinRemapConfig(GPIO_Remap_SWJ_JTAGDisable, ENABLE); diff --git a/flight/CopterControl/System/pios_usb_board_data.c b/flight/CopterControl/System/pios_usb_board_data.c index 4f02ce424..1993320d4 100644 --- a/flight/CopterControl/System/pios_usb_board_data.c +++ b/flight/CopterControl/System/pios_usb_board_data.c @@ -31,6 +31,7 @@ #include "pios_usb_board_data.h" /* struct usb_*, USB_* */ #include "pios_sys.h" /* PIOS_SYS_SerialNumberGet */ #include "pios_usbhook.h" /* PIOS_USBHOOK_* */ +#include "pios_usb_util.h" /* PIOS_USB_UTIL_AsciiToUtf8 */ static const uint8_t usb_product_id[28] = { sizeof(usb_product_id), @@ -50,40 +51,15 @@ static const uint8_t usb_product_id[28] = { 'l', 0, }; -static uint8_t usb_serial_number[52] = { +static uint8_t usb_serial_number[2 + PIOS_SYS_SERIAL_NUM_ASCII_LEN*2 + (sizeof(PIOS_USB_BOARD_SN_SUFFIX)-1)*2] = { sizeof(usb_serial_number), USB_DESC_TYPE_STRING, - 0, 0, - 0, 0, - 0, 0, - 0, 0, - 0, 0, - 0, 0, - 0, 0, - 0, 0, - 0, 0, - 0, 0, - 0, 0, - 0, 0, - 0, 0, - 0, 0, - 0, 0, - 0, 0, - 0, 0, - 0, 0, - 0, 0, - 0, 0, - 0, 0, - 0, 0, - 0, 0, - 0, 0, - 0, 0 }; static const struct usb_string_langid usb_lang_id = { .bLength = sizeof(usb_lang_id), .bDescriptorType = USB_DESC_TYPE_STRING, - .bLangID = htousbs(USB_LANGID_ENGLISH_UK), + .bLangID = htousbs(USB_LANGID_ENGLISH_US), }; static const uint8_t usb_vendor_id[28] = { @@ -107,11 +83,13 @@ static const uint8_t usb_vendor_id[28] = { int32_t PIOS_USB_BOARD_DATA_Init(void) { /* Load device serial number into serial number string */ - uint8_t sn[25]; + uint8_t sn[PIOS_SYS_SERIAL_NUM_ASCII_LEN + 1]; PIOS_SYS_SerialNumberGet((char *)sn); - for (uint8_t i = 0; sn[i] != '\0' && (2 * i) < usb_serial_number[0]; i++) { - usb_serial_number[2 + 2 * i] = sn[i]; - } + + /* Concatenate the device serial number and the appropriate suffix ("+BL" or "+FW") into the USB serial number */ + uint8_t * utf8 = &(usb_serial_number[2]); + utf8 = PIOS_USB_UTIL_AsciiToUtf8(utf8, sn, PIOS_SYS_SERIAL_NUM_ASCII_LEN); + utf8 = PIOS_USB_UTIL_AsciiToUtf8(utf8, (uint8_t *)PIOS_USB_BOARD_SN_SUFFIX, sizeof(PIOS_USB_BOARD_SN_SUFFIX)-1); PIOS_USBHOOK_RegisterString(USB_STRING_DESC_PRODUCT, (uint8_t *)&usb_product_id, sizeof(usb_product_id)); PIOS_USBHOOK_RegisterString(USB_STRING_DESC_SERIAL, (uint8_t *)&usb_serial_number, sizeof(usb_serial_number)); diff --git a/flight/PipXtreme/aes.c b/flight/Libraries/aes.c similarity index 100% rename from flight/PipXtreme/aes.c rename to flight/Libraries/aes.c diff --git a/flight/PipXtreme/inc/aes.h b/flight/Libraries/inc/aes.h similarity index 100% rename from flight/PipXtreme/inc/aes.h rename to flight/Libraries/inc/aes.h diff --git a/flight/Libraries/inc/packet_handler.h b/flight/Libraries/inc/packet_handler.h new file mode 100644 index 000000000..f60372998 --- /dev/null +++ b/flight/Libraries/inc/packet_handler.h @@ -0,0 +1,122 @@ +/** + ****************************************************************************** + * @addtogroup OpenPilotSystem OpenPilot System + * @{ + * @addtogroup OpenPilotLibraries OpenPilot System Libraries + * @{ + * + * @file packet_handler.h + * @author The OpenPilot Team, http://www.openpilot.org Copyright (C) 2012. + * @brief A packet handler for handeling radio packet transmission. + * @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 __PACKET_HANDLER_H__ +#define __PACKET_HANDLER_H__ + +// Public defines / macros +#define PHPacketSize(p) ((uint8_t*)(p->data) + p->header.data_size - (uint8_t*)p) +#define PHPacketSizeECC(p) ((uint8_t*)(p->data) + p->header.data_size + RS_ECC_NPARITY - (uint8_t*)p) + +// Public types +typedef enum { + PACKET_TYPE_NONE = 0, + PACKET_TYPE_CONNECT, // for requesting a connection + PACKET_TYPE_DISCONNECT, // to tell the other modem they cannot connect to us + PACKET_TYPE_READY, // tells the other modem we are ready to accept more data + PACKET_TYPE_NOTREADY, // tells the other modem we're not ready to accept more data - we can also send user data in this packet type + PACKET_TYPE_STATUS, // broadcasts status of this modem + PACKET_TYPE_DATARATE, // for changing the RF data rate + PACKET_TYPE_PING, // used to check link is still up + PACKET_TYPE_ADJUST_TX_PWR, // used to ask the other modem to adjust it's tx power + PACKET_TYPE_DATA, // data packet (packet contains user data) + PACKET_TYPE_ACKED_DATA, // data packet that requies an ACK + PACKET_TYPE_PPM, // PPM relay values + PACKET_TYPE_ACK, + PACKET_TYPE_NACK +} PHPacketType; + +typedef struct { + uint32_t destination_id; + uint32_t source_id; + uint8_t type; + uint8_t data_size; + uint8_t tx_seq; + uint8_t rx_seq; + int8_t rssi; + int8_t afc; +} PHPacketHeader; + +#define PH_MAX_DATA (PIOS_PH_MAX_PACKET - sizeof(PHPacketHeader) - RS_ECC_NPARITY) +#define PH_PACKET_SIZE(p) (p->data + p->header.data_size - (uint8_t*)p + RS_ECC_NPARITY) +typedef struct { + PHPacketHeader header; + uint8_t data[PH_MAX_DATA + RS_ECC_NPARITY]; +} PHPacket, *PHPacketHandle; + +#define PH_PPM_DATA_SIZE(p) ((uint8_t*)((p)->ecc) - (uint8_t*)(((PHPacketHandle)(p))->data)) +typedef struct { + PHPacketHeader header; + uint16_t channels[PIOS_RCVR_MAX_CHANNELS]; + uint8_t ecc[RS_ECC_NPARITY]; +} PHPpmPacket, *PHPpmPacketHandle; + +#define PH_STATUS_DATA_SIZE(p) ((uint8_t*)((p)->ecc) - (uint8_t*)(((PHPacketHandle)(p))->data)) +typedef struct { + PHPacketHeader header; + uint16_t retries; + uint16_t errors; + uint16_t uavtalk_errors; + uint16_t resets; + uint8_t ecc[RS_ECC_NPARITY]; +} PHStatusPacket, *PHStatusPacketHandle; + +typedef struct { + uint8_t winSize; + uint16_t maxConnections; +} PacketHandlerConfig; + +typedef int32_t (*PHOutputStream)(PHPacketHandle packet); +typedef void (*PHDataHandler)(uint8_t *data, uint8_t len); +typedef void (*PHStatusHandler)(PHStatusPacketHandle s); +typedef void (*PHPPMHandler)(uint16_t *channels); + +typedef uint32_t PHInstHandle; + +// Public functions +PHInstHandle PHInitialize(PacketHandlerConfig *cfg); +void PHRegisterOutputStream(PHInstHandle h, PHOutputStream f); +void PHRegisterDataHandler(PHInstHandle h, PHDataHandler f); +void PHRegisterStatusHandler(PHInstHandle h, PHStatusHandler f); +void PHRegisterPPMHandler(PHInstHandle h, PHPPMHandler f); +uint32_t PHConnect(PHInstHandle h, uint32_t dest_id); +PHPacketHandle PHGetRXPacket(PHInstHandle h); +void PHReleaseTXPacket(PHInstHandle h, PHPacketHandle p); +PHPacketHandle PHGetTXPacket(PHInstHandle h); +void PHReleaseTXPacket(PHInstHandle h, PHPacketHandle p); +uint8_t PHTransmitPacket(PHInstHandle h, PHPacketHandle p); +int32_t PHVerifyPacket(PHInstHandle h, PHPacketHandle p, uint16_t received_len); +uint8_t PHReceivePacket(PHInstHandle h, PHPacketHandle p, bool rx_error); + +#endif // __PACKET_HANDLER_H__ + +/** + * @} + * @} + */ diff --git a/flight/Libraries/packet_handler.c b/flight/Libraries/packet_handler.c new file mode 100644 index 000000000..fc78764db --- /dev/null +++ b/flight/Libraries/packet_handler.c @@ -0,0 +1,507 @@ +/** + ****************************************************************************** + * @addtogroup OpenPilotSystem OpenPilot System + * @{ + * @addtogroup OpenPilotLibraries OpenPilot System Libraries + * @{ + * + * @file packet_handler.c + * @author The OpenPilot Team, http://www.openpilot.org Copyright (C) 2012. + * @brief A packet handler for handeling radio packet transmission. + * @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 "openpilot.h" +#include "packet_handler.h" +#include "aes.h" +#include "ecc.h" + +extern char *debug_msg; + +// Private types and constants +typedef struct { + PacketHandlerConfig cfg; + PHPacket *tx_packets; + uint8_t tx_win_start; + uint8_t tx_win_end; + PHPacket *rx_packets; + uint8_t rx_win_start; + uint8_t rx_win_end; + uint16_t tx_seq_id; + PHOutputStream stream; + xSemaphoreHandle lock; + PHOutputStream output_stream; + PHDataHandler data_handler; + PHStatusHandler status_handler; + PHPPMHandler ppm_handler; +} PHPacketData, *PHPacketDataHandle; + +// Private functions +static uint8_t PHLSendAck(PHPacketDataHandle data, PHPacketHandle p); +static uint8_t PHLSendNAck(PHPacketDataHandle data, PHPacketHandle p); +static uint8_t PHLTransmitPacket(PHPacketDataHandle data, PHPacketHandle p); + +/** + * Initialize the Packet Handler library + * \param[in] txWinSize The transmission window size (number of tx packet buffers). + * \param[in] streme A callback function for transmitting the packet. + * \param[in] id The source ID of transmitter. + * \return PHInstHandle The Pachet Handler instance data. + * \return 0 Failure + */ +PHInstHandle PHInitialize(PacketHandlerConfig *cfg) +{ + // Allocate the primary structure + PHPacketDataHandle data = pvPortMalloc(sizeof(PHPacketData)); + if (!data) + return 0; + data->cfg = *cfg; + data->tx_seq_id = 0; + + // Allocate the packet windows + data->tx_packets = pvPortMalloc(sizeof(PHPacket) * data->cfg.winSize); + data->rx_packets = pvPortMalloc(sizeof(PHPacket) * data->cfg.winSize); + + // Initialize the windows + data->tx_win_start = data->tx_win_end = 0; + data->rx_win_start = data->rx_win_end = 0; + for (uint8_t i = 0; i < data->cfg.winSize; ++i) + { + data->tx_packets[i].header.type = PACKET_TYPE_NONE; + data->rx_packets[i].header.type = PACKET_TYPE_NONE; + } + + // Create the lock + data->lock = xSemaphoreCreateRecursiveMutex(); + + // Initialize the ECC library. + initialize_ecc(); + + // Return the structure. + return (PHInstHandle)data; +} + +/** + * Register an output stream handler + * \param[in] h The packet handler instance data pointer. + * \param[in] f The output stream handler function + */ +void PHRegisterOutputStream(PHInstHandle h, PHOutputStream f) +{ + PHPacketDataHandle data = (PHPacketDataHandle)h; + + data->output_stream = f; +} + +/** + * Register a data handler + * \param[in] h The packet handler instance data pointer. + * \param[in] f The data handler function + */ +void PHRegisterDataHandler(PHInstHandle h, PHDataHandler f) +{ + PHPacketDataHandle data = (PHPacketDataHandle)h; + + data->data_handler = f; +} + +/** + * Register a PPM packet handler + * \param[in] h The packet handler instance data pointer. + * \param[in] f The PPM handler function + */ +void PHRegisterStatusHandler(PHInstHandle h, PHStatusHandler f) +{ + PHPacketDataHandle data = (PHPacketDataHandle)h; + + data->status_handler = f; +} + +/** + * Register a PPM packet handler + * \param[in] h The packet handler instance data pointer. + * \param[in] f The PPM handler function + */ +void PHRegisterPPMHandler(PHInstHandle h, PHPPMHandler f) +{ + PHPacketDataHandle data = (PHPacketDataHandle)h; + + data->ppm_handler = f; +} + +/** + * Get a packet out of the transmit buffer. + * \param[in] h The packet handler instance data pointer. + * \param[in] dest_id The destination ID of this connection + * \return PHPacketHandle A pointer to the packet buffer. + * \return 0 No packets buffers avaiable in the transmit window. + */ +uint32_t PHConnect(PHInstHandle h, uint32_t dest_id) +{ + return 1; +} + +/** + * Get a packet out of the transmit buffer. + * \param[in] h The packet handler instance data pointer. + * \return PHPacketHandle A pointer to the packet buffer. + * \return 0 No packets buffers avaiable in the transmit window. + */ +PHPacketHandle PHGetTXPacket(PHInstHandle h) +{ + PHPacketDataHandle data = (PHPacketDataHandle)h; + + // Lock + xSemaphoreTakeRecursive(data->lock, portMAX_DELAY); + PHPacketHandle p = data->tx_packets + data->tx_win_end; + + // Is the window full? + uint8_t next_end = (data->tx_win_end + 1) % data->cfg.winSize; + if(next_end == data->tx_win_start) + { + xSemaphoreGiveRecursive(data->lock); + return NULL; + } + data->tx_win_end = next_end; + + // Release lock + xSemaphoreGiveRecursive(data->lock); + + // Return a pointer to the packet at the end of the TX window. + return p; +} + +/** + * Release a packet from the transmit packet buffer window. + * \param[in] h The packet handler instance data pointer. + * \param[in] p A pointer to the packet buffer. + * \return Nothing + */ +void PHReleaseTXPacket(PHInstHandle h, PHPacketHandle p) +{ + PHPacketDataHandle data = (PHPacketDataHandle)h; + + // Lock + xSemaphoreTakeRecursive(data->lock, portMAX_DELAY); + + // Change the packet type so we know this packet is unused. + p->header.type = PACKET_TYPE_NONE; + + // If this packet is at the start of the window, increment the start index. + while ((data->tx_win_start != data->tx_win_end) && + (data->tx_packets[data->tx_win_start].header.type == PACKET_TYPE_NONE)) + data->tx_win_start = (data->tx_win_start + 1) % data->cfg.winSize; + + // Release lock + xSemaphoreGiveRecursive(data->lock); +} + +/** + * Get a packet out of the receive buffer. + * \param[in] h The packet handler instance data pointer. + * \return PHPacketHandle A pointer to the packet buffer. + * \return 0 No packets buffers avaiable in the transmit window. + */ +PHPacketHandle PHGetRXPacket(PHInstHandle h) +{ + PHPacketDataHandle data = (PHPacketDataHandle)h; + + // Lock + xSemaphoreTakeRecursive(data->lock, portMAX_DELAY); + PHPacketHandle p = data->rx_packets + data->rx_win_end; + + // Is the window full? + uint8_t next_end = (data->rx_win_end + 1) % data->cfg.winSize; + if(next_end == data->rx_win_start) + { + // Release lock + xSemaphoreGiveRecursive(data->lock); + return NULL; + } + data->rx_win_end = next_end; + + // Release lock + xSemaphoreGiveRecursive(data->lock); + + // Return a pointer to the packet at the end of the TX window. + return p; +} + +/** + * Release a packet from the receive packet buffer window. + * \param[in] h The packet handler instance data pointer. + * \param[in] p A pointer to the packet buffer. + * \return Nothing + */ +void PHReleaseRXPacket(PHInstHandle h, PHPacketHandle p) +{ + PHPacketDataHandle data = (PHPacketDataHandle)h; + + // Lock + xSemaphoreTakeRecursive(data->lock, portMAX_DELAY); + + // Change the packet type so we know this packet is unused. + p->header.type = PACKET_TYPE_NONE; + + // If this packet is at the start of the window, increment the start index. + while ((data->rx_win_start != data->rx_win_end) && + (data->rx_packets[data->rx_win_start].header.type == PACKET_TYPE_NONE)) + data->rx_win_start = (data->rx_win_start + 1) % data->cfg.winSize; + + // Release lock + xSemaphoreGiveRecursive(data->lock); +} + +/** + * Transmit a packet from the transmit packet buffer window. + * \param[in] h The packet handler instance data pointer. + * \param[in] p A pointer to the packet buffer. + * \return 1 Success + * \return 0 Failure + */ +uint8_t PHTransmitPacket(PHInstHandle h, PHPacketHandle p) +{ + PHPacketDataHandle data = (PHPacketDataHandle)h; + + // Try to transmit the packet. + if (!PHLTransmitPacket(data, p)) + return 0; + + // If this packet doesn't require an ACK, remove it from the TX window. + switch (p->header.type) { + case PACKET_TYPE_READY: + case PACKET_TYPE_NOTREADY: + case PACKET_TYPE_DATA: + case PACKET_TYPE_PPM: + PHReleaseTXPacket(h, p); + break; + } + + return 1; +} + +/** + * Verify that a buffer contains a valid packet. + * \param[in] h The packet handler instance data pointer. + * \param[in] p A pointer to the packet buffer. + * \param[in] received_len The length of data received. + * \return < 0 Failure + * \return > 0 Number of bytes consumed. + */ +int32_t PHVerifyPacket(PHInstHandle h, PHPacketHandle p, uint16_t received_len) +{ + + // Verify the packet length. + // Note: The last two bytes should be the RSSI and AFC. + uint16_t len = PHPacketSizeECC(p); + if (received_len < (len + 2)) + { + DEBUG_PRINTF(1, "Packet length error %d %d\n\r", received_len, len + 2); + return -1; + } + + // Attempt to correct any errors in the packet. + decode_data((unsigned char*)p, len); + + // Check that there were no unfixed errors. + bool rx_error = check_syndrome() != 0; + if(rx_error) + { + DEBUG_PRINTF(1, "Error in packet\n\r"); + return -2; + } + + return len + 2; +} + +/** + * Process a packet that has been received. + * \param[in] h The packet handler instance data pointer. + * \param[in] p A pointer to the packet buffer. + * \param[in] received_len The length of data received. + * \return 0 Failure + * \return 1 Success + */ +uint8_t PHReceivePacket(PHInstHandle h, PHPacketHandle p, bool rx_error) +{ + PHPacketDataHandle data = (PHPacketDataHandle)h; + uint16_t len = PHPacketSizeECC(p); + + // Add the RSSI and AFC to the packet. + p->header.rssi = *(((int8_t*)p) + len); + p->header.afc = *(((int8_t*)p) + len + 1); + + switch (p->header.type) { + + case PACKET_TYPE_STATUS: + + if (!rx_error) + + // Pass on the channels to the status handler. + if(data->status_handler) + data->status_handler((PHStatusPacketHandle)p); + + break; + + case PACKET_TYPE_ACKED_DATA: + + // Send the ACK / NACK + if (rx_error) + { + DEBUG_PRINTF(1, "Sending NACK\n\r"); + PHLSendNAck(data, p); + } + else + { + + PHLSendAck(data, p); + + // Pass on the data. + if(data->data_handler) + data->data_handler(p->data, p->header.data_size); + } + + break; + + case PACKET_TYPE_ACK: + { + // Find the packet ID in the TX buffer, and free it. + unsigned int i = 0; + for (unsigned int i = 0; i < data->cfg.winSize; ++i) + if (data->tx_packets[i].header.tx_seq == p->header.rx_seq) + PHReleaseTXPacket(h, data->tx_packets + i); +#ifdef DEBUG_LEVEL + if (i == data->cfg.winSize) + DEBUG_PRINTF(1, "Error finding acked packet to release\n\r"); +#endif + } + break; + + case PACKET_TYPE_NACK: + { + // Resend the packet. + unsigned int i = 0; + for ( ; i < data->cfg.winSize; ++i) + if (data->tx_packets[i].header.tx_seq == p->header.rx_seq) + PHLTransmitPacket(data, data->tx_packets + i); +#ifdef DEBUG_LEVEL + if (i == data->cfg.winSize) + DEBUG_PRINTF(1, "Error finding acked packet to NACK\n\r"); + DEBUG_PRINTF(1, "Resending after NACK\n\r"); +#endif + } + break; + + case PACKET_TYPE_PPM: + + if (!rx_error) + + // Pass on the channels to the PPM handler. + if(data->ppm_handler) + data->ppm_handler(((PHPpmPacketHandle)p)->channels); + + break; + + case PACKET_TYPE_DATA: + + if (!rx_error) + + // Pass on the data to the data handler. + if(data->data_handler) + data->data_handler(p->data, p->header.data_size); + + break; + + default: + break; + } + + // Release the packet. + PHReleaseRXPacket(h, p); + + return 1; +} + +/** + * Transmit a packet from the transmit packet buffer window. + * \param[in] data The packet handler instance data pointer. + * \param[in] p A pointer to the packet buffer. + * \return 1 Success + * \return 0 Failure + */ +static uint8_t PHLTransmitPacket(PHPacketDataHandle data, PHPacketHandle p) +{ + + if(!data->output_stream) + return 0; + + // Set the sequence ID to the current ID. + p->header.tx_seq = data->tx_seq_id++; + + // Add the error correcting code. + encode_data((unsigned char*)p, PHPacketSize(p), (unsigned char*)p); + + // Transmit the packet using the output stream. + if(data->output_stream(p) == -1) + return 0; + + return 1; +} + +/** + * Send an ACK packet. + * \param[in] data The packet handler instance data pointer. + * \param[in] p A pointer to the packet buffer of the packet to be ACKed. + * \return 1 Success + * \return 0 Failure + */ +static uint8_t PHLSendAck(PHPacketDataHandle data, PHPacketHandle p) +{ + + // Create the ACK message + PHPacketHeader ack; + ack.destination_id = p->header.source_id; + ack.type = PACKET_TYPE_ACK; + ack.rx_seq = p->header.tx_seq; + ack.data_size = 0; + + // Send the packet. + return PHLTransmitPacket(data, (PHPacketHandle)&ack); +} + +/** + * Send an NAck packet. + * \param[in] data The packet handler instance data pointer. + * \param[in] p A pointer to the packet buffer of the packet to be ACKed. + * \return 1 Success + * \return 0 Failure + */ +static uint8_t PHLSendNAck(PHPacketDataHandle data, PHPacketHandle p) +{ + + // Create the NAck message + PHPacketHeader ack; + ack.destination_id = p->header.source_id; + ack.type = PACKET_TYPE_NACK; + ack.rx_seq = p->header.tx_seq; + ack.data_size = 0; + + // Set the packet. + return PHLTransmitPacket(data, (PHPacketHandle)&ack); +} diff --git a/flight/Libraries/rscode/LICENSE b/flight/Libraries/rscode/LICENSE new file mode 100644 index 000000000..daab5a625 --- /dev/null +++ b/flight/Libraries/rscode/LICENSE @@ -0,0 +1,10 @@ + * (C) Henry Minsky (hqm@alum.mit.edu) 1991-2009 + * + * This software library is licensed under terms of the GNU GENERAL + * PUBLIC LICENSE. [See file gpl.txt] + * + * Commercial licensing is available under a separate license, please + * contact author for details. + * + * Latest source code and other info at http://rscode.sourceforge.net + diff --git a/flight/Libraries/rscode/Makefile b/flight/Libraries/rscode/Makefile new file mode 100644 index 000000000..daa12624f --- /dev/null +++ b/flight/Libraries/rscode/Makefile @@ -0,0 +1,50 @@ +# Makefile for Cross Interleaved Reed Solomon encoder/decoder +# +# (c) Henry Minsky, Universal Access 1991-1996 +# + +RANLIB = ranlib +AR = ar + + +VERSION = 1.0 +DIRNAME= rscode-$(VERSION) + + +CC = gcc +# OPTIMIZE_FLAGS = -O69 +DEBUG_FLAGS = -g +CFLAGS = -Wall -Wstrict-prototypes $(OPTIMIZE_FLAGS) $(DEBUG_FLAGS) -I.. +LDFLAGS = $(OPTIMIZE_FLAGS) $(DEBUG_FLAGS) + +LIB_CSRC = rs.c galois.c berlekamp.c crcgen.c +LIB_HSRC = ecc.h +LIB_OBJS = rs.o galois.o berlekamp.o crcgen.o + +TARGET_LIB = libecc.a +TEST_PROGS = example + +TARGETS = $(TARGET_LIB) $(TEST_PROGS) + +all: $(TARGETS) + +$(TARGET_LIB): $(LIB_OBJS) + $(RM) $@ + $(AR) cq $@ $(LIB_OBJS) + if [ "$(RANLIB)" ]; then $(RANLIB) $@; fi + +example: example.o galois.o berlekamp.o crcgen.o rs.o + gcc -o example example.o -L. -lecc + +clean: + rm -f *.o example libecc.a + rm -f *~ + +dist: + (cd ..; tar -cvf rscode-$(VERSION).tar $(DIRNAME)) + +depend: + makedepend $(SRCS) + +# DO NOT DELETE THIS LINE -- make depend depends on it. + diff --git a/flight/Libraries/rscode/README b/flight/Libraries/rscode/README new file mode 100644 index 000000000..92d68b3d8 --- /dev/null +++ b/flight/Libraries/rscode/README @@ -0,0 +1,27 @@ +RSCODE version 1.3 + +See the files + +config.doc documentation of some compile time parameters +rs.doc overview of the Reed-Solomon coding program +rs.man a man page, slightly outdated at this point +example.c a simple example of encoding,decoding, and error correction + +Makefile should work on a Sun system, may require GNU make. + + +Henry Minsky +hqm@alum.mit.edu + + + * (c) Henry Minsky (hqm@alum.mit.edu) 1991-2009 + * + * This software library is licensed under terms of the GNU GENERAL + * PUBLIC LICENSE. (See gpl.txt) + * + * Commercial licensing is available under a separate license, please + * contact author for details. + * + * Source code is available at http://rscode.sourceforge.net + + diff --git a/flight/Libraries/rscode/berlekamp.c b/flight/Libraries/rscode/berlekamp.c new file mode 100644 index 000000000..ef91991e3 --- /dev/null +++ b/flight/Libraries/rscode/berlekamp.c @@ -0,0 +1,324 @@ +/*********************************************************************** + * Copyright Henry Minsky (hqm@alum.mit.edu) 1991-2009 + * + * This software library is licensed under terms of the GNU GENERAL + * PUBLIC LICENSE + * + * + * RSCODE 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. + * + * RSCODE 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 Rscode. If not, see . + * + * Commercial licensing is available under a separate license, please + * contact author for details. + * + * Source code is available at http://rscode.sourceforge.net + * Berlekamp-Peterson and Berlekamp-Massey Algorithms for error-location + * + * From Cain, Clark, "Error-Correction Coding For Digital Communications", pp. 205. + * + * This finds the coefficients of the error locator polynomial. + * + * The roots are then found by looking for the values of a^n + * where evaluating the polynomial yields zero. + * + * Error correction is done using the error-evaluator equation on pp 207. + * + */ + +#include +#include "ecc.h" + +/* The Error Locator Polynomial, also known as Lambda or Sigma. Lambda[0] == 1 */ +static int Lambda[MAXDEG]; + +/* The Error Evaluator Polynomial */ +static int Omega[MAXDEG]; + +/* local ANSI declarations */ +static int compute_discrepancy(int lambda[], int S[], int L, int n); +static void init_gamma(int gamma[]); +static void compute_modified_omega (void); +static void mul_z_poly (int src[]); + +/* error locations found using Chien's search*/ +static int ErrorLocs[256]; +static int NErrors; + +/* erasure flags */ +static int ErasureLocs[256]; +static int NErasures; + +/* From Cain, Clark, "Error-Correction Coding For Digital Communications", pp. 216. */ +void +Modified_Berlekamp_Massey (void) +{ + int n, L, L2, k, d, i; + int psi[MAXDEG], psi2[MAXDEG], D[MAXDEG]; + int gamma[MAXDEG]; + + /* initialize Gamma, the erasure locator polynomial */ + init_gamma(gamma); + + /* initialize to z */ + copy_poly(D, gamma); + mul_z_poly(D); + + copy_poly(psi, gamma); + k = -1; L = NErasures; + + for (n = NErasures; n < RS_ECC_NPARITY; n++) { + + d = compute_discrepancy(psi, synBytes, L, n); + + if (d != 0) { + + /* psi2 = psi - d*D */ + for (i = 0; i < MAXDEG; i++) psi2[i] = psi[i] ^ gmult(d, D[i]); + + + if (L < (n-k)) { + L2 = n-k; + k = n-L; + /* D = scale_poly(ginv(d), psi); */ + for (i = 0; i < MAXDEG; i++) D[i] = gmult(psi[i], ginv(d)); + L = L2; + } + + /* psi = psi2 */ + for (i = 0; i < MAXDEG; i++) psi[i] = psi2[i]; + } + + mul_z_poly(D); + } + + for(i = 0; i < MAXDEG; i++) Lambda[i] = psi[i]; + compute_modified_omega(); + + +} + +/* given Psi (called Lambda in Modified_Berlekamp_Massey) and synBytes, + compute the combined erasure/error evaluator polynomial as + Psi*S mod z^4 + */ +void +compute_modified_omega () +{ + int i; + int product[MAXDEG*2]; + + mult_polys(product, Lambda, synBytes); + zero_poly(Omega); + for(i = 0; i < RS_ECC_NPARITY; i++) Omega[i] = product[i]; + +} + +/* polynomial multiplication */ +void +mult_polys (int dst[], int p1[], int p2[]) +{ + int i, j; + int tmp1[MAXDEG*2]; + + for (i=0; i < (MAXDEG*2); i++) dst[i] = 0; + + for (i = 0; i < MAXDEG; i++) { + for(j=MAXDEG; j<(MAXDEG*2); j++) tmp1[j]=0; + + /* scale tmp1 by p1[i] */ + for(j=0; j= i; j--) tmp1[j] = tmp1[j-i]; + for (j = 0; j < i; j++) tmp1[j] = 0; + + /* add into partial product */ + for(j=0; j < (MAXDEG*2); j++) dst[j] ^= tmp1[j]; + } +} + + + +/* gamma = product (1-z*a^Ij) for erasure locs Ij */ +void +init_gamma (int gamma[]) +{ + int e, tmp[MAXDEG]; + + zero_poly(gamma); + zero_poly(tmp); + gamma[0] = 1; + + for (e = 0; e < NErasures; e++) { + copy_poly(tmp, gamma); + scale_poly(gexp[ErasureLocs[e]], tmp); + mul_z_poly(tmp); + add_polys(gamma, tmp); + } +} + + + +void +compute_next_omega (int d, int A[], int dst[], int src[]) +{ + int i; + for ( i = 0; i < MAXDEG; i++) { + dst[i] = src[i] ^ gmult(d, A[i]); + } +} + + + +int +compute_discrepancy (int lambda[], int S[], int L, int n) +{ + int i, sum=0; + + for (i = 0; i <= L; i++) + sum ^= gmult(lambda[i], S[n-i]); + return (sum); +} + +/********** polynomial arithmetic *******************/ + +void add_polys (int dst[], int src[]) +{ + int i; + for (i = 0; i < MAXDEG; i++) dst[i] ^= src[i]; +} + +void copy_poly (int dst[], int src[]) +{ + int i; + for (i = 0; i < MAXDEG; i++) dst[i] = src[i]; +} + +void scale_poly (int k, int poly[]) +{ + int i; + for (i = 0; i < MAXDEG; i++) poly[i] = gmult(k, poly[i]); +} + + +void zero_poly (int poly[]) +{ + int i; + for (i = 0; i < MAXDEG; i++) poly[i] = 0; +} + + +/* multiply by z, i.e., shift right by 1 */ +static void mul_z_poly (int src[]) +{ + int i; + for (i = MAXDEG-1; i > 0; i--) src[i] = src[i-1]; + src[0] = 0; +} + + +/* Finds all the roots of an error-locator polynomial with coefficients + * Lambda[j] by evaluating Lambda at successive values of alpha. + * + * This can be tested with the decoder's equations case. + */ + + +void +Find_Roots (void) +{ + int sum, r, k; + NErrors = 0; + + for (r = 1; r < 256; r++) { + sum = 0; + /* evaluate lambda at r */ + for (k = 0; k < RS_ECC_NPARITY+1; k++) { + sum ^= gmult(gexp[(k*r)%255], Lambda[k]); + } + if (sum == 0) + { + ErrorLocs[NErrors] = (255-r); NErrors++; + //if (DEBUG) fprintf(stderr, "Root found at r = %d, (255-r) = %d\n", r, (255-r)); + } + } +} + +/* Combined Erasure And Error Magnitude Computation + * + * Pass in the codeword, its size in bytes, as well as + * an array of any known erasure locations, along the number + * of these erasures. + * + * Evaluate Omega(actually Psi)/Lambda' at the roots + * alpha^(-i) for error locs i. + * + * Returns 1 if everything ok, or 0 if an out-of-bounds error is found + * + */ + +int +correct_errors_erasures (unsigned char codeword[], + int csize, + int nerasures, + int erasures[]) +{ + int r, i, j, err; + + /* If you want to take advantage of erasure correction, be sure to + set NErasures and ErasureLocs[] with the locations of erasures. + */ + NErasures = nerasures; + for (i = 0; i < NErasures; i++) ErasureLocs[i] = erasures[i]; + + Modified_Berlekamp_Massey(); + Find_Roots(); + + + if ((NErrors <= RS_ECC_NPARITY) && NErrors > 0) { + + /* first check for illegal error locs */ + for (r = 0; r < NErrors; r++) { + if (ErrorLocs[r] >= csize) { + //if (DEBUG) fprintf(stderr, "Error loc i=%d outside of codeword length %d\n", i, csize); + return(0); + } + } + + for (r = 0; r < NErrors; r++) { + int num, denom; + i = ErrorLocs[r]; + /* evaluate Omega at alpha^(-i) */ + + num = 0; + for (j = 0; j < MAXDEG; j++) + num ^= gmult(Omega[j], gexp[((255-i)*j)%255]); + + /* evaluate Lambda' (derivative) at alpha^(-i) ; all odd powers disappear */ + denom = 0; + for (j = 1; j < MAXDEG; j += 2) { + denom ^= gmult(Lambda[j], gexp[((255-i)*(j-1)) % 255]); + } + + err = gmult(num, ginv(denom)); + //if (DEBUG) fprintf(stderr, "Error magnitude %#x at loc %d\n", err, csize-i); + + codeword[csize-i-1] ^= err; + } + return(1); + } + else { + //if (DEBUG && NErrors) fprintf(stderr, "Uncorrectable codeword\n"); + return(0); + } +} + diff --git a/flight/Libraries/rscode/config.doc b/flight/Libraries/rscode/config.doc new file mode 100644 index 000000000..77771893d --- /dev/null +++ b/flight/Libraries/rscode/config.doc @@ -0,0 +1,18 @@ +The basic coding parameters are defined using +macros, and an executable can be made by compiling using macro +definitions defining the values of the following names in the file +"ecc.h": + +The important compile time parameter is the number of parity bytes, +specified by the #define NPAR. + +The library is shipped with + +#define NPAR 4 + +The error-correction routines are polynomial in the number of +parity bytes, so try to keep NPAR small for high performance. + +Remember, the sum of the message length (in bytes) plus parity bytes +must be less than or equal to 255. + diff --git a/flight/Libraries/rscode/crcgen.c b/flight/Libraries/rscode/crcgen.c new file mode 100644 index 000000000..487dba5d0 --- /dev/null +++ b/flight/Libraries/rscode/crcgen.c @@ -0,0 +1,66 @@ +/***************************** + * Copyright Henry Minsky (hqm@alum.mit.edu) 1991-2009 + * + * This software library is licensed under terms of the GNU GENERAL + * PUBLIC LICENSE + * + * RSCODE 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. + * + * RSCODE 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 Rscode. If not, see . + + * Commercial licensing is available under a separate license, please + * contact author for details. + * + * Source code is available at http://rscode.sourceforge.net + * + * CRC-CCITT generator simulator for byte wide data. + * + * + * CRC-CCITT = x^16 + x^12 + x^5 + 1 + * + * + ******************************/ + + +#include "ecc.h" + +BIT16 crchware(BIT16 data, BIT16 genpoly, BIT16 accum); + +/* Computes the CRC-CCITT checksum on array of byte data, length len +*/ +BIT16 crc_ccitt(unsigned char *msg, int len) +{ + int i; + BIT16 acc = 0; + + for (i = 0; i < len; i++) { + acc = crchware((BIT16) msg[i], (BIT16) 0x1021, acc); + } + + return(acc); +} + +/* models crc hardware (minor variation on polynomial division algorithm) */ +BIT16 crchware(BIT16 data, BIT16 genpoly, BIT16 accum) +{ + static BIT16 i; + data <<= 8; + for (i = 8; i > 0; i--) { + if ((data ^ accum) & 0x8000) + accum = ((accum << 1) ^ genpoly) & 0xFFFF; + else + accum = (accum<<1) & 0xFFFF; + data = (data<<1) & 0xFFFF; + } + return (accum); +} + diff --git a/flight/Libraries/rscode/ecc.h b/flight/Libraries/rscode/ecc.h new file mode 100644 index 000000000..bf56a0b9a --- /dev/null +++ b/flight/Libraries/rscode/ecc.h @@ -0,0 +1,98 @@ +/* Reed Solomon Coding for glyphs + * Copyright Henry Minsky (hqm@alum.mit.edu) 1991-2009 + * + * This software library is licensed under terms of the GNU GENERAL + * PUBLIC LICENSE + * + * RSCODE 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. + * + * RSCODE 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 Rscode. If not, see . + * + * Source code is available at http://rscode.sourceforge.net + * + * Commercial licensing is available under a separate license, please + * contact author for details. + * + */ + +/**************************************************************** + + Below is NPAR, the only compile-time parameter you should have to + modify. + + It is the number of parity bytes which will be appended to + your data to create a codeword. + + Note that the maximum codeword size is 255, so the + sum of your message length plus parity should be less than + or equal to this maximum limit. + + In practice, you will get slooow error correction and decoding + if you use more than a reasonably small number of parity bytes. + (say, 10 or 20) + + ****************************************************************/ + +/****************************************************************/ + + +#include + +#define TRUE 1 +#define FALSE 0 + +typedef unsigned long BIT32; +typedef unsigned short BIT16; + +/* **************************************************************** */ + +/* Maximum degree of various polynomials. */ +#define MAXDEG (RS_ECC_NPARITY*2) + +/*************************************/ +/* Encoder parity bytes */ +extern int pBytes[MAXDEG]; + +/* Decoder syndrome bytes */ +extern int synBytes[MAXDEG]; + +/* print debugging info */ +extern int DEBUG; + +/* Reed Solomon encode/decode routines */ +void initialize_ecc (void); +int check_syndrome (void); +void decode_data (unsigned char data[], int nbytes); +void encode_data (unsigned char msg[], int nbytes, unsigned char dst[]); + +/* CRC-CCITT checksum generator */ +BIT16 crc_ccitt(unsigned char *msg, int len); + +/* galois arithmetic tables */ +extern const int gexp[]; +extern const int glog[]; + +void init_galois_tables (void); +int ginv(int elt); +int gmult(int a, int b); + + +/* Error location routines */ +int correct_errors_erasures (unsigned char codeword[], int csize,int nerasures, int erasures[]); + +/* polynomial arithmetic */ +void add_polys(int dst[], int src[]) ; +void scale_poly(int k, int poly[]); +void mult_polys(int dst[], int p1[], int p2[]); + +void copy_poly(int dst[], int src[]); +void zero_poly(int poly[]); diff --git a/flight/Libraries/rscode/example.c b/flight/Libraries/rscode/example.c new file mode 100644 index 000000000..b4df5b87f --- /dev/null +++ b/flight/Libraries/rscode/example.c @@ -0,0 +1,128 @@ +/* Example use of Reed-Solomon library + * + * Copyright Henry Minsky (hqm@alum.mit.edu) 1991-2009 + * + * This software library is licensed under terms of the GNU GENERAL + * PUBLIC LICENSE + * + * RSCODE 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. + * + * RSCODE 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 Rscode. If not, see . + + * Commercial licensing is available under a separate license, please + * contact author for details. + * + * This same code demonstrates the use of the encodier and + * decoder/error-correction routines. + * + * We are assuming we have at least four bytes of parity (NPAR >= 4). + * + * This gives us the ability to correct up to two errors, or + * four erasures. + * + * In general, with E errors, and K erasures, you will need + * 2E + K bytes of parity to be able to correct the codeword + * back to recover the original message data. + * + * You could say that each error 'consumes' two bytes of the parity, + * whereas each erasure 'consumes' one byte. + * + * Thus, as demonstrated below, we can inject one error (location unknown) + * and two erasures (with their locations specified) and the + * error-correction routine will be able to correct the codeword + * back to the original message. + * */ + +#include +#include +#include "ecc.h" + +unsigned char msg[] = "Nervously I loaded the twin ducks aboard the revolving pl\ +atform."; +unsigned char codeword[256]; + +/* Some debugging routines to introduce errors or erasures + into a codeword. + */ + +/* Introduce a byte error at LOC */ +void +byte_err (int err, int loc, unsigned char *dst) +{ + printf("Adding Error at loc %d, data %#x\n", loc, dst[loc-1]); + dst[loc-1] ^= err; +} + +/* Pass in location of error (first byte position is + labeled starting at 1, not 0), and the codeword. +*/ +void +byte_erasure (int loc, unsigned char dst[], int cwsize, int erasures[]) +{ + printf("Erasure at loc %d, data %#x\n", loc, dst[loc-1]); + dst[loc-1] = 0; +} + + +int +main (int argc, char *argv[]) +{ + + int erasures[16]; + int nerasures = 0; + + /* Initialization the ECC library */ + + initialize_ecc (); + + /* ************** */ + + /* Encode data into codeword, adding NPAR parity bytes */ + encode_data(msg, sizeof(msg), codeword); + + printf("Encoded data is: \"%s\"\n", codeword); + +#define ML (sizeof (msg) + NPAR) + + + /* Add one error and two erasures */ + byte_err(0x35, 3, codeword); + + byte_err(0x23, 17, codeword); + byte_err(0x34, 19, codeword); + + + printf("with some errors: \"%s\"\n", codeword); + + /* We need to indicate the position of the erasures. Eraseure + positions are indexed (1 based) from the end of the message... */ + + erasures[nerasures++] = ML-17; + erasures[nerasures++] = ML-19; + + + /* Now decode -- encoded codeword size must be passed */ + decode_data(codeword, ML); + + /* check if syndrome is all zeros */ + if (check_syndrome () != 0) { + correct_errors_erasures (codeword, + ML, + nerasures, + erasures); + + printf("Corrected codeword: \"%s\"\n", codeword); + } + + exit(0); +} + diff --git a/flight/Libraries/rscode/galois.c b/flight/Libraries/rscode/galois.c new file mode 100644 index 000000000..6326715d0 --- /dev/null +++ b/flight/Libraries/rscode/galois.c @@ -0,0 +1,164 @@ +/***************************** + * Copyright Henry Minsky (hqm@alum.mit.edu) 1991-2009 + * + * This software library is licensed under terms of the GNU GENERAL + * PUBLIC LICENSE + * + * RSCODE 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. + * + * RSCODE 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 Rscode. If not, see . + + * Commercial licensing is available under a separate license, please + * contact author for details. + * + * Source code is available at http://rscode.sourceforge.net + * + * + * Multiplication and Arithmetic on Galois Field GF(256) + * + * From Mee, Daniel, "Magnetic Recording, Volume III", Ch. 5 by Patel. + * + * + ******************************/ + + +#include +#include +#include "ecc.h" + +/* This is one of 14 irreducible polynomials + * of degree 8 and cycle length 255. (Ch 5, pp. 275, Magnetic Recording) + * The high order 1 bit is implicit */ +/* x^8 + x^4 + x^3 + x^2 + 1 */ +#define PPOLY 0x1D + + +const int gexp[512] = { + 1, 2, 4, 8, 16, 32, 64, 128, 29, 58, 116, 232, 205, 135, 19, 38, + 76, 152, 45, 90, 180, 117, 234, 201, 143, 3, 6, 12, 24, 48, 96, 192, + 157, 39, 78, 156, 37, 74, 148, 53, 106, 212, 181, 119, 238, 193, 159, 35, + 70, 140, 5, 10, 20, 40, 80, 160, 93, 186, 105, 210, 185, 111, 222, 161, + 95, 190, 97, 194, 153, 47, 94, 188, 101, 202, 137, 15, 30, 60, 120, 240, + 253, 231, 211, 187, 107, 214, 177, 127, 254, 225, 223, 163, 91, 182, 113, 226, + 217, 175, 67, 134, 17, 34, 68, 136, 13, 26, 52, 104, 208, 189, 103, 206, + 129, 31, 62, 124, 248, 237, 199, 147, 59, 118, 236, 197, 151, 51, 102, 204, + 133, 23, 46, 92, 184, 109, 218, 169, 79, 158, 33, 66, 132, 21, 42, 84, + 168, 77, 154, 41, 82, 164, 85, 170, 73, 146, 57, 114, 228, 213, 183, 115, + 230, 209, 191, 99, 198, 145, 63, 126, 252, 229, 215, 179, 123, 246, 241, 255, + 227, 219, 171, 75, 150, 49, 98, 196, 149, 55, 110, 220, 165, 87, 174, 65, + 130, 25, 50, 100, 200, 141, 7, 14, 28, 56, 112, 224, 221, 167, 83, 166, + 81, 162, 89, 178, 121, 242, 249, 239, 195, 155, 43, 86, 172, 69, 138, 9, + 18, 36, 72, 144, 61, 122, 244, 245, 247, 243, 251, 235, 203, 139, 11, 22, + 44, 88, 176, 125, 250, 233, 207, 131, 27, 54, 108, 216, 173, 71, 142, 1, + 2, 4, 8, 16, 32, 64, 128, 29, 58, 116, 232, 205, 135, 19, 38, 76, + 152, 45, 90, 180, 117, 234, 201, 143, 3, 6, 12, 24, 48, 96, 192, 157, + 39, 78, 156, 37, 74, 148, 53, 106, 212, 181, 119, 238, 193, 159, 35, 70, + 140, 5, 10, 20, 40, 80, 160, 93, 186, 105, 210, 185, 111, 222, 161, 95, + 190, 97, 194, 153, 47, 94, 188, 101, 202, 137, 15, 30, 60, 120, 240, 253, + 231, 211, 187, 107, 214, 177, 127, 254, 225, 223, 163, 91, 182, 113, 226, 217, + 175, 67, 134, 17, 34, 68, 136, 13, 26, 52, 104, 208, 189, 103, 206, 129, + 31, 62, 124, 248, 237, 199, 147, 59, 118, 236, 197, 151, 51, 102, 204, 133, + 23, 46, 92, 184, 109, 218, 169, 79, 158, 33, 66, 132, 21, 42, 84, 168, + 77, 154, 41, 82, 164, 85, 170, 73, 146, 57, 114, 228, 213, 183, 115, 230, + 209, 191, 99, 198, 145, 63, 126, 252, 229, 215, 179, 123, 246, 241, 255, 227, + 219, 171, 75, 150, 49, 98, 196, 149, 55, 110, 220, 165, 87, 174, 65, 130, + 25, 50, 100, 200, 141, 7, 14, 28, 56, 112, 224, 221, 167, 83, 166, 81, + 162, 89, 178, 121, 242, 249, 239, 195, 155, 43, 86, 172, 69, 138, 9, 18, + 36, 72, 144, 61, 122, 244, 245, 247, 243, 251, 235, 203, 139, 11, 22, 44, + 88, 176, 125, 250, 233, 207, 131, 27, 54, 108, 216, 173, 71, 142, 1, 0, +}; +const int glog[256] = { + 0, 0, 1, 25, 2, 50, 26, 198, 3, 223, 51, 238, 27, 104, 199, 75, + 4, 100, 224, 14, 52, 141, 239, 129, 28, 193, 105, 248, 200, 8, 76, 113, + 5, 138, 101, 47, 225, 36, 15, 33, 53, 147, 142, 218, 240, 18, 130, 69, + 29, 181, 194, 125, 106, 39, 249, 185, 201, 154, 9, 120, 77, 228, 114, 166, + 6, 191, 139, 98, 102, 221, 48, 253, 226, 152, 37, 179, 16, 145, 34, 136, + 54, 208, 148, 206, 143, 150, 219, 189, 241, 210, 19, 92, 131, 56, 70, 64, + 30, 66, 182, 163, 195, 72, 126, 110, 107, 58, 40, 84, 250, 133, 186, 61, + 202, 94, 155, 159, 10, 21, 121, 43, 78, 212, 229, 172, 115, 243, 167, 87, + 7, 112, 192, 247, 140, 128, 99, 13, 103, 74, 222, 237, 49, 197, 254, 24, + 227, 165, 153, 119, 38, 184, 180, 124, 17, 68, 146, 217, 35, 32, 137, 46, + 55, 63, 209, 91, 149, 188, 207, 205, 144, 135, 151, 178, 220, 252, 190, 97, + 242, 86, 211, 171, 20, 42, 93, 158, 132, 60, 57, 83, 71, 109, 65, 162, + 31, 45, 67, 216, 183, 123, 164, 118, 196, 23, 73, 236, 127, 12, 111, 246, + 108, 161, 59, 82, 41, 157, 85, 170, 251, 96, 134, 177, 187, 204, 62, 90, + 203, 89, 95, 176, 156, 169, 160, 81, 11, 245, 22, 235, 122, 117, 44, 215, + 79, 174, 213, 233, 230, 231, 173, 232, 116, 214, 244, 234, 168, 80, 88, 175, +}; + + +//static void init_exp_table (void); + + +void +init_galois_tables (void) +{ + /* initialize the table of powers of alpha */ + //init_exp_table(); +} + + +#ifdef NEVER +static void +init_exp_table (void) +{ + int i, z; + int pinit,p1,p2,p3,p4,p5,p6,p7,p8; + + pinit = p2 = p3 = p4 = p5 = p6 = p7 = p8 = 0; + p1 = 1; + + gexp[0] = 1; + gexp[255] = gexp[0]; + glog[0] = 0; /* shouldn't log[0] be an error? */ + + for (i = 1; i < 256; i++) { + pinit = p8; + p8 = p7; + p7 = p6; + p6 = p5; + p5 = p4 ^ pinit; + p4 = p3 ^ pinit; + p3 = p2 ^ pinit; + p2 = p1; + p1 = pinit; + gexp[i] = p1 + p2*2 + p3*4 + p4*8 + p5*16 + p6*32 + p7*64 + p8*128; + gexp[i+255] = gexp[i]; + } + + for (i = 1; i < 256; i++) { + for (z = 0; z < 256; z++) { + if (gexp[z] == i) { + glog[i] = z; + break; + } + } + } +} +#endif + +/* multiplication using logarithms */ +int gmult(int a, int b) +{ + int i,j; + if (a==0 || b == 0) return (0); + i = glog[a]; + j = glog[b]; + return (gexp[i+j]); +} + + +int ginv (int elt) +{ + return (gexp[255-glog[elt]]); +} + diff --git a/flight/Libraries/rscode/gpl.txt b/flight/Libraries/rscode/gpl.txt new file mode 100644 index 000000000..94a9ed024 --- /dev/null +++ b/flight/Libraries/rscode/gpl.txt @@ -0,0 +1,674 @@ + GNU GENERAL PUBLIC LICENSE + Version 3, 29 June 2007 + + Copyright (C) 2007 Free Software Foundation, Inc. + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + + Preamble + + The GNU General Public License is a free, copyleft license for +software and other kinds of works. + + The licenses for most software and other practical works are designed +to take away your freedom to share and change the works. By contrast, +the GNU General Public License is intended to guarantee your freedom to +share and change all versions of a program--to make sure it remains free +software for all its users. We, the Free Software Foundation, use the +GNU General Public License for most of our software; it applies also to +any other work released this way by its authors. You can apply it to +your programs, too. + + When we speak of free software, we are referring to freedom, not +price. Our General Public Licenses are designed to make sure that you +have the freedom to distribute copies of free software (and charge for +them if you wish), that you receive source code or can get it if you +want it, that you can change the software or use pieces of it in new +free programs, and that you know you can do these things. + + To protect your rights, we need to prevent others from denying you +these rights or asking you to surrender the rights. Therefore, you have +certain responsibilities if you distribute copies of the software, or if +you modify it: responsibilities to respect the freedom of others. + + For example, if you distribute copies of such a program, whether +gratis or for a fee, you must pass on to the recipients the same +freedoms that you received. You must make sure that they, too, receive +or can get the source code. And you must show them these terms so they +know their rights. + + Developers that use the GNU GPL protect your rights with two steps: +(1) assert copyright on the software, and (2) offer you this License +giving you legal permission to copy, distribute and/or modify it. + + For the developers' and authors' protection, the GPL clearly explains +that there is no warranty for this free software. For both users' and +authors' sake, the GPL requires that modified versions be marked as +changed, so that their problems will not be attributed erroneously to +authors of previous versions. + + Some devices are designed to deny users access to install or run +modified versions of the software inside them, although the manufacturer +can do so. This is fundamentally incompatible with the aim of +protecting users' freedom to change the software. The systematic +pattern of such abuse occurs in the area of products for individuals to +use, which is precisely where it is most unacceptable. Therefore, we +have designed this version of the GPL to prohibit the practice for those +products. If such problems arise substantially in other domains, we +stand ready to extend this provision to those domains in future versions +of the GPL, as needed to protect the freedom of users. + + Finally, every program is threatened constantly by software patents. +States should not allow patents to restrict development and use of +software on general-purpose computers, but in those that do, we wish to +avoid the special danger that patents applied to a free program could +make it effectively proprietary. To prevent this, the GPL assures that +patents cannot be used to render the program non-free. + + The precise terms and conditions for copying, distribution and +modification follow. + + TERMS AND CONDITIONS + + 0. Definitions. + + "This License" refers to version 3 of the GNU General Public License. + + "Copyright" also means copyright-like laws that apply to other kinds of +works, such as semiconductor masks. + + "The Program" refers to any copyrightable work licensed under this +License. Each licensee is addressed as "you". "Licensees" and +"recipients" may be individuals or organizations. + + To "modify" a work means to copy from or adapt all or part of the work +in a fashion requiring copyright permission, other than the making of an +exact copy. The resulting work is called a "modified version" of the +earlier work or a work "based on" the earlier work. + + A "covered work" means either the unmodified Program or a work based +on the Program. + + To "propagate" a work means to do anything with it that, without +permission, would make you directly or secondarily liable for +infringement under applicable copyright law, except executing it on a +computer or modifying a private copy. Propagation includes copying, +distribution (with or without modification), making available to the +public, and in some countries other activities as well. + + To "convey" a work means any kind of propagation that enables other +parties to make or receive copies. Mere interaction with a user through +a computer network, with no transfer of a copy, is not conveying. + + An interactive user interface displays "Appropriate Legal Notices" +to the extent that it includes a convenient and prominently visible +feature that (1) displays an appropriate copyright notice, and (2) +tells the user that there is no warranty for the work (except to the +extent that warranties are provided), that licensees may convey the +work under this License, and how to view a copy of this License. If +the interface presents a list of user commands or options, such as a +menu, a prominent item in the list meets this criterion. + + 1. Source Code. + + The "source code" for a work means the preferred form of the work +for making modifications to it. "Object code" means any non-source +form of a work. + + A "Standard Interface" means an interface that either is an official +standard defined by a recognized standards body, or, in the case of +interfaces specified for a particular programming language, one that +is widely used among developers working in that language. + + The "System Libraries" of an executable work include anything, other +than the work as a whole, that (a) is included in the normal form of +packaging a Major Component, but which is not part of that Major +Component, and (b) serves only to enable use of the work with that +Major Component, or to implement a Standard Interface for which an +implementation is available to the public in source code form. A +"Major Component", in this context, means a major essential component +(kernel, window system, and so on) of the specific operating system +(if any) on which the executable work runs, or a compiler used to +produce the work, or an object code interpreter used to run it. + + The "Corresponding Source" for a work in object code form means all +the source code needed to generate, install, and (for an executable +work) run the object code and to modify the work, including scripts to +control those activities. However, it does not include the work's +System Libraries, or general-purpose tools or generally available free +programs which are used unmodified in performing those activities but +which are not part of the work. For example, Corresponding Source +includes interface definition files associated with source files for +the work, and the source code for shared libraries and dynamically +linked subprograms that the work is specifically designed to require, +such as by intimate data communication or control flow between those +subprograms and other parts of the work. + + The Corresponding Source need not include anything that users +can regenerate automatically from other parts of the Corresponding +Source. + + The Corresponding Source for a work in source code form is that +same work. + + 2. Basic Permissions. + + All rights granted under this License are granted for the term of +copyright on the Program, and are irrevocable provided the stated +conditions are met. This License explicitly affirms your unlimited +permission to run the unmodified Program. The output from running a +covered work is covered by this License only if the output, given its +content, constitutes a covered work. This License acknowledges your +rights of fair use or other equivalent, as provided by copyright law. + + You may make, run and propagate covered works that you do not +convey, without conditions so long as your license otherwise remains +in force. You may convey covered works to others for the sole purpose +of having them make modifications exclusively for you, or provide you +with facilities for running those works, provided that you comply with +the terms of this License in conveying all material for which you do +not control copyright. Those thus making or running the covered works +for you must do so exclusively on your behalf, under your direction +and control, on terms that prohibit them from making any copies of +your copyrighted material outside their relationship with you. + + Conveying under any other circumstances is permitted solely under +the conditions stated below. Sublicensing is not allowed; section 10 +makes it unnecessary. + + 3. Protecting Users' Legal Rights From Anti-Circumvention Law. + + No covered work shall be deemed part of an effective technological +measure under any applicable law fulfilling obligations under article +11 of the WIPO copyright treaty adopted on 20 December 1996, or +similar laws prohibiting or restricting circumvention of such +measures. + + When you convey a covered work, you waive any legal power to forbid +circumvention of technological measures to the extent such circumvention +is effected by exercising rights under this License with respect to +the covered work, and you disclaim any intention to limit operation or +modification of the work as a means of enforcing, against the work's +users, your or third parties' legal rights to forbid circumvention of +technological measures. + + 4. Conveying Verbatim Copies. + + You may convey verbatim copies of the Program's source code as you +receive it, in any medium, provided that you conspicuously and +appropriately publish on each copy an appropriate copyright notice; +keep intact all notices stating that this License and any +non-permissive terms added in accord with section 7 apply to the code; +keep intact all notices of the absence of any warranty; and give all +recipients a copy of this License along with the Program. + + You may charge any price or no price for each copy that you convey, +and you may offer support or warranty protection for a fee. + + 5. Conveying Modified Source Versions. + + You may convey a work based on the Program, or the modifications to +produce it from the Program, in the form of source code under the +terms of section 4, provided that you also meet all of these conditions: + + a) The work must carry prominent notices stating that you modified + it, and giving a relevant date. + + b) The work must carry prominent notices stating that it is + released under this License and any conditions added under section + 7. This requirement modifies the requirement in section 4 to + "keep intact all notices". + + c) You must license the entire work, as a whole, under this + License to anyone who comes into possession of a copy. This + License will therefore apply, along with any applicable section 7 + additional terms, to the whole of the work, and all its parts, + regardless of how they are packaged. This License gives no + permission to license the work in any other way, but it does not + invalidate such permission if you have separately received it. + + d) If the work has interactive user interfaces, each must display + Appropriate Legal Notices; however, if the Program has interactive + interfaces that do not display Appropriate Legal Notices, your + work need not make them do so. + + A compilation of a covered work with other separate and independent +works, which are not by their nature extensions of the covered work, +and which are not combined with it such as to form a larger program, +in or on a volume of a storage or distribution medium, is called an +"aggregate" if the compilation and its resulting copyright are not +used to limit the access or legal rights of the compilation's users +beyond what the individual works permit. Inclusion of a covered work +in an aggregate does not cause this License to apply to the other +parts of the aggregate. + + 6. Conveying Non-Source Forms. + + You may convey a covered work in object code form under the terms +of sections 4 and 5, provided that you also convey the +machine-readable Corresponding Source under the terms of this License, +in one of these ways: + + a) Convey the object code in, or embodied in, a physical product + (including a physical distribution medium), accompanied by the + Corresponding Source fixed on a durable physical medium + customarily used for software interchange. + + b) Convey the object code in, or embodied in, a physical product + (including a physical distribution medium), accompanied by a + written offer, valid for at least three years and valid for as + long as you offer spare parts or customer support for that product + model, to give anyone who possesses the object code either (1) a + copy of the Corresponding Source for all the software in the + product that is covered by this License, on a durable physical + medium customarily used for software interchange, for a price no + more than your reasonable cost of physically performing this + conveying of source, or (2) access to copy the + Corresponding Source from a network server at no charge. + + c) Convey individual copies of the object code with a copy of the + written offer to provide the Corresponding Source. This + alternative is allowed only occasionally and noncommercially, and + only if you received the object code with such an offer, in accord + with subsection 6b. + + d) Convey the object code by offering access from a designated + place (gratis or for a charge), and offer equivalent access to the + Corresponding Source in the same way through the same place at no + further charge. You need not require recipients to copy the + Corresponding Source along with the object code. If the place to + copy the object code is a network server, the Corresponding Source + may be on a different server (operated by you or a third party) + that supports equivalent copying facilities, provided you maintain + clear directions next to the object code saying where to find the + Corresponding Source. Regardless of what server hosts the + Corresponding Source, you remain obligated to ensure that it is + available for as long as needed to satisfy these requirements. + + e) Convey the object code using peer-to-peer transmission, provided + you inform other peers where the object code and Corresponding + Source of the work are being offered to the general public at no + charge under subsection 6d. + + A separable portion of the object code, whose source code is excluded +from the Corresponding Source as a System Library, need not be +included in conveying the object code work. + + A "User Product" is either (1) a "consumer product", which means any +tangible personal property which is normally used for personal, family, +or household purposes, or (2) anything designed or sold for incorporation +into a dwelling. In determining whether a product is a consumer product, +doubtful cases shall be resolved in favor of coverage. For a particular +product received by a particular user, "normally used" refers to a +typical or common use of that class of product, regardless of the status +of the particular user or of the way in which the particular user +actually uses, or expects or is expected to use, the product. A product +is a consumer product regardless of whether the product has substantial +commercial, industrial or non-consumer uses, unless such uses represent +the only significant mode of use of the product. + + "Installation Information" for a User Product means any methods, +procedures, authorization keys, or other information required to install +and execute modified versions of a covered work in that User Product from +a modified version of its Corresponding Source. The information must +suffice to ensure that the continued functioning of the modified object +code is in no case prevented or interfered with solely because +modification has been made. + + If you convey an object code work under this section in, or with, or +specifically for use in, a User Product, and the conveying occurs as +part of a transaction in which the right of possession and use of the +User Product is transferred to the recipient in perpetuity or for a +fixed term (regardless of how the transaction is characterized), the +Corresponding Source conveyed under this section must be accompanied +by the Installation Information. But this requirement does not apply +if neither you nor any third party retains the ability to install +modified object code on the User Product (for example, the work has +been installed in ROM). + + The requirement to provide Installation Information does not include a +requirement to continue to provide support service, warranty, or updates +for a work that has been modified or installed by the recipient, or for +the User Product in which it has been modified or installed. Access to a +network may be denied when the modification itself materially and +adversely affects the operation of the network or violates the rules and +protocols for communication across the network. + + Corresponding Source conveyed, and Installation Information provided, +in accord with this section must be in a format that is publicly +documented (and with an implementation available to the public in +source code form), and must require no special password or key for +unpacking, reading or copying. + + 7. Additional Terms. + + "Additional permissions" are terms that supplement the terms of this +License by making exceptions from one or more of its conditions. +Additional permissions that are applicable to the entire Program shall +be treated as though they were included in this License, to the extent +that they are valid under applicable law. If additional permissions +apply only to part of the Program, that part may be used separately +under those permissions, but the entire Program remains governed by +this License without regard to the additional permissions. + + When you convey a copy of a covered work, you may at your option +remove any additional permissions from that copy, or from any part of +it. (Additional permissions may be written to require their own +removal in certain cases when you modify the work.) You may place +additional permissions on material, added by you to a covered work, +for which you have or can give appropriate copyright permission. + + Notwithstanding any other provision of this License, for material you +add to a covered work, you may (if authorized by the copyright holders of +that material) supplement the terms of this License with terms: + + a) Disclaiming warranty or limiting liability differently from the + terms of sections 15 and 16 of this License; or + + b) Requiring preservation of specified reasonable legal notices or + author attributions in that material or in the Appropriate Legal + Notices displayed by works containing it; or + + c) Prohibiting misrepresentation of the origin of that material, or + requiring that modified versions of such material be marked in + reasonable ways as different from the original version; or + + d) Limiting the use for publicity purposes of names of licensors or + authors of the material; or + + e) Declining to grant rights under trademark law for use of some + trade names, trademarks, or service marks; or + + f) Requiring indemnification of licensors and authors of that + material by anyone who conveys the material (or modified versions of + it) with contractual assumptions of liability to the recipient, for + any liability that these contractual assumptions directly impose on + those licensors and authors. + + All other non-permissive additional terms are considered "further +restrictions" within the meaning of section 10. If the Program as you +received it, or any part of it, contains a notice stating that it is +governed by this License along with a term that is a further +restriction, you may remove that term. If a license document contains +a further restriction but permits relicensing or conveying under this +License, you may add to a covered work material governed by the terms +of that license document, provided that the further restriction does +not survive such relicensing or conveying. + + If you add terms to a covered work in accord with this section, you +must place, in the relevant source files, a statement of the +additional terms that apply to those files, or a notice indicating +where to find the applicable terms. + + Additional terms, permissive or non-permissive, may be stated in the +form of a separately written license, or stated as exceptions; +the above requirements apply either way. + + 8. Termination. + + You may not propagate or modify a covered work except as expressly +provided under this License. Any attempt otherwise to propagate or +modify it is void, and will automatically terminate your rights under +this License (including any patent licenses granted under the third +paragraph of section 11). + + However, if you cease all violation of this License, then your +license from a particular copyright holder is reinstated (a) +provisionally, unless and until the copyright holder explicitly and +finally terminates your license, and (b) permanently, if the copyright +holder fails to notify you of the violation by some reasonable means +prior to 60 days after the cessation. + + Moreover, your license from a particular copyright holder is +reinstated permanently if the copyright holder notifies you of the +violation by some reasonable means, this is the first time you have +received notice of violation of this License (for any work) from that +copyright holder, and you cure the violation prior to 30 days after +your receipt of the notice. + + Termination of your rights under this section does not terminate the +licenses of parties who have received copies or rights from you under +this License. If your rights have been terminated and not permanently +reinstated, you do not qualify to receive new licenses for the same +material under section 10. + + 9. Acceptance Not Required for Having Copies. + + You are not required to accept this License in order to receive or +run a copy of the Program. Ancillary propagation of a covered work +occurring solely as a consequence of using peer-to-peer transmission +to receive a copy likewise does not require acceptance. However, +nothing other than this License grants you permission to propagate or +modify any covered work. These actions infringe copyright if you do +not accept this License. Therefore, by modifying or propagating a +covered work, you indicate your acceptance of this License to do so. + + 10. Automatic Licensing of Downstream Recipients. + + Each time you convey a covered work, the recipient automatically +receives a license from the original licensors, to run, modify and +propagate that work, subject to this License. You are not responsible +for enforcing compliance by third parties with this License. + + An "entity transaction" is a transaction transferring control of an +organization, or substantially all assets of one, or subdividing an +organization, or merging organizations. If propagation of a covered +work results from an entity transaction, each party to that +transaction who receives a copy of the work also receives whatever +licenses to the work the party's predecessor in interest had or could +give under the previous paragraph, plus a right to possession of the +Corresponding Source of the work from the predecessor in interest, if +the predecessor has it or can get it with reasonable efforts. + + You may not impose any further restrictions on the exercise of the +rights granted or affirmed under this License. For example, you may +not impose a license fee, royalty, or other charge for exercise of +rights granted under this License, and you may not initiate litigation +(including a cross-claim or counterclaim in a lawsuit) alleging that +any patent claim is infringed by making, using, selling, offering for +sale, or importing the Program or any portion of it. + + 11. Patents. + + A "contributor" is a copyright holder who authorizes use under this +License of the Program or a work on which the Program is based. The +work thus licensed is called the contributor's "contributor version". + + A contributor's "essential patent claims" are all patent claims +owned or controlled by the contributor, whether already acquired or +hereafter acquired, that would be infringed by some manner, permitted +by this License, of making, using, or selling its contributor version, +but do not include claims that would be infringed only as a +consequence of further modification of the contributor version. For +purposes of this definition, "control" includes the right to grant +patent sublicenses in a manner consistent with the requirements of +this License. + + Each contributor grants you a non-exclusive, worldwide, royalty-free +patent license under the contributor's essential patent claims, to +make, use, sell, offer for sale, import and otherwise run, modify and +propagate the contents of its contributor version. + + In the following three paragraphs, a "patent license" is any express +agreement or commitment, however denominated, not to enforce a patent +(such as an express permission to practice a patent or covenant not to +sue for patent infringement). To "grant" such a patent license to a +party means to make such an agreement or commitment not to enforce a +patent against the party. + + If you convey a covered work, knowingly relying on a patent license, +and the Corresponding Source of the work is not available for anyone +to copy, free of charge and under the terms of this License, through a +publicly available network server or other readily accessible means, +then you must either (1) cause the Corresponding Source to be so +available, or (2) arrange to deprive yourself of the benefit of the +patent license for this particular work, or (3) arrange, in a manner +consistent with the requirements of this License, to extend the patent +license to downstream recipients. "Knowingly relying" means you have +actual knowledge that, but for the patent license, your conveying the +covered work in a country, or your recipient's use of the covered work +in a country, would infringe one or more identifiable patents in that +country that you have reason to believe are valid. + + If, pursuant to or in connection with a single transaction or +arrangement, you convey, or propagate by procuring conveyance of, a +covered work, and grant a patent license to some of the parties +receiving the covered work authorizing them to use, propagate, modify +or convey a specific copy of the covered work, then the patent license +you grant is automatically extended to all recipients of the covered +work and works based on it. + + A patent license is "discriminatory" if it does not include within +the scope of its coverage, prohibits the exercise of, or is +conditioned on the non-exercise of one or more of the rights that are +specifically granted under this License. You may not convey a covered +work if you are a party to an arrangement with a third party that is +in the business of distributing software, under which you make payment +to the third party based on the extent of your activity of conveying +the work, and under which the third party grants, to any of the +parties who would receive the covered work from you, a discriminatory +patent license (a) in connection with copies of the covered work +conveyed by you (or copies made from those copies), or (b) primarily +for and in connection with specific products or compilations that +contain the covered work, unless you entered into that arrangement, +or that patent license was granted, prior to 28 March 2007. + + Nothing in this License shall be construed as excluding or limiting +any implied license or other defenses to infringement that may +otherwise be available to you under applicable patent law. + + 12. No Surrender of Others' Freedom. + + If conditions are imposed on you (whether by court order, agreement or +otherwise) that contradict the conditions of this License, they do not +excuse you from the conditions of this License. If you cannot convey a +covered work so as to satisfy simultaneously your obligations under this +License and any other pertinent obligations, then as a consequence you may +not convey it at all. For example, if you agree to terms that obligate you +to collect a royalty for further conveying from those to whom you convey +the Program, the only way you could satisfy both those terms and this +License would be to refrain entirely from conveying the Program. + + 13. Use with the GNU Affero General Public License. + + Notwithstanding any other provision of this License, you have +permission to link or combine any covered work with a work licensed +under version 3 of the GNU Affero General Public License into a single +combined work, and to convey the resulting work. The terms of this +License will continue to apply to the part which is the covered work, +but the special requirements of the GNU Affero General Public License, +section 13, concerning interaction through a network will apply to the +combination as such. + + 14. Revised Versions of this License. + + The Free Software Foundation may publish revised and/or new versions of +the GNU General Public License from time to time. Such new versions will +be similar in spirit to the present version, but may differ in detail to +address new problems or concerns. + + Each version is given a distinguishing version number. If the +Program specifies that a certain numbered version of the GNU General +Public License "or any later version" applies to it, you have the +option of following the terms and conditions either of that numbered +version or of any later version published by the Free Software +Foundation. If the Program does not specify a version number of the +GNU General Public License, you may choose any version ever published +by the Free Software Foundation. + + If the Program specifies that a proxy can decide which future +versions of the GNU General Public License can be used, that proxy's +public statement of acceptance of a version permanently authorizes you +to choose that version for the Program. + + Later license versions may give you additional or different +permissions. However, no additional obligations are imposed on any +author or copyright holder as a result of your choosing to follow a +later version. + + 15. Disclaimer of Warranty. + + THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY +APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT +HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY +OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, +THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM +IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF +ALL NECESSARY SERVICING, REPAIR OR CORRECTION. + + 16. Limitation of Liability. + + IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING +WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS +THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY +GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE +USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF +DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD +PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), +EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF +SUCH DAMAGES. + + 17. Interpretation of Sections 15 and 16. + + If the disclaimer of warranty and limitation of liability provided +above cannot be given local legal effect according to their terms, +reviewing courts shall apply local law that most closely approximates +an absolute waiver of all civil liability in connection with the +Program, unless a warranty or assumption of liability accompanies a +copy of the Program in return for a fee. + + END OF TERMS AND CONDITIONS + + How to Apply These Terms to Your New Programs + + If you develop a new program, and you want it to be of the greatest +possible use to the public, the best way to achieve this is to make it +free software which everyone can redistribute and change under these terms. + + To do so, attach the following notices to the program. It is safest +to attach them to the start of each source file to most effectively +state the exclusion of warranty; and each file should have at least +the "copyright" line and a pointer to where the full notice is found. + + + Copyright (C) + + 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, see . + +Also add information on how to contact you by electronic and paper mail. + + If the program does terminal interaction, make it output a short +notice like this when it starts in an interactive mode: + + Copyright (C) + This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'. + This is free software, and you are welcome to redistribute it + under certain conditions; type `show c' for details. + +The hypothetical commands `show w' and `show c' should show the appropriate +parts of the General Public License. Of course, your program's commands +might be different; for a GUI interface, you would use an "about box". + + You should also get your employer (if you work as a programmer) or school, +if any, to sign a "copyright disclaimer" for the program, if necessary. +For more information on this, and how to apply and follow the GNU GPL, see +. + + The GNU General Public License does not permit incorporating your program +into proprietary programs. If your program is a subroutine library, you +may consider it more useful to permit linking proprietary applications with +the library. If this is what you want to do, use the GNU Lesser General +Public License instead of this License. But first, please read +. diff --git a/flight/Libraries/rscode/rs.c b/flight/Libraries/rscode/rs.c new file mode 100644 index 000000000..5373b3ea0 --- /dev/null +++ b/flight/Libraries/rscode/rs.c @@ -0,0 +1,207 @@ +/* + * Reed Solomon Encoder/Decoder + * + * Copyright Henry Minsky (hqm@alum.mit.edu) 1991-2009 + * + * This software library is licensed under terms of the GNU GENERAL + * PUBLIC LICENSE + * + * RSCODE 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. + * + * RSCODE 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 Rscode. If not, see . + + * Commercial licensing is available under a separate license, please + * contact author for details. + * + * Source code is available at http://rscode.sourceforge.net + */ + +#include +#include +#include "ecc.h" + +/* Encoder parity bytes */ +int pBytes[MAXDEG]; + +/* Decoder syndrome bytes */ +int synBytes[MAXDEG]; + +/* generator polynomial */ +int genPoly[MAXDEG*2]; + +int DEBUG = FALSE; + +static void +compute_genpoly (int nbytes, int genpoly[]); + +/* Initialize lookup tables, polynomials, etc. */ +void +initialize_ecc () +{ + /* Initialize the galois field arithmetic tables */ + init_galois_tables(); + + /* Compute the encoder generator polynomial */ + compute_genpoly(RS_ECC_NPARITY, genPoly); +} + +void +zero_fill_from (unsigned char buf[], int from, int to) +{ + int i; + for (i = from; i < to; i++) buf[i] = 0; +} + +/* debugging routines */ +void +print_parity (void) +{ +#ifdef NEVER + int i; + printf("Parity Bytes: "); + for (i = 0; i < RS_ECC_NPARITY; i++) + printf("[%d]:%x, ",i,pBytes[i]); + printf("\n"); +#endif +} + + +void +print_syndrome (void) +{ +#ifdef NEVER + int i; + printf("Syndrome Bytes: "); + for (i = 0; i < RS_ECC_NPARITY; i++) + printf("[%d]:%x, ",i,synBytes[i]); + printf("\n"); +#endif +} + +/* Append the parity bytes onto the end of the message */ +void +build_codeword (unsigned char msg[], int nbytes, unsigned char dst[]) +{ + int i; + + for (i = 0; i < nbytes; i++) dst[i] = msg[i]; + + for (i = 0; i < RS_ECC_NPARITY; i++) { + dst[i+nbytes] = pBytes[RS_ECC_NPARITY-1-i]; + } +} + +/********************************************************** + * Reed Solomon Decoder + * + * Computes the syndrome of a codeword. Puts the results + * into the synBytes[] array. + */ + +void +decode_data(unsigned char data[], int nbytes) +{ + int i, j, sum; + for (j = 0; j < RS_ECC_NPARITY; j++) { + sum = 0; + for (i = 0; i < nbytes; i++) { + sum = data[i] ^ gmult(gexp[j+1], sum); + } + synBytes[j] = sum; + } +} + + +/* Check if the syndrome is zero */ +int +check_syndrome (void) +{ + int i, nz = 0; + for (i =0 ; i < RS_ECC_NPARITY; i++) { + if (synBytes[i] != 0) { + nz = 1; + break; + } + } + return nz; +} + + +void +debug_check_syndrome (void) +{ +#ifdef NEVER + int i; + + for (i = 0; i < 3; i++) { + printf(" inv log S[%d]/S[%d] = %d\n", i, i+1, + glog[gmult(synBytes[i], ginv(synBytes[i+1]))]); + } +#endif +} + + +/* Create a generator polynomial for an n byte RS code. + * The coefficients are returned in the genPoly arg. + * Make sure that the genPoly array which is passed in is + * at least n+1 bytes long. + */ + +static void +compute_genpoly (int nbytes, int genpoly[]) +{ + int i, tp[256], tp1[256]; + + /* multiply (x + a^n) for n = 1 to nbytes */ + + zero_poly(tp1); + tp1[0] = 1; + + for (i = 1; i <= nbytes; i++) { + zero_poly(tp); + tp[0] = gexp[i]; /* set up x+a^n */ + tp[1] = 1; + + mult_polys(genpoly, tp, tp1); + copy_poly(tp1, genpoly); + } +} + +/* Simulate a LFSR with generator polynomial for n byte RS code. + * Pass in a pointer to the data array, and amount of data. + * + * The parity bytes are deposited into pBytes[], and the whole message + * and parity are copied to dest to make a codeword. + * + */ + +void +encode_data (unsigned char msg[], int nbytes, unsigned char dst[]) +{ + int i, LFSR[RS_ECC_NPARITY+1],dbyte, j; + + for(i=0; i < RS_ECC_NPARITY+1; i++) LFSR[i]=0; + + for (i = 0; i < nbytes; i++) { + dbyte = msg[i] ^ LFSR[RS_ECC_NPARITY-1]; + for (j = RS_ECC_NPARITY-1; j > 0; j--) { + LFSR[j] = LFSR[j-1] ^ gmult(genPoly[j], dbyte); + } + LFSR[0] = gmult(genPoly[0], dbyte); + } + + for (i = 0; i < RS_ECC_NPARITY; i++) + pBytes[i] = LFSR[i]; + + build_codeword(msg, nbytes, dst); +} + diff --git a/flight/Libraries/rscode/rs.doc b/flight/Libraries/rscode/rs.doc new file mode 100644 index 000000000..651f76c78 --- /dev/null +++ b/flight/Libraries/rscode/rs.doc @@ -0,0 +1,86 @@ + + +Introduction to Reed Solomon Codes: + +Henry Minsky, Universal Access Inc. +hqm@alum.mit.edu + +[For details see Cain, Clark, "Error-Correction Coding For Digital +Communications", pp. 205.] The Reed-Solomon Code is an algebraic code +belonging to the class of BCH (Bose-Chaudry-Hocquehen) multiple burst +correcting cyclic codes. The Reed Solomon code operates on bytes of +fixed length. + +Given m parity bytes, a Reed-Solomon code can correct up to m byte +errors in known positions (erasures), or detect and correct up to m/2 +byte errors in unknown positions. + +This is an implementation of a Reed-Solomon code with 8 bit bytes, and +a configurable number of parity bytes. The maximum sequence length +(codeword) that can be generated is 255 bytes, including parity bytes. +In practice, shorter sequences are used. + +ENCODING: The basic principle of encoding is to find the remainder of +the message divided by a generator polynomial G(x). The encoder works +by simulating a Linear Feedback Shift Register with degree equal to +G(x), and feedback taps with the coefficents of the generating +polynomial of the code. + +The rs.c file contains an algorithm to generate the encoder polynomial +for any number of bytes of parity, configurable as the NPAR constant +in the file ecc.h. + +For this RS code, G(x) = (x-a^1)(x-a^2)(x-a^3)(x-a^4)...(x-a^NPAR) +where 'a' is a primitive element of the Galois Field GF(256) (== 2). + +DECODING + +The decoder generates four syndrome bytes, which will be all zero if +the message has no errors. If there are errors, the location and value +of the errors can be determined in a number of ways. + +Computing the syndromes is easily done as a sum of products, see pp. +179 [Rhee 89]. + +Fundamentally, the syndome bytes form four simultaneous equations +which can be solved to find the error locations. Once error locations +are known, the syndrome bytes can be used to find the value of the +errors, and they can thus be corrected. + +A simplified solution for locating and correcting single errors is +given in Cain and Clark, Ch. 5. + +The more general error-location algorithm is the Berlekamp-Massey +algorithm, which will locate up to four errors, by iteratively solving +for the error-locator polynomial. The Modified Berlekamp Massey +algorithm takes as initial conditions any known suspicious bytes +(erasure flags) which you may have (such as might be flagged by +a laser demodulator, or deduced from a failure in a cross-interleaved +block code row or column). + +Once the location of errors is known, error correction is done using +the error-evaluator polynomial. + +APPLICATION IDEAS + +As an example application, this library could be used to implement the +Compact Disc standard of 24 data bytes and 4 parity bytes. A RS code +with 24 data bytes and 4 parity bytes is referred to as a (28,24) RS +code. A (n, k) RS code is said to have efficiency k/n. This first +(28,24) coding is called the C2 or level 2 encoding, because in a +doubly encoded scheme, the codewords are decoded at the second +decoding step. + +In following the approach used by Compact Disc digital audio, the 28 +byte C2 codewords are four way interleaved and then the interleaved +data is encoded again with a (32,28) RS code. The is the C1 encoding +stage. This produces what is known as a "product code", and has +excellent error correction capability due to the imposition of +two-dimensional structure on the parity checks. The interleave helps +to insure against the case that a multibyte burst error wipes out more +than two bytes in each codeword. The cross-correction capability of +the product code can provide backup if in fact there are more than 2 +uncorrectable errors in a block. + + + diff --git a/flight/PipXtreme/inc/watchdog.h b/flight/Modules/PipXtreme/inc/pipxtrememod.h similarity index 76% rename from flight/PipXtreme/inc/watchdog.h rename to flight/Modules/PipXtreme/inc/pipxtrememod.h index ba3fba199..01c8a3964 100644 --- a/flight/PipXtreme/inc/watchdog.h +++ b/flight/Modules/PipXtreme/inc/pipxtrememod.h @@ -1,9 +1,14 @@ /** ****************************************************************************** + * @addtogroup OpenPilotModules OpenPilot Modules + * @{ + * @addtogroup PipXtremeModule PipXtreme Module + * @{ + * + * @file pipxtrememod.h + * @author The OpenPilot Team, http://www.openpilot.org Copyright (C) 2012. + * @brief The PipXtreme system module * - * @file watchdog.h - * @author The OpenPilot Team, http://www.openpilot.org Copyright (C) 2010. - * @brief RF Module hardware layer * @see The GNU Public License (GPL) Version 3 * *****************************************************************************/ @@ -22,11 +27,9 @@ * with this program; if not, write to the Free Software Foundation, Inc., * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ +#ifndef PIPXTREMEMOD_H +#define PIPXTREMEMOD_H -#ifndef _WATCHDOG_H_ -#define _WATCHDOG_H_ +int32_t PipXtremeModInitialize(void); -uint16_t watchdog_Init(uint16_t delayMs); -void watchdog_Clear(void); - -#endif +#endif // PIPXTREMEMOD_H diff --git a/flight/Modules/PipXtreme/pipxtrememod.c b/flight/Modules/PipXtreme/pipxtrememod.c new file mode 100644 index 000000000..5165e1781 --- /dev/null +++ b/flight/Modules/PipXtreme/pipxtrememod.c @@ -0,0 +1,201 @@ +/** + ****************************************************************************** + * @addtogroup OpenPilotModules OpenPilot Modules + * @brief The OpenPilot Modules do the majority of the control in OpenPilot. The + * @ref PipXtremeModule The PipXtreme Module is the equivalanet of the System + * Module for the PipXtreme modem. it starts all the other modules. + # This is done through the @ref PIOS "PIOS Hardware abstraction layer", + # which then contains hardware specific implementations + * (currently only STM32 supported) + * + * @{ + * @addtogroup PipXtremeModule PipXtreme Module + * @brief Initializes PIOS and other modules runs monitoring + * After initializing all the modules runs basic monitoring and + * alarms. + * @{ + * + * @file pipxtrememod.c + * @author The OpenPilot Team, http://www.openpilot.org Copyright (C) 2012. + * @brief System module + * + * @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 +#include +#include +#include "systemmod.h" + +// Private constants +#define SYSTEM_UPDATE_PERIOD_MS 1000 +#define LED_BLINK_RATE_HZ 5 + +#if defined(PIOS_SYSTEM_STACK_SIZE) +#define STACK_SIZE_BYTES PIOS_SYSTEM_STACK_SIZE +#else +#define STACK_SIZE_BYTES 924 +#endif + +#define TASK_PRIORITY (tskIDLE_PRIORITY+2) + +// Private types + +// Private variables +static uint32_t idleCounter; +static uint32_t idleCounterClear; +static xTaskHandle systemTaskHandle; +static bool stackOverflow; +static bool mallocFailed; + +// Private functions +static void systemTask(void *parameters); + +/** + * Create the module task. + * \returns 0 on success or -1 if initialization failed + */ +int32_t PipXtremeModStart(void) +{ + // Initialize vars + stackOverflow = false; + mallocFailed = false; + // Create pipxtreme system task + xTaskCreate(systemTask, (signed char *)"PipXtreme", STACK_SIZE_BYTES/4, NULL, TASK_PRIORITY, &systemTaskHandle); + // Register task + TaskMonitorAdd(TASKINFO_RUNNING_SYSTEM, systemTaskHandle); + + return 0; +} + +/** + * Initialize the module, called on startup. + * \returns 0 on success or -1 if initialization failed + */ +int32_t PipXtremeModInitialize(void) +{ + + // Must registers objects here for system thread because ObjectManager started in OpenPilotInit + + // Initialize out status object. + PipXStatusInitialize(); + PipXStatusData pipxStatus; + PipXStatusGet(&pipxStatus); + + // Get our hardware information. + const struct pios_board_info * bdinfo = &pios_board_info_blob; + + pipxStatus.BoardType= bdinfo->board_type; + PIOS_BL_HELPER_FLASH_Read_Description(pipxStatus.Description, PIPXSTATUS_DESCRIPTION_NUMELEM); + PIOS_SYS_SerialNumberGetBinary(pipxStatus.CPUSerial); + pipxStatus.BoardRevision= bdinfo->board_rev; + + // Update the object + PipXStatusSet(&pipxStatus); + + // Call the module start function. + PipXtremeModStart(); + + return 0; +} + +MODULE_INITCALL(PipXtremeModInitialize, 0) + +/** + * System task, periodically executes every SYSTEM_UPDATE_PERIOD_MS + */ +static void systemTask(void *parameters) +{ + portTickType lastSysTime; + + /* create all modules thread */ + MODULE_TASKCREATE_ALL; + + if (mallocFailed) { + /* We failed to malloc during task creation, + * system behaviour is undefined. Reset and let + * the BootFault code recover for us. + */ + PIOS_SYS_Reset(); + } + + // Initialize vars + idleCounter = 0; + idleCounterClear = 0; + lastSysTime = xTaskGetTickCount(); + + // Main system loop + while (1) { + + // Flash the heartbeat LED +#if defined(PIOS_LED_HEARTBEAT) + PIOS_LED_Toggle(PIOS_LED_HEARTBEAT); +#endif /* PIOS_LED_HEARTBEAT */ + + // Wait until next period + vTaskDelayUntil(&lastSysTime, SYSTEM_UPDATE_PERIOD_MS / portTICK_RATE_MS); + } +} + +/** + * Called by the RTOS when the CPU is idle, used to measure the CPU idle time. + */ +void vApplicationIdleHook(void) +{ + // Called when the scheduler has no tasks to run + if (idleCounterClear == 0) { + ++idleCounter; + } else { + idleCounter = 0; + idleCounterClear = 0; + } +} + +/** + * Called by the RTOS when a stack overflow is detected. + */ +#define DEBUG_STACK_OVERFLOW 0 +void vApplicationStackOverflowHook(xTaskHandle * pxTask, signed portCHAR * pcTaskName) +{ + stackOverflow = true; +#if DEBUG_STACK_OVERFLOW + static volatile bool wait_here = true; + while(wait_here); + wait_here = true; +#endif +} + +/** + * Called by the RTOS when a malloc call fails. + */ +#define DEBUG_MALLOC_FAILURES 0 +void vApplicationMallocFailedHook(void) +{ + mallocFailed = true; +#if DEBUG_MALLOC_FAILURES + static volatile bool wait_here = true; + while(wait_here); + wait_here = true; +#endif +} + +/** + * @} + * @} + */ diff --git a/flight/Modules/RadioComBridge/RadioComBridge.c b/flight/Modules/RadioComBridge/RadioComBridge.c new file mode 100644 index 000000000..5797f4189 --- /dev/null +++ b/flight/Modules/RadioComBridge/RadioComBridge.c @@ -0,0 +1,1069 @@ +/** + ****************************************************************************** + * @addtogroup OpenPilotModules OpenPilot Modules + * @{ + * @addtogroup RadioComBridgeModule Com Port to Radio Bridge Module + * @brief Bridge Com and Radio ports + * @{ + * + * @file RadioComBridge.c + * @author The OpenPilot Team, http://www.openpilot.org Copyright (C) 2012. + * @brief Bridges selected Com Port to the COM VCP emulated serial port + * @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 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#if defined(PIOS_INCLUDE_FLASH_EEPROM) +#include +#endif + +#include + +// **************** +// Private constants + +#define TEMP_BUFFER_SIZE 25 +#define STACK_SIZE_BYTES 150 +#define TASK_PRIORITY (tskIDLE_PRIORITY + 1) +#define BRIDGE_BUF_LEN 512 +#define MAX_RETRIES 2 +#define RETRY_TIMEOUT_MS 20 +#define STATS_UPDATE_PERIOD_MS 2000 +#define RADIOSTATS_UPDATE_PERIOD_MS 1000 +#define MAX_LOST_CONTACT_TIME 4 +#define PACKET_QUEUE_SIZE 10 +#define MAX_PORT_DELAY 200 +#define EV_PACKET_RECEIVED 0x20 +#define EV_SEND_ACK 0x40 +#define EV_SEND_NACK 0x80 + +// **************** +// Private types + +typedef struct { + uint32_t pairID; + uint16_t retries; + uint16_t errors; + uint16_t uavtalk_errors; + uint16_t resets; + int8_t rssi; + uint8_t lastContact; +} PairStats; + +typedef struct { + // The task handles. + xTaskHandle comUAVTalkTaskHandle; + xTaskHandle radioReceiveTaskHandle; + xTaskHandle sendPacketTaskHandle; + xTaskHandle sendDataTaskHandle; + xTaskHandle radioStatusTaskHandle; + xTaskHandle transparentCommTaskHandle; + xTaskHandle ppmInputTaskHandle; + + // The UAVTalk connection on the com side. + UAVTalkConnection inUAVTalkCon; + UAVTalkConnection outUAVTalkCon; + + // Queue handles. + xQueueHandle sendPacketQueue; + xQueueHandle objEventQueue; + + // Error statistics. + uint32_t comTxErrors; + uint32_t comTxRetries; + uint32_t comRxErrors; + uint32_t radioTxErrors; + uint32_t radioTxRetries; + uint32_t radioRxErrors; + uint32_t UAVTalkErrors; + uint32_t packetErrors; + uint16_t txBytes; + uint16_t rxBytes; + + // The destination ID + uint32_t destination_id; + + // The packet timeout. + portTickType send_timeout; + uint16_t min_packet_size; + + // Track other radios that are in range. + PairStats pairStats[PIPXSTATUS_PAIRIDS_NUMELEM]; + +} RadioComBridgeData; + +typedef struct { + uint32_t com_port; + uint8_t *buffer; + uint16_t length; + uint16_t index; + uint16_t data_length; +} ReadBuffer, *BufferedReadHandle; + +// **************** +// Private functions + +static void comUAVTalkTask(void *parameters); +static void radioReceiveTask(void *parameters); +static void sendPacketTask(void *parameters); +static void sendDataTask(void *parameters); +static void transparentCommTask(void * parameters); +static void radioStatusTask(void *parameters); +static void ppmInputTask(void *parameters); +static int32_t transmitData(uint8_t * data, int32_t length); +static int32_t transmitPacket(PHPacketHandle packet); +static void receiveData(uint8_t *buf, uint8_t len); +static void StatusHandler(PHStatusPacketHandle p); +static void PPMHandler(uint16_t *channels); +static BufferedReadHandle BufferedReadInit(uint32_t com_port, uint16_t buffer_length); +static bool BufferedRead(BufferedReadHandle h, uint8_t *value, uint32_t timeout_ms); +static void BufferedReadSetCom(BufferedReadHandle h, uint32_t com_port); +static void updateSettings(); + +// **************** +// Private variables + +static RadioComBridgeData *data; + +/** + * Start the module + * \return -1 if initialisation failed + * \return 0 on success + */ +static int32_t RadioComBridgeStart(void) +{ + if(data) { + // Start the tasks + xTaskCreate(comUAVTalkTask, (signed char *)"ComUAVTalk", STACK_SIZE_BYTES, NULL, TASK_PRIORITY + 2, &(data->comUAVTalkTaskHandle)); + if(PIOS_COM_TRANS_COM) + xTaskCreate(transparentCommTask, (signed char *)"transparentComm", STACK_SIZE_BYTES, NULL, TASK_PRIORITY + 2, &(data->transparentCommTaskHandle)); + xTaskCreate(radioReceiveTask, (signed char *)"RadioReceive", STACK_SIZE_BYTES, NULL, TASK_PRIORITY+ 2, &(data->radioReceiveTaskHandle)); + xTaskCreate(sendPacketTask, (signed char *)"SendPacketTask", STACK_SIZE_BYTES, NULL, TASK_PRIORITY + 2, &(data->sendPacketTaskHandle)); + xTaskCreate(sendDataTask, (signed char *)"SendDataTask", STACK_SIZE_BYTES, NULL, TASK_PRIORITY+ 2, &(data->sendDataTaskHandle)); + xTaskCreate(radioStatusTask, (signed char *)"RadioStatus", STACK_SIZE_BYTES, NULL, TASK_PRIORITY, &(data->radioStatusTaskHandle)); + if(PIOS_PPM_RECEIVER) + xTaskCreate(ppmInputTask, (signed char *)"PPMInputTask", STACK_SIZE_BYTES, NULL, TASK_PRIORITY + 2, &(data->ppmInputTaskHandle)); +#ifdef PIOS_INCLUDE_WDG + PIOS_WDG_RegisterFlag(PIOS_WDG_COMUAVTALK); + if(PIOS_COM_TRANS_COM) + PIOS_WDG_RegisterFlag(PIOS_WDG_TRANSCOMM); + PIOS_WDG_RegisterFlag(PIOS_WDG_RADIORECEIVE); + PIOS_WDG_RegisterFlag(PIOS_WDG_SENDPACKET); + //PIOS_WDG_RegisterFlag(PIOS_WDG_SENDDATA); + if(PIOS_PPM_RECEIVER) + PIOS_WDG_RegisterFlag(PIOS_WDG_PPMINPUT); +#endif + return 0; + } + + return -1; +} + +/** + * Initialise the module + * \return -1 if initialisation failed + * \return 0 on success + */ +static int32_t RadioComBridgeInitialize(void) +{ + + // allocate and initialize the static data storage only if module is enabled + data = (RadioComBridgeData *)pvPortMalloc(sizeof(RadioComBridgeData)); + if (!data) + return -1; + + // Initialize the UAVObjects that we use + GCSReceiverInitialize(); + PipXStatusInitialize(); + ObjectPersistenceInitialize(); + updateSettings(); + + // Initialise UAVTalk + data->inUAVTalkCon = UAVTalkInitialize(0); + data->outUAVTalkCon = UAVTalkInitialize(&transmitData); + + // Initialize the queues. + data->sendPacketQueue = xQueueCreate(PACKET_QUEUE_SIZE, sizeof(PHPacketHandle)); + data->objEventQueue = xQueueCreate(PACKET_QUEUE_SIZE, sizeof(UAVObjEvent)); + + // Initialize the statistics. + data->radioTxErrors = 0; + data->radioTxRetries = 0; + data->radioRxErrors = 0; + data->comTxErrors = 0; + data->comTxRetries = 0; + data->comRxErrors = 0; + data->UAVTalkErrors = 0; + data->packetErrors = 0; + + // Register the callbacks with the packet handler + PHRegisterOutputStream(pios_packet_handler, transmitPacket); + PHRegisterDataHandler(pios_packet_handler, receiveData); + PHRegisterStatusHandler(pios_packet_handler, StatusHandler); + PHRegisterPPMHandler(pios_packet_handler, PPMHandler); + + // Initialize the packet send timeout + data->send_timeout = 25; // ms + data->min_packet_size = 50; + + // Initialize the detected device statistics. + for (uint8_t i = 0; i < PIPXSTATUS_PAIRIDS_NUMELEM; ++i) + { + data->pairStats[i].pairID = 0; + data->pairStats[i].rssi = -127; + data->pairStats[i].retries = 0; + data->pairStats[i].errors = 0; + data->pairStats[i].uavtalk_errors = 0; + data->pairStats[i].resets = 0; + data->pairStats[i].lastContact = 0; + } + // The first slot is reserved for our current pairID + PipXSettingsPairIDGet(&(data->pairStats[0].pairID)); + + // Configure our UAVObjects for updates. + UAVObjConnectQueue(UAVObjGetByName("PipXStatus"), data->objEventQueue, EV_UPDATED | EV_UPDATED_MANUAL | EV_UPDATE_REQ); + UAVObjConnectQueue(UAVObjGetByName("GCSReceiver"), data->objEventQueue, EV_UPDATED | EV_UPDATED_MANUAL | EV_UPDATE_REQ); + UAVObjConnectQueue(UAVObjGetByName("ObjectPersistence"), data->objEventQueue, EV_UPDATED | EV_UPDATED_MANUAL); + + return 0; +} +MODULE_INITCALL(RadioComBridgeInitialize, RadioComBridgeStart) + +/** + * Reads UAVTalk messages froma com port and creates packets out of them. + */ +static void comUAVTalkTask(void *parameters) +{ + PHPacketHandle p = NULL; + + // Create the buffered reader. + BufferedReadHandle f = BufferedReadInit(PIOS_COM_UAVTALK, TEMP_BUFFER_SIZE); + + while (1) { + +#ifdef PIOS_INCLUDE_WDG + // Update the watchdog timer. + PIOS_WDG_UpdateFlag(PIOS_WDG_COMUAVTALK); +#endif /* PIOS_INCLUDE_WDG */ + + // Receive from USB HID if available, otherwise UAVTalk com if it's available. +#if defined(PIOS_INCLUDE_USB) + // Determine input port (USB takes priority over telemetry port) + if (PIOS_USB_CheckAvailable(0)) + BufferedReadSetCom(f, PIOS_COM_USB_HID); + else +#endif /* PIOS_INCLUDE_USB */ + { + if (PIOS_COM_UAVTALK) + BufferedReadSetCom(f, PIOS_COM_UAVTALK); + else + { + vTaskDelay(5); + continue; + } + } + + // Read the next byte + uint8_t rx_byte; + if(!BufferedRead(f, &rx_byte, MAX_PORT_DELAY)) + continue; + data->txBytes++; + + // Get a TX packet from the packet handler if required. + if (p == NULL) + { + + // Wait until we receive a sync. + UAVTalkRxState state = UAVTalkProcessInputStreamQuiet(data->inUAVTalkCon, rx_byte); + if (state != UAVTALK_STATE_TYPE) + continue; + + // Get a packet when we see the sync + p = PHGetTXPacket(pios_packet_handler); + + // No packets available? + if (p == NULL) + { + DEBUG_PRINTF(2, "Packet dropped!\n\r"); + continue; + } + + // Initialize the packet. + p->header.destination_id = data->destination_id; + p->header.source_id = PIOS_RFM22B_DeviceID(pios_rfm22b_id); + //p->header.type = PACKET_TYPE_ACKED_DATA; + p->header.type = PACKET_TYPE_DATA; + p->data[0] = rx_byte; + p->header.data_size = 1; + continue; + } + + // Insert this byte. + p->data[p->header.data_size++] = rx_byte; + + // Keep reading until we receive a completed packet. + UAVTalkRxState state = UAVTalkProcessInputStreamQuiet(data->inUAVTalkCon, rx_byte); + UAVTalkConnectionData *connection = (UAVTalkConnectionData*)(data->inUAVTalkCon); + UAVTalkInputProcessor *iproc = &(connection->iproc); + + if (state == UAVTALK_STATE_COMPLETE) + { + // Is this a local UAVObject? + // We only generate GcsReceiver ojects, we don't consume them. + if ((iproc->obj != NULL) && (iproc->objId != GCSRECEIVER_OBJID)) + { + // We treat the ObjectPersistence object differently + if(iproc->objId == OBJECTPERSISTENCE_OBJID) + { + // Unpack object, if the instance does not exist it will be created! + UAVObjUnpack(iproc->obj, iproc->instId, connection->rxBuffer); + + // Get the ObjectPersistence object. + ObjectPersistenceData obj_per; + ObjectPersistenceGet(&obj_per); + + // Is this concerning or setting object? + if (obj_per.ObjectID == PIPXSETTINGS_OBJID) + { + // Queue up the ACK. + UAVObjEvent ev; + ev.obj = iproc->obj; + ev.instId = iproc->instId; + ev.event = EV_SEND_ACK; + xQueueSend(data->objEventQueue, &ev, MAX_PORT_DELAY); + + // Is this a save, load, or delete? + bool success = true; + switch (obj_per.Operation) + { + case OBJECTPERSISTENCE_OPERATION_LOAD: + { +#if defined(PIOS_INCLUDE_FLASH_EEPROM) + // Load the settings. + PipXSettingsData pipxSettings; + if (PIOS_EEPROM_Load((uint8_t*)&pipxSettings, sizeof(PipXSettingsData)) == 0) + PipXSettingsSet(&pipxSettings); + else + success = false; +#endif + break; + } + case OBJECTPERSISTENCE_OPERATION_SAVE: + { +#if defined(PIOS_INCLUDE_FLASH_EEPROM) + // Save the settings. + PipXSettingsData pipxSettings; + PipXSettingsGet(&pipxSettings); + int32_t ret = PIOS_EEPROM_Save((uint8_t*)&pipxSettings, sizeof(PipXSettingsData)); + if (ret != 0) + success = false; +#endif + break; + } + default: + break; + } + if (success == true) + { + obj_per.Operation = OBJECTPERSISTENCE_OPERATION_COMPLETED; + ObjectPersistenceSet(&obj_per); + } + + // Release the packet, since we don't need it. + PHReleaseTXPacket(pios_packet_handler, p); + } + else + { + // Otherwise, queue the packet for transmission. + xQueueSend(data->sendPacketQueue, &p, MAX_PORT_DELAY); + } + } + else + { + UAVObjEvent ev; + ev.obj = iproc->obj; + ev.instId = 0; + switch (iproc->type) + { + case UAVTALK_TYPE_OBJ: + // Unpack object, if the instance does not exist it will be created! + UAVObjUnpack(iproc->obj, iproc->instId, connection->rxBuffer); + break; + case UAVTALK_TYPE_OBJ_REQ: + // Queue up an object send request. + ev.event = EV_UPDATE_REQ; + xQueueSend(data->objEventQueue, &ev, MAX_PORT_DELAY); + break; + case UAVTALK_TYPE_OBJ_ACK: + if (UAVObjUnpack(iproc->obj, iproc->instId, connection->rxBuffer) == 0) + { + // Queue up an ACK + ev.event = EV_SEND_ACK; + xQueueSend(data->objEventQueue, &ev, MAX_PORT_DELAY); + } + break; + } + + // Release the packet, since we don't need it. + PHReleaseTXPacket(pios_packet_handler, p); + } + } + else + { + // Queue the packet for transmission. + xQueueSend(data->sendPacketQueue, &p, MAX_PORT_DELAY); + } + p = NULL; + + } else if(state == UAVTALK_STATE_ERROR) { + DEBUG_PRINTF(1, "UAVTalk FAILED!\n\r"); + data->UAVTalkErrors++; + + // Send a NACK if required. + if((iproc->obj) && (iproc->type == UAVTALK_TYPE_OBJ_ACK)) + { + // Queue up a NACK + UAVObjEvent ev; + ev.obj = iproc->obj; + ev.event = EV_SEND_NACK; + xQueueSend(data->objEventQueue, &ev, MAX_PORT_DELAY); + + // Release the packet and start over again. + PHReleaseTXPacket(pios_packet_handler, p); + } + else + { + // Transmit the packet anyway... + xQueueSend(data->sendPacketQueue, &p, MAX_PORT_DELAY); + } + p = NULL; + } + } +} + +/** + * The radio to com bridge task. + */ +static void radioReceiveTask(void *parameters) +{ + PHPacketHandle p = NULL; + + /* Handle radio -> usart/usb direction */ + while (1) { + uint32_t rx_bytes; + +#ifdef PIOS_INCLUDE_WDG + // Update the watchdog timer. + PIOS_WDG_UpdateFlag(PIOS_WDG_RADIORECEIVE); +#endif /* PIOS_INCLUDE_WDG */ + + // Get a RX packet from the packet handler if required. + if (p == NULL) + p = PHGetRXPacket(pios_packet_handler); + + if(p == NULL) { + DEBUG_PRINTF(2, "RX Packet Unavailable.!\n\r"); + // Wait a bit for a packet to come available. + vTaskDelay(5); + continue; + } + + // Receive data from the radio port + rx_bytes = PIOS_COM_ReceiveBuffer(PIOS_COM_RADIO, (uint8_t*)p, PIOS_PH_MAX_PACKET, MAX_PORT_DELAY); + if(rx_bytes == 0) + continue; + data->rxBytes += rx_bytes; + + // Verify that the packet is valid and pass it on. + if(PHVerifyPacket(pios_packet_handler, p, rx_bytes) > 0) { + UAVObjEvent ev; + ev.obj = (UAVObjHandle)p; + ev.event = EV_PACKET_RECEIVED; + xQueueSend(data->objEventQueue, &ev, portMAX_DELAY); + } else + { + data->packetErrors++; + PHReceivePacket(pios_packet_handler, p, false); + } + p = NULL; + } +} + +/** + * Send packets to the radio. + */ +static void sendPacketTask(void *parameters) +{ + PHPacketHandle p; + + // Loop forever + while (1) { +#ifdef PIOS_INCLUDE_WDG + // Update the watchdog timer. + PIOS_WDG_UpdateFlag(PIOS_WDG_SENDPACKET); +#endif /* PIOS_INCLUDE_WDG */ + // Wait for a packet on the queue. + if (xQueueReceive(data->sendPacketQueue, &p, MAX_PORT_DELAY) == pdTRUE) { + // Send the packet. + if(!PHTransmitPacket(pios_packet_handler, p)) + PHReleaseTXPacket(pios_packet_handler, p); + } + } +} + +/** + * Send packets to the radio. + */ +static void sendDataTask(void *parameters) +{ + UAVObjEvent ev; + + // Loop forever + while (1) { +#ifdef PIOS_INCLUDE_WDG + // Update the watchdog timer. + // NOTE: this is temporarily turned off becase PIOS_Com_SendBuffer appears to block for an uncontrollable time, + // and SendBufferNonBlocking doesn't seem to be working in this case. + //PIOS_WDG_UpdateFlag(PIOS_WDG_SENDDATA); +#endif /* PIOS_INCLUDE_WDG */ + // Wait for a packet on the queue. + if (xQueueReceive(data->objEventQueue, &ev, MAX_PORT_DELAY) == pdTRUE) { + if ((ev.event == EV_UPDATED) || (ev.event == EV_UPDATE_REQ)) + { + // Send update (with retries) + uint32_t retries = 0; + int32_t success = -1; + while (retries < MAX_RETRIES && success == -1) { + success = UAVTalkSendObject(data->outUAVTalkCon, ev.obj, 0, 0, RETRY_TIMEOUT_MS); + ++retries; + } + data->comTxRetries += retries; + } + else if(ev.event == EV_SEND_ACK) + { + // Send the ACK + uint32_t retries = 0; + int32_t success = -1; + while (retries < MAX_RETRIES && success == -1) { + success = UAVTalkSendAck(data->outUAVTalkCon, ev.obj, ev.instId); + ++retries; + } + data->comTxRetries += retries; + } + else if(ev.event == EV_SEND_NACK) + { + // Send the NACK + uint32_t retries = 0; + int32_t success = -1; + while (retries < MAX_RETRIES && success == -1) { + success = UAVTalkSendNack(data->outUAVTalkCon, UAVObjGetID(ev.obj)); + ++retries; + } + data->comTxRetries += retries; + } + else if(ev.event == EV_PACKET_RECEIVED) + { + // Receive the packet. + PHReceivePacket(pios_packet_handler, (PHPacketHandle)ev.obj, false); + } + } + } +} + +/** + * The com to radio bridge task. + */ +static void transparentCommTask(void * parameters) +{ + portTickType packet_start_time = 0; + uint32_t timeout = MAX_PORT_DELAY; + PHPacketHandle p = NULL; + + /* Handle usart/usb -> radio direction */ + while (1) { + +#ifdef PIOS_INCLUDE_WDG + // Update the watchdog timer. + PIOS_WDG_UpdateFlag(PIOS_WDG_TRANSCOMM); +#endif /* PIOS_INCLUDE_WDG */ + + // Get a TX packet from the packet handler if required. + if (p == NULL) + { + p = PHGetTXPacket(pios_packet_handler); + + // No packets available? + if (p == NULL) + { + // Wait a bit for a packet to come available. + vTaskDelay(5); + continue; + } + + // Initialize the packet. + p->header.destination_id = data->destination_id; + p->header.source_id = PIOS_RFM22B_DeviceID(pios_rfm22b_id); + //p->header.type = PACKET_TYPE_ACKED_DATA; + p->header.type = PACKET_TYPE_DATA; + p->header.data_size = 0; + } + + // Receive data from the com port + uint32_t cur_rx_bytes = PIOS_COM_ReceiveBuffer(PIOS_COM_TRANS_COM, p->data + p->header.data_size, + PH_MAX_DATA - p->header.data_size, timeout); + + // Do we have an data to send? + p->header.data_size += cur_rx_bytes; + if (p->header.data_size > 0) { + + // Check how long since last update + portTickType cur_sys_time = xTaskGetTickCount(); + + // Is this the start of a packet? + if(packet_start_time == 0) + packet_start_time = cur_sys_time; + + // Just send the packet on wraparound + bool send_packet = (cur_sys_time < packet_start_time); + if (!send_packet) + { + portTickType dT = (cur_sys_time - packet_start_time) / portTICK_RATE_MS; + if (dT > data->send_timeout) + send_packet = true; + else + timeout = data->send_timeout - dT; + } + + // Also send the packet if the size is over the minimum. + send_packet |= (p->header.data_size > data->min_packet_size); + + // Should we send this packet? + if (send_packet) + { + // Queue the packet for transmission. + xQueueSend(data->sendPacketQueue, &p, MAX_PORT_DELAY); + + // Reset the timeout + timeout = MAX_PORT_DELAY; + p = NULL; + packet_start_time = 0; + } + } + } +} + +/** + * The stats update task. + */ +static void radioStatusTask(void *parameters) +{ + PHStatusPacket status_packet; + + while (1) { + PipXStatusData pipxStatus; + uint32_t pairID; + + // Get object data + PipXStatusGet(&pipxStatus); + PipXSettingsPairIDGet(&pairID); + + // Update the status + pipxStatus.DeviceID = PIOS_RFM22B_DeviceID(pios_rfm22b_id); + pipxStatus.RSSI = PIOS_RFM22B_RSSI(pios_rfm22b_id); + pipxStatus.Retries = data->comTxRetries; + pipxStatus.Errors = data->packetErrors; + pipxStatus.UAVTalkErrors = data->UAVTalkErrors; + pipxStatus.Resets = PIOS_RFM22B_Resets(pios_rfm22b_id); + pipxStatus.TXRate = (uint16_t)((float)(data->txBytes * 1000) / STATS_UPDATE_PERIOD_MS); + data->txBytes = 0; + pipxStatus.RXRate = (uint16_t)((float)(data->rxBytes * 1000) / STATS_UPDATE_PERIOD_MS); + data->rxBytes = 0; + pipxStatus.LinkState = PIPXSTATUS_LINKSTATE_DISCONNECTED; + + // Update the potential pairing contacts + for (uint8_t i = 0; i < PIPXSTATUS_PAIRIDS_NUMELEM; ++i) + { + pipxStatus.PairIDs[i] = data->pairStats[i].pairID; + pipxStatus.PairSignalStrengths[i] = data->pairStats[i].rssi; + data->pairStats[i].lastContact++; + // Add the paired devices stats to ours. + if(data->pairStats[i].pairID == pairID) + { + pipxStatus.Retries += data->pairStats[i].retries; + pipxStatus.Errors += data->pairStats[i].errors; + pipxStatus.UAVTalkErrors += data->pairStats[i].uavtalk_errors; + pipxStatus.Resets += data->pairStats[i].resets; + pipxStatus.LinkState = PIPXSTATUS_LINKSTATE_CONNECTED; + } + } + + // Update the object + PipXStatusSet(&pipxStatus); + + // Broadcast the status. + { + static uint16_t cntr = 0; + if(cntr++ == RADIOSTATS_UPDATE_PERIOD_MS / STATS_UPDATE_PERIOD_MS) + { + // Queue the status message + status_packet.header.destination_id = 0xffffffff; + status_packet.header.type = PACKET_TYPE_STATUS; + status_packet.header.data_size = PH_STATUS_DATA_SIZE(&status_packet); + status_packet.header.source_id = pipxStatus.DeviceID; + status_packet.header.rssi = pipxStatus.RSSI; + status_packet.retries = data->comTxRetries; + status_packet.errors = data->packetErrors; + status_packet.uavtalk_errors = data->UAVTalkErrors; + status_packet.resets = PIOS_RFM22B_Resets(pios_rfm22b_id); + PHPacketHandle sph = (PHPacketHandle)&status_packet; + xQueueSend(data->sendPacketQueue, &sph, MAX_PORT_DELAY); + cntr = 0; + } + } + + // Delay until the next update period. + vTaskDelay(STATS_UPDATE_PERIOD_MS / portTICK_RATE_MS); + } +} + +/** + * The PPM input task. + */ +static void ppmInputTask(void *parameters) +{ + PHPpmPacket ppm_packet; + PHPacketHandle pph = (PHPacketHandle)&ppm_packet; + + while (1) { + +#ifdef PIOS_INCLUDE_WDG + // Update the watchdog timer. + PIOS_WDG_UpdateFlag(PIOS_WDG_PPMINPUT); +#endif /* PIOS_INCLUDE_WDG */ + + // Send the PPM packet + for (uint8_t i = 1; i <= PIOS_PPM_NUM_INPUTS; ++i) + ppm_packet.channels[i - 1] = PIOS_RCVR_Read(PIOS_PPM_RECEIVER, i); + + // Send the packet. + ppm_packet.header.destination_id = data->destination_id; + ppm_packet.header.source_id = PIOS_RFM22B_DeviceID(pios_rfm22b_id); + ppm_packet.header.type = PACKET_TYPE_PPM; + ppm_packet.header.data_size = PH_PPM_DATA_SIZE(&ppm_packet); + xQueueSend(data->sendPacketQueue, &pph, MAX_PORT_DELAY); + + // Delay until the next update period. + vTaskDelay(PIOS_PPM_PACKET_UPDATE_PERIOD_MS / portTICK_RATE_MS); + } +} + +/** + * Transmit data buffer to the com port. + * \param[in] buf Data buffer to send + * \param[in] length Length of buffer + * \return -1 on failure + * \return number of bytes transmitted on success + */ +static int32_t transmitData(uint8_t *buf, int32_t length) +{ + uint32_t outputPort = PIOS_COM_UAVTALK; +#if defined(PIOS_INCLUDE_USB) + // Determine output port (USB takes priority over telemetry port) + if (PIOS_USB_CheckAvailable(0) && PIOS_COM_USB_HID) + outputPort = PIOS_COM_USB_HID; +#endif /* PIOS_INCLUDE_USB */ + if(outputPort) + return PIOS_COM_SendBuffer(outputPort, buf, length); + else + return -1; +} + +/** + * Transmit a packet to the radio port. + * \param[in] buf Data buffer to send + * \param[in] length Length of buffer + * \return -1 on failure + * \return number of bytes transmitted on success + */ +static int32_t transmitPacket(PHPacketHandle p) +{ + return PIOS_COM_SendBuffer(PIOS_COM_RADIO, (uint8_t*)p, PH_PACKET_SIZE(p)); +} + +/** + * Receive a packet + * \param[in] buf The received data buffer + * \param[in] length Length of buffer + */ +static void receiveData(uint8_t *buf, uint8_t len) +{ + // Packet data should go to transparent com if it's configured, + // USB HID if it's connected, otherwise, UAVTalk com if it's configured. + uint32_t outputPort = PIOS_COM_TRANS_COM; + if (!outputPort) + { + outputPort = PIOS_COM_UAVTALK; +#if defined(PIOS_INCLUDE_USB) + // Determine output port (USB takes priority over telemetry port) + if (PIOS_USB_CheckAvailable(0) && PIOS_COM_USB_HID) + outputPort = PIOS_COM_USB_HID; +#endif /* PIOS_INCLUDE_USB */ + } + if (!outputPort) + return; + + // Send the received data to the com port + if (PIOS_COM_SendBuffer(outputPort, buf, len) != len) + // Error on transmit + data->comTxErrors++; +} + +/** + * Receive a status packet + * \param[in] status The status structure + */ +static void StatusHandler(PHStatusPacketHandle status) +{ + uint32_t id = status->header.source_id; + bool found = false; + // Have we seen this device recently? + uint8_t id_idx = 0; + for ( ; id_idx < PIPXSTATUS_PAIRIDS_NUMELEM; ++id_idx) + if(data->pairStats[id_idx].pairID == id) + { + found = true; + break; + } + + // If we have seen it, update the RSSI and reset the last contact couter + if(found) + { + data->pairStats[id_idx].rssi = status->header.rssi; + data->pairStats[id_idx].retries = status->retries; + data->pairStats[id_idx].errors = status->errors; + data->pairStats[id_idx].uavtalk_errors = status->uavtalk_errors; + data->pairStats[id_idx].resets = status->resets; + data->pairStats[id_idx].lastContact = 0; + } + + // Remove any contacts that we haven't seen for a while. + for (id_idx = 0; id_idx < PIPXSTATUS_PAIRIDS_NUMELEM; ++id_idx) + { + if(data->pairStats[id_idx].lastContact > MAX_LOST_CONTACT_TIME) + { + data->pairStats[id_idx].pairID = 0; + data->pairStats[id_idx].rssi = -127; + data->pairStats[id_idx].retries = 0; + data->pairStats[id_idx].errors = 0; + data->pairStats[id_idx].uavtalk_errors = 0; + data->pairStats[id_idx].resets = 0; + data->pairStats[id_idx].lastContact = 0; + } + } + + // If we haven't seen it, find a slot to put it in. + if (!found) + { + uint32_t pairID; + PipXSettingsPairIDGet(&pairID); + + uint8_t min_idx = 0; + if(id != pairID) + { + int8_t min_rssi = data->pairStats[0].rssi; + for (id_idx = 1; id_idx < PIPXSTATUS_PAIRIDS_NUMELEM; ++id_idx) + { + if(data->pairStats[id_idx].rssi < min_rssi) + { + min_rssi = data->pairStats[id_idx].rssi; + min_idx = id_idx; + } + } + } + data->pairStats[min_idx].pairID = id; + data->pairStats[min_idx].rssi = status->header.rssi; + data->pairStats[min_idx].retries = status->retries; + data->pairStats[min_idx].errors = status->errors; + data->pairStats[min_idx].uavtalk_errors = status->uavtalk_errors; + data->pairStats[min_idx].resets = status->resets; + data->pairStats[min_idx].lastContact = 0; + } +} + +/** + * Receive a ppm packet + * \param[in] channels The ppm channels + */ +static void PPMHandler(uint16_t *channels) +{ + GCSReceiverData rcvr; + + // Copy the receiver channels into the GCSReceiver object. + for (uint8_t i = 0; i < GCSRECEIVER_CHANNEL_NUMELEM; ++i) + rcvr.Channel[i] = channels[i]; + + // Set the GCSReceiverData object. + GCSReceiverSet(&rcvr); +} + +static BufferedReadHandle BufferedReadInit(uint32_t com_port, uint16_t buffer_length) +{ + BufferedReadHandle h = (BufferedReadHandle)pvPortMalloc(sizeof(ReadBuffer)); + if (!h) + return NULL; + + h->com_port = com_port; + h->buffer = (uint8_t*)pvPortMalloc(buffer_length); + h->length = buffer_length; + h->index = 0; + h->data_length = 0; + + if (h->buffer == NULL) + return NULL; + + return h; +} + +static bool BufferedRead(BufferedReadHandle h, uint8_t *value, uint32_t timeout_ms) +{ + // Read some data if required. + if(h->index == h->data_length) + { + uint32_t rx_bytes = PIOS_COM_ReceiveBuffer(h->com_port, h->buffer, h->length, timeout_ms); + if (rx_bytes == 0) + return false; + h->index = 0; + h->data_length = rx_bytes; + } + + // Return the next byte. + *value = h->buffer[h->index++]; + return true; +} + +static void BufferedReadSetCom(BufferedReadHandle h, uint32_t com_port) +{ + h->com_port = com_port; +} + +/** + * Update the telemetry settings, called on startup. + * FIXME: This should be in the TelemetrySettings object. But objects + * have too much overhead yet. Also the telemetry has no any specific + * settings, etc. Thus the HwSettings object which contains the + * telemetry port speed is used for now. + */ +static void updateSettings() +{ + + // Get the settings. + PipXSettingsData pipxSettings; + PipXSettingsGet(&pipxSettings); + + // Initialize the destination ID + data->destination_id = pipxSettings.PairID ? pipxSettings.PairID : 0xffffffff; + DEBUG_PRINTF(2, "PairID: %x\n\r", data->destination_id); + + if (PIOS_COM_TELEMETRY) { + switch (pipxSettings.TelemetrySpeed) { + case PIPXSETTINGS_TELEMETRYSPEED_2400: + PIOS_COM_ChangeBaud(PIOS_COM_TELEMETRY, 2400); + break; + case PIPXSETTINGS_TELEMETRYSPEED_4800: + PIOS_COM_ChangeBaud(PIOS_COM_TELEMETRY, 4800); + break; + case PIPXSETTINGS_TELEMETRYSPEED_9600: + PIOS_COM_ChangeBaud(PIOS_COM_TELEMETRY, 9600); + break; + case PIPXSETTINGS_TELEMETRYSPEED_19200: + PIOS_COM_ChangeBaud(PIOS_COM_TELEMETRY, 19200); + break; + case PIPXSETTINGS_TELEMETRYSPEED_38400: + PIOS_COM_ChangeBaud(PIOS_COM_TELEMETRY, 38400); + break; + case PIPXSETTINGS_TELEMETRYSPEED_57600: + PIOS_COM_ChangeBaud(PIOS_COM_TELEMETRY, 57600); + break; + case PIPXSETTINGS_TELEMETRYSPEED_115200: + PIOS_COM_ChangeBaud(PIOS_COM_TELEMETRY, 115200); + break; + } + } + if (PIOS_COM_FLEXI) { + switch (pipxSettings.FlexiSpeed) { + case PIPXSETTINGS_TELEMETRYSPEED_2400: + PIOS_COM_ChangeBaud(PIOS_COM_FLEXI, 2400); + break; + case PIPXSETTINGS_TELEMETRYSPEED_4800: + PIOS_COM_ChangeBaud(PIOS_COM_FLEXI, 4800); + break; + case PIPXSETTINGS_TELEMETRYSPEED_9600: + PIOS_COM_ChangeBaud(PIOS_COM_FLEXI, 9600); + break; + case PIPXSETTINGS_TELEMETRYSPEED_19200: + PIOS_COM_ChangeBaud(PIOS_COM_FLEXI, 19200); + break; + case PIPXSETTINGS_TELEMETRYSPEED_38400: + PIOS_COM_ChangeBaud(PIOS_COM_FLEXI, 38400); + break; + case PIPXSETTINGS_TELEMETRYSPEED_57600: + PIOS_COM_ChangeBaud(PIOS_COM_FLEXI, 57600); + break; + case PIPXSETTINGS_TELEMETRYSPEED_115200: + PIOS_COM_ChangeBaud(PIOS_COM_FLEXI, 115200); + break; + } + } + if (PIOS_COM_VCP) { + switch (pipxSettings.VCPSpeed) { + case PIPXSETTINGS_TELEMETRYSPEED_2400: + PIOS_COM_ChangeBaud(PIOS_COM_VCP, 2400); + break; + case PIPXSETTINGS_TELEMETRYSPEED_4800: + PIOS_COM_ChangeBaud(PIOS_COM_VCP, 4800); + break; + case PIPXSETTINGS_TELEMETRYSPEED_9600: + PIOS_COM_ChangeBaud(PIOS_COM_VCP, 9600); + break; + case PIPXSETTINGS_TELEMETRYSPEED_19200: + PIOS_COM_ChangeBaud(PIOS_COM_VCP, 19200); + break; + case PIPXSETTINGS_TELEMETRYSPEED_38400: + PIOS_COM_ChangeBaud(PIOS_COM_VCP, 38400); + break; + case PIPXSETTINGS_TELEMETRYSPEED_57600: + PIOS_COM_ChangeBaud(PIOS_COM_VCP, 57600); + break; + case PIPXSETTINGS_TELEMETRYSPEED_115200: + PIOS_COM_ChangeBaud(PIOS_COM_VCP, 115200); + break; + } + } +} diff --git a/flight/PipXtreme/inc/gpio_in.h b/flight/Modules/RadioComBridge/inc/radiocombridge.h similarity index 75% rename from flight/PipXtreme/inc/gpio_in.h rename to flight/Modules/RadioComBridge/inc/radiocombridge.h index 7bfd53375..cb9862b9a 100644 --- a/flight/PipXtreme/inc/gpio_in.h +++ b/flight/Modules/RadioComBridge/inc/radiocombridge.h @@ -1,41 +1,39 @@ -/** - ****************************************************************************** - * - * @file gpio_in.h - * @author The OpenPilot Team, http://www.openpilot.org Copyright (C) 2010. - * @brief GPIO 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 __GPIO_IN_H__ -#define __GPIO_IN_H__ - -// ***************************************************************** - -void GPIO_IN_Init(void); -bool GPIO_IN(uint8_t num); - -// ***************************************************************** - -#endif - -/** - * @} - * @} - */ +/** + ****************************************************************************** + * @addtogroup OpenPilotModules OpenPilot Modules + * @{ + * @addtogroup RadioComBridgeModule Com Port to Radio Bridge Module + * @brief Bridge Com and Radio ports + * @{ + * + * @file radiocombridge.h + * @author The OpenPilot Team, http://www.openpilot.org Copyright (C) 2010. + * @brief Include file of the telemetry module. + * @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 RADIOCOMBRIDGE_H +#define RADIOCOMBRIDGE_H + +#endif // RADIOCOMBRIDGE_H + +/** + * @} + * @} + */ diff --git a/flight/Modules/Stabilization/stabilization.c b/flight/Modules/Stabilization/stabilization.c index 34a89870f..571e6ac7a 100644 --- a/flight/Modules/Stabilization/stabilization.c +++ b/flight/Modules/Stabilization/stabilization.c @@ -99,6 +99,15 @@ static void SettingsUpdatedCb(UAVObjEvent * ev); int32_t StabilizationStart() { // Initialize variables + // Create object queue + queue = xQueueCreate(MAX_QUEUE_SIZE, sizeof(UAVObjEvent)); + + // Listen for updates. + // AttitudeActualConnectQueue(queue); + GyrosConnectQueue(queue); + + StabilizationSettingsConnectCallback(SettingsUpdatedCb); + SettingsUpdatedCb(StabilizationSettingsHandle()); // Start main task xTaskCreate(stabilizationTask, (signed char*)"Stabilization", STACK_SIZE_BYTES/4, NULL, TASK_PRIORITY, &taskHandle); @@ -119,17 +128,6 @@ int32_t StabilizationInitialize() RateDesiredInitialize(); #endif - // Create object queue - queue = xQueueCreate(MAX_QUEUE_SIZE, sizeof(UAVObjEvent)); - - // Listen for updates. - // AttitudeActualConnectQueue(queue); - GyrosConnectQueue(queue); - - StabilizationSettingsConnectCallback(SettingsUpdatedCb); - SettingsUpdatedCb(StabilizationSettingsHandle()); - // Start main task - return 0; } diff --git a/flight/PiOS.posix/Boards/pios_board.h b/flight/PiOS.posix/Boards/pios_board.h new file mode 100644 index 000000000..9917a1d23 --- /dev/null +++ b/flight/PiOS.posix/Boards/pios_board.h @@ -0,0 +1,10 @@ +#ifndef PIOS_BOARD_H_ +#define PIOS_BOARD_H_ + +#ifdef USE_SIM_POSIX +#include "sim_posix.h" +#else +#error Board definition has not been provided. +#endif + +#endif /* PIOS_BOARD_H_ */ diff --git a/flight/PiOS.posix/Boards/sim_posix.h b/flight/PiOS.posix/Boards/sim_posix.h new file mode 100644 index 000000000..6fbe14551 --- /dev/null +++ b/flight/PiOS.posix/Boards/sim_posix.h @@ -0,0 +1,263 @@ +/** + ****************************************************************************** + * @addtogroup OpenPilotSystem OpenPilot System + * @{ + * @addtogroup OpenPilotCore OpenPilot Core + * @{ + * @file pios_board.h + * @author The OpenPilot Team, http://www.openpilot.org Copyright (C) 2012. + * @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 SIM_POSIX_H_ +#define SIM_POSIX_H_ + + +/** + * glue macros for file IO + **/ +#define FILEINFO FILE* +#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) + +//------------------------ +// Timers and Channels Used +//------------------------ +/* +Timer | Channel 1 | Channel 2 | Channel 3 | Channel 4 +------+-----------+-----------+-----------+---------- +TIM1 | | | | +TIM2 | --------------- PIOS_DELAY ----------------- +TIM3 | | | | +TIM4 | | | | +TIM5 | | | | +TIM6 | | | | +TIM7 | | | | +TIM8 | | | | +------+-----------+-----------+-----------+---------- +*/ + +//------------------------ +// DMA Channels Used +//------------------------ +/* Channel 1 - */ +/* Channel 2 - SPI1 RX */ +/* Channel 3 - SPI1 TX */ +/* Channel 4 - SPI2 RX */ +/* Channel 5 - SPI2 TX */ +/* Channel 6 - */ +/* Channel 7 - */ +/* Channel 8 - */ +/* Channel 9 - */ +/* Channel 10 - */ +/* Channel 11 - */ +/* Channel 12 - */ + +//------------------------ +// BOOTLOADER_SETTINGS +//------------------------ +//#define BOARD_READABLE true +//#define BOARD_WRITABLE true +//#define MAX_DEL_RETRYS 3 + + +//------------------------ +// PIOS_LED +//------------------------ +#define PIOS_LED_NUM 3 +#define PIOS_LED_HEARTBEAT 0 +#define PIOS_LED_ALARM 1 + +//------------------------ +// PIOS_SPI +// See also pios_board.c +//------------------------ +//#define PIOS_SPI_MAX_DEVS 3 + +//------------------------ +// PIOS_WDG +//------------------------ +#define PIOS_WATCHDOG_TIMEOUT 250 +//#define PIOS_WDG_REGISTER RTC_BKP_DR4 +#define PIOS_WDG_ACTUATOR 0x0001 +#define PIOS_WDG_STABILIZATION 0x0002 +#define PIOS_WDG_ATTITUDE 0x0004 +#define PIOS_WDG_MANUAL 0x0008 +#define PIOS_WDG_SENSORS 0x0010 + +//------------------------ +// PIOS_I2C +// See also pios_board.c +//------------------------ +//#define PIOS_I2C_MAX_DEVS 3 +//extern uint32_t pios_i2c_mag_adapter_id; +//#define PIOS_I2C_MAIN_ADAPTER (pios_i2c_mag_adapter_id) + +//------------------------- +// PIOS_USART +// +// See also pios_board.c +//------------------------- +//#define PIOS_USART_MAX_DEVS 5 + +//------------------------- +// PIOS_COM +// +// See also pios_board.c +//------------------------- +#define PIOS_COM_MAX_DEVS 25 +extern uint32_t pios_com_telem_rf_id; +extern uint32_t pios_com_gps_id; +extern uint32_t pios_com_aux_id; +extern uint32_t pios_com_telem_usb_id; +extern uint32_t pios_com_bridge_id; +extern uint32_t pios_com_vcp_id; +#define PIOS_COM_AUX (pios_com_aux_id) +#define PIOS_COM_GPS (pios_com_gps_id) +#define PIOS_COM_TELEM_USB (pios_com_telem_usb_id) +#define PIOS_COM_TELEM_RF (pios_com_telem_rf_id) +#define PIOS_COM_BRIDGE (pios_com_bridge_id) +#define PIOS_COM_VCP (pios_com_vcp_id) +#define PIOS_COM_DEBUG PIOS_COM_AUX + +//------------------------ +// TELEMETRY +//------------------------ +#define TELEM_QUEUE_SIZE 20 +#define PIOS_TELEM_STACK_SIZE 624 + +#define PIOS_COM_BUFFER_SIZE 1024 +#define PIOS_UDP_RX_BUFFER_SIZE PIOS_COM_BUFFER_SIZE +#define PIOS_UDP_TX_BUFFER_SIZE PIOS_COM_BUFFER_SIZE + +//------------------------- +// System Settings +// +// See also System_stm32f4xx.c +//------------------------- +//These macros are deprecated +//please use PIOS_PERIPHERAL_APBx_CLOCK According to the table below +//#define PIOS_MASTER_CLOCK +//#define PIOS_PERIPHERAL_CLOCK +//#define PIOS_PERIPHERAL_CLOCK + +#define PIOS_SYSCLK 168000000 +// Peripherals that belongs to APB1 are: +// DAC |PWR |CAN1,2 +// I2C1,2,3 |UART4,5 |USART3,2 +// I2S3Ext |SPI3/I2S3 |SPI2/I2S2 +// I2S2Ext |IWDG |WWDG +// RTC/BKP reg +// TIM2,3,4,5,6,7,12,13,14 + +// Calculated as SYSCLK / APBPresc * (APBPre == 1 ? 1 : 2) +// Default APB1 Prescaler = 4 +//#define PIOS_PERIPHERAL_APB1_CLOCK (PIOS_SYSCLK / 2) + +// Peripherals belonging to APB2 +// SDIO |EXTI |SYSCFG |SPI1 +// ADC1,2,3 +// USART1,6 +// TIM1,8,9,10,11 +// +// Default APB2 Prescaler = 2 +// +//#define PIOS_PERIPHERAL_APB2_CLOCK PIOS_SYSCLK + + +//------------------------- +// Interrupt Priorities +//------------------------- +//#define PIOS_IRQ_PRIO_LOW 12 // lower than RTOS +//#define PIOS_IRQ_PRIO_MID 8 // higher than RTOS +//#define PIOS_IRQ_PRIO_HIGH 5 // for SPI, ADC, I2C etc... +//#define PIOS_IRQ_PRIO_HIGHEST 4 // for USART etc... + +//------------------------ +// PIOS_RCVR +// See also pios_board.c +//------------------------ +#define PIOS_RCVR_MAX_DEVS 3 +#define PIOS_RCVR_MAX_CHANNELS 12 + +//------------------------- +// Receiver PPM input +//------------------------- +//#define PIOS_PPM_MAX_DEVS 1 +//#define PIOS_PPM_NUM_INPUTS 12 + +//------------------------- +// Receiver PWM input +//------------------------- +//#define PIOS_PWM_MAX_DEVS 1 +//#define PIOS_PWM_NUM_INPUTS 8 + +//------------------------- +// Receiver SPEKTRUM input +//------------------------- +//#define PIOS_SPEKTRUM_MAX_DEVS 2 +//#define PIOS_SPEKTRUM_NUM_INPUTS 12 + +//------------------------- +// Receiver S.Bus input +//------------------------- +//#define PIOS_SBUS_MAX_DEVS 1 +//#define PIOS_SBUS_NUM_INPUTS (16+2) + +//------------------------- +// Receiver DSM input +//------------------------- +//#define PIOS_DSM_MAX_DEVS 2 +//#define PIOS_DSM_NUM_INPUTS 12 + +//------------------------- +// Servo outputs +//------------------------- +//#define PIOS_SERVO_UPDATE_HZ 50 +//#define PIOS_SERVOS_INITIAL_POSITION 0 /* dont want to start motors, have no pulse till settings loaded */ +#define PIOS_SERVO_NUM_OUTPUTS 8 +#define PIOS_SERVO_NUM_TIMERS PIOS_SERVO_NUM_OUTPUTS +//-------------------------- +// Timer controller settings +//-------------------------- +//#define PIOS_TIM_MAX_DEVS 6 + +//------------------------- +// ADC +// None. +//------------------------- + +//------------------------- +// USB +//------------------------- +//#define PIOS_USB_MAX_DEVS 1 +//#define PIOS_USB_ENABLED 1 /* Should remove all references to this */ +//#define PIOS_USB_HID_MAX_DEVS 1 + +#endif /* SIM_POSIX_H_ */ +/** + * @} + * @} + */ diff --git a/flight/PiOS.posix/inc/pios_delay.h b/flight/PiOS.posix/inc/pios_delay.h index dcd9bb68d..4b79e3ef1 100644 --- a/flight/PiOS.posix/inc/pios_delay.h +++ b/flight/PiOS.posix/inc/pios_delay.h @@ -1,37 +1,48 @@ -/** - ****************************************************************************** - * - * @file pios_settings.h - * @author The OpenPilot Team, http://www.openpilot.org Copyright (C) 2010. - * Parts by Thorsten Klose (tk@midibox.org) - * @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(uint16_t uS); -extern int32_t PIOS_DELAY_WaitmS(uint16_t mS); - - -#endif /* PIOS_DELAY_H */ +/** + ****************************************************************************** + * @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) 2010. + * @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 */ + +/** + * @} + * @} + */ diff --git a/flight/PiOS.posix/inc/pios_led.h b/flight/PiOS.posix/inc/pios_led.h index 42b0d2443..6ce08b0a0 100644 --- a/flight/PiOS.posix/inc/pios_led.h +++ b/flight/PiOS.posix/inc/pios_led.h @@ -1,43 +1,39 @@ -/** - ****************************************************************************** - * - * @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 - -/* Type Definitions */ - -#if (PIOS_LED_NUM == 1) -typedef enum {LED1 = 0} LedTypeDef; -#elif (PIOS_LED_NUM == 2) -typedef enum {LED1 = 0, LED2 = 1} LedTypeDef; -#endif - -/* Public Functions */ -extern void PIOS_LED_Init(void); -extern void PIOS_LED_On(LedTypeDef LED); -extern void PIOS_LED_Off(LedTypeDef LED); -extern void PIOS_LED_Toggle(LedTypeDef LED); - -#endif /* PIOS_LED_H */ +/** + ****************************************************************************** + * @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_On(uint32_t led_id); +extern void PIOS_LED_Off(uint32_t led_id); +extern void PIOS_LED_Toggle(uint32_t led_id); +extern void PIOS_LED_Init(); + +#endif /* PIOS_LED_H */ diff --git a/flight/PiOS.posix/inc/pios_posix.h b/flight/PiOS.posix/inc/pios_posix.h index b458f77b6..2b411d270 100644 --- a/flight/PiOS.posix/inc/pios_posix.h +++ b/flight/PiOS.posix/inc/pios_posix.h @@ -35,10 +35,10 @@ typedef enum {FALSE = 0, TRUE = !FALSE} bool; #define true TRUE #endif -#define FILEINFO FILE* +//#define FILEINFO FILE* -#define PIOS_SERVO_NUM_OUTPUTS 8 -#define PIOS_SERVO_NUM_TIMERS PIOS_SERVO_NUM_OUTPUTS +//#define PIOS_SERVO_NUM_OUTPUTS 8 +//#define PIOS_SERVO_NUM_TIMERS PIOS_SERVO_NUM_OUTPUTS #endif diff --git a/flight/PiOS.posix/inc/pios_udp_priv.h b/flight/PiOS.posix/inc/pios_udp_priv.h index 999e192e9..5ce32a01a 100644 --- a/flight/PiOS.posix/inc/pios_udp_priv.h +++ b/flight/PiOS.posix/inc/pios_udp_priv.h @@ -45,7 +45,11 @@ struct pios_udp_cfg { typedef struct { const struct pios_udp_cfg * cfg; +#if defined(PIOS_INCLUDE_FREERTOS) + xTaskHandle rxThread; +#else pthread_t rxThread; +#endif int socket; struct sockaddr_in server; @@ -66,6 +70,6 @@ typedef struct { extern int32_t PIOS_UDP_Init(uint32_t * udp_id, const struct pios_udp_cfg * cfg); - +extern const struct pios_com_driver pios_udp_com_driver; #endif /* PIOS_UDP_PRIV_H */ diff --git a/flight/PiOS.posix/pios.h b/flight/PiOS.posix/pios.h index 9256891b1..8e96fa092 100644 --- a/flight/PiOS.posix/pios.h +++ b/flight/PiOS.posix/pios.h @@ -29,7 +29,7 @@ #define PIOS_H /* PIOS Feature Selection */ -#include "pios_config_posix.h" +#include "pios_config.h" #include #if defined(PIOS_INCLUDE_FREERTOS) @@ -52,7 +52,7 @@ #include "pios_initcall.h" /* PIOS Board Specific Device Configuration */ -#include "pios_board_posix.h" +#include "pios_board.h" /* PIOS Hardware Includes (posix) */ #include diff --git a/flight/PiOS.posix/posix/Libraries/FreeRTOS/Source/portable/GCC/Posix/corvuscorax/port_linux.c b/flight/PiOS.posix/posix/Libraries/FreeRTOS/Source/portable/GCC/Posix/corvuscorax/port_linux.c deleted file mode 100644 index 20fa0cb9e..000000000 --- a/flight/PiOS.posix/posix/Libraries/FreeRTOS/Source/portable/GCC/Posix/corvuscorax/port_linux.c +++ /dev/null @@ -1,1024 +0,0 @@ -/* - 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 -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -/* Scheduler includes. */ -#include "FreeRTOS.h" -#include "task.h" -/*-----------------------------------------------------------*/ - -#define MAX_NUMBER_OF_TASKS ( _POSIX_THREAD_THREADS_MAX ) -/*-----------------------------------------------------------*/ - -/* 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; - xTaskHandle hTask; - unsigned portBASE_TYPE uxCriticalNesting; -} xThreadState; -/*-----------------------------------------------------------*/ - -static xThreadState *pxThreads; -static pthread_once_t hSigSetupThread = PTHREAD_ONCE_INIT; -static pthread_attr_t xThreadAttributes; -static pthread_mutex_t xSuspendResumeThreadMutex = PTHREAD_MUTEX_INITIALIZER; -//static pthread_mutex_t xSingleThreadMutex = PTHREAD_MUTEX_INITIALIZER; -static pthread_mutex_t xRunningThreadMutex = PTHREAD_MUTEX_INITIALIZER; -static pthread_t hMainThread = ( pthread_t )NULL; -static pthread_t hActiveThread = ( pthread_t )NULL; -static pthread_t hRequestedThread = ( pthread_t )NULL; -/*-----------------------------------------------------------*/ - -static volatile portBASE_TYPE xSentinel = 0; -static volatile portBASE_TYPE xGeneralFuckedUpIndicator = 0; -static volatile portBASE_TYPE xVeryFirstTask = 1; -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 prvSetupTimerInterrupt( void ); -static void *prvWaitForStart( void * pvParams ); -static void prvSuspendSignalHandler(int sig); -//static void prvResumeSignalHandler(int sig); -static void prvSetupSignalsAndSchedulerPolicy( void ); -static void prvSuspendThread( pthread_t xThreadId ); -static void prvResumeThread( pthread_t xThreadId ); -static pthread_t prvGetThreadHandle( xTaskHandle hTask ); -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 ); -/*-----------------------------------------------------------*/ -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; -tskTCB* prvGetTaskHandle( pthread_t hThread ) -{ -portLONG lIndex; - - if (pxThreads==NULL) return NULL; - - for ( lIndex = 0; lIndex < MAX_NUMBER_OF_TASKS; lIndex++ ) - { - if ( pxThreads[ lIndex ].hThread == hThread ) - { - return pxThreads[ lIndex ].hTask; - } - } - return NULL; -} - -#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( stderr, "%s(%li)\t%s\t%i:",debug_task_handle->pcTaskName,(long)pthread_self(),__func__,__LINE__)): \ - (fprintf( stderr, "__unknown__(%li)\t%s\t%i:",(long)pthread_self(),__func__,__LINE__)) \ - |1)?( \ - ((fprintf( stderr, __VA_ARGS__ )|1)?real_pthread_mutex_unlock( &xPrintfMutex ):0) \ - ):0 ):0 ) - - //int xbla; - //#define debug_printf(...) xbla=0 - 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 vTaskSwitchContext() ( (debug_printf("SWITCHCONTEXT!\n")|1)?vTaskSwitchContext():vTaskSwitchContext() ) -#else - #define debug_printf(...) -#endif - -/*-----------------------------------------------------------*/ - -void prvSuspendThread( pthread_t xThreadId ) -{ -portBASE_TYPE xResult; -// xResult = pthread_mutex_lock( &xSuspendResumeThreadMutex ); -// if ( 0 == xResult ) -// { - /* Set-up for the Suspend Signal handler? */ - //xSentinel = 0; -//portBASE_TYPE aSentinel=xSentinel; - xResult = pthread_kill( xThreadId, SIG_SUSPEND ); -// xResult = pthread_mutex_unlock( &xSuspendResumeThreadMutex ); -// while ( ( aSentinel == xSentinel ) && ( pdTRUE != xServicingTick ) ) -// { -// sched_yield(); -// } -// } -} -/*-----------------------------------------------------------*/ - -void prvResumeThread( pthread_t xThreadId ) -{ -portBASE_TYPE xResult; -// if ( 0 == pthread_mutex_lock( &xSuspendResumeThreadMutex ) ) -// { - if ( pthread_self() != xThreadId ) - { - xResult = pthread_kill( xThreadId, SIG_RESUME ); - } -// xResult = pthread_mutex_unlock( &xSuspendResumeThreadMutex ); -// } -} -#define prvSuspendThread(thread) debug_printf("calling SuspendThread(%li)\n",(long)thread); prvSuspendThread(thread) -#define prvResumeThread(thread) debug_printf("calling ResumeThread(%li)\n",(long)thread); prvResumeThread(thread) - -/* - * Exception handlers. - */ -void vPortYield( void ); -void vPortSystemTickHandler( int sig ); - -/* - * Start first task is a separate function so it can be tested in isolation. - */ -void vPortStartFirstTask( void ); -/*-----------------------------------------------------------*/ - -/* - * 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 ) ); - - (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(); - if ( 0 == pthread_mutex_lock( &xSuspendResumeThreadMutex ) ) { - while (hActiveThread!=hRequestedThread && !xVeryFirstTask) { - (void)pthread_mutex_unlock( &xSuspendResumeThreadMutex ); - sched_yield(); - (void)pthread_mutex_lock( &xSuspendResumeThreadMutex ); - } - - - lIndexOfLastAddedTask = prvGetFreeThreadState(); - - /* Create the new pThread. */ - /* On creation of the very first thread, RunningThreadMutex is not claimed yet - * by the master thread - do that! */ - if (xVeryFirstTask==1) { - debug_printf("Seting up very first task (main) - MAIN is ACTIVE TASK\n"); - if (0 == pthread_mutex_lock( &xRunningThreadMutex)) { - xVeryFirstTask=0; - hActiveThread=pthread_self(); - hRequestedThread=hActiveThread; - } else { - printf("Failed to acquire lock for first task"); - exit(1); - } - - } - - if ( 0 != pthread_create( &( pxThreads[ lIndexOfLastAddedTask ].hThread ), &xThreadAttributes, prvWaitForStart, (void *)pxThisThreadParams ) ) - { - /* Thread create failed, signal the failure */ - pxTopOfStack = 0; - } - - /* Wait until the task suspends. */ - xSentinel=0; - (void)pthread_mutex_unlock( &xRunningThreadMutex ); - while ( xSentinel == 0 ) { - sched_yield(); - } - (void)pthread_mutex_lock( &xRunningThreadMutex ); - hActiveThread=pthread_self(); - debug_printf("ACTIVE THREAD RECLAIMED!\n"); - (void)pthread_mutex_unlock( &xSuspendResumeThreadMutex ); - } else { - debug_printf("mutex locking failed\n"); - exit(1); - } - vPortExitCritical(); - - return pxTopOfStack; -} -/*-----------------------------------------------------------*/ - -void vPortStartFirstTask( void ) -{ - /* Initialise the critical nesting count ready for the first task. */ - uxCriticalNesting = 0; - - /* Start the first task. */ - vPortEnableInterrupts(); - - /* Start the first task. */ - hRequestedThread=prvGetThreadHandle( xTaskGetCurrentTaskHandle()); - prvResumeThread( hRequestedThread ); - - sched_yield(); -} -/*-----------------------------------------------------------*/ - -/* - * See header file for description. - */ -portBASE_TYPE xPortStartScheduler( void ) -{ -portBASE_TYPE xResult; -int iSignal; -sigset_t xSignals; -sigset_t xSignalToBlock; -sigset_t xSignalsBlocked; -portLONG lIndex; - - /* Establish the signals to block before they are needed. */ - sigfillset( &xSignalToBlock ); - - /* Block until the end */ - (void)pthread_sigmask( SIG_SETMASK, &xSignalToBlock, &xSignalsBlocked ); - - for ( lIndex = 0; lIndex < MAX_NUMBER_OF_TASKS; lIndex++ ) - { - pxThreads[ lIndex ].uxCriticalNesting = 0; - } - - /* Start the timer that generates the tick ISR. Interrupts are disabled - here already. */ - prvSetupTimerInterrupt(); - - /* Start the first task. Will not return unless all threads are killed. */ - vPortStartFirstTask(); - - /* This is the end signal we are looking for. */ - sigemptyset( &xSignals ); - sigaddset( &xSignals, SIG_RESUME ); - sigaddset( &xSignals, SIG_TICK ); - - /* Allow other threads to run */ - (void)pthread_mutex_unlock( &xRunningThreadMutex ); - debug_printf( "MAIN thread is entering main signal wait loop!\n"); - - while ( pdTRUE != xSchedulerEnd ) - { - if ( 0 != sigwait( &xSignals, &iSignal ) ) - { - printf( "Main thread spurious signal: %d\n", iSignal ); - } - /** - * Tick handler is called from here - AND ONLY FROM HERE - * (needed for cygwin - but should work on all) - */ - if (iSignal==SIG_TICK) { - vPortSystemTickHandler(iSignal); - } - if (iSignal==SIG_RESUME && pdTRUE != xSchedulerEnd) { - debug_printf("main: forwarding signal to %li\n",(long)hRequestedThread); - (void)pthread_kill( hRequestedThread, SIG_RESUME ); - } - } - - printf( "Cleaning Up, Exiting.\n" ); - /* Cleanup the mutexes */ - //xResult = pthread_mutex_destroy( &xSuspendResumeThreadMutex ); - //xResult = pthread_mutex_destroy( &xSingleThreadMutex ); - xResult = pthread_mutex_destroy( &xRunningThreadMutex ); - 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 - * xSingleThreadMutex 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; - - /** - * Sentinel - do not change context while the running task is not equal the task supposed to run - */ - if ( 0 == pthread_mutex_lock( &xSuspendResumeThreadMutex ) ) - { - /** - * Make sure we don't create outdated resume signals - */ - while (hActiveThread!=hRequestedThread) { - (void)pthread_mutex_unlock( &xSuspendResumeThreadMutex ); - sched_yield(); - (void)pthread_mutex_lock( &xSuspendResumeThreadMutex ); - } - xTaskToSuspend = prvGetThreadHandle( xTaskGetCurrentTaskHandle() ); - - vTaskSwitchContext(); - - xTaskToResume = prvGetThreadHandle( xTaskGetCurrentTaskHandle() ); - if ( xTaskToSuspend != xTaskToResume ) - { - /* Remember and switch the critical nesting. */ - prvSetTaskCriticalNesting( xTaskToSuspend, uxCriticalNesting ); - uxCriticalNesting = prvGetTaskCriticalNesting( xTaskToResume ); - /* Switch tasks. */ - hRequestedThread = xTaskToResume; - prvResumeThread( xTaskToResume ); - //prvSuspendThread( xTaskToSuspend ); -if (prvGetThreadHandle(xTaskGetCurrentTaskHandle())!=xTaskToResume) { - debug_printf("\n what the fuck???? someone else did a switchcontext?!?\n"); -} - (void)pthread_mutex_unlock( &xSuspendResumeThreadMutex ); - prvSuspendSignalHandler(SIG_SUSPEND); - return; - } - else - { - /* Yielding to self */ - (void)pthread_mutex_unlock( &xSuspendResumeThreadMutex ); - } - } -} -/*-----------------------------------------------------------*/ - -void vPortDisableInterrupts( void ) -{ - xInterruptsEnabled = pdFALSE; -} -/*-----------------------------------------------------------*/ - -void vPortEnableInterrupts( void ) -{ - xInterruptsEnabled = pdTRUE; -} -/*-----------------------------------------------------------*/ - -portBASE_TYPE xPortSetInterruptMask( void ) -{ -portBASE_TYPE xReturn = xInterruptsEnabled; - xInterruptsEnabled = pdFALSE; - return xReturn; -} -/*-----------------------------------------------------------*/ - -void vPortClearInterruptMask( portBASE_TYPE xMask ) -{ - xInterruptsEnabled = xMask; -} -/*-----------------------------------------------------------*/ - -/* - * Setup the systick timer to generate the tick interrupts at the required - * frequency. - */ -void prvSetupTimerInterrupt( void ) -{ -struct itimerval itimer, oitimer; -portTickType xMicroSeconds = portTICK_RATE_MICROSECONDS; - - debug_printf("init %li microseconds\n",(long)xMicroSeconds); - /* Initialise the structure with the current timer information. */ - if ( 0 == getitimer( TIMER_TYPE, &itimer ) ) - { - /* Set the interval between timer events. */ - itimer.it_interval.tv_sec = 0; - itimer.it_interval.tv_usec = xMicroSeconds; - - /* Set the current count-down. */ - itimer.it_value.tv_sec = 0; - itimer.it_value.tv_usec = xMicroSeconds; - - /* Set-up the timer interrupt. */ - if ( 0 != setitimer( TIMER_TYPE, &itimer, &oitimer ) ) - { - printf( "Set Timer problem.\n" ); - } - } - else - { - printf( "Get Timer problem.\n" ); - } -} -/*-----------------------------------------------------------*/ - -void vPortSystemTickHandler( int sig ) -{ -pthread_t xTaskToSuspend; -pthread_t xTaskToResume; -struct timespec timeout; - - //debug_printf("received %i\n",sig); - /** - * do not call tick handler if - * - interrupts are disabled - * - tick handler is still running - * - old task switch not yet completed (wrong task running) - */ - if ( ( pdTRUE == xInterruptsEnabled ) && ( pdTRUE != xServicingTick ) && ( hRequestedThread == hActiveThread ) ) - { - xServicingTick = pdTRUE; - if ( 0 == pthread_mutex_trylock( &xSuspendResumeThreadMutex ) ) - { - debug_printf("does handle tick\n"); - - /** - * this shouldn't ever happen - but WELL... - * Make sure we don't create outdated resume signals - */ - if (hActiveThread!=hRequestedThread) { - xServicingTick = pdFALSE; - xPendYield = pdTRUE; - (void)pthread_mutex_unlock( &xSuspendResumeThreadMutex ); - return; - } - - xTaskToSuspend = prvGetThreadHandle( xTaskGetCurrentTaskHandle() ); - /* Tick Increment. */ - vTaskIncrementTick(); - - /* Select Next Task. */ -#if ( configUSE_PREEMPTION == 1 ) - vTaskSwitchContext(); -#endif - xTaskToResume = prvGetThreadHandle( xTaskGetCurrentTaskHandle() ); - //hRequestedThread = xTaskToResume; - - /* The only thread that can process this tick is the running thread. */ - if ( xTaskToSuspend != xTaskToResume ) - { - /* Suspend the current task. */ - hRequestedThread = 0; - prvSuspendThread( xTaskToSuspend ); - timeout.tv_sec=0; - timeout.tv_nsec=10000; - while ( 0 != pthread_mutex_timedlock( &xRunningThreadMutex,&timeout ) ) { - prvSuspendThread( xTaskToSuspend ); - timeout.tv_sec=0; - timeout.tv_nsec=10000; - } - /* - if ( 0 != pthread_mutex_lock( &xRunningThreadMutex)) { - debug_printf("mutex lock failed!\n"); - exit(1); - } - */ - //if ( 0 == pthread_mutex_lock( &xRunningThreadMutex) ) { - /* Remember and switch the critical nesting. */ - prvSetTaskCriticalNesting( xTaskToSuspend, uxCriticalNesting ); - uxCriticalNesting = prvGetTaskCriticalNesting( xTaskToResume ); - /* Resume next task. */ - hRequestedThread = xTaskToResume; - prvResumeThread( xTaskToResume ); -if (prvGetThreadHandle(xTaskGetCurrentTaskHandle())!=xTaskToResume) { -debug_printf("\n what the fuck???? someone else did a switchcontext?!?\n"); -} - (void)pthread_mutex_unlock( &xRunningThreadMutex ); - } - else - { - /* Release the lock as we are Resuming. */ - // (void)pthread_mutex_unlock( &xSingleThreadMutex ); - } - } - else - { - xPendYield = pdTRUE; - } - (void)pthread_mutex_unlock( &xSuspendResumeThreadMutex ); - xServicingTick = pdFALSE; - } - else - { - debug_printf("will NOT handle tick\n"); - xPendYield = pdTRUE; - } -} -/*-----------------------------------------------------------*/ - -void vPortForciblyEndThread( void *pxTaskToDelete ) -{ -xTaskHandle hTaskToDelete = ( xTaskHandle )pxTaskToDelete; -pthread_t xTaskToDelete; -pthread_t xTaskToResume; -portBASE_TYPE xResult; - -// if ( 0 == pthread_mutex_lock( &xSingleThreadMutex ) ) -// { - xTaskToDelete = prvGetThreadHandle( hTaskToDelete ); - xTaskToResume = prvGetThreadHandle( xTaskGetCurrentTaskHandle() ); - - if ( xTaskToResume == xTaskToDelete ) - { - if ( 0 == pthread_mutex_lock( &xSuspendResumeThreadMutex ) ) { - /** - * Make sure we don't create outdated resume signals - */ - while (hActiveThread!=hRequestedThread) { - (void)pthread_mutex_unlock( &xSuspendResumeThreadMutex ); - sched_yield(); - (void)pthread_mutex_lock( &xSuspendResumeThreadMutex ); - } - /* This is a suicidal thread, need to select a different task to run. */ - vTaskSwitchContext(); - xTaskToResume = prvGetThreadHandle( xTaskGetCurrentTaskHandle() ); - hRequestedThread = xTaskToResume; - (void)pthread_mutex_unlock( &xSuspendResumeThreadMutex ); - } else { - debug_printf("mutex lock failed!\n"); - exit(1); - } - } - - 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( &xSingleThreadMutex ); - } - else - { - /* Resume the other thread. */ - prvResumeThread( xTaskToResume ); - /* Pthread Clean-up function will note the cancellation. */ - /* Release the execution. */ - uxCriticalNesting = 0; - vPortEnableInterrupts(); -// (void)pthread_mutex_unlock( &xSingleThreadMutex ); - (void)pthread_mutex_unlock( &xRunningThreadMutex ); - /* Commit suicide */ - pthread_exit( (void *)1 ); - } -// } -} -/*-----------------------------------------------------------*/ - -void *prvWaitForStart( void * pvParams ) -{ -xParams * pxParams = ( xParams * )pvParams; -pdTASK_CODE pvCode = pxParams->pxCode; -void * pParams = pxParams->pvParams; -sigset_t xSignals; - vPortFree( pvParams ); - - pthread_cleanup_push( prvDeleteThread, (void *)pthread_self() ); - - if ( 0 == pthread_mutex_lock( &xRunningThreadMutex ) ) - { - xSentinel=1; - hActiveThread=pthread_self(); - debug_printf("temporarily made ACTIVE THREAD!\n"); - - sigemptyset( &xSignals ); - sigaddset( &xSignals, SIG_RESUME ); - /* set up proc mask */ - pthread_sigmask(SIG_SETMASK,&xSignals,NULL); - - prvSuspendSignalHandler(SIG_SUSPEND); - //prvSuspendThread( pthread_self() ); - } else { - debug_printf("now this is just WRONG!\n"); - exit(1); - } - - pvCode( pParams ); - - pthread_cleanup_pop( 1 ); - return (void *)NULL; -} -/*-----------------------------------------------------------*/ - -void prvSuspendSignalHandler(int sig) -{ -sigset_t xSignals; -//sigset_t xPendingSignals; - - /* Only interested in the resume signal. */ - sigemptyset( &xSignals ); - sigaddset( &xSignals, SIG_RESUME ); - sigaddset( &xSignals, SIG_SUSPEND ); - - /* Unlock the Running thread mutex to allow the resumed task to continue. */ - if ( 0 != pthread_mutex_unlock( &xRunningThreadMutex ) ) - { - printf( "Releasing someone else's lock.\n" ); - } - - debug_printf("SUSPENDING until SIG_RESUME received\n"); - /* Wait on the resume signal. */ - while (hRequestedThread != pthread_self()) { - if ( 0 != sigwait( &xSignals, &sig ) ) - { - printf( "SSH: Sw %d\n", sig ); - /* tricky one - shouldn't ever happen - trying to resolve situation as graceful as possible */ - debug_printf("ALERT AAAAH PANIC! - sigwait failed.....\n\n\n"); - /* Signal main thread something just went HORRIBLY wrong */ - xGeneralFuckedUpIndicator = 2; - //(void)pthread_mutex_lock( &xRunningThreadMutex ); - //(void)pthread_kill( pthread_self(), SIG_SUSPEND ); - //return; - } - } - /* Yield the Scheduler to ensure that the yielding thread completes. */ - if ( 0 != pthread_mutex_lock( &xRunningThreadMutex ) ) - { - //(void)pthread_mutex_unlock( &xSingleThreadMutex ); - debug_printf("critical - mutex acquiring of active thread failed!\n"); - exit(1); - } - hActiveThread = pthread_self(); - - /* 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(); - } - if (hRequestedThread==pthread_self()) { - /* doesn't look too bad, does it? */ - xGeneralFuckedUpIndicator = 0; - } - debug_printf("ACTIVE THREAD!\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, sigresume, sigtick; -portLONG lIndex; - - 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 ); - - sigresume.sa_flags = 0; - //sigresume.sa_handler = prvResumeSignalHandler; - sigresume.sa_handler = SIG_IGN; - sigfillset( &sigresume.sa_mask ); - - sigtick.sa_flags = 0; - //sigtick.sa_handler = vPortSystemTickHandler; - sigtick.sa_handler = SIG_IGN; - sigfillset( &sigtick.sa_mask ); - - if ( 0 != sigaction( SIG_SUSPEND, &sigsuspendself, NULL ) ) - { - printf( "Problem installing SIG_SUSPEND_SELF\n" ); - } - //if ( 0 != sigaction( SIG_RESUME, &sigresume, NULL ) ) - //{ - // printf( "Problem installing SIG_RESUME\n" ); - //} - if ( 0 != sigaction( SIG_TICK, &sigtick, NULL ) ) - { - printf( "Problem installing SIG_TICK\n" ); - } - printf( "Running as PID: %d\n", getpid() ); -} -/*-----------------------------------------------------------*/ - -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; - - 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; - } - } - } -} -/*-----------------------------------------------------------*/ - -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; -} -/*-----------------------------------------------------------*/ diff --git a/flight/PiOS.posix/posix/Libraries/FreeRTOS/Source/portable/GCC/Posix/corvuscorax/port_new-thread-implementation_works-on-linux.c b/flight/PiOS.posix/posix/Libraries/FreeRTOS/Source/portable/GCC/Posix/corvuscorax/port_new-thread-implementation_works-on-linux.c deleted file mode 100755 index 7f38e2a2d..000000000 --- a/flight/PiOS.posix/posix/Libraries/FreeRTOS/Source/portable/GCC/Posix/corvuscorax/port_new-thread-implementation_works-on-linux.c +++ /dev/null @@ -1,1042 +0,0 @@ -/* - 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 -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -/* Scheduler includes. */ -#include "FreeRTOS.h" -#include "task.h" -/*-----------------------------------------------------------*/ - -#define MAX_NUMBER_OF_TASKS ( _POSIX_THREAD_THREADS_MAX ) -/*-----------------------------------------------------------*/ - -/* 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; - xTaskHandle hTask; - unsigned portBASE_TYPE uxCriticalNesting; -} xThreadState; -/*-----------------------------------------------------------*/ - -static xThreadState *pxThreads; -static pthread_once_t hSigSetupThread = PTHREAD_ONCE_INIT; -static pthread_attr_t xThreadAttributes; -static pthread_mutex_t xSuspendResumeThreadMutex = PTHREAD_MUTEX_INITIALIZER; -//static pthread_mutex_t xSingleThreadMutex = PTHREAD_MUTEX_INITIALIZER; -static pthread_mutex_t xRunningThreadMutex = PTHREAD_MUTEX_INITIALIZER; -static pthread_mutex_t xPrintfMutex = PTHREAD_MUTEX_INITIALIZER; -static pthread_t hMainThread = ( pthread_t )NULL; -static pthread_t hActiveThread = ( pthread_t )NULL; -static pthread_t hRequestedThread = ( pthread_t )NULL; -/*-----------------------------------------------------------*/ - -static volatile portBASE_TYPE xSentinel = 0; -static volatile portBASE_TYPE xGeneralFuckedUpIndicator = 0; -static volatile portBASE_TYPE xVeryFirstTask = 1; -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 prvSetupTimerInterrupt( void ); -static void *prvWaitForStart( void * pvParams ); -static void prvSuspendSignalHandler(int sig); -//static void prvResumeSignalHandler(int sig); -static void prvSetupSignalsAndSchedulerPolicy( void ); -static void prvSuspendThread( pthread_t xThreadId ); -static void prvResumeThread( pthread_t xThreadId ); -static pthread_t prvGetThreadHandle( xTaskHandle hTask ); -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 ); -static void prvResolveFuckup( 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; -tskTCB* prvGetTaskHandle( pthread_t hThread ) -{ -portLONG lIndex; - - if (pxThreads==NULL) return NULL; - - for ( lIndex = 0; lIndex < MAX_NUMBER_OF_TASKS; lIndex++ ) - { - if ( pxThreads[ lIndex ].hThread == hThread ) - { - return pxThreads[ lIndex ].hTask; - } - } - return NULL; -} - - -#define debug_printf(...) ( (real_pthread_mutex_lock( &xPrintfMutex )|1)?( \ - ( \ - (NULL != (debug_task_handle = prvGetTaskHandle(pthread_self())) )? \ - (fprintf( stderr, "%s(%li)\t%s\t%i:",debug_task_handle->pcTaskName,(long)pthread_self(),__func__,__LINE__)): \ - (fprintf( stderr, "__unknown__(%li)\t%s\t%i:",(long)pthread_self(),__func__,__LINE__)) \ - |1)?( \ - ((fprintf( stderr, __VA_ARGS__ )|1)?real_pthread_mutex_unlock( &xPrintfMutex ):0) \ - ):0 ):0 ) - -//int xbla; -//#define debug_printf(...) xbla=0 -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 vTaskSwitchContext() ( (debug_printf("SWITCHCONTEXT!\n")|1)?vTaskSwitchContext():vTaskSwitchContext() ) -*/ -/*-----------------------------------------------------------*/ - -void prvSuspendThread( pthread_t xThreadId ) -{ -portBASE_TYPE xResult; -// xResult = pthread_mutex_lock( &xSuspendResumeThreadMutex ); -// if ( 0 == xResult ) -// { - /* Set-up for the Suspend Signal handler? */ - //xSentinel = 0; -//portBASE_TYPE aSentinel=xSentinel; - xResult = pthread_kill( xThreadId, SIG_SUSPEND ); -// xResult = pthread_mutex_unlock( &xSuspendResumeThreadMutex ); -// while ( ( aSentinel == xSentinel ) && ( pdTRUE != xServicingTick ) ) -// { -// sched_yield(); -// } -// } -} -/*-----------------------------------------------------------*/ - -void prvResumeThread( pthread_t xThreadId ) -{ -portBASE_TYPE xResult; -// if ( 0 == pthread_mutex_lock( &xSuspendResumeThreadMutex ) ) -// { - if ( pthread_self() != xThreadId ) - { - xResult = pthread_kill( xThreadId, SIG_RESUME ); - } -// xResult = pthread_mutex_unlock( &xSuspendResumeThreadMutex ); -// } -} -#define prvSuspendThread(thread) debug_printf("calling SuspendThread(%li)\n",(long)thread); prvSuspendThread(thread) -#define prvResumeThread(thread) debug_printf("calling ResumeThread(%li)\n",(long)thread); prvResumeThread(thread) - -/* - * Exception handlers. - */ -void vPortYield( void ); -void vPortSystemTickHandler( int sig ); - -/* - * Start first task is a separate function so it can be tested in isolation. - */ -void vPortStartFirstTask( void ); -/*-----------------------------------------------------------*/ - -/* - * 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 ) ); - - (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(); - - /* Create the new pThread. */ - /* On creation of the very first thread, RunningThreadMutex is not claimed yet - * by the master thread - do that! */ - if (xVeryFirstTask==1) { - if (0 == pthread_mutex_lock( &xRunningThreadMutex)) { - xVeryFirstTask=0; - } else { - printf("Failed to acquire lock for first task"); - exit(1); - } - - } - - if ( 0 != pthread_create( &( pxThreads[ lIndexOfLastAddedTask ].hThread ), &xThreadAttributes, prvWaitForStart, (void *)pxThisThreadParams ) ) - { - /* Thread create failed, signal the failure */ - pxTopOfStack = 0; - } - - /* Wait until the task suspends. */ - xSentinel=0; - (void)pthread_mutex_unlock( &xRunningThreadMutex ); - while ( xSentinel == 0 ) { - sched_yield(); - } - (void)pthread_mutex_lock( &xRunningThreadMutex ); - vPortExitCritical(); - - return pxTopOfStack; -} -/*-----------------------------------------------------------*/ - -void vPortStartFirstTask( void ) -{ - /* Initialise the critical nesting count ready for the first task. */ - uxCriticalNesting = 0; - - /* Start the first task. */ - vPortEnableInterrupts(); - - /* Start the first task. */ - hRequestedThread=prvGetThreadHandle( xTaskGetCurrentTaskHandle()); - prvResumeThread( hRequestedThread ); - - sched_yield(); -} -/*-----------------------------------------------------------*/ - -/* - * See header file for description. - */ -portBASE_TYPE xPortStartScheduler( void ) -{ -portBASE_TYPE xResult; -int iSignal; -int fuckedUpCount=0; -sigset_t xSignals; -sigset_t xSignalToBlock; -sigset_t xSignalsBlocked; -portLONG lIndex; - - /* Establish the signals to block before they are needed. */ - sigfillset( &xSignalToBlock ); - - /* Block until the end */ - (void)pthread_sigmask( SIG_SETMASK, &xSignalToBlock, &xSignalsBlocked ); - - for ( lIndex = 0; lIndex < MAX_NUMBER_OF_TASKS; lIndex++ ) - { - pxThreads[ lIndex ].uxCriticalNesting = 0; - } - - /* Start the timer that generates the tick ISR. Interrupts are disabled - here already. */ - prvSetupTimerInterrupt(); - - /* Start the first task. Will not return unless all threads are killed. */ - vPortStartFirstTask(); - - /* This is the end signal we are looking for. */ - sigemptyset( &xSignals ); - sigaddset( &xSignals, SIG_RESUME ); - sigaddset( &xSignals, SIG_TICK ); - - /* Allow other threads to run */ - (void)pthread_mutex_unlock( &xRunningThreadMutex ); - debug_printf( "MAIN thread is entering main signal wait loop!\n"); - - while ( pdTRUE != xSchedulerEnd ) - { - if ( 0 != sigwait( &xSignals, &iSignal ) ) - { - printf( "Main thread spurious signal: %d\n", iSignal ); - } - /** - * Tick handler is called from here - AND ONLY FROM HERE - * (needed for cygwin - but should work on all) - */ - if (iSignal==SIG_TICK) { - if (xGeneralFuckedUpIndicator!=0) { - fuckedUpCount++; - if (fuckedUpCount>10) { - fuckedUpCount=0; - prvResolveFuckup(); - } - } else { - fuckedUpCount=0; - } - vPortSystemTickHandler(iSignal); - } - if (iSignal==SIG_RESUME && pdTRUE != xSchedulerEnd) { - debug_printf( "ALERT! Main received SIG_RESUME that was supposed to go elsewhere!"); - } - } - - printf( "Cleaning Up, Exiting.\n" ); - /* Cleanup the mutexes */ - //xResult = pthread_mutex_destroy( &xSuspendResumeThreadMutex ); - //xResult = pthread_mutex_destroy( &xSingleThreadMutex ); - xResult = pthread_mutex_destroy( &xRunningThreadMutex ); - 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 - * xSingleThreadMutex 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; - - /** - * Sentinel - do not change context while the running task is not equal the task supposed to run - */ - if ( 0 == pthread_mutex_lock( &xSuspendResumeThreadMutex ) ) - { - /** - * Make sure we don't create outdated resume signals - */ - while (hActiveThread!=hRequestedThread) { - sched_yield(); - } - xTaskToSuspend = prvGetThreadHandle( xTaskGetCurrentTaskHandle() ); - - vTaskSwitchContext(); - - xTaskToResume = prvGetThreadHandle( xTaskGetCurrentTaskHandle() ); - hRequestedThread = xTaskToResume; - if ( xTaskToSuspend != xTaskToResume ) - { - /* Remember and switch the critical nesting. */ - prvSetTaskCriticalNesting( xTaskToSuspend, uxCriticalNesting ); - uxCriticalNesting = prvGetTaskCriticalNesting( xTaskToResume ); - /* Switch tasks. */ - prvResumeThread( xTaskToResume ); - //prvSuspendThread( xTaskToSuspend ); -if (prvGetThreadHandle(xTaskGetCurrentTaskHandle())!=xTaskToResume) { - debug_printf("\n what the fuck???? someone else did a switchcontext?!?\n"); -} - (void)pthread_mutex_unlock( &xSuspendResumeThreadMutex ); - prvSuspendSignalHandler(SIG_SUSPEND); - return; - } - else - { - /* Yielding to self */ - (void)pthread_mutex_unlock( &xSuspendResumeThreadMutex ); - } - } -} -/*-----------------------------------------------------------*/ - -void vPortDisableInterrupts( void ) -{ - xInterruptsEnabled = pdFALSE; -} -/*-----------------------------------------------------------*/ - -void vPortEnableInterrupts( void ) -{ - xInterruptsEnabled = pdTRUE; -} -/*-----------------------------------------------------------*/ - -portBASE_TYPE xPortSetInterruptMask( void ) -{ -portBASE_TYPE xReturn = xInterruptsEnabled; - xInterruptsEnabled = pdFALSE; - return xReturn; -} -/*-----------------------------------------------------------*/ - -void vPortClearInterruptMask( portBASE_TYPE xMask ) -{ - xInterruptsEnabled = xMask; -} -/*-----------------------------------------------------------*/ - -/* - * Setup the systick timer to generate the tick interrupts at the required - * frequency. - */ -void prvSetupTimerInterrupt( void ) -{ -struct itimerval itimer, oitimer; -portTickType xMicroSeconds = portTICK_RATE_MICROSECONDS; - - debug_printf("init %li microseconds\n",(long)xMicroSeconds); - /* Initialise the structure with the current timer information. */ - if ( 0 == getitimer( TIMER_TYPE, &itimer ) ) - { - /* Set the interval between timer events. */ - itimer.it_interval.tv_sec = 0; - itimer.it_interval.tv_usec = xMicroSeconds; - - /* Set the current count-down. */ - itimer.it_value.tv_sec = 0; - itimer.it_value.tv_usec = xMicroSeconds; - - /* Set-up the timer interrupt. */ - if ( 0 != setitimer( TIMER_TYPE, &itimer, &oitimer ) ) - { - printf( "Set Timer problem.\n" ); - } - } - else - { - printf( "Get Timer problem.\n" ); - } -} -/*-----------------------------------------------------------*/ - -void vPortSystemTickHandler( int sig ) -{ -pthread_t xTaskToSuspend; -pthread_t xTaskToResume; -struct timespec timeout; - - //debug_printf("received %i\n",sig); - /** - * do not call tick handler if - * - interrupts are disabled - * - tick handler is still running - * - old task switch not yet completed (wrong task running) - */ - if ( ( pdTRUE == xInterruptsEnabled ) && ( pdTRUE != xServicingTick ) && ( hRequestedThread == hActiveThread ) ) - { - if ( 0 == pthread_mutex_trylock( &xSuspendResumeThreadMutex ) ) - { - //debug_printf("will handle tick\n"); - xServicingTick = pdTRUE; - - /** - * this shouldn't ever happen - but WELL... - * Make sure we don't create outdated resume signals - */ - while (hActiveThread!=hRequestedThread) { - sched_yield(); - } - - xTaskToSuspend = prvGetThreadHandle( xTaskGetCurrentTaskHandle() ); - /* Tick Increment. */ - vTaskIncrementTick(); - - /* Select Next Task. */ -#if ( configUSE_PREEMPTION == 1 ) - vTaskSwitchContext(); -#endif - xTaskToResume = prvGetThreadHandle( xTaskGetCurrentTaskHandle() ); - hRequestedThread = xTaskToResume; - - /* The only thread that can process this tick is the running thread. */ - if ( xTaskToSuspend != xTaskToResume ) - { - /* Suspend the current task. */ - prvSuspendThread( xTaskToSuspend ); - timeout.tv_sec=0; - timeout.tv_nsec=10000; - //if ( 0 == pthread_mutex_timedlock( &xRunningThreadMutex,&timeout ) ) { - if ( 0 == pthread_mutex_lock( &xRunningThreadMutex) ) { - /* Remember and switch the critical nesting. */ - prvSetTaskCriticalNesting( xTaskToSuspend, uxCriticalNesting ); - uxCriticalNesting = prvGetTaskCriticalNesting( xTaskToResume ); - /* Resume next task. */ - prvResumeThread( xTaskToResume ); -if (prvGetThreadHandle(xTaskGetCurrentTaskHandle())!=xTaskToResume) { - debug_printf("\n what the fuck???? someone else did a switchcontext?!?\n"); -} - (void)pthread_mutex_unlock( &xRunningThreadMutex ); - } else { - debug_printf("Oh dear - tick handler could not acquire lock!\n\n"); - //prvResumeThread( xTaskToSuspend ); - xGeneralFuckedUpIndicator=3; - } - } - else - { - /* Release the lock as we are Resuming. */ - // (void)pthread_mutex_unlock( &xSingleThreadMutex ); - } - xServicingTick = pdFALSE; - } - else - { - xPendYield = pdTRUE; - } - (void)pthread_mutex_unlock( &xSuspendResumeThreadMutex ); - } - else - { - debug_printf("will NOT handle tick\n"); - xPendYield = pdTRUE; - } -} -/*-----------------------------------------------------------*/ - -void vPortForciblyEndThread( void *pxTaskToDelete ) -{ -xTaskHandle hTaskToDelete = ( xTaskHandle )pxTaskToDelete; -pthread_t xTaskToDelete; -pthread_t xTaskToResume; -portBASE_TYPE xResult; - -// if ( 0 == pthread_mutex_lock( &xSingleThreadMutex ) ) -// { - xTaskToDelete = prvGetThreadHandle( hTaskToDelete ); - xTaskToResume = prvGetThreadHandle( xTaskGetCurrentTaskHandle() ); - - if ( xTaskToResume == xTaskToDelete ) - { - if ( 0 == pthread_mutex_lock( &xSuspendResumeThreadMutex ) ) { - /** - * Make sure we don't create outdated resume signals - */ - while (hActiveThread!=hRequestedThread) { - sched_yield(); - } - /* This is a suicidal thread, need to select a different task to run. */ - vTaskSwitchContext(); - xTaskToResume = prvGetThreadHandle( xTaskGetCurrentTaskHandle() ); - hRequestedThread = xTaskToResume; - (void)pthread_mutex_unlock( &xSuspendResumeThreadMutex ); - } else { - debug_printf("THIS was never meant to happen\n"); - exit(1); - } - } - - 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( &xSingleThreadMutex ); - } - else - { - /* Resume the other thread. */ - prvResumeThread( xTaskToResume ); - /* Pthread Clean-up function will note the cancellation. */ - /* Release the execution. */ - uxCriticalNesting = 0; - vPortEnableInterrupts(); -// (void)pthread_mutex_unlock( &xSingleThreadMutex ); - (void)pthread_mutex_unlock( &xRunningThreadMutex ); - /* Commit suicide */ - pthread_exit( (void *)1 ); - } -// } -} -/*-----------------------------------------------------------*/ - -void *prvWaitForStart( void * pvParams ) -{ -xParams * pxParams = ( xParams * )pvParams; -pdTASK_CODE pvCode = pxParams->pxCode; -void * pParams = pxParams->pvParams; -sigset_t xSignals; - vPortFree( pvParams ); - - pthread_cleanup_push( prvDeleteThread, (void *)pthread_self() ); - - if ( 0 == pthread_mutex_lock( &xRunningThreadMutex ) ) - { - xSentinel=1; - - sigemptyset( &xSignals ); - sigaddset( &xSignals, SIG_RESUME ); - /* set up proc mask */ - pthread_sigmask(SIG_SETMASK,&xSignals,NULL); - - prvSuspendSignalHandler(SIG_SUSPEND); - //prvSuspendThread( pthread_self() ); - } else { - debug_printf("now this is just WRONG!\n"); - exit(1); - } - - pvCode( pParams ); - - pthread_cleanup_pop( 1 ); - return (void *)NULL; -} -/*-----------------------------------------------------------*/ - -void prvSuspendSignalHandler(int sig) -{ -sigset_t xSignals; -//sigset_t xPendingSignals; - - /* Only interested in the resume signal. */ - sigemptyset( &xSignals ); - sigaddset( &xSignals, SIG_RESUME ); - sigaddset( &xSignals, SIG_SUSPEND ); - - /* Unlock the Running thread mutex to allow the resumed task to continue. */ - if ( 0 != pthread_mutex_unlock( &xRunningThreadMutex ) ) - { - printf( "Releasing someone else's lock.\n" ); - } - - //debug_printf("SUSPENDING until SIG_RESUME received\n"); - /* Wait on the resume signal. */ - while (hRequestedThread != pthread_self()) { - if ( 0 != sigwait( &xSignals, &sig ) ) - { - printf( "SSH: Sw %d\n", sig ); - /* tricky one - shouldn't ever happen - trying to resolve situation as graceful as possible */ - debug_printf("ALERT AAAAH PANIC! - sigwait failed.....\n\n\n"); - /* Signal main thread something just went HORRIBLY wrong */ - xGeneralFuckedUpIndicator = 2; - //(void)pthread_mutex_lock( &xRunningThreadMutex ); - //(void)pthread_kill( pthread_self(), SIG_SUSPEND ); - //return; - } else if (sig == SIG_RESUME) { - //debug_printf("received signal %i\n",sig); - /* Make sure the right thread received the signal */ - if (hRequestedThread != pthread_self() ) { - debug_printf( "ALERT! Received SIG_RESUME which is already outdated!\n active thread is %li\n",(long)hRequestedThread); - /* Signal main thread something just went wrong */ - xGeneralFuckedUpIndicator = 1; - /* - if (0 == sigpending(&xPendingSignals)) { - if (sigismember(&xPendingSignals,SIG_SUSPEND)) { - debug_printf( "reason: we slept too long...\n"); - //(void)sigwait(&xPendingSignals,&sig); - // we can safely return - signal is already pending - return; - } - } - debug_printf( "reason: unknown! - whatever ...\n\n"); - */ - //exit(1); - //(void)pthread_kill( xTaskToResume, SIG_RESUME ); - //(void)pthread_mutex_lock( &xRunningThreadMutex ); - //(void)pthread_kill( pthread_self(), SIG_SUSPEND ); - //return; - } - } - } - /* Yield the Scheduler to ensure that the yielding thread completes. */ - if ( 0 != pthread_mutex_lock( &xRunningThreadMutex ) ) - { - //(void)pthread_mutex_unlock( &xSingleThreadMutex ); - debug_printf("critical - mutex acquiring of active thread failed!\n"); - exit(1); - } - hActiveThread = pthread_self(); - - /* 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(); - } - if (hRequestedThread==pthread_self()) { - /* doesn't look too bad, does it? */ - xGeneralFuckedUpIndicator = 0; - } - //debug_printf("ACTIVE THREAD!\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, sigresume, sigtick; -portLONG lIndex; - - 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 ); - - sigresume.sa_flags = 0; - //sigresume.sa_handler = prvResumeSignalHandler; - sigresume.sa_handler = SIG_IGN; - sigfillset( &sigresume.sa_mask ); - - sigtick.sa_flags = 0; - //sigtick.sa_handler = vPortSystemTickHandler; - sigtick.sa_handler = SIG_IGN; - sigfillset( &sigtick.sa_mask ); - - if ( 0 != sigaction( SIG_SUSPEND, &sigsuspendself, NULL ) ) - { - printf( "Problem installing SIG_SUSPEND_SELF\n" ); - } - //if ( 0 != sigaction( SIG_RESUME, &sigresume, NULL ) ) - //{ - // printf( "Problem installing SIG_RESUME\n" ); - //} - if ( 0 != sigaction( SIG_TICK, &sigtick, NULL ) ) - { - printf( "Problem installing SIG_TICK\n" ); - } - printf( "Running as PID: %d\n", getpid() ); -} -/*-----------------------------------------------------------*/ - -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; - - 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; - } - } - } -} -/*-----------------------------------------------------------*/ - -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; -} -/*-----------------------------------------------------------*/ -/** - * Scheduler f***d up - we got to fix that - */ -void prvResolveFuckup( void ) -{ - - printf("Scheduler fucked up again - lets try to fix it...\n"); - printf("sending sig_suspend to thread that is supposed to be dead...\n"); - prvSuspendThread(hActiveThread); - printf("acquire running lock..."); - if ( 0 == pthread_mutex_lock( &xRunningThreadMutex) ) { - printf("sending sig_resume to thread that is supposed to be running...\n"); - prvResumeThread(hRequestedThread); - printf("giving up mutex...\n"); - (void)pthread_mutex_unlock(&xRunningThreadMutex); - } - -} -/*-----------------------------------------------------------*/ diff --git a/flight/PiOS.posix/posix/Libraries/FreeRTOS/Source/portable/GCC/Posix/corvuscorax/port_test-for-macos.c b/flight/PiOS.posix/posix/Libraries/FreeRTOS/Source/portable/GCC/Posix/corvuscorax/port_test-for-macos.c deleted file mode 100644 index 81af9bcec..000000000 --- a/flight/PiOS.posix/posix/Libraries/FreeRTOS/Source/portable/GCC/Posix/corvuscorax/port_test-for-macos.c +++ /dev/null @@ -1,1026 +0,0 @@ -/* - 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 -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -/* Scheduler includes. */ -#include "FreeRTOS.h" -#include "task.h" -/*-----------------------------------------------------------*/ - -#define MAX_NUMBER_OF_TASKS ( _POSIX_THREAD_THREADS_MAX ) -/*-----------------------------------------------------------*/ - -/* 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; - xTaskHandle hTask; - unsigned portBASE_TYPE uxCriticalNesting; -} xThreadState; -/*-----------------------------------------------------------*/ - -static xThreadState *pxThreads; -static pthread_once_t hSigSetupThread = PTHREAD_ONCE_INIT; -static pthread_attr_t xThreadAttributes; -static pthread_mutex_t xSuspendResumeThreadMutex = PTHREAD_MUTEX_INITIALIZER; -//static pthread_mutex_t xSingleThreadMutex = PTHREAD_MUTEX_INITIALIZER; -static pthread_mutex_t xRunningThreadMutex = PTHREAD_MUTEX_INITIALIZER; -static pthread_mutex_t xPrintfMutex = PTHREAD_MUTEX_INITIALIZER; -static pthread_t hMainThread = ( pthread_t )NULL; -static pthread_t hActiveThread = ( pthread_t )NULL; -static pthread_t hRequestedThread = ( pthread_t )NULL; -/*-----------------------------------------------------------*/ - -static volatile portBASE_TYPE xSentinel = 0; -static volatile portBASE_TYPE xGeneralFuckedUpIndicator = 0; -static volatile portBASE_TYPE xVeryFirstTask = 1; -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 prvSetupTimerInterrupt( void ); -static void *prvWaitForStart( void * pvParams ); -static void prvSuspendSignalHandler(int sig); -//static void prvResumeSignalHandler(int sig); -static void prvSetupSignalsAndSchedulerPolicy( void ); -static void prvSuspendThread( pthread_t xThreadId ); -static void prvResumeThread( pthread_t xThreadId ); -static pthread_t prvGetThreadHandle( xTaskHandle hTask ); -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 ); -/*-----------------------------------------------------------*/ -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; -tskTCB* prvGetTaskHandle( pthread_t hThread ) -{ -portLONG lIndex; - - if (pxThreads==NULL) return NULL; - - for ( lIndex = 0; lIndex < MAX_NUMBER_OF_TASKS; lIndex++ ) - { - if ( pxThreads[ lIndex ].hThread == hThread ) - { - return pxThreads[ lIndex ].hTask; - } - } - return NULL; -} - - -#define debug_printf(...) ( (real_pthread_mutex_lock( &xPrintfMutex )|1)?( \ - ( \ - (NULL != (debug_task_handle = prvGetTaskHandle(pthread_self())) )? \ - (fprintf( stderr, "%s(%li)\t%s\t%i:",debug_task_handle->pcTaskName,(long)pthread_self(),__func__,__LINE__)): \ - (fprintf( stderr, "__unknown__(%li)\t%s\t%i:",(long)pthread_self(),__func__,__LINE__)) \ - |1)?( \ - ((fprintf( stderr, __VA_ARGS__ )|1)?real_pthread_mutex_unlock( &xPrintfMutex ):0) \ - ):0 ):0 ) - -//int xbla; -//#define debug_printf(...) xbla=0 -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 vTaskSwitchContext() ( (debug_printf("SWITCHCONTEXT!\n")|1)?vTaskSwitchContext():vTaskSwitchContext() ) -/*-----------------------------------------------------------*/ - -void prvSuspendThread( pthread_t xThreadId ) -{ -portBASE_TYPE xResult; -// xResult = pthread_mutex_lock( &xSuspendResumeThreadMutex ); -// if ( 0 == xResult ) -// { - /* Set-up for the Suspend Signal handler? */ - //xSentinel = 0; -//portBASE_TYPE aSentinel=xSentinel; - xResult = pthread_kill( xThreadId, SIG_SUSPEND ); -// xResult = pthread_mutex_unlock( &xSuspendResumeThreadMutex ); -// while ( ( aSentinel == xSentinel ) && ( pdTRUE != xServicingTick ) ) -// { -// sched_yield(); -// } -// } -} -/*-----------------------------------------------------------*/ - -void prvResumeThread( pthread_t xThreadId ) -{ -portBASE_TYPE xResult; -// if ( 0 == pthread_mutex_lock( &xSuspendResumeThreadMutex ) ) -// { - if ( pthread_self() != xThreadId ) - { - xResult = pthread_kill( xThreadId, SIG_RESUME ); - } -// xResult = pthread_mutex_unlock( &xSuspendResumeThreadMutex ); -// } -} -#define prvSuspendThread(thread) debug_printf("calling SuspendThread(%li)\n",(long)thread); prvSuspendThread(thread) -#define prvResumeThread(thread) debug_printf("calling ResumeThread(%li)\n",(long)thread); prvResumeThread(thread) - -/* - * Exception handlers. - */ -void vPortYield( void ); -void vPortSystemTickHandler( int sig ); - -/* - * Start first task is a separate function so it can be tested in isolation. - */ -void vPortStartFirstTask( void ); -/*-----------------------------------------------------------*/ - -/* - * 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 ) ); - - (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(); - if ( 0 == pthread_mutex_lock( &xSuspendResumeThreadMutex ) ) { - while (hActiveThread!=hRequestedThread && !xVeryFirstTask) { - (void)pthread_mutex_unlock( &xSuspendResumeThreadMutex ); - sched_yield(); - (void)pthread_mutex_lock( &xSuspendResumeThreadMutex ); - } - - - lIndexOfLastAddedTask = prvGetFreeThreadState(); - - /* Create the new pThread. */ - /* On creation of the very first thread, RunningThreadMutex is not claimed yet - * by the master thread - do that! */ - if (xVeryFirstTask==1) { - debug_printf("Seting up very first task (main) - MAIN is ACTIVE TASK\n"); - if (0 == pthread_mutex_lock( &xRunningThreadMutex)) { - xVeryFirstTask=0; - hActiveThread=pthread_self(); - hRequestedThread=hActiveThread; - } else { - printf("Failed to acquire lock for first task"); - exit(1); - } - - } - - if ( 0 != pthread_create( &( pxThreads[ lIndexOfLastAddedTask ].hThread ), &xThreadAttributes, prvWaitForStart, (void *)pxThisThreadParams ) ) - { - /* Thread create failed, signal the failure */ - pxTopOfStack = 0; - } - - /* Wait until the task suspends. */ - xSentinel=0; - (void)pthread_mutex_unlock( &xRunningThreadMutex ); - while ( xSentinel == 0 ) { - sched_yield(); - } - (void)pthread_mutex_lock( &xRunningThreadMutex ); - hActiveThread=pthread_self(); - debug_printf("ACTIVE THREAD RECLAIMED!\n"); - (void)pthread_mutex_unlock( &xSuspendResumeThreadMutex ); - } else { - debug_printf("mutex locking failed\n"); - exit(1); - } - vPortExitCritical(); - - return pxTopOfStack; -} -/*-----------------------------------------------------------*/ - -void vPortStartFirstTask( void ) -{ - /* Initialise the critical nesting count ready for the first task. */ - uxCriticalNesting = 0; - - /* Start the first task. */ - vPortEnableInterrupts(); - - /* Start the first task. */ - hRequestedThread=prvGetThreadHandle( xTaskGetCurrentTaskHandle()); - prvResumeThread( hRequestedThread ); - - sched_yield(); -} -/*-----------------------------------------------------------*/ - -/* - * See header file for description. - */ -portBASE_TYPE xPortStartScheduler( void ) -{ -portBASE_TYPE xResult; -int iSignal; -sigset_t xSignals; -sigset_t xSignalToBlock; -sigset_t xSignalsBlocked; -portLONG lIndex; - - /* Establish the signals to block before they are needed. */ - sigfillset( &xSignalToBlock ); - - /* Block until the end */ - (void)pthread_sigmask( SIG_SETMASK, &xSignalToBlock, &xSignalsBlocked ); - - for ( lIndex = 0; lIndex < MAX_NUMBER_OF_TASKS; lIndex++ ) - { - pxThreads[ lIndex ].uxCriticalNesting = 0; - } - - /* Start the timer that generates the tick ISR. Interrupts are disabled - here already. */ - prvSetupTimerInterrupt(); - - /* Start the first task. Will not return unless all threads are killed. */ - vPortStartFirstTask(); - - /* This is the end signal we are looking for. */ - sigemptyset( &xSignals ); - sigaddset( &xSignals, SIG_RESUME ); - sigaddset( &xSignals, SIG_TICK ); - - /* Allow other threads to run */ - (void)pthread_mutex_unlock( &xRunningThreadMutex ); - debug_printf( "MAIN thread is entering main signal wait loop!\n"); - - while ( pdTRUE != xSchedulerEnd ) - { - if ( 0 != sigwait( &xSignals, &iSignal ) ) - { - printf( "Main thread spurious signal: %d\n", iSignal ); - } - /** - * Tick handler is called from here - AND ONLY FROM HERE - * (needed for cygwin - but should work on all) - */ - if (iSignal==SIG_TICK) { - vPortSystemTickHandler(iSignal); - } - if (iSignal==SIG_RESUME && pdTRUE != xSchedulerEnd) { - debug_printf("main: forwarding signal to %li\n",(long)hRequestedThread); - (void)pthread_kill( hRequestedThread, SIG_RESUME ); - } - } - - printf( "Cleaning Up, Exiting.\n" ); - /* Cleanup the mutexes */ - //xResult = pthread_mutex_destroy( &xSuspendResumeThreadMutex ); - //xResult = pthread_mutex_destroy( &xSingleThreadMutex ); - xResult = pthread_mutex_destroy( &xRunningThreadMutex ); - 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 - * xSingleThreadMutex 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; - - /** - * Sentinel - do not change context while the running task is not equal the task supposed to run - */ - if ( 0 == pthread_mutex_lock( &xSuspendResumeThreadMutex ) ) - { - /** - * Make sure we don't create outdated resume signals - */ - while (hActiveThread!=hRequestedThread) { - (void)pthread_mutex_unlock( &xSuspendResumeThreadMutex ); - sched_yield(); - (void)pthread_mutex_lock( &xSuspendResumeThreadMutex ); - } - xTaskToSuspend = prvGetThreadHandle( xTaskGetCurrentTaskHandle() ); - - vTaskSwitchContext(); - - xTaskToResume = prvGetThreadHandle( xTaskGetCurrentTaskHandle() ); - if ( xTaskToSuspend != xTaskToResume ) - { - /* Remember and switch the critical nesting. */ - prvSetTaskCriticalNesting( xTaskToSuspend, uxCriticalNesting ); - uxCriticalNesting = prvGetTaskCriticalNesting( xTaskToResume ); - /* Switch tasks. */ - hRequestedThread = xTaskToResume; - prvResumeThread( xTaskToResume ); - //prvSuspendThread( xTaskToSuspend ); -if (prvGetThreadHandle(xTaskGetCurrentTaskHandle())!=xTaskToResume) { - debug_printf("\n what the fuck???? someone else did a switchcontext?!?\n"); -} - (void)pthread_mutex_unlock( &xSuspendResumeThreadMutex ); - prvSuspendSignalHandler(SIG_SUSPEND); - return; - } - else - { - /* Yielding to self */ - (void)pthread_mutex_unlock( &xSuspendResumeThreadMutex ); - } - } -} -/*-----------------------------------------------------------*/ - -void vPortDisableInterrupts( void ) -{ - xInterruptsEnabled = pdFALSE; -} -/*-----------------------------------------------------------*/ - -void vPortEnableInterrupts( void ) -{ - xInterruptsEnabled = pdTRUE; -} -/*-----------------------------------------------------------*/ - -portBASE_TYPE xPortSetInterruptMask( void ) -{ -portBASE_TYPE xReturn = xInterruptsEnabled; - xInterruptsEnabled = pdFALSE; - return xReturn; -} -/*-----------------------------------------------------------*/ - -void vPortClearInterruptMask( portBASE_TYPE xMask ) -{ - xInterruptsEnabled = xMask; -} -/*-----------------------------------------------------------*/ - -/* - * Setup the systick timer to generate the tick interrupts at the required - * frequency. - */ -void prvSetupTimerInterrupt( void ) -{ -struct itimerval itimer, oitimer; -portTickType xMicroSeconds = portTICK_RATE_MICROSECONDS; - - debug_printf("init %li microseconds\n",(long)xMicroSeconds); - /* Initialise the structure with the current timer information. */ - if ( 0 == getitimer( TIMER_TYPE, &itimer ) ) - { - /* Set the interval between timer events. */ - itimer.it_interval.tv_sec = 0; - itimer.it_interval.tv_usec = xMicroSeconds; - - /* Set the current count-down. */ - itimer.it_value.tv_sec = 0; - itimer.it_value.tv_usec = xMicroSeconds; - - /* Set-up the timer interrupt. */ - if ( 0 != setitimer( TIMER_TYPE, &itimer, &oitimer ) ) - { - printf( "Set Timer problem.\n" ); - } - } - else - { - printf( "Get Timer problem.\n" ); - } -} -/*-----------------------------------------------------------*/ - -void vPortSystemTickHandler( int sig ) -{ -pthread_t xTaskToSuspend; -pthread_t xTaskToResume; -struct timespec timeout; - - //debug_printf("received %i\n",sig); - /** - * do not call tick handler if - * - interrupts are disabled - * - tick handler is still running - * - old task switch not yet completed (wrong task running) - */ - if ( ( pdTRUE == xInterruptsEnabled ) && ( pdTRUE != xServicingTick ) && ( hRequestedThread == hActiveThread ) ) - { - xServicingTick = pdTRUE; - if ( 0 == pthread_mutex_trylock( &xSuspendResumeThreadMutex ) ) - { - debug_printf("does handle tick\n"); - - /** - * this shouldn't ever happen - but WELL... - * Make sure we don't create outdated resume signals - */ - if (hActiveThread!=hRequestedThread) { - xServicingTick = pdFALSE; - xPendYield = pdTRUE; - (void)pthread_mutex_unlock( &xSuspendResumeThreadMutex ); - return; - } - - xTaskToSuspend = prvGetThreadHandle( xTaskGetCurrentTaskHandle() ); - /* Tick Increment. */ - vTaskIncrementTick(); - - /* Select Next Task. */ -#if ( configUSE_PREEMPTION == 1 ) - vTaskSwitchContext(); -#endif - xTaskToResume = prvGetThreadHandle( xTaskGetCurrentTaskHandle() ); - //hRequestedThread = xTaskToResume; - - /* The only thread that can process this tick is the running thread. */ - if ( xTaskToSuspend != xTaskToResume ) - { - /* Suspend the current task. */ - hRequestedThread = 0; - prvSuspendThread( xTaskToSuspend ); - timeout.tv_sec=0; - timeout.tv_nsec=10000; - /*while ( 0 != pthread_mutex_timedlock( &xRunningThreadMutex,&timeout ) ) { - prvSuspendThread( xTaskToSuspend ); - timeout.tv_sec=0; - timeout.tv_nsec=10000; - } - */ - if ( 0 != pthread_mutex_lock( &xRunningThreadMutex)) { - debug_printf("mutex lock failed!\n"); - exit(1); - } - //if ( 0 == pthread_mutex_lock( &xRunningThreadMutex) ) { - /* Remember and switch the critical nesting. */ - prvSetTaskCriticalNesting( xTaskToSuspend, uxCriticalNesting ); - uxCriticalNesting = prvGetTaskCriticalNesting( xTaskToResume ); - /* Resume next task. */ - hRequestedThread = xTaskToResume; - prvResumeThread( xTaskToResume ); -if (prvGetThreadHandle(xTaskGetCurrentTaskHandle())!=xTaskToResume) { -debug_printf("\n what the fuck???? someone else did a switchcontext?!?\n"); -} - (void)pthread_mutex_unlock( &xRunningThreadMutex ); - } - else - { - /* Release the lock as we are Resuming. */ - // (void)pthread_mutex_unlock( &xSingleThreadMutex ); - } - } - else - { - xPendYield = pdTRUE; - } - (void)pthread_mutex_unlock( &xSuspendResumeThreadMutex ); - xServicingTick = pdFALSE; - } - else - { - debug_printf("will NOT handle tick\n"); - xPendYield = pdTRUE; - } -} -/*-----------------------------------------------------------*/ - -void vPortForciblyEndThread( void *pxTaskToDelete ) -{ -xTaskHandle hTaskToDelete = ( xTaskHandle )pxTaskToDelete; -pthread_t xTaskToDelete; -pthread_t xTaskToResume; -portBASE_TYPE xResult; - -// if ( 0 == pthread_mutex_lock( &xSingleThreadMutex ) ) -// { - xTaskToDelete = prvGetThreadHandle( hTaskToDelete ); - xTaskToResume = prvGetThreadHandle( xTaskGetCurrentTaskHandle() ); - - if ( xTaskToResume == xTaskToDelete ) - { - if ( 0 == pthread_mutex_lock( &xSuspendResumeThreadMutex ) ) { - /** - * Make sure we don't create outdated resume signals - */ - while (hActiveThread!=hRequestedThread) { - (void)pthread_mutex_unlock( &xSuspendResumeThreadMutex ); - sched_yield(); - (void)pthread_mutex_lock( &xSuspendResumeThreadMutex ); - } - /* This is a suicidal thread, need to select a different task to run. */ - vTaskSwitchContext(); - xTaskToResume = prvGetThreadHandle( xTaskGetCurrentTaskHandle() ); - hRequestedThread = xTaskToResume; - (void)pthread_mutex_unlock( &xSuspendResumeThreadMutex ); - } else { - debug_printf("mutex lock failed!\n"); - exit(1); - } - } - - 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( &xSingleThreadMutex ); - } - else - { - /* Resume the other thread. */ - prvResumeThread( xTaskToResume ); - /* Pthread Clean-up function will note the cancellation. */ - /* Release the execution. */ - uxCriticalNesting = 0; - vPortEnableInterrupts(); -// (void)pthread_mutex_unlock( &xSingleThreadMutex ); - (void)pthread_mutex_unlock( &xRunningThreadMutex ); - /* Commit suicide */ - pthread_exit( (void *)1 ); - } -// } -} -/*-----------------------------------------------------------*/ - -void *prvWaitForStart( void * pvParams ) -{ -xParams * pxParams = ( xParams * )pvParams; -pdTASK_CODE pvCode = pxParams->pxCode; -void * pParams = pxParams->pvParams; -sigset_t xSignals; - vPortFree( pvParams ); - - pthread_cleanup_push( prvDeleteThread, (void *)pthread_self() ); - - if ( 0 == pthread_mutex_lock( &xRunningThreadMutex ) ) - { - xSentinel=1; - hActiveThread=pthread_self(); - debug_printf("temporarily made ACTIVE THREAD!\n"); - - sigemptyset( &xSignals ); - sigaddset( &xSignals, SIG_RESUME ); - /* set up proc mask */ - pthread_sigmask(SIG_SETMASK,&xSignals,NULL); - - prvSuspendSignalHandler(SIG_SUSPEND); - //prvSuspendThread( pthread_self() ); - } else { - debug_printf("now this is just WRONG!\n"); - exit(1); - } - - pvCode( pParams ); - - pthread_cleanup_pop( 1 ); - return (void *)NULL; -} -/*-----------------------------------------------------------*/ - -void prvSuspendSignalHandler(int sig) -{ -sigset_t xSignals; -//sigset_t xPendingSignals; - - /* Only interested in the resume signal. */ - sigemptyset( &xSignals ); - sigaddset( &xSignals, SIG_RESUME ); - sigaddset( &xSignals, SIG_SUSPEND ); - - /* Unlock the Running thread mutex to allow the resumed task to continue. */ - if ( 0 != pthread_mutex_unlock( &xRunningThreadMutex ) ) - { - printf( "Releasing someone else's lock.\n" ); - } - - debug_printf("SUSPENDING until SIG_RESUME received\n"); - /* Wait on the resume signal. */ - while (hRequestedThread != pthread_self()) { - if ( 0 != sigwait( &xSignals, &sig ) ) - { - printf( "SSH: Sw %d\n", sig ); - /* tricky one - shouldn't ever happen - trying to resolve situation as graceful as possible */ - debug_printf("ALERT AAAAH PANIC! - sigwait failed.....\n\n\n"); - /* Signal main thread something just went HORRIBLY wrong */ - xGeneralFuckedUpIndicator = 2; - //(void)pthread_mutex_lock( &xRunningThreadMutex ); - //(void)pthread_kill( pthread_self(), SIG_SUSPEND ); - //return; - } else if (sig == SIG_RESUME) { - //debug_printf("received signal %i\n",sig); - /* Make sure the right thread received the signal */ - if (hRequestedThread != pthread_self() ) { - debug_printf( "resume_signalhandler: forwarding to %li\n",(long)hRequestedThread); - (void)pthread_kill( hRequestedThread, SIG_RESUME ); - } - } - } - /* Yield the Scheduler to ensure that the yielding thread completes. */ - if ( 0 != pthread_mutex_lock( &xRunningThreadMutex ) ) - { - //(void)pthread_mutex_unlock( &xSingleThreadMutex ); - debug_printf("critical - mutex acquiring of active thread failed!\n"); - exit(1); - } - hActiveThread = pthread_self(); - - /* 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(); - } - if (hRequestedThread==pthread_self()) { - /* doesn't look too bad, does it? */ - xGeneralFuckedUpIndicator = 0; - } - debug_printf("ACTIVE THREAD!\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, sigresume, sigtick; -portLONG lIndex; - - 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 ); - - sigresume.sa_flags = 0; - //sigresume.sa_handler = prvResumeSignalHandler; - sigresume.sa_handler = SIG_IGN; - sigfillset( &sigresume.sa_mask ); - - sigtick.sa_flags = 0; - //sigtick.sa_handler = vPortSystemTickHandler; - sigtick.sa_handler = SIG_IGN; - sigfillset( &sigtick.sa_mask ); - - if ( 0 != sigaction( SIG_SUSPEND, &sigsuspendself, NULL ) ) - { - printf( "Problem installing SIG_SUSPEND_SELF\n" ); - } - //if ( 0 != sigaction( SIG_RESUME, &sigresume, NULL ) ) - //{ - // printf( "Problem installing SIG_RESUME\n" ); - //} - if ( 0 != sigaction( SIG_TICK, &sigtick, NULL ) ) - { - printf( "Problem installing SIG_TICK\n" ); - } - printf( "Running as PID: %d\n", getpid() ); -} -/*-----------------------------------------------------------*/ - -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; - - 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; - } - } - } -} -/*-----------------------------------------------------------*/ - -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; -} -/*-----------------------------------------------------------*/ diff --git a/flight/PiOS.posix/posix/Libraries/FreeRTOS/Source/portable/GCC/Posix/corvuscorax/port_with-debugging-output.c b/flight/PiOS.posix/posix/Libraries/FreeRTOS/Source/portable/GCC/Posix/corvuscorax/port_with-debugging-output.c deleted file mode 100755 index a9679b712..000000000 --- a/flight/PiOS.posix/posix/Libraries/FreeRTOS/Source/portable/GCC/Posix/corvuscorax/port_with-debugging-output.c +++ /dev/null @@ -1,1097 +0,0 @@ -/* - 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 -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -/* Scheduler includes. */ -#include "FreeRTOS.h" -#include "task.h" -/*-----------------------------------------------------------*/ - -#define MAX_NUMBER_OF_TASKS ( _POSIX_THREAD_THREADS_MAX ) -/*-----------------------------------------------------------*/ - -/* 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; - xTaskHandle hTask; - unsigned portBASE_TYPE uxCriticalNesting; -} xThreadState; -/*-----------------------------------------------------------*/ - -static xThreadState *pxThreads; -static pthread_once_t hSigSetupThread = PTHREAD_ONCE_INIT; -static pthread_attr_t xThreadAttributes; -static pthread_mutex_t xSuspendResumeThreadMutex = PTHREAD_MUTEX_INITIALIZER; -//static pthread_mutex_t xSingleThreadMutex = PTHREAD_MUTEX_INITIALIZER; -static pthread_mutex_t xRunningThreadMutex = PTHREAD_MUTEX_INITIALIZER; -static pthread_mutex_t xPrintfMutex = PTHREAD_MUTEX_INITIALIZER; -static pthread_t hMainThread = ( pthread_t )NULL; -static pthread_t hActiveThread = ( pthread_t )NULL; -static pthread_t hRequestedThread = ( pthread_t )NULL; -/*-----------------------------------------------------------*/ - -static volatile portBASE_TYPE xSentinel = 0; -static volatile portBASE_TYPE xGeneralFuckedUpIndicator = 0; -static volatile portBASE_TYPE xVeryFirstTask = 1; -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 prvSetupTimerInterrupt( void ); -static void *prvWaitForStart( void * pvParams ); -static void prvSuspendSignalHandler(int sig); -//static void prvResumeSignalHandler(int sig); -static void prvSetupSignalsAndSchedulerPolicy( void ); -static void prvSuspendThread( pthread_t xThreadId ); -static void prvResumeThread( pthread_t xThreadId ); -static pthread_t prvGetThreadHandle( xTaskHandle hTask ); -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 ); -static void prvResolveFuckup( 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; -tskTCB* prvGetTaskHandle( pthread_t hThread ) -{ -portLONG lIndex; - - if (pxThreads==NULL) return NULL; - - for ( lIndex = 0; lIndex < MAX_NUMBER_OF_TASKS; lIndex++ ) - { - if ( pxThreads[ lIndex ].hThread == hThread ) - { - return pxThreads[ lIndex ].hTask; - } - } - return NULL; -} - - -#define debug_printf(...) ( (real_pthread_mutex_lock( &xPrintfMutex )|1)?( \ - ( \ - (NULL != (debug_task_handle = prvGetTaskHandle(pthread_self())) )? \ - (fprintf( stderr, "%s(%li)\t%s\t%i:",debug_task_handle->pcTaskName,(long)pthread_self(),__func__,__LINE__)): \ - (fprintf( stderr, "__unknown__(%li)\t%s\t%i:",(long)pthread_self(),__func__,__LINE__)) \ - |1)?( \ - ((fprintf( stderr, __VA_ARGS__ )|1)?real_pthread_mutex_unlock( &xPrintfMutex ):0) \ - ):0 ):0 ) - -//int xbla; -//#define debug_printf(...) xbla=0 -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_mutex_trylock(...) ( pthread_mutex_trylock(__VA_ARGS__)==0?((debug_printf(" -:)- pthread_mutex_trylock(%s) success\n",#__VA_ARGS__)|1)?0:0):-1) -#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 vTaskSwitchContext() ( (debug_printf("SWITCHCONTEXT!\n")|1)?vTaskSwitchContext():vTaskSwitchContext() ) -/*-----------------------------------------------------------*/ - -void prvSuspendThread( pthread_t xThreadId ) -{ -portBASE_TYPE xResult; -// xResult = pthread_mutex_lock( &xSuspendResumeThreadMutex ); -// if ( 0 == xResult ) -// { - /* Set-up for the Suspend Signal handler? */ - //xSentinel = 0; -//portBASE_TYPE aSentinel=xSentinel; - xResult = pthread_kill( xThreadId, SIG_SUSPEND ); -// xResult = pthread_mutex_unlock( &xSuspendResumeThreadMutex ); -// while ( ( aSentinel == xSentinel ) && ( pdTRUE != xServicingTick ) ) -// { -// sched_yield(); -// } -// } -} -/*-----------------------------------------------------------*/ - -void prvResumeThread( pthread_t xThreadId ) -{ -portBASE_TYPE xResult; -// if ( 0 == pthread_mutex_lock( &xSuspendResumeThreadMutex ) ) -// { - if ( pthread_self() != xThreadId ) - { - xResult = pthread_kill( xThreadId, SIG_RESUME ); - } -// xResult = pthread_mutex_unlock( &xSuspendResumeThreadMutex ); -// } -} -#define prvSuspendThread(thread) debug_printf("calling SuspendThread(%li)\n",(long)thread); prvSuspendThread(thread) -#define prvResumeThread(thread) debug_printf("calling ResumeThread(%li)\n",(long)thread); prvResumeThread(thread) - -/* - * Exception handlers. - */ -void vPortYield( void ); -void vPortSystemTickHandler( int sig ); - -/* - * Start first task is a separate function so it can be tested in isolation. - */ -void vPortStartFirstTask( void ); -/*-----------------------------------------------------------*/ - -/* - * 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 ) ); - - (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(); - if ( 0 == pthread_mutex_lock( &xSuspendResumeThreadMutex ) ) { - while (hActiveThread!=hRequestedThread && !xVeryFirstTask) { - (void)pthread_mutex_unlock( &xSuspendResumeThreadMutex ); - sched_yield(); - (void)pthread_mutex_lock( &xSuspendResumeThreadMutex ); - } - - - lIndexOfLastAddedTask = prvGetFreeThreadState(); - - /* Create the new pThread. */ - /* On creation of the very first thread, RunningThreadMutex is not claimed yet - * by the master thread - do that! */ - if (xVeryFirstTask==1) { - debug_printf("Seting up very first task (main) - MAIN is ACTIVE TASK\n"); - if (0 == pthread_mutex_lock( &xRunningThreadMutex)) { - xVeryFirstTask=0; - hActiveThread=pthread_self(); - hRequestedThread=hActiveThread; - } else { - printf("Failed to acquire lock for first task"); - exit(1); - } - - } - - if ( 0 != pthread_create( &( pxThreads[ lIndexOfLastAddedTask ].hThread ), &xThreadAttributes, prvWaitForStart, (void *)pxThisThreadParams ) ) - { - /* Thread create failed, signal the failure */ - pxTopOfStack = 0; - } - - /* Wait until the task suspends. */ - xSentinel=0; - (void)pthread_mutex_unlock( &xRunningThreadMutex ); - while ( xSentinel == 0 ) { - sched_yield(); - } - (void)pthread_mutex_lock( &xRunningThreadMutex ); - hActiveThread=pthread_self(); - debug_printf("ACTIVE THREAD RECLAIMED!\n"); - (void)pthread_mutex_unlock( &xSuspendResumeThreadMutex ); - } else { - debug_printf("mutex locking failed\n"); - exit(1); - } - vPortExitCritical(); - - return pxTopOfStack; -} -/*-----------------------------------------------------------*/ - -void vPortStartFirstTask( void ) -{ - /* Initialise the critical nesting count ready for the first task. */ - uxCriticalNesting = 0; - - /* Start the first task. */ - vPortEnableInterrupts(); - - /* Start the first task. */ - hRequestedThread=prvGetThreadHandle( xTaskGetCurrentTaskHandle()); - prvResumeThread( hRequestedThread ); - - sched_yield(); -} -/*-----------------------------------------------------------*/ - -/* - * See header file for description. - */ -portBASE_TYPE xPortStartScheduler( void ) -{ -portBASE_TYPE xResult; -int iSignal; -int fuckedUpCount=0; -sigset_t xSignals; -sigset_t xSignalToBlock; -sigset_t xSignalsBlocked; -portLONG lIndex; - - /* Establish the signals to block before they are needed. */ - sigfillset( &xSignalToBlock ); - - /* Block until the end */ - (void)pthread_sigmask( SIG_SETMASK, &xSignalToBlock, &xSignalsBlocked ); - - for ( lIndex = 0; lIndex < MAX_NUMBER_OF_TASKS; lIndex++ ) - { - pxThreads[ lIndex ].uxCriticalNesting = 0; - } - - /* Start the timer that generates the tick ISR. Interrupts are disabled - here already. */ - prvSetupTimerInterrupt(); - - /* Start the first task. Will not return unless all threads are killed. */ - vPortStartFirstTask(); - - /* This is the end signal we are looking for. */ - sigemptyset( &xSignals ); - sigaddset( &xSignals, SIG_RESUME ); - sigaddset( &xSignals, SIG_TICK ); - - /* Allow other threads to run */ - (void)pthread_mutex_unlock( &xRunningThreadMutex ); - debug_printf( "MAIN thread is entering main signal wait loop!\n"); - - while ( pdTRUE != xSchedulerEnd ) - { - if ( 0 != sigwait( &xSignals, &iSignal ) ) - { - printf( "Main thread spurious signal: %d\n", iSignal ); - } - /** - * Tick handler is called from here - AND ONLY FROM HERE - * (needed for cygwin - but should work on all) - */ - if (iSignal==SIG_TICK) { - if (xGeneralFuckedUpIndicator!=0 && hActiveThread!=hRequestedThread) { - fuckedUpCount++; - if (fuckedUpCount>10) { - fuckedUpCount=0; - prvResolveFuckup(); - } - } else { - fuckedUpCount=0; - } - vPortSystemTickHandler(iSignal); - } - if (iSignal==SIG_RESUME && pdTRUE != xSchedulerEnd) { - debug_printf( "ALERT! Main received SIG_RESUME that was supposed to go elsewhere!"); - } - } - - printf( "Cleaning Up, Exiting.\n" ); - /* Cleanup the mutexes */ - //xResult = pthread_mutex_destroy( &xSuspendResumeThreadMutex ); - //xResult = pthread_mutex_destroy( &xSingleThreadMutex ); - xResult = pthread_mutex_destroy( &xRunningThreadMutex ); - 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 - * xSingleThreadMutex 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; - - /** - * Sentinel - do not change context while the running task is not equal the task supposed to run - */ -// if ( 0 == pthread_mutex_lock( &xSuspendResumeThreadMutex ) ) - while ( 0 != pthread_mutex_trylock ( &xSuspendResumeThreadMutex ) ) { - sched_yield(); - } - - /** - * Make sure we don't create outdated resume signals - */ - while (hActiveThread!=hRequestedThread) { - (void)pthread_mutex_unlock( &xSuspendResumeThreadMutex ); - sched_yield(); - while (0 != pthread_mutex_trylock( &xSuspendResumeThreadMutex )) { - sched_yield(); - } - } - xTaskToSuspend = prvGetThreadHandle( xTaskGetCurrentTaskHandle() ); - - vTaskSwitchContext(); - - xTaskToResume = prvGetThreadHandle( xTaskGetCurrentTaskHandle() ); - if ( xTaskToSuspend != xTaskToResume ) - { - /* Remember and switch the critical nesting. */ - prvSetTaskCriticalNesting( xTaskToSuspend, uxCriticalNesting ); - uxCriticalNesting = prvGetTaskCriticalNesting( xTaskToResume ); - /* Switch tasks. */ - hRequestedThread = xTaskToResume; - prvResumeThread( xTaskToResume ); - //prvSuspendThread( xTaskToSuspend ); -if (prvGetThreadHandle(xTaskGetCurrentTaskHandle())!=xTaskToResume) { -debug_printf("\n what the fuck???? someone else did a switchcontext?!?\n"); -} - (void)pthread_mutex_unlock( &xSuspendResumeThreadMutex ); - prvSuspendSignalHandler(SIG_SUSPEND); - return; - } - else - { - /* Yielding to self */ - (void)pthread_mutex_unlock( &xSuspendResumeThreadMutex ); - } -} -/*-----------------------------------------------------------*/ - -void vPortDisableInterrupts( void ) -{ - xInterruptsEnabled = pdFALSE; -} -/*-----------------------------------------------------------*/ - -void vPortEnableInterrupts( void ) -{ - xInterruptsEnabled = pdTRUE; -} -/*-----------------------------------------------------------*/ - -portBASE_TYPE xPortSetInterruptMask( void ) -{ -portBASE_TYPE xReturn = xInterruptsEnabled; - xInterruptsEnabled = pdFALSE; - return xReturn; -} -/*-----------------------------------------------------------*/ - -void vPortClearInterruptMask( portBASE_TYPE xMask ) -{ - xInterruptsEnabled = xMask; -} -/*-----------------------------------------------------------*/ - -/* - * Setup the systick timer to generate the tick interrupts at the required - * frequency. - */ -void prvSetupTimerInterrupt( void ) -{ -struct itimerval itimer, oitimer; -portTickType xMicroSeconds = portTICK_RATE_MICROSECONDS; - - debug_printf("init %li microseconds\n",(long)xMicroSeconds); - /* Initialise the structure with the current timer information. */ - if ( 0 == getitimer( TIMER_TYPE, &itimer ) ) - { - /* Set the interval between timer events. */ - itimer.it_interval.tv_sec = 0; - itimer.it_interval.tv_usec = xMicroSeconds; - - /* Set the current count-down. */ - itimer.it_value.tv_sec = 0; - itimer.it_value.tv_usec = xMicroSeconds; - - /* Set-up the timer interrupt. */ - if ( 0 != setitimer( TIMER_TYPE, &itimer, &oitimer ) ) - { - printf( "Set Timer problem.\n" ); - } - } - else - { - printf( "Get Timer problem.\n" ); - } -} -/*-----------------------------------------------------------*/ - -void vPortSystemTickHandler( int sig ) -{ -pthread_t xTaskToSuspend; -pthread_t xTaskToResume; -struct timespec timeout; - - //debug_printf("received %i\n",sig); - /** - * do not call tick handler if - * - interrupts are disabled - * - tick handler is still running - * - old task switch not yet completed (wrong task running) - */ - if ( ( pdTRUE == xInterruptsEnabled ) && ( pdTRUE != xServicingTick ) && ( hRequestedThread == hActiveThread ) ) - { - xServicingTick = pdTRUE; - if ( 0 == pthread_mutex_trylock( &xSuspendResumeThreadMutex ) ) - { - debug_printf("does handle tick\n"); - - /** - * this shouldn't ever happen - but WELL... - * Make sure we don't create outdated resume signals - */ - if (hActiveThread!=hRequestedThread) { - xServicingTick = pdFALSE; - xPendYield = pdTRUE; - (void)pthread_mutex_unlock( &xSuspendResumeThreadMutex ); - return; - } - - xTaskToSuspend = prvGetThreadHandle( xTaskGetCurrentTaskHandle() ); - /* Tick Increment. */ - vTaskIncrementTick(); - - /* Select Next Task. */ -#if ( configUSE_PREEMPTION == 1 ) - vTaskSwitchContext(); -#endif - xTaskToResume = prvGetThreadHandle( xTaskGetCurrentTaskHandle() ); - //hRequestedThread = xTaskToResume; - - /* The only thread that can process this tick is the running thread. */ - if ( xTaskToSuspend != xTaskToResume ) - { - /* Suspend the current task. */ - hRequestedThread = 0; - prvSuspendThread( xTaskToSuspend ); - //timeout.tv_sec=0; - //timeout.tv_nsec=10000; - //sched_yield(); - while ( 0 != pthread_mutex_lock( &xRunningThreadMutex) ) { - prvSuspendThread( xTaskToSuspend ); - timeout.tv_sec=0; - timeout.tv_nsec=1; - nanosleep(&timeout,0); - } - //if ( 0 == pthread_mutex_lock( &xRunningThreadMutex) ) { - /* Remember and switch the critical nesting. */ - prvSetTaskCriticalNesting( xTaskToSuspend, uxCriticalNesting ); - uxCriticalNesting = prvGetTaskCriticalNesting( xTaskToResume ); - /* Resume next task. */ - hRequestedThread = xTaskToResume; - prvResumeThread( xTaskToResume ); -if (prvGetThreadHandle(xTaskGetCurrentTaskHandle())!=xTaskToResume) { -debug_printf("\n what the fuck???? someone else did a switchcontext?!?\n"); -} - (void)pthread_mutex_unlock( &xRunningThreadMutex ); - } - else - { - /* Release the lock as we are Resuming. */ - // (void)pthread_mutex_unlock( &xSingleThreadMutex ); - } - } - else - { - xPendYield = pdTRUE; - } - (void)pthread_mutex_unlock( &xSuspendResumeThreadMutex ); - xServicingTick = pdFALSE; - } - else - { - debug_printf("will NOT handle tick\n"); - xPendYield = pdTRUE; - } -} -/*-----------------------------------------------------------*/ - -void vPortForciblyEndThread( void *pxTaskToDelete ) -{ -xTaskHandle hTaskToDelete = ( xTaskHandle )pxTaskToDelete; -pthread_t xTaskToDelete; -pthread_t xTaskToResume; -portBASE_TYPE xResult; - -// if ( 0 == pthread_mutex_lock( &xSingleThreadMutex ) ) -// { - xTaskToDelete = prvGetThreadHandle( hTaskToDelete ); - xTaskToResume = prvGetThreadHandle( xTaskGetCurrentTaskHandle() ); - - if ( xTaskToResume == xTaskToDelete ) - { - if ( 0 == pthread_mutex_lock( &xSuspendResumeThreadMutex ) ) { - /** - * Make sure we don't create outdated resume signals - */ - while (hActiveThread!=hRequestedThread) { - (void)pthread_mutex_unlock( &xSuspendResumeThreadMutex ); - sched_yield(); - (void)pthread_mutex_lock( &xSuspendResumeThreadMutex ); - } - /* This is a suicidal thread, need to select a different task to run. */ - vTaskSwitchContext(); - xTaskToResume = prvGetThreadHandle( xTaskGetCurrentTaskHandle() ); - hRequestedThread = xTaskToResume; - (void)pthread_mutex_unlock( &xSuspendResumeThreadMutex ); - } else { - debug_printf("mutex lock failed!\n"); - exit(1); - } - } - - 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( &xSingleThreadMutex ); - } - else - { - /* Resume the other thread. */ - prvResumeThread( xTaskToResume ); - /* Pthread Clean-up function will note the cancellation. */ - /* Release the execution. */ - uxCriticalNesting = 0; - vPortEnableInterrupts(); -// (void)pthread_mutex_unlock( &xSingleThreadMutex ); - (void)pthread_mutex_unlock( &xRunningThreadMutex ); - /* Commit suicide */ - pthread_exit( (void *)1 ); - } -// } -} -/*-----------------------------------------------------------*/ - -void *prvWaitForStart( void * pvParams ) -{ -xParams * pxParams = ( xParams * )pvParams; -pdTASK_CODE pvCode = pxParams->pxCode; -void * pParams = pxParams->pvParams; -sigset_t xSignals; - vPortFree( pvParams ); - - pthread_cleanup_push( prvDeleteThread, (void *)pthread_self() ); - - if ( 0 == pthread_mutex_lock( &xRunningThreadMutex ) ) - { - xSentinel=1; - hActiveThread=pthread_self(); - debug_printf("temporarily made ACTIVE THREAD!\n"); - - sigemptyset( &xSignals ); - sigaddset( &xSignals, SIG_RESUME ); - /* set up proc mask */ - pthread_sigmask(SIG_SETMASK,&xSignals,NULL); - - prvSuspendSignalHandler(SIG_SUSPEND); - //prvSuspendThread( pthread_self() ); - } else { - debug_printf("now this is just WRONG!\n"); - exit(1); - } - - pvCode( pParams ); - - pthread_cleanup_pop( 1 ); - return (void *)NULL; -} -/*-----------------------------------------------------------*/ - -void prvSuspendSignalHandler(int sig) -{ -sigset_t xSignals; -//sigset_t xPendingSignals; - - /* Only interested in the resume signal. */ - sigemptyset( &xSignals ); - sigaddset( &xSignals, SIG_RESUME ); - sigaddset( &xSignals, SIG_SUSPEND ); - - /* Unlock the Running thread mutex to allow the resumed task to continue. */ - if ( 0 != pthread_mutex_unlock( &xRunningThreadMutex ) ) - { - printf( "Releasing someone else's lock.\n" ); - } - - debug_printf("SUSPENDING until SIG_RESUME received\n"); - /* Wait on the resume signal. */ - while (hRequestedThread != pthread_self()) { - if ( 0 != sigwait( &xSignals, &sig ) ) - { - //printf( "SSH: Sw %d\n", sig ); - /* tricky one - shouldn't ever happen - trying to resolve situation as graceful as possible */ - debug_printf("ALERT AAAAH PANIC! - sigwait failed.....\n\n\n"); - /* Signal main thread something just went HORRIBLY wrong */ - xGeneralFuckedUpIndicator = 2; - sched_yield(); - //(void)pthread_mutex_lock( &xRunningThreadMutex ); - //(void)pthread_kill( pthread_self(), SIG_SUSPEND ); - //return; - } else if (sig == SIG_RESUME) { - //debug_printf("received signal %i\n",sig); - /* Make sure the right thread received the signal */ - if (hRequestedThread != pthread_self() ) { - debug_printf( "ALERT! Received SIG_RESUME which is already outdated!\n active thread is %li\n",(long)hRequestedThread); - /* Signal main thread something just went wrong */ - xGeneralFuckedUpIndicator = 1; - /* - if (0 == sigpending(&xPendingSignals)) { - if (sigismember(&xPendingSignals,SIG_SUSPEND)) { - debug_printf( "reason: we slept too long...\n"); - //(void)sigwait(&xPendingSignals,&sig); - // we can safely return - signal is already pending - return; - } - } - debug_printf( "reason: unknown! - whatever ...\n\n"); - */ - //exit(1); - //(void)pthread_kill( xTaskToResume, SIG_RESUME ); - //(void)pthread_mutex_lock( &xRunningThreadMutex ); - //(void)pthread_kill( pthread_self(), SIG_SUSPEND ); - //return; - } - } - } - /* Yield the Scheduler to ensure that the yielding thread completes. */ - if ( 0 != pthread_mutex_lock( &xRunningThreadMutex ) ) - { - //(void)pthread_mutex_unlock( &xSingleThreadMutex ); - debug_printf("critical - mutex acquiring of active thread failed!\n"); - exit(1); - } - hActiveThread = pthread_self(); - - /* 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(); - } - if (hRequestedThread==pthread_self()) { - /* doesn't look too bad, does it? */ - xGeneralFuckedUpIndicator = 0; - } - debug_printf("ACTIVE THREAD!\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, sigresume, sigtick; -portLONG lIndex; - - 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 ); - - sigresume.sa_flags = 0; - //sigresume.sa_handler = prvResumeSignalHandler; - sigresume.sa_handler = SIG_IGN; - sigfillset( &sigresume.sa_mask ); - - sigtick.sa_flags = 0; - //sigtick.sa_handler = vPortSystemTickHandler; - sigtick.sa_handler = SIG_IGN; - sigfillset( &sigtick.sa_mask ); - - if ( 0 != sigaction( SIG_SUSPEND, &sigsuspendself, NULL ) ) - { - printf( "Problem installing SIG_SUSPEND_SELF\n" ); - } - //if ( 0 != sigaction( SIG_RESUME, &sigresume, NULL ) ) - //{ - // printf( "Problem installing SIG_RESUME\n" ); - //} - if ( 0 != sigaction( SIG_TICK, &sigtick, NULL ) ) - { - printf( "Problem installing SIG_TICK\n" ); - } - printf( "Running as PID: %d\n", getpid() ); -} -/*-----------------------------------------------------------*/ - -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; - - 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; - } - } - } -} -/*-----------------------------------------------------------*/ - -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; -} -/*-----------------------------------------------------------*/ -/** - * Scheduler f***d up - we got to fix that - */ -void prvResolveFuckup( void ) -{ -struct timespec timeout; -pthread_t xTaskToResume; - - (void)pthread_mutex_lock ( &xSuspendResumeThreadMutex); - if (hActiveThread == hRequestedThread) { - debug_printf("emergency handler started - but not needed - returning\n"); - return; - } - printf("\nScheduler fucked up again - lets try to fix it...\n"); - if (hRequestedThread==0) { - printf("\nno supposedly active thread - fixing\n"); - xTaskToResume = prvGetThreadHandle( xTaskGetCurrentTaskHandle() ); - - } else { - xTaskToResume = hRequestedThread; - } - printf("\nsending sig_suspend to thread that is supposed to be dead...\n"); - prvSuspendThread(hActiveThread); - printf("\nacquire running lock...\n"); - //timeout.tv_sec=0; - //timeout.tv_nsec=100; - sched_yield(); - while ( 0 != pthread_mutex_trylock( &xRunningThreadMutex) ) { - prvSuspendThread(hActiveThread); - timeout.tv_sec=0; - timeout.tv_nsec=1; - nanosleep(&timeout,NULL); - } - printf("\nsending sig_resume to thread that is supposed to be running...\n"); - prvResumeThread(xTaskToResume); - printf("\ngiving up mutex...\n"); - (void)pthread_mutex_unlock(&xRunningThreadMutex); - (void)pthread_mutex_unlock ( &xSuspendResumeThreadMutex); - -} -/*-----------------------------------------------------------*/ diff --git a/flight/PiOS.posix/posix/Libraries/FreeRTOS/Source/portable/GCC/Posix/corvuscorax/scheduler.txt b/flight/PiOS.posix/posix/Libraries/FreeRTOS/Source/portable/GCC/Posix/corvuscorax/scheduler.txt deleted file mode 100644 index dc1815cea..000000000 --- a/flight/PiOS.posix/posix/Libraries/FreeRTOS/Source/portable/GCC/Posix/corvuscorax/scheduler.txt +++ /dev/null @@ -1,42 +0,0 @@ -thread initial START: - -master gives up running mutex -master waits for sentinel set -master akquires running mutex - -thread akquires RUNNING_MUTEX -threads sets sentinel -thread suspends itself - - - -thread SUSPEND: - -thread gives up RUNNING_MUTEX -thread waits for sig_resume -thread akquires RUNNING_MUTEX -thread runs - - -thread END: - -if other: -delete the other thread -if self: -thread gives up RUNNING_MUTEX -thread sends sig_resume to new active thread -thread self kills - - -thread YIELD -thread sends sig_resume to new active thread -thread suspends itself - - -time tick yield -tick handler sends SUSPEND to running thread -tick handler akquires RUNNING_MUTEX -tick handler sends sig_resume to new active thread -tock handler gives up RUNNING_MUTEX -tick handler ends - diff --git a/flight/PiOS.posix/posix/Libraries/FreeRTOS/Source/portable/GCC/Posix/corvuscorax/test_case_1_sleep.c b/flight/PiOS.posix/posix/Libraries/FreeRTOS/Source/portable/GCC/Posix/corvuscorax/test_case_1_sleep.c deleted file mode 100644 index b173eb9bc..000000000 --- a/flight/PiOS.posix/posix/Libraries/FreeRTOS/Source/portable/GCC/Posix/corvuscorax/test_case_1_sleep.c +++ /dev/null @@ -1,35 +0,0 @@ -/** - * small test program whether signals between threads work as they should - */ - -#include -#include -#include - -void sighandler(int sig) { - write(2,".",1); - return; -} - -void* threadstart(void* arg) { - - while (1) { - sleep(1); - } -} - -int main(char** argc, int argv) { - - pthread_t testthread1; - struct sigaction action; - - action.sa_handler=sighandler; - action.sa_flags=0; - sigfillset( &action.sa_mask ); - sigaction(SIGUSR1,&action,NULL); - - pthread_create(&testthread1,NULL,threadstart,NULL); - while (1) { - pthread_kill(testthread1,SIGUSR1); - } -} diff --git a/flight/PiOS.posix/posix/Libraries/FreeRTOS/Source/portable/GCC/Posix/corvuscorax/test_case_2_nanosleep.c b/flight/PiOS.posix/posix/Libraries/FreeRTOS/Source/portable/GCC/Posix/corvuscorax/test_case_2_nanosleep.c deleted file mode 100644 index c01679a18..000000000 --- a/flight/PiOS.posix/posix/Libraries/FreeRTOS/Source/portable/GCC/Posix/corvuscorax/test_case_2_nanosleep.c +++ /dev/null @@ -1,38 +0,0 @@ -/** - * small test program whether signals between threads work as they should - */ - -#include -#include -#include - -void sighandler(int sig) { - write(2,".",1); - return; -} - -void* threadstart(void* arg) { -struct timespec sleeptime; - - while (1) { - sleeptime.tv_sec=1; - sleeptime.tv_nsec=0; - nanosleep(&sleeptime,NULL); - } -} - -int main(char** argc, int argv) { - - pthread_t testthread1; - struct sigaction action; - - action.sa_handler=sighandler; - action.sa_flags=0; - sigfillset( &action.sa_mask ); - sigaction(SIGUSR1,&action,NULL); - - pthread_create(&testthread1,NULL,threadstart,NULL); - while (1) { - pthread_kill(testthread1,SIGUSR1); - } -} diff --git a/flight/PiOS.posix/posix/Libraries/FreeRTOS/Source/portable/GCC/Posix/corvuscorax/test_case_3_select.c b/flight/PiOS.posix/posix/Libraries/FreeRTOS/Source/portable/GCC/Posix/corvuscorax/test_case_3_select.c deleted file mode 100644 index 9fc852774..000000000 --- a/flight/PiOS.posix/posix/Libraries/FreeRTOS/Source/portable/GCC/Posix/corvuscorax/test_case_3_select.c +++ /dev/null @@ -1,40 +0,0 @@ -/** - * small test program whether signals between threads work as they should - */ - -#include -#include -#include -#include -#include - -void sighandler(int sig) { - write(2,".",1); - return; -} - -void* threadstart(void* arg) { -struct timeval sleeptime; - - while (1) { - sleeptime.tv_sec=1; - sleeptime.tv_usec=0; - select(0,NULL,NULL,NULL,&sleeptime); - } -} - -int main(char** argc, int argv) { - - pthread_t testthread1; - struct sigaction action; - - action.sa_handler=sighandler; - action.sa_flags=0; - sigfillset( &action.sa_mask ); - sigaction(SIGUSR1,&action,NULL); - - pthread_create(&testthread1,NULL,threadstart,NULL); - while (1) { - pthread_kill(testthread1,SIGUSR1); - } -} diff --git a/flight/PiOS.posix/posix/Libraries/FreeRTOS/Source/portable/GCC/Posix/corvuscorax/test_case_4_mutex_lock.c b/flight/PiOS.posix/posix/Libraries/FreeRTOS/Source/portable/GCC/Posix/corvuscorax/test_case_4_mutex_lock.c deleted file mode 100644 index d5bf3119f..000000000 --- a/flight/PiOS.posix/posix/Libraries/FreeRTOS/Source/portable/GCC/Posix/corvuscorax/test_case_4_mutex_lock.c +++ /dev/null @@ -1,41 +0,0 @@ -/** - * small etst program whether signals between threads work as they should - */ - -#include -#include - -static pthread_mutex_t Mutex = PTHREAD_MUTEX_INITIALIZER; - -/** - * actual test program - */ - -void sighandler(int sig) { - write(2,".",1); - return; -} - -void* threadstart(void* arg) { - - while (1) { - pthread_mutex_lock(&Mutex); - } -} - -int main(char** argc, int argv) { - - pthread_t testthread1; - struct sigaction action; - - action.sa_handler=sighandler; - action.sa_flags=0; - sigfillset( &action.sa_mask ); - sigaction(SIGUSR1,&action,NULL); - - pthread_mutex_lock(&Mutex); - pthread_create(&testthread1,NULL,threadstart,NULL); - while (1) { - pthread_kill(testthread1,SIGUSR1); - } -} diff --git a/flight/PiOS.posix/posix/Libraries/FreeRTOS/Source/portable/GCC/Posix/corvuscorax/test_case_5_pselect.c b/flight/PiOS.posix/posix/Libraries/FreeRTOS/Source/portable/GCC/Posix/corvuscorax/test_case_5_pselect.c deleted file mode 100644 index a3d98b8bd..000000000 --- a/flight/PiOS.posix/posix/Libraries/FreeRTOS/Source/portable/GCC/Posix/corvuscorax/test_case_5_pselect.c +++ /dev/null @@ -1,42 +0,0 @@ -/** - * small test program whether signals between threads work as they should - */ - -#include -#include -#include -#include -#include - -void sighandler(int sig) { - write(2,".",1); - return; -} - -void* threadstart(void* arg) { -sigset_t sigset; -struct timespec sleeptime; - - while (1) { - sleeptime.tv_sec=1; - sleeptime.tv_nsec=0; - sigemptyset(&sigset); - pselect(0,NULL,NULL,NULL,&sleeptime,&sigset); - } -} - -int main(char** argc, int argv) { - - pthread_t testthread1; - struct sigaction action; - - action.sa_handler=sighandler; - action.sa_flags=0; - sigfillset( &action.sa_mask ); - sigaction(SIGUSR1,&action,NULL); - - pthread_create(&testthread1,NULL,threadstart,NULL); - while (1) { - pthread_kill(testthread1,SIGUSR1); - } -} diff --git a/flight/PiOS.posix/posix/Libraries/FreeRTOS/Source/portable/GCC/Posix/corvuscorax/test_case_6_sched_yield.c b/flight/PiOS.posix/posix/Libraries/FreeRTOS/Source/portable/GCC/Posix/corvuscorax/test_case_6_sched_yield.c deleted file mode 100644 index 58fc902ea..000000000 --- a/flight/PiOS.posix/posix/Libraries/FreeRTOS/Source/portable/GCC/Posix/corvuscorax/test_case_6_sched_yield.c +++ /dev/null @@ -1,35 +0,0 @@ -/** - * small test program whether signals between threads work as they should - */ - -#include -#include -#include - -void sighandler(int sig) { - write(2,".",1); - return; -} - -void* threadstart(void* arg) { - - while (1) { - sched_yield(); - } -} - -int main(char** argc, int argv) { - - pthread_t testthread1; - struct sigaction action; - - action.sa_handler=sighandler; - action.sa_flags=0; - sigfillset( &action.sa_mask ); - sigaction(SIGUSR1,&action,NULL); - - pthread_create(&testthread1,NULL,threadstart,NULL); - while (1) { - pthread_kill(testthread1,SIGUSR1); - } -} diff --git a/flight/PiOS.posix/posix/Libraries/FreeRTOS/Source/portable/GCC/Posix/corvuscorax/test_case_7_busy_waiting.c b/flight/PiOS.posix/posix/Libraries/FreeRTOS/Source/portable/GCC/Posix/corvuscorax/test_case_7_busy_waiting.c deleted file mode 100644 index d3a808e61..000000000 --- a/flight/PiOS.posix/posix/Libraries/FreeRTOS/Source/portable/GCC/Posix/corvuscorax/test_case_7_busy_waiting.c +++ /dev/null @@ -1,34 +0,0 @@ -/** - * small test program whether signals between threads work as they should - */ - -#include -#include -#include - -void sighandler(int sig) { - write(2,".",1); - return; -} - -void* threadstart(void* arg) { - - while (1) { - } -} - -int main(char** argc, int argv) { - - pthread_t testthread1; - struct sigaction action; - - action.sa_handler=sighandler; - action.sa_flags=0; - sigfillset( &action.sa_mask ); - sigaction(SIGUSR1,&action,NULL); - - pthread_create(&testthread1,NULL,threadstart,NULL); - while (1) { - pthread_kill(testthread1,SIGUSR1); - } -} diff --git a/flight/PiOS.posix/posix/Libraries/FreeRTOS/Source/portable/GCC/Posix/corvuscorax/test_case_8_io.c b/flight/PiOS.posix/posix/Libraries/FreeRTOS/Source/portable/GCC/Posix/corvuscorax/test_case_8_io.c deleted file mode 100644 index 3f21c3238..000000000 --- a/flight/PiOS.posix/posix/Libraries/FreeRTOS/Source/portable/GCC/Posix/corvuscorax/test_case_8_io.c +++ /dev/null @@ -1,36 +0,0 @@ -/** - * small test program whether signals between threads work as they should - */ - -#include -#include -#include - -void sighandler(int sig) { - write(2,".",1); - return; -} - -void* threadstart(void* arg) { - char buf[1024]; - - while (1) { - read(1,buf,512); - } -} - -int main(char** argc, int argv) { - - pthread_t testthread1; - struct sigaction action; - - action.sa_handler=sighandler; - action.sa_flags=0; - sigfillset( &action.sa_mask ); - sigaction(SIGUSR1,&action,NULL); - - pthread_create(&testthread1,NULL,threadstart,NULL); - while (1) { - pthread_kill(testthread1,SIGUSR1); - } -} diff --git a/flight/PiOS.posix/posix/Libraries/FreeRTOS/Source/portable/GCC/Posix/corvuscorax/thread_signal_test.c b/flight/PiOS.posix/posix/Libraries/FreeRTOS/Source/portable/GCC/Posix/corvuscorax/thread_signal_test.c deleted file mode 100644 index 7a230399f..000000000 --- a/flight/PiOS.posix/posix/Libraries/FreeRTOS/Source/portable/GCC/Posix/corvuscorax/thread_signal_test.c +++ /dev/null @@ -1,62 +0,0 @@ -/** - * small etst program whether signals between threads work as they should - */ - -#include -#include -#include -#include - -static pthread_mutex_t Mutex = PTHREAD_MUTEX_INITIALIZER; - -void sighandler(int sig) { - printf("signal handler called in thread %li - signal %i\n",(long)pthread_self(),sig); -} - - -void* threadstart(void* arg) { -struct timespec timeout; -struct sigaction action; - printf("thread %li started\n",(long)pthread_self()); - - printf("installing signal handler\n"); - action.sa_handler=sighandler; - action.sa_flags=0; - sigfillset( &action.sa_mask ); - sigaction(SIGUSR1,&action,NULL); - - printf("getting mutex\n"); - pthread_mutex_lock(&Mutex); - printf("got mutex\n"); - - - while (1) { - timeout.tv_sec=1; - timeout.tv_nsec=0; - nanosleep(&timeout,0); - printf("thread %li still running...\n",(long)pthread_self()); - } - -} - - -int main(char** argc, int argv) { - -pthread_t testthread1; -pthread_t testthread2; -printf("thread test program\n"); -sleep(5); -printf("starting thread 1\n"); -pthread_create(&testthread1,NULL,threadstart,NULL); -sleep(5); -printf("starting thread 2\n"); -pthread_create(&testthread2,NULL,threadstart,NULL); -while (1) { - sleep(5); - printf("sending SIG_USR1 to thread 1\n"); - pthread_kill(testthread1,SIGUSR1); - sleep(5); - printf("sending SIG_USR1 to thread 2\n"); - pthread_kill(testthread2,SIGUSR1); -} -} diff --git a/flight/PiOS.posix/posix/Libraries/FreeRTOS/Source/portable/GCC/Posix/corvuscorax/thread_signal_test2.c b/flight/PiOS.posix/posix/Libraries/FreeRTOS/Source/portable/GCC/Posix/corvuscorax/thread_signal_test2.c deleted file mode 100644 index d6df0a023..000000000 --- a/flight/PiOS.posix/posix/Libraries/FreeRTOS/Source/portable/GCC/Posix/corvuscorax/thread_signal_test2.c +++ /dev/null @@ -1,128 +0,0 @@ -/** - * small etst program whether signals between threads work as they should - */ - -#include -#include -#include -#include -#include - -static pthread_mutex_t Mutex = PTHREAD_MUTEX_INITIALIZER; - -/** - * printf is not thread safe - this little helper function allow debug output in thread safe context - */ -/* write a string to a filehandle */ -void print_char(int fh, char *c) { - int t=0; - while (c[t]!=0) t++; - write(fh,c,t); -} - -/* create a dezimal string from an integer */ -int int2char(char* x,unsigned long i) { - if (i==0) { - return 0; - } - int k=int2char(&x[0],i/10); - x[k]='0'+(i%10); - x[k+1]=0; - return k+1; -} -/* print a number*/ -void print_number(int fh, long i) { - char buffer[39]; // 39 characters are enough to store a 128 bit integer in dezimal notation (~~3.4* 10^38) - - if (i==0) { - print_char(fh,"0"); - } else { - if (i<0) { - buffer[0]='-'; - int2char(&buffer[1],-i); - } else { - int2char(buffer,i); - } - print_char(fh,buffer); - } -} - -/** - * actual test program - */ - -void sighandler(int sig) { - print_char(2,"signal handler called in thread "); - print_number(2,(long)pthread_self()); - print_char(2," - signal "); - print_number(2,sig); - print_char(2,"\n"); -} - - -void* threadstart(void* arg) { -struct timespec timeout; -int t; - print_char(2,"thread "); - print_number(2,(long)pthread_self()); - print_char(2," started \n"); - - while (1) { - print_char(2,"getting mutex\n"); - pthread_mutex_lock(&Mutex); - print_char(2,"got mutex\n"); - - - for (t=0;t<20;t++) { - timeout.tv_sec=1; - timeout.tv_nsec=0; - nanosleep(&timeout,0); - - print_char(2,"thread "); - print_number(2,(long)pthread_self()); - print_char(2," still running...\n"); - } - pthread_mutex_unlock(&Mutex); - sleep(1); - } -} - - -int main(char** argc, int argv) { - - pthread_t testthread1; - pthread_t testthread2; - struct sigaction action; - print_char(2,"thread test program\n\n"); - - print_char(2,"demonstrate print function\n"); - long t=1; - while (t!=0) { - print_number(2,t); - print_char(2," >> "); - t=(t>0)?t*2:t/2; - } - print_number(2,t); - print_char(2,"\ndone\n\n"); - - print_char(2,"installing signal handler\n"); - action.sa_handler=sighandler; - action.sa_flags=0; - sigfillset( &action.sa_mask ); - sigaction(SIGUSR1,&action,NULL); - - sleep(5); - print_char(2,"starting thread 1\n"); - pthread_create(&testthread1,NULL,threadstart,NULL); - sleep(5); - print_char(2,"starting thread 2\n"); - pthread_create(&testthread2,NULL,threadstart,NULL); - while (1) { - sleep(5); - print_char(2,"sending SIG_USR1 to thread 1\n"); - pthread_kill(testthread1,SIGUSR1); - sleep(5); - print_char(2,"sending SIG_USR1 to thread 2\n"); - pthread_kill(testthread2,SIGUSR1); - } -} diff --git a/flight/PiOS.posix/posix/Libraries/FreeRTOS/Source/portable/GCC/Posix/corvuscorax/thread_signal_test3.c b/flight/PiOS.posix/posix/Libraries/FreeRTOS/Source/portable/GCC/Posix/corvuscorax/thread_signal_test3.c deleted file mode 100644 index 8e8c9dbf0..000000000 --- a/flight/PiOS.posix/posix/Libraries/FreeRTOS/Source/portable/GCC/Posix/corvuscorax/thread_signal_test3.c +++ /dev/null @@ -1,46 +0,0 @@ -/** - * small etst program whether signals between threads work as they should - */ - -#include -#include -#include - - -/** - * actual test program - */ - -void sighandler(int sig) { - return; -} - - -void* threadstart(void* arg) { -struct timespec timeout; -int t; - - while (1) { - timeout.tv_sec=0; - timeout.tv_nsec=1; - nanosleep(&timeout,0); - } -} - - -int main(char** argc, int argv) { - - pthread_t testthread1; - struct sigaction action; - - - action.sa_handler=sighandler; - action.sa_flags=0; - sigfillset( &action.sa_mask ); - sigaction(SIGUSR1,&action,NULL); - - pthread_create(&testthread1,NULL,threadstart,NULL); - while (1) { - pthread_kill(testthread1,SIGUSR1); - } -} diff --git a/flight/PiOS.posix/posix/Libraries/FreeRTOS/Source/portable/GCC/Posix/peabody124/port-pthread_cond.c b/flight/PiOS.posix/posix/Libraries/FreeRTOS/Source/portable/GCC/Posix/peabody124/port-pthread_cond.c deleted file mode 100644 index 8eab3b367..000000000 --- a/flight/PiOS.posix/posix/Libraries/FreeRTOS/Source/portable/GCC/Posix/peabody124/port-pthread_cond.c +++ /dev/null @@ -1,1179 +0,0 @@ -/* - 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 -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - - -/* Scheduler includes. */ -#include "FreeRTOS.h" -#include "task.h" -/*-----------------------------------------------------------*/ - -#define MAX_NUMBER_OF_TASKS ( _POSIX_THREAD_THREADS_MAX ) -/*-----------------------------------------------------------*/ - -#ifdef __APPLE__ - #define COND_SIGNALING - #define CHECK_TASK_RESUMES - #define RUNNING_THREAD_MUTEX - #define TICK_SIGNAL -#endif -#ifdef __CYGWIN__ - #define COND_SIGNALING - #define CHECK_TASK_RESUMES -#endif -#ifdef __linux__ - #define COND_SIGNALING -// #define CHECK_TASK_RESUMES - #define RUNNING_THREAD_MUTEX - #define TICK_SIGNAL -#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_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 - -//#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( stderr, "%20s(%li)\t%20s\t%i: ",debug_task_handle->pcTaskName,(long)pthread_self(),__func__,__LINE__)): \ - (fprintf( stderr, "%20s(%li)\t%20s\t%i: ","__unknown__",(long)pthread_self(),__func__,__LINE__)) \ - |1)?( \ - ((fprintf( stderr, __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_trylock(...) ( (debug_printf(" -!- pthread_mutex_trylock(%s)\n",#__VA_ARGS__)|1)?pthread_mutex_trylock(__VA_ARGS__):0 ) - #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( stderr, "%20s(%li)\t%20s\t%i: ",debug_task_handle->pcTaskName,(long)pthread_self(),__func__,__LINE__)): \ - (fprintf( stderr, "%20s(%li)\t%20s\t%i: ","__unknown__",(long)pthread_self(),__func__,__LINE__)) \ - |1)?( \ - ((fprintf( stderr, __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 */ -// pthread_condattr_t condAttr; -// assert( 0 == pthread_condattr_init( &condAttr ) ); - 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 */ -// pthread_mutexattr_t mutexAttr; -// assert( 0 == pthread_mutexattr_init( &mutexAttr ) ); -// assert( 0 == pthread_mutexattr_settype( &mutexAttr, PTHREAD_MUTEX_ERRORCHECK ) ); - 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. */ - sigemptyset( &xSignalToBlock ); - sigaddset( &xSignalToBlock, SIG_SUSPEND ); - (void)pthread_sigmask( SIG_SETMASK, &xSignalToBlock, NULL ); - - for ( lIndex = 0; lIndex < MAX_NUMBER_OF_TASKS; lIndex++ ) - { - pxThreads[ lIndex ].uxCriticalNesting = 0; - } - - /* Start the first task. Will not return unless all threads are killed. */ - vPortStartFirstTask(); - - /* Unfortunately things are stable if we start ticking during setup. This need to be */ - /* checked careful in startup on hardware */ - usleep(1000000); - -#ifdef TICK_SIGNAL - struct itimerval itimer; - portTickType xMicroSeconds = portTICK_RATE_MICROSECONDS; - - debug_printf("init %li microseconds\n",(long)xMicroSeconds); - /* Initialise the structure with the current timer information. */ - assert ( 0 == getitimer( TIMER_TYPE, &itimer ) ); - - /* Set the interval between timer events. */ - itimer.it_interval.tv_sec = 0; - itimer.it_interval.tv_usec = xMicroSeconds; - - /* Set the current count-down. */ - itimer.it_value.tv_sec = 0; - itimer.it_value.tv_usec = xMicroSeconds; - - struct sigaction sigtick; - sigtick.sa_flags = 0; - sigtick.sa_handler = vPortSystemTickHandler; - sigfillset( &sigtick.sa_mask ); - assert ( 0 == sigaction( SIG_TICK, &sigtick, NULL ) ); - - /* Set-up the timer interrupt. */ - assert ( 0 == setitimer( TIMER_TYPE, &itimer, NULL ) ); - - sigemptyset( &xSignalToBlock ); - sigaddset( &xSignalToBlock, SIG_SUSPEND ); - (void)pthread_sigmask( SIG_SETMASK, &xSignalToBlock, NULL ); - - while(1) - { - usleep(1000); - sched_yield(); - } -#else - - struct timespec x; - while( pdTRUE != xSchedulerEnd ) { - x.tv_sec=0; - x.tv_nsec=portTICK_RATE_MICROSECONDS * 1000; - nanosleep(&x,NULL); -// printf("."); fflush(stdout); - vPortSystemTickHandler(SIG_TICK); -// printf("*"); fflush(stdout); - } - -#endif - 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; -int retVal; -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 ); - sigaddset( &xSignals, SIG_TICK ); - pthread_sigmask( SIG_SETMASK, &xSignals, NULL ); - - oldTask = xTaskGetCurrentTaskHandle(); - xTaskToSuspend = prvGetThreadHandle( xTaskGetCurrentTaskHandle() ); - - retVal = pthread_mutex_trylock( &xSwappingThreadMutex ); - while( retVal != 0 ) { - - assert( retVal == EBUSY ); - - /* If we can't get the mutex, that means an interrupt is running and we */ - /* should keep an eye out if this task should suspend so the interrupt */ - /* routine doesn't stall waiting for this task to pause */ - debug_printf( "Waiting to get swapping mutex from ISR\r\n" ); - - xTaskToSuspend = prvGetThreadHandle( xTaskGetCurrentTaskHandle() ); - - if( prvGetThreadHandle( xTaskGetCurrentTaskHandle() ) != pthread_self() ) { - debug_printf( "The current task isn't even us. Pausing now, deal with possible interrupt later.\r\n" ); - pauseThread( THREAD_PAUSE_YIELD ); - - /* Now we are resuming, want to be able to catch this interrupt again */ - sigemptyset( &xSignals ); - sigaddset( &xSignals, SIG_TICK ); - pthread_sigmask( SIG_SETMASK, &xSignals, NULL); - return; - } - sched_yield(); - retVal = pthread_mutex_trylock( &xSwappingThreadMutex ); - } - - /* At this point we have the lock, active task shouldn't change */ - if(xTaskToSuspend != pthread_self() ) { - debug_printf( "The current task isn't even us, letting interrupt happen. Watch for swap.\r\n" ); - - assert( pthread_mutex_unlock( &xSwappingThreadMutex ) == 0); - - pauseThread( THREAD_PAUSE_YIELD ); - - /* Now we are resuming, want to be able to catch this interrupt again */ - sigemptyset( &xSignals ); - sigaddset( &xSignals, SIG_TICK ); - pthread_sigmask( SIG_SETMASK, &xSignals, NULL); - return; - } - - assert( xTaskToSuspend == pthread_self() ); // race condition I didn't account for - - 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 ); - sigaddset( &xSignals, SIG_TICK ); - pthread_sigmask( SIG_SETMASK, &xSignals, NULL); -} -/*-----------------------------------------------------------*/ - -void vPortDisableInterrupts( void ) -{ - //debug_printf("\r\n"); - xInterruptsEnabled = pdFALSE; -} -/*-----------------------------------------------------------*/ - -void vPortEnableInterrupts( void ) -{ - //debug_printf("\r\n"); - xInterruptsEnabled = pdTRUE; -} -/*-----------------------------------------------------------*/ - -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() ); - - /* Need to set this before updating the task in case it notices before the */ - /* interrupt is set */ - xSuspended = pdFALSE; - xStarted = pdFALSE; - - /* 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 ) - { - /* 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); - - assert( pthread_kill( xTaskToSuspend, SIG_SUSPEND ) == 0); - -#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 - { - debug_printf( "Waiting for old task to suspend\r\n" ); - debug_printf( "Sent signal\r\n" ); - sched_yield(); - } - debug_printf( "Suspended\r\n" ); - -#ifdef CHECK_TASK_RESUMES - while( xStarted == pdFALSE) -#endif - { - debug_printf( "Waiting for new task to resume\r\n" ); -#ifdef COND_SIGNALING - // Set resume condition for specific thread - pthread_cond_t * hCond = prvGetConditionHandle( xTaskGetCurrentTaskHandle() ); - assert( pthread_cond_signal( hCond ) == 0 ); -#endif - - 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; - } - debug_printf("Exiting\r\n"); -} -/*-----------------------------------------------------------*/ - -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 ); - sigaddset( &xSignals, SIG_TICK ); - assert( pthread_sigmask( SIG_SETMASK, &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 ); - sigaddset( &xSignals, SIG_TICK ); - 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 true\r\n", (long int) pthread_self() ); - xSuspended = pdTRUE; - -#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 - - 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(1000); - 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 ); - -#ifdef CHECK_TASK_RESUMES - /* This would seem like a major bug, but can happen because now we send extra suspend signals */ - /* if they aren't caught */ - if( pthread_self() == prvGetThreadHandle( xTaskGetCurrentTaskHandle() ) ) { - debug_printf( "Marked as current task, resuming\r\n" ); - return; - } -#endif - - /* Check that we aren't suspending when we should be running. This bug would need tracking down */ -// assert( pthread_self() != prvGetThreadHandle(xTaskGetCurrentTaskHandle() ) ); - - /* Block further suspend signals. They need to go to their thread */ - sigemptyset( &xBlockSignals ); - sigaddset( &xBlockSignals, SIG_SUSPEND ); - sigaddset( &xBlockSignals, SIG_TICK ); - assert( pthread_sigmask( SIG_SETMASK, &xBlockSignals, NULL ) == 0); - - while( pthread_self() != prvGetThreadHandle( xTaskGetCurrentTaskHandle() ) ) - { - debug_printf( "Incorrectly woke up. Repausing\r\n" ); - pauseThread( THREAD_PAUSE_INTERRUPT ); - } - - 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 ); - sigaddset( &xBlockSignals, SIG_TICK ); - assert( 0 == 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; - sigemptyset( &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; -} -/*-----------------------------------------------------------*/ diff --git a/flight/PiOS.posix/posix/Libraries/FreeRTOS/Source/portable/GCC/Posix/peabody124/port-stupidlysimplerversion.c b/flight/PiOS.posix/posix/Libraries/FreeRTOS/Source/portable/GCC/Posix/peabody124/port-stupidlysimplerversion.c deleted file mode 100644 index 53d49b094..000000000 --- a/flight/PiOS.posix/posix/Libraries/FreeRTOS/Source/portable/GCC/Posix/peabody124/port-stupidlysimplerversion.c +++ /dev/null @@ -1,1109 +0,0 @@ -/* - 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 -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - - -/* Scheduler includes. */ -#include "FreeRTOS.h" -#include "task.h" -/*-----------------------------------------------------------*/ - -#define MAX_NUMBER_OF_TASKS ( _POSIX_THREAD_THREADS_MAX ) -/*-----------------------------------------------------------*/ - -#define DB_P(x) // x - - -/* 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; - unsigned portBASE_TYPE uxCriticalNesting; -} xThreadState; -/*-----------------------------------------------------------*/ - -static xThreadState *pxThreads; -static pthread_once_t hSigSetupThread = PTHREAD_ONCE_INIT; -static pthread_attr_t xThreadAttributes; -static pthread_mutex_t xRunningThread = PTHREAD_MUTEX_INITIALIZER; -static pthread_mutex_t xSuspendResumeThreadMutex = PTHREAD_MUTEX_INITIALIZER; -static pthread_mutex_t xSingleThreadMutex = PTHREAD_MUTEX_INITIALIZER; -static pthread_t hMainThread = ( pthread_t )NULL; -/*-----------------------------------------------------------*/ - -static volatile portBASE_TYPE xSentinel = 0; -static volatile portBASE_TYPE xHandover = 0; -static volatile portBASE_TYPE xSchedulerEnd = pdFALSE; -static volatile portBASE_TYPE xInterruptsEnabled = pdTRUE; -static volatile portBASE_TYPE xInterruptsCurrent = 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 prvResumeSignalHandler(int sig); -static void prvSetupSignalsAndSchedulerPolicy( void ); -static void prvSuspendThread( pthread_t xThreadId ); -static void pauseThread(); -//static void prvResumeThread( pthread_t xThreadId ); -static pthread_t prvGetThreadHandle( xTaskHandle hTask ); -static pthread_cond_t prvGetThreadCondition( xTaskHandle hTask ); -static pthread_mutex_t prvGetThreadMutex( xTaskHandle hTask ); -static xTaskHandle prvGetThreadTask( 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 DEBUG_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( stderr, "%20s(%li)\t%20s\t%i: ",debug_task_handle->pcTaskName,(long)pthread_self(),__func__,__LINE__)): \ - (fprintf( stderr, "%20s(%li)\t%20s\t%i: ","__unknown__",(long)pthread_self(),__func__,__LINE__)) \ - |1)?( \ - ((fprintf( stderr, __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 ) -#else - #define debug_error(...) ( (pthread_mutex_lock( &xPrintfMutex )|1)?( \ - ( \ - (NULL != (debug_task_handle = prvGetTaskHandle(pthread_self())) )? \ - (fprintf( stderr, "%20s(%li)\t%20s\t%i: ",debug_task_handle->pcTaskName,(long)pthread_self(),__func__,__LINE__)): \ - (fprintf( stderr, "%20s(%li)\t%20s\t%i: ","__unknown__",(long)pthread_self(),__func__,__LINE__)) \ - |1)?( \ - ((fprintf( stderr, __VA_ARGS__ )|1)?pthread_mutex_unlock( &xPrintfMutex ):0) \ - ):0 ):0 ) - - #define debug_printf(...) -#endif - - - - - -//#define debug_printf(...) fprintf( stderr, __VA_ARGS__ ); -/* - * 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; -tskTCB * prvGetTaskHandle( pthread_t hThread ) -{ - portLONG lIndex; - - if (pxThreads==NULL) return NULL; - - for ( lIndex = 0; lIndex < MAX_NUMBER_OF_TASKS; lIndex++ ) - { - if ( pxThreads[ lIndex ].hThread == hThread ) - { - return pxThreads[ lIndex ].hTask; - } - } - return NULL; -} - - -/* - * 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(); - } /*else { - sigset_t xSignals; - sigemptyset( &xSignals ); - sigaddset( &xSignals, SIG_TICK ); - pthread_sigmask( SIG_BLOCK, &xSignals, NULL ); - } */ - - - /* 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(); - - /* Create a condition signal for this thread */ -/* pthread_condattr_t condAttr; - assert( 0 == pthread_condattr_init(&condAttr) ); - assert( 0 == pthread_cond_init( &( pxThreads[ lIndexOfLastAddedTask ].hCond ), &condAttr ) ); */ - - /* Create a condition mutex for this thread */ -/* pthread_mutexattr_t mutexAttr; - assert( 0 == pthread_mutexattr_init( &mutexAttr ) ); - assert( 0 == pthread_mutexattr_settype( &mutexAttr, PTHREAD_MUTEX_ERRORCHECK ) ); - assert( 0 == pthread_mutex_init( &( pxThreads[ lIndexOfLastAddedTask ].hMutex ), &mutexAttr ) );*/ - - /* 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(); - - /* Start the first task. */ - //prvResumeThread( prvGetThreadHandle( xTaskGetCurrentTaskHandle() ) ); - - debug_printf( "Sending resume signal to %li\r\n", (long int) prvGetThreadHandle( xTaskGetCurrentTaskHandle() ) ); -// pthread_kill( prvGetThreadHandle( xTaskGetCurrentTaskHandle() ), SIG_RESUME ); - // Set resume condition for specific thread - //pthread_cond_t hCond = prvGetThreadCondition( xTaskGetCurrentTaskHandle() ); - //assert( pthread_cond_signal( &hCond ) == 0 ); - -} -/*-----------------------------------------------------------*/ - -/* - * See header file for description. - */ -portBASE_TYPE xPortStartScheduler( void ) -{ -portBASE_TYPE xResult; -sigset_t xSignals; -sigset_t xSignalToBlock; -sigset_t xSignalsBlocked; -portLONG lIndex; - - debug_printf( "xPortStartScheduler\r\n" ); - - /* Establish the signals to block before they are needed. */ - sigfillset( &xSignalToBlock ); - sigaddset( &xSignalToBlock, SIG_SUSPEND ); -/* sigaddset( &xSignalToBlock, SIG_RESUME ); - sigaddset( &xSignalToBlock, SIG_TICK ); */ - - - /* Block until the end */ - (void)pthread_sigmask( SIG_SETMASK, &xSignalToBlock, &xSignalsBlocked ); - - for ( lIndex = 0; lIndex < MAX_NUMBER_OF_TASKS; lIndex++ ) - { - pxThreads[ lIndex ].uxCriticalNesting = 0; - } - - /* Start the timer that generates the tick ISR. Interrupts are disabled - here already. */ -// prvSetupTimerInterrupt(); - - /* Start the first task. Will not return unless all threads are killed. */ - vPortStartFirstTask(); - - /* This is the end signal we are looking for. */ - sigemptyset( &xSignals ); - sigaddset( &xSignals, SIG_RESUME ); - - while( pdTRUE != xSchedulerEnd ) { - struct timespec x; - x.tv_sec=0; - x.tv_nsec=1000000; - nanosleep(&x,NULL); - printf("."); fflush(stdout); - vPortSystemTickHandler(SIG_TICK); - } - - debug_printf( "Cleaning Up, Exiting.\n" ); - /* Cleanup the mutexes */ - xResult = pthread_mutex_destroy( &xSuspendResumeThreadMutex ); - xResult = pthread_mutex_destroy( &xSingleThreadMutex ); - vPortFree( (void *)pxThreads ); - - /* Should not get here! */ - return 0; -} -/*-----------------------------------------------------------*/ - -void vPortEndScheduler( void ) -{ -portBASE_TYPE xNumberOfThreads; -portBASE_TYPE xResult; - - DB_P("vPortEndScheduler\r\n"); - - 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 - * xSingleThreadMutex is already owned by an original call to Yield. Therefore, - * simply indicate that a yield is required soon. - */ - - DB_P("vPortYieldFromISR\r\n"); - - xPendYield = pdTRUE; -} -/*-----------------------------------------------------------*/ - -void vPortEnterCritical( void ) -{ - DB_P("vPortEnterCritical\r\n"); - - vPortDisableInterrupts(); - uxCriticalNesting++; -} -/*-----------------------------------------------------------*/ - -void vPortExitCritical( void ) -{ - DB_P("vPortExitCritical\r\n"); - /* 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; - - /* 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 */ - - sigemptyset( &xSignals ); - sigaddset( &xSignals, SIG_SUSPEND ); - pthread_sigmask( SIG_SETMASK, &xSignals, NULL ); - - assert( pthread_mutex_lock( &xSingleThreadMutex ) == 0); - - 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( &xSingleThreadMutex ) ); - debug_printf( "The current task isn't even us, letting interrupt happen\r\n" ); - /* Now we are resuming, want to be able to catch this interrupt again */ - sigemptyset( &xSignals ); - pthread_sigmask( SIG_SETMASK, &xSignals, NULL); - return; - } - - /* Get new task then release the task switching mutex */ - vTaskSwitchContext(); - xTaskToResume = prvGetThreadHandle( xTaskGetCurrentTaskHandle() ); - assert( pthread_mutex_unlock( &xSingleThreadMutex ) == 0); - - if ( pthread_self() != xTaskToResume ) - { - /* Remember and switch the critical nesting. */ - prvSetTaskCriticalNesting( xTaskToSuspend, uxCriticalNesting ); - uxCriticalNesting = prvGetTaskCriticalNesting( xTaskToResume ); - - /* pausing self if switching tasks, can now rely on other thread waking itself up */ - pauseThread(); - } - - /* Now we are resuming, want to be able to catch this interrupt again */ - sigemptyset( &xSignals ); - pthread_sigmask( SIG_SETMASK, &xSignals, NULL); -} -/*-----------------------------------------------------------*/ - -void vPortDisableInterrupts( void ) -{ - DB_P("vPortDisableInterrupts\r\n"); - xInterruptsEnabled = pdFALSE; -} -/*-----------------------------------------------------------*/ - -void vPortEnableInterrupts( void ) -{ - DB_P("vPortEnableInterrupts\r\n"); - xInterruptsEnabled = pdTRUE; -} -/*-----------------------------------------------------------*/ - -portBASE_TYPE xPortSetInterruptMask( void ) -{ -portBASE_TYPE xReturn = xInterruptsEnabled; - DB_P("vPortsetInterruptMask\r\n"); - xInterruptsEnabled = pdFALSE; - return xReturn; -} -/*-----------------------------------------------------------*/ - -void vPortClearInterruptMask( portBASE_TYPE xMask ) -{ - DB_P("vPortClearInterruptMask\r\n"); - xInterruptsEnabled = xMask; -} -/*-----------------------------------------------------------*/ - - -void vPortSystemTickHandler( int sig ) -{ -pthread_t xTaskToSuspend; -pthread_t xTaskToResume; -portBASE_TYPE xInterruptValue; -tskTCB * oldTask, * newTask; -int lockResult; - - DB_P("vPortSystemTickHandler"); - xInterruptValue = xInterruptsEnabled; - debug_printf( "\r\n\r\n" ); - debug_printf( "(xInterruptsEnabled = %i, xServicingTick = %i)\r\n", (int) xInterruptValue != 0, (int) xServicingTick != 0); - if ( ( pdTRUE == xInterruptValue ) && ( pdTRUE != xServicingTick ) ) - { - debug_printf( "Checking for lock ...\r\n" ); - lockResult = pthread_mutex_trylock( &xSingleThreadMutex ); -// lockResult = 0; - debug_printf( "Done\r\n" ); - if ( 0 == lockResult) - { - 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() ); - - /* The only thread that can process this tick is the running thread. */ - if ( xTaskToSuspend != xTaskToResume ) - { - /* 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); - prvSuspendThread( xTaskToSuspend ); /* Suspend the current task. */ - debug_printf( "Swapped From %li(%s) to %li(%s)\r\n", (long int) xTaskToSuspend, oldTask->pcTaskName, (long int) xTaskToResume, newTask->pcTaskName); - } - xServicingTick = pdFALSE; - (void)pthread_mutex_unlock( &xSingleThreadMutex ); - } - else - { - debug_printf( "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( &xSingleThreadMutex ) ) - { - 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( &xSingleThreadMutex ); - } - else - { - /* Resume the other thread. */ - //prvResumeThread( xTaskToResume ); - assert( 0 ); - - /* Pthread Clean-up function will note the cancellation. */ - /* Release the execution. */ - uxCriticalNesting = 0; - vPortEnableInterrupts(); - (void)pthread_mutex_unlock( &xSingleThreadMutex ); - /* 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() ); - - xSentinel = 1; // tell creating block to resume - - /* 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); - - debug_printf( "Delaying before the pause to make sure system knows about task\r\n" ); - struct timespec x; - x.tv_sec=0; - x.tv_nsec=10000000; - nanosleep(&x,NULL); - - // wait for resume signal - debug_printf("Pausing newly created thread\r\n"); -// pthread_mutex_lock( &xRunningThread ); -// pauseThread(); - - while (1) { - if( pthread_self() == prvGetThreadHandle(xTaskGetCurrentTaskHandle() ) ) - { - // assert( 0 == pthread_mutex_lock( &xRunningThread ) ); - break; - } - else { - struct timespec x; - x.tv_sec=0; - x.tv_nsec=100000; - nanosleep(&x,NULL); - sched_yield(); - } - - } - - // no longer want to block any signals - sigemptyset( &xSignals ); - assert( pthread_sigmask( SIG_SETMASK, &xSignals, NULL ) == 0); - debug_printf("Starting first run\r\n"); - - //xHandover = 1; - //assert ( 0 == pthread_mutex_lock( &xSingleThreadMutex ) ) - - pvCode( pParams ); - - pthread_cleanup_pop( 1 ); - return (void *)NULL; -} -/*-----------------------------------------------------------*/ - -void pauseThread() -{ - debug_printf("\r\n"); - -// assert( 0 == pthread_mutex_unlock( &xRunningThread ) ); - while (1) { - if( pthread_self() == prvGetThreadHandle(xTaskGetCurrentTaskHandle() ) ) - { -// assert( 0 == pthread_mutex_lock( &xRunningThread ) ); - return; - } - else { - struct timespec x; - x.tv_sec=0; - x.tv_nsec=100000; - nanosleep(&x,NULL); - sched_yield(); - } - - } - xTaskHandle hTask = prvGetThreadTask( pthread_self() ); - pthread_cond_t hCond = prvGetThreadCondition( hTask ); - pthread_mutex_t hMutex = prvGetThreadMutex( hTask ); - // while( !shouldResume ) { - pthread_cond_wait( &hCond, &hMutex ); - assert( 0 == pthread_mutex_lock( &xRunningThread ) ); - // } -} - -void prvSuspendSignalHandler(int sig) -{ -sigset_t xBlockSignals; - - debug_printf( "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() ) ) 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); - - /* Unlock the Single thread mutex to allow the resumed task to continue. */ - //assert ( 0 == pthread_mutex_unlock( &xSingleThreadMutex ) ); - - // Set resume condition for specific thread -/* pthread_cond_t hCond = prvGetThreadCondition( xTaskGetCurrentTaskHandle() ); - assert( pthread_cond_signal( &hCond ) == 0 ); */ - - pauseThread(); - - while( pthread_self() != prvGetThreadHandle( xTaskGetCurrentTaskHandle() ) ) - { - debug_printf( "Incorrectly woke up. Repausing\r\n" ); - pauseThread(); - } - - /* 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 prvSuspendThread( pthread_t xThreadId ) -{ - debug_printf( "Suspending %li\r\n", (long int) xThreadId); - /* Set-up for the Suspend Signal handler? */ - xSentinel = 0; - - if( pthread_self() == xThreadId ) { - debug_printf( "Pausing self, no reason to call signal handler\r\n" ); - pauseThread(); - } - else { - debug_printf( "About to kill %li\r\n", (long int) xThreadId ); - assert( pthread_kill( xThreadId, SIG_SUSPEND ) == 0); - debug_printf( "Killed %li\r\n", (long int) xThreadId ); - } - - -// while ( ( xSentinel == 0 ) && ( pdTRUE != xServicingTick ) ) - { -// debug_printf( "sched_yield()\r\n" ); - sched_yield(); - } -} -/*-----------------------------------------------------------*/ - -/*void prvResumeSignalHandler(int sig) -{ - - DB_P("prvResumeSignalHandler\r\n"); - - debug_printf( "prvResumeSignalHandler getLock"); - while(1); - // Yield the Scheduler to ensure that the yielding thread completes. - if ( 0 == pthread_mutex_lock( &xSingleThreadMutex ) ) - { - debug_printf( "prvResumeSignalHandler: unlocking xSingleThreadMutex (%li)\r\n", (long int) pthread_self()); - (void)pthread_mutex_unlock( &xSingleThreadMutex ); - } -}*/ -/*-----------------------------------------------------------*/ - -/*void prvResumeThread( pthread_t xThreadId ) -{ -portBASE_TYPE xResult; - - DB_P("prvResumeThread\r\n"); - debug_printf( "getLock\r\n" ); - if ( 0 == pthread_mutex_lock( &xSuspendResumeThreadMutex ) ) - { - debug_printf( "Resuming %li\r\n", (long int) xThreadId ); - if ( pthread_self() != xThreadId ) - { - //xResult = pthread_kill( xThreadId, SIG_RESUME ); - debug_printf( "No longer doing anything. Suspend handler for previous thread should start %li\r\n", (long int) xThreadId ); - } - else { - debug_printf( "Thread attempting to resume itself. This is not expected behavior\r\n" ); - kill( getpid(), SIGKILL ); - } - - xResult = pthread_mutex_unlock( &xSuspendResumeThreadMutex ); - } - else { - debug_printf("Error getting lock to resume thread\r\n"); - kill( getpid(), SIGKILL ); - } - -} */ -/*-----------------------------------------------------------*/ - -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 prvGetThreadMutex( 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 prvGetThreadTask( pthread_t hThread ) -{ -xTaskHandle hTask; -portLONG lIndex; - - for ( lIndex = 0; lIndex < MAX_NUMBER_OF_TASKS; lIndex++ ) - { - if ( pxThreads[ lIndex ].hThread == hThread ) - { - hTask = pxThreads[ lIndex ].hTask; - break; - } - } - return hTask; -} - -/*-----------------------------------------------------------*/ -pthread_cond_t prvGetThreadCondition( xTaskHandle hTask ) -{ -pthread_cond_t hCond; -portLONG lIndex; - - for ( lIndex = 0; lIndex < MAX_NUMBER_OF_TASKS; lIndex++ ) - { - if ( pxThreads[ lIndex ].hTask == hTask ) - { - hCond = pxThreads[ lIndex ].hCond; - break; - } - } - return hCond; -} - -/*-----------------------------------------------------------*/ -pthread_t prvGetThreadHandle( xTaskHandle hTask ) -{ - pthread_t hThread = ( pthread_t )NULL; - portLONG lIndex; - - DB_P("prvGetThreadHandle\r\n"); - - 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; - - DB_P("prvGetFreeThreadState\r\n"); - - 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; - DB_P("prvSetTaskCriticalNesting\r\n"); - 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; - - DB_P("prvGetTaskCriticalNesting\r\n"); - - 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; - - DB_P("prvDeleteThread\r\n"); - - 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; - } - } - } -} -/*-----------------------------------------------------------*/ - -void vPortFindTicksPerSecond( void ) -{ - DB_P("vPortFindTicksPerSecond\r\n"); - - /* 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; - - DB_P("ulPortGetTimerValue\r\n"); - - 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; -} -/*-----------------------------------------------------------*/ diff --git a/flight/PiOS.posix/posix/Libraries/FreeRTOS/Source/portable/GCC/Posix/peabody124/port.c b/flight/PiOS.posix/posix/Libraries/FreeRTOS/Source/portable/GCC/Posix/peabody124/port.c deleted file mode 100644 index 128434fe3..000000000 --- a/flight/PiOS.posix/posix/Libraries/FreeRTOS/Source/portable/GCC/Posix/peabody124/port.c +++ /dev/null @@ -1,1085 +0,0 @@ -/* - 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 -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - - -/* 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_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 - -//#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( stderr, "%20s(%li)\t%20s\t%i: ",debug_task_handle->pcTaskName,(long)pthread_self(),__func__,__LINE__)): \ - (fprintf( stderr, "%20s(%li)\t%20s\t%i: ","__unknown__",(long)pthread_self(),__func__,__LINE__)) \ - |1)?( \ - ((fprintf( stderr, __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( stderr, "%20s(%li)\t%20s\t%i: ",debug_task_handle->pcTaskName,(long)pthread_self(),__func__,__LINE__)): \ - (fprintf( stderr, "%20s(%li)\t%20s\t%i: ","__unknown__",(long)pthread_self(),__func__,__LINE__)) \ - |1)?( \ - ((fprintf( stderr, __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 */ -// pthread_condattr_t condAttr; -// assert( 0 == pthread_condattr_init( &condAttr ) ); - 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 */ -// pthread_mutexattr_t mutexAttr; -// assert( 0 == pthread_mutexattr_init( &mutexAttr ) ); -// assert( 0 == pthread_mutexattr_settype( &mutexAttr, PTHREAD_MUTEX_ERRORCHECK ) ); - 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; - } - - /* Start the first task. Will not return unless all threads are killed. */ - vPortStartFirstTask(); - - struct timespec x; - usleep(1000000); - while( pdTRUE != xSchedulerEnd ) { - x.tv_sec=0; - x.tv_nsec=portTICK_RATE_MICROSECONDS * 1000; - nanosleep(&x,NULL); - //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"); - xInterruptsEnabled = pdFALSE; -} -/*-----------------------------------------------------------*/ - -void vPortEnableInterrupts( void ) -{ - //debug_printf("\r\n"); - xInterruptsEnabled = pdTRUE; -} -/*-----------------------------------------------------------*/ - -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() ); - -#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; -} -/*-----------------------------------------------------------*/ diff --git a/flight/PiOS.posix/posix/Libraries/FreeRTOS/Source/portable/GCC/Posix/peabody124/tasks.c b/flight/PiOS.posix/posix/Libraries/FreeRTOS/Source/portable/GCC/Posix/peabody124/tasks.c deleted file mode 100644 index 20f9ab309..000000000 --- a/flight/PiOS.posix/posix/Libraries/FreeRTOS/Source/portable/GCC/Posix/peabody124/tasks.c +++ /dev/null @@ -1,2332 +0,0 @@ -/* - 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 -#include -#include -#include -#include -#include - -/* Defining MPU_WRAPPERS_INCLUDED_FROM_API_FILE prevents task.h from redefining -all the API functions to use the MPU wrappers. That should only be done when -task.h is included from an application file. */ -#define MPU_WRAPPERS_INCLUDED_FROM_API_FILE - -#include "FreeRTOS.h" -#include "task.h" -#include "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 -/*-----------------------------------------------------------*/ - - - - diff --git a/flight/PiOS.posix/posix/Libraries/FreeRTOS/Source/portable/GCC/Posix/port.c b/flight/PiOS.posix/posix/Libraries/FreeRTOS/Source/portable/GCC/Posix/port.c new file mode 100644 index 000000000..1deb36cc7 --- /dev/null +++ b/flight/PiOS.posix/posix/Libraries/FreeRTOS/Source/portable/GCC/Posix/port.c @@ -0,0 +1,1092 @@ +/* + Copyright (C) 2011 Corvus Corax from OpenPilot.org + based on linux port from William Davy + + 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. + *----------------------------------------------------------*/ + + +/** Description of scheduler: + +This scheduler is based on posix signals to halt or preempt tasks, and on +pthread conditions to resume them. + +Each FreeRTOS thread is created as a posix thread, with a signal handler to +SIGUSR1 (SIG_SUSPEND) signals. + +Suspension of a thread is done by setting the threads state to +"YIELDING/PREEMPTING", then signaling the thread until the signal handler +changes that state to "SLEEPING", thus acknowledging the suspend. + +The thread will then wait within the signal handler for a thread specific +condition to be set, which allows it to resume operation, setting its state to +"RUNNING" + +The running thread also always holds a mutex (xRunningThreadMutex) which is +given up only when the thread suspends. + +On thread creation the new thread will acquire this mutex, then yield. + +Both preemption and yielding is done using the same mechanism, sending a +SIG_SUSPEND to the preempted thread respectively to itself, however different +synchronization safeguards apply depending if a thread suspends itself or is +suspended remotely + +Preemption is done by the main scheduler thread which attempts to run a tick +handler at accurate intervals using nanosleep and gettimeofday, which allows +more accurate high frequency ticks than a timer signal handler. + +All public functions in this port are protected by a safeguard mutex which +assures priority access on all data objects + +This approach is tested and works both on Linux and BSD style Unix (MAC OS X) + +*/ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/* Scheduler includes. */ +#include "FreeRTOS.h" +#include "task.h" +/*-----------------------------------------------------------*/ + +#define MAX_NUMBER_OF_TASKS ( _POSIX_THREAD_THREADS_MAX ) +/*-----------------------------------------------------------*/ + +#define PORT_PRINT(...) fprintf(stderr,__VA_ARGS__) +#define PORT_ASSERT(assertion) if ( !(assertion) ) { PORT_PRINT("Assertion failed in %s:%i " #assertion "\n",__FILE__,__LINE__); int volatile assfail=0; assfail=assfail/assfail; } + + +#define PORT_LOCK(mutex) PORT_ASSERT( 0 == pthread_mutex_lock(&(mutex)) ) +#define PORT_TRYLOCK(mutex) pthread_mutex_trylock(&(mutex)) +#define PORT_UNLOCK(mutex) PORT_ASSERT( 0 == pthread_mutex_unlock(&(mutex)) ) + + +/* 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; + xTaskHandle hTask; + unsigned portBASE_TYPE uxCriticalNesting; + pthread_mutex_t threadSleepMutex; + pthread_cond_t threadSleepCond; + volatile enum {THREAD_SLEEPING,THREAD_RUNNING,THREAD_STARTING,THREAD_YIELDING,THREAD_PREEMPTING,THREAD_WAKING} threadStatus; +} xThreadState; +/*-----------------------------------------------------------*/ + +/* Needed to keep track of critical section depth before scheduler got started */ +static xThreadState xDummyThread = { .uxCriticalNesting=0, .threadStatus=THREAD_RUNNING }; + +static xThreadState *pxThreads = NULL; +static pthread_once_t hSigSetupThread = PTHREAD_ONCE_INIT; +static pthread_attr_t xThreadAttributes; +static pthread_mutex_t xRunningThreadMutex = PTHREAD_MUTEX_INITIALIZER; +static pthread_mutex_t xYieldingThreadMutex = PTHREAD_MUTEX_INITIALIZER; +static pthread_mutex_t xResumingThreadMutex = PTHREAD_MUTEX_INITIALIZER; +static pthread_mutex_t xGuardMutex = PTHREAD_MUTEX_INITIALIZER; +/*-----------------------------------------------------------*/ + +static volatile portBASE_TYPE xSchedulerEnd = pdFALSE; +static volatile portBASE_TYPE xSchedulerStarted = pdFALSE; +static volatile portBASE_TYPE xInterruptsEnabled = pdFALSE; +static volatile portBASE_TYPE xSchedulerNesting = 0; +static volatile portBASE_TYPE xPendYield = pdFALSE; +static volatile portLONG lIndexOfLastAddedTask = 0; +/*-----------------------------------------------------------*/ + +/* + * Setup the timer to generate the tick interrupts. + */ +static void *prvWaitForStart( void * pvParams ); +static void prvSuspendSignalHandler(int sig); +static void prvSetupSignalsAndSchedulerPolicy( void ); +static void prvResumeThread( xThreadState* xThreadId ); +static xThreadState* prvGetThreadHandle( xTaskHandle hTask ); +static xThreadState* prvGetThreadHandleByThread( pthread_t hThread ); +static portLONG prvGetFreeThreadState( void ); +static void prvDeleteThread( void *xThreadId ); +static void prvPortYield(); +/*-----------------------------------------------------------*/ + +/* + * Exception handlers. + */ +void vPortYield( void ); +void vPortSystemTickHandler( void ); + +/* + * Start first task is a separate function so it can be tested in isolation. + */ +void vPortStartFirstTask( void ); +/*-----------------------------------------------------------*/ + +/** + * inline macro functions + * (easierto debug than macros) + */ +static inline void PORT_ENTER() { + while( prvGetThreadHandleByThread(pthread_self())->threadStatus!=THREAD_RUNNING) sched_yield(); + PORT_LOCK( xGuardMutex ); + PORT_ASSERT( xSchedulerStarted?( prvGetThreadHandleByThread(pthread_self())==prvGetThreadHandle(xTaskGetCurrentTaskHandle()) ):pdTRUE ) +} + +static inline void PORT_LEAVE() { + PORT_ASSERT( xSchedulerStarted?( prvGetThreadHandleByThread(pthread_self())==prvGetThreadHandle(xTaskGetCurrentTaskHandle()) ):pdTRUE ); + PORT_ASSERT( prvGetThreadHandleByThread(pthread_self())->threadStatus==THREAD_RUNNING ); + PORT_UNLOCK( xGuardMutex ); +} + +/*-----------------------------------------------------------*/ + +/** + * Creates a new thread. + */ +portSTACK_TYPE *pxPortInitialiseStack( portSTACK_TYPE *pxTopOfStack, pdTASK_CODE pxCode, void *pvParameters ) +{ + /* Should actually keep this struct on the stack. */ + xParams *pxThisThreadParams = pvPortMalloc( sizeof( xParams ) ); + + /* Initialize scheduler during first call */ + (void)pthread_once( &hSigSetupThread, prvSetupSignalsAndSchedulerPolicy ); + + /** + * port enter needs to be delayed since pvPortMalloc() and + * SetupSignalsAndSchedulerPolicy() both call critical section code + */ + PORT_ENTER(); + + /* 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; + + lIndexOfLastAddedTask = prvGetFreeThreadState(); + + PORT_LOCK( xYieldingThreadMutex ); + + pxThreads[ lIndexOfLastAddedTask ].threadStatus = THREAD_STARTING; + pxThreads[ lIndexOfLastAddedTask ].uxCriticalNesting = 0; + + /* create the thead */ + PORT_ASSERT( 0 == pthread_create( &( pxThreads[ lIndexOfLastAddedTask ].hThread ), &xThreadAttributes, prvWaitForStart, (void *)pxThisThreadParams ) ); + + /* Let the task run a bit and wait until it suspends. */ + while ( pxThreads[ lIndexOfLastAddedTask ].threadStatus == THREAD_STARTING ) sched_yield(); + + /* this ensures the sleeping thread reached deep sleep (and not more) */ + PORT_UNLOCK( xYieldingThreadMutex ); + + PORT_LEAVE(); + + return pxTopOfStack; +} +/*-----------------------------------------------------------*/ + +/** + * Initially the schedulers main thread holds the running thread mutex. + * it needs to be given up, to allow the first running task to execute + */ +void vPortStartFirstTask( void ) +{ + /* Mark scheduler as started */ + xSchedulerStarted = pdTRUE; + + /* Start the first task. */ + prvResumeThread( prvGetThreadHandle( xTaskGetCurrentTaskHandle() ) ); + + /* Give up running thread handle */ + PORT_UNLOCK(xRunningThreadMutex); +} +/*-----------------------------------------------------------*/ + +/** + * After tasks have been set up the main thread goes into a sleeping loop, but + * allows to be interrupted by timer ticks. + */ +portBASE_TYPE xPortStartScheduler( void ) +{ + portBASE_TYPE xResult; + sigset_t xSignalToBlock; + + /** + * note: NO PORT_ENTER ! - this is the supervisor thread which runs outside + * of the schedulers context + */ + + /* do not respond to SUSPEND signal (but all others) */ + sigemptyset( &xSignalToBlock ); + (void)pthread_sigmask( SIG_SETMASK, &xSignalToBlock, NULL ); + sigemptyset(&xSignalToBlock); + sigaddset(&xSignalToBlock,SIG_SUSPEND); + (void)pthread_sigmask(SIG_BLOCK, &xSignalToBlock, NULL); + + /* Start the first task. This gives up the RunningThreadMutex*/ + vPortStartFirstTask(); + + /** + * Main scheduling loop. Call the tick handler every + * portTICK_RATE_MICROSECONDS + */ + portLONG sleepTimeUS = portTICK_RATE_MICROSECONDS; + portLONG actualSleepTime; + struct timeval lastTime,currentTime; + gettimeofday( &lastTime, NULL ); + struct timespec wait; + + while ( pdTRUE != xSchedulerEnd ) + { + /* wait for the specified wait time */ + wait.tv_sec = sleepTimeUS / 1000000; + wait.tv_nsec = 1000 * ( sleepTimeUS % 1000000 ); + nanosleep( &wait, NULL ); + + /* check the time */ + gettimeofday( ¤tTime, NULL); + actualSleepTime = 1000000 * ( currentTime.tv_sec - lastTime.tv_sec ) + ( currentTime.tv_usec - lastTime.tv_usec ); + + /* only hit the tick if we slept at least half the period */ + if ( actualSleepTime >= sleepTimeUS/2 ) { + + vPortSystemTickHandler(); + + /* check the time again */ + gettimeofday( ¤tTime, NULL); + actualSleepTime = 1000000 * ( currentTime.tv_sec - lastTime.tv_sec ) + ( currentTime.tv_usec - lastTime.tv_usec ); + + /* sleep until the next tick is due */ + sleepTimeUS += portTICK_RATE_MICROSECONDS; + } + + /* reduce remaining sleep time by the slept time */ + sleepTimeUS -= actualSleepTime; + lastTime = currentTime; + + /* safety checks */ + if (sleepTimeUS <=0 || sleepTimeUS >= 3 * portTICK_RATE_MICROSECONDS) sleepTimeUS = portTICK_RATE_MICROSECONDS; + + } + + PORT_PRINT( "Cleaning Up, Exiting.\n" ); + /* Cleanup the mutexes */ + xResult = pthread_mutex_destroy( &xRunningThreadMutex ); + xResult = pthread_mutex_destroy( &xYieldingThreadMutex ); + xResult = pthread_mutex_destroy( &xGuardMutex ); + vPortFree( (void *)pxThreads ); + + /* Should not get here! */ + return 0; +} +/*-----------------------------------------------------------*/ + +/** + * quickly clean up all running threads, without asking them first + */ +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; +} +/*-----------------------------------------------------------*/ + +/** + * we must assume this one is called from outside the schedulers context + * (ISR's, signal handlers, or non-freertos threads) + * we cannot safely assume mutual exclusion + */ +void vPortYieldFromISR( void ) +{ + xPendYield = pdTRUE; +} +/*-----------------------------------------------------------*/ + +/** + * enter a critical section (public) + */ +void vPortEnterCritical( void ) +{ + PORT_ENTER(); + xInterruptsEnabled = pdFALSE; + prvGetThreadHandleByThread(pthread_self())->uxCriticalNesting++; + PORT_LEAVE(); +} +/*-----------------------------------------------------------*/ + +/** + * leave a critical section (public) + */ +void vPortExitCritical( void ) +{ + PORT_ENTER(); + + /* Check for unmatched exits. */ + PORT_ASSERT( prvGetThreadHandleByThread(pthread_self())->uxCriticalNesting > 0 ); + if ( prvGetThreadHandleByThread(pthread_self())->uxCriticalNesting > 0 ) + { + prvGetThreadHandleByThread(pthread_self())->uxCriticalNesting--; + } + + /* If we have reached 0 then re-enable the interrupts. */ + if( prvGetThreadHandleByThread(pthread_self())->uxCriticalNesting == 0 ) + { + /* Have we missed ticks? This is the equivalent of pending an interrupt. */ + if ( pdTRUE == xPendYield ) + { + xPendYield = pdFALSE; + prvPortYield(); + } + + xInterruptsEnabled = pdTRUE; + + } + + PORT_LEAVE(); +} +/*-----------------------------------------------------------*/ + +/** + * code to self-yield a task + * (without the mutex encapsulation) + * for internal use + */ +void prvPortYield() +{ + xThreadState *xTaskToSuspend, *xTaskToResume; + + /* timer handler should NOT get in our way (just in case) */ + xInterruptsEnabled = pdFALSE; + + /* suspend the current task */ + xTaskToSuspend = prvGetThreadHandleByThread( pthread_self() ); + + /** + * make sure not to suspend threads that are already trying to do so + */ + PORT_ASSERT( xTaskToSuspend->threadStatus == THREAD_RUNNING ); + + /** + * FreeRTOS switch context + */ + vTaskSwitchContext(); + + /** + * find out which task to resume + */ + xTaskToResume = prvGetThreadHandle( xTaskGetCurrentTaskHandle() ); + if ( xTaskToSuspend != xTaskToResume ) + { + /* Resume the other thread first */ + prvResumeThread( xTaskToResume ); + + /* prepare the current task for yielding */ + xTaskToSuspend->threadStatus = THREAD_YIELDING; + + /** + * Send signals until the signal handler acknowledges. How long that takes + * depends on the systems signal implementation. During a preemption we + * will see the actual THREAD_SLEEPING STATE - but when yielding we + * would only see a future THREAD_RUNNING after having woken up - both is + * OK + */ + while ( xTaskToSuspend->threadStatus == THREAD_YIELDING ) { + pthread_kill( xTaskToSuspend->hThread, SIG_SUSPEND ); + sched_yield(); + } + + /** + * mark: once we reach this point, the task has already slept and awaken anew + */ + + } else { + /** + * no context switch - keep running + */ + if (xTaskToResume->uxCriticalNesting==0) { + xInterruptsEnabled = pdTRUE; + } + } + +} +/*-----------------------------------------------------------*/ + +/** + * public yield function - secure + */ +void vPortYield( void ) +{ + PORT_ENTER(); + + prvPortYield(); + + PORT_LEAVE(); +} +/*-----------------------------------------------------------*/ + +/** + * public function to disable interrupts + */ +void vPortDisableInterrupts( void ) +{ + PORT_ENTER(); + + xInterruptsEnabled = pdFALSE; + + PORT_LEAVE(); +} +/*-----------------------------------------------------------*/ + +/** + * public function to enable interrupts + */ +void vPortEnableInterrupts( void ) +{ + PORT_ENTER(); + + /** + * It is bad practice to enable interrupts explicitly while in a critical section + * most likely this is a bug - better prevent the userspace from being stupid + */ + PORT_ASSERT( prvGetThreadHandleByThread(pthread_self())->uxCriticalNesting == 0 ); + + xInterruptsEnabled = pdTRUE; + + PORT_LEAVE(); +} +/*-----------------------------------------------------------*/ + +/** + * set and clear interrupt masks are used by FreeRTOS to enter and leave critical sections + * with unknown nexting level - but we DO know the nesting level + */ +portBASE_TYPE xPortSetInterruptMask( void ) +{ + portBASE_TYPE xReturn; + + PORT_ENTER(); + + xReturn = xInterruptsEnabled; + + xInterruptsEnabled = pdFALSE; + + prvGetThreadHandleByThread(pthread_self())->uxCriticalNesting++; + + PORT_LEAVE(); + + return xReturn; +} +/*-----------------------------------------------------------*/ + +/** + * sets the "interrupt mask back to a stored setting + */ +void vPortClearInterruptMask( portBASE_TYPE xMask ) +{ + PORT_ENTER(); + + /** + * we better make sure the calling code behaves + * if it doesn't it might indicate something went seriously wrong + */ + PORT_ASSERT( xMask == pdTRUE || xMask == pdFALSE ); + PORT_ASSERT( + ( prvGetThreadHandleByThread(pthread_self())->uxCriticalNesting == 1 && xMask==pdTRUE ) + || + ( prvGetThreadHandleByThread(pthread_self())->uxCriticalNesting > 1 && xMask==pdFALSE ) + ); + + xInterruptsEnabled = xMask; + if (prvGetThreadHandleByThread(pthread_self())->uxCriticalNesting>0) { + prvGetThreadHandleByThread(pthread_self())->uxCriticalNesting--; + } + + PORT_LEAVE(); +} + +/*-----------------------------------------------------------*/ + +/** + * the tick handler is just an ordinary function, called by the supervisor thread periodically + */ +void vPortSystemTickHandler() +{ + /** + * the problem with the tick handler is, that it runs outside of the schedulers domain - worse, + * on a multi core machine there might be a task running *right now* + * - we need to stop it in order to do anything. However we need to make sure we are able to first + */ + PORT_LOCK( xGuardMutex ); + + /* thread MUST be running */ + if ( prvGetThreadHandle(xTaskGetCurrentTaskHandle())->threadStatus!=THREAD_RUNNING ) { + xPendYield = pdTRUE; + PORT_UNLOCK( xGuardMutex ); + return; + } + + /* interrupts MUST be enabled */ + if ( xInterruptsEnabled != pdTRUE ) { + xPendYield = pdTRUE; + PORT_UNLOCK( xGuardMutex ); + return; + } + + /* this should always be true, but it can't harm to check */ + PORT_ASSERT( prvGetThreadHandle(xTaskGetCurrentTaskHandle())->uxCriticalNesting==0 ); + + /* acquire switching mutex for synchronization */ + PORT_LOCK(xYieldingThreadMutex); + + xThreadState *xTaskToSuspend = prvGetThreadHandle( xTaskGetCurrentTaskHandle() ); + + + /** + * halt current task - this means NO task is running! + * Send signals until the signal handler acknowledges. how long that takes + * depends on the systems signal implementation. During a preemption we + * will see the actual THREAD_SLEEPING STATE when yielding we would only + * see a future THREAD_RUNNING after having woken up both is OK + * note: we do NOT give up switchingThreadMutex! + */ + xTaskToSuspend->threadStatus = THREAD_PREEMPTING; + while ( xTaskToSuspend->threadStatus != THREAD_SLEEPING ) { + pthread_kill( xTaskToSuspend->hThread, SIG_SUSPEND ); + sched_yield(); + } + + /** + * synchronize and acquire the running thread mutex + */ + PORT_UNLOCK( xYieldingThreadMutex ); + PORT_LOCK( xRunningThreadMutex ); + + /** + * now the tick handler runs INSTEAD of the currently active thread + * - even on a multicore system + * failure to do so can lead to unexpected results during + * vTaskIncrementTick()... + */ + + /** + * call tick handler + */ + vTaskIncrementTick(); + + +#if ( configUSE_PREEMPTION == 1 ) + /** + * while we are here we can as well switch the running thread + */ + vTaskSwitchContext(); + + xTaskToSuspend = prvGetThreadHandle( xTaskGetCurrentTaskHandle() ); +#endif + + /** + * wake up the task (again) + */ + prvResumeThread( xTaskToSuspend ); + + /** + * give control to the userspace task + */ + PORT_UNLOCK( xRunningThreadMutex ); + + /* finish up */ + PORT_UNLOCK( xGuardMutex ); +} +/*-----------------------------------------------------------*/ + +/** + * thread kill implementation + */ +void vPortForciblyEndThread( void *pxTaskToDelete ) +{ +xTaskHandle hTaskToDelete = ( xTaskHandle )pxTaskToDelete; +xThreadState* xTaskToDelete; +xThreadState* xTaskToResume; +portBASE_TYPE xResult; + + PORT_ENTER(); + + xTaskToDelete = prvGetThreadHandle( hTaskToDelete ); + xTaskToResume = prvGetThreadHandle( xTaskGetCurrentTaskHandle() ); + + PORT_ASSERT( xTaskToDelete ); + PORT_ASSERT( xTaskToResume ); + + if ( xTaskToResume == xTaskToDelete ) + { + /* This is a suicidal thread, need to select a different task to run. */ + vTaskSwitchContext(); + xTaskToResume = prvGetThreadHandle( xTaskGetCurrentTaskHandle() ); + } + + if ( pthread_self() != xTaskToDelete->hThread ) + { + /* Cancelling a thread that is not me. */ + + /* Send a signal to wake the task so that it definitely cancels. */ + pthread_testcancel(); + xResult = pthread_cancel( xTaskToDelete->hThread ); + + } + else + { + /* Resume the other thread. */ + prvResumeThread( xTaskToResume ); + /* Pthread Clean-up function will note the cancellation. */ + /* Release the execution. */ + + PORT_UNLOCK( xRunningThreadMutex ); + + //PORT_LEAVE(); + PORT_UNLOCK( xGuardMutex ); + /* Commit suicide */ + pthread_exit( (void *)1 ); + } + PORT_LEAVE(); +} +/*-----------------------------------------------------------*/ + +/** + * any new thread first acquires the runningThreadMutex, but then suspends + * immediately, giving control back to the thread starting the new one + */ +void *prvWaitForStart( void * pvParams ) +{ + xParams * pxParams = ( xParams * )pvParams; + pdTASK_CODE pvCode = pxParams->pxCode; + void * pParams = pxParams->pvParams; + sigset_t xSignalToBlock; + xThreadState * myself = prvGetThreadHandleByThread( pthread_self() ); + + pthread_cleanup_push( prvDeleteThread, (void *)pthread_self() ); + + /* do respond to signals */ + sigemptyset( &xSignalToBlock ); + (void)pthread_sigmask( SIG_SETMASK, &xSignalToBlock, NULL ); + + /** + * Suspend ourselves. It's important to do that first + * because until we come back from this we run outside the schedulers scope + * and can't call functions like vPortFree() safely + */ + while ( myself->threadStatus == THREAD_STARTING ) { + pthread_kill( myself->hThread, SIG_SUSPEND ); + sched_yield(); + } + + /** + * now we have returned from the dead - reborn as a real thread inside the + * schedulers scope. + */ + vPortFree( pvParams ); + + /* run the actual payload */ + pvCode( pParams ); + + pthread_cleanup_pop( 1 ); + return (void *)NULL; +} +/*-----------------------------------------------------------*/ + +/** + * The suspend signal handler is called when a thread gets a SIGSUSPEND + * signal, which is supposed to send it to sleep + */ +void prvSuspendSignalHandler(int sig) +{ + + portBASE_TYPE hangover; + + /* make sure who we are */ + xThreadState* myself = prvGetThreadHandleByThread(pthread_self()); + PORT_ASSERT( myself ); + + /* make sure we are actually supposed to sleep */ + if (myself->threadStatus != THREAD_YIELDING && myself->threadStatus != THREAD_STARTING && myself->threadStatus != THREAD_PREEMPTING ) { + /* Spurious signal has arrived, we are not really supposed to halt. + * Not a real problem, we can safely ignore that. */ + return; + } + + /* we need that to wake up later (cond_wait needs a mutex locked) */ + PORT_LOCK(myself->threadSleepMutex); + + /* even waking up is a bit different depending on how we went to sleep */ + hangover = myself->threadStatus; + + myself->threadStatus = THREAD_SLEEPING; + + if ( hangover == THREAD_STARTING ) { + /** + * Synchronization with spawning thread through YieldingMutex + * This thread does NOT have the running thread mutex + * because it never officially ran before. + * It will get that mutex on wakeup though. + */ + PORT_LOCK(xYieldingThreadMutex); + PORT_UNLOCK(xYieldingThreadMutex); + } else if ( hangover == THREAD_YIELDING) { + /** + * The caller is the same thread as the signal handler. + * No synchronization possible or needed. + * But we need to unlock the mutexes it holds, so + * other threads can run. + */ + PORT_UNLOCK(xRunningThreadMutex ); + PORT_UNLOCK(xGuardMutex ); + } else if ( hangover == THREAD_PREEMPTING) { + /** + * The caller is the tick handler. + * Use YieldingMutex for synchronization + * Give up RunningThreadMutex, so the tick handler + * can take it and start another thread. + */ + PORT_LOCK(xYieldingThreadMutex); + PORT_UNLOCK(xRunningThreadMutex ); + PORT_UNLOCK(xYieldingThreadMutex); + } + + /* deep sleep until wake condition is met*/ + pthread_cond_wait( &myself->threadSleepCond, &myself->threadSleepMutex ); + + /* waking */ + myself->threadStatus = THREAD_WAKING; + + /* synchronize with waker - quick assertion if the right thread got the condition sent to*/ + PORT_LOCK(xResumingThreadMutex); + PORT_ASSERT(prvGetThreadHandle( xTaskGetCurrentTaskHandle())==myself); + PORT_UNLOCK(xResumingThreadMutex); + + /* we don't need that condition mutex anymore */ + PORT_UNLOCK(myself->threadSleepMutex); + + /* we ARE the running thread now (the one and only) */ + PORT_LOCK(xRunningThreadMutex); + + /** + * and we have important stuff to do, nobody should interfere with + * ( GuardMutex is usually set by PORT_ENTER() ) + * */ + PORT_LOCK( xGuardMutex ); + if ( myself->uxCriticalNesting == 0 ) + { + xInterruptsEnabled = pdTRUE; + } + else + { + xInterruptsEnabled = pdFALSE; + } + + myself->threadStatus = THREAD_RUNNING; + + /** + * if we jump back to user code, we are done with important stuff, + * but if we had yielded we are still in protected code after returning. + **/ + if (hangover!=THREAD_YIELDING) { + PORT_UNLOCK( xGuardMutex ); + } + +} +/*-----------------------------------------------------------*/ + +/** + * Signal the condition. + * Unlike pthread_kill this actually is supposed to be reliable, so we need no + * checks on the outcome. + */ +void prvResumeThread( xThreadState* xThreadId ) +{ + PORT_ASSERT( xThreadId ); + + PORT_LOCK( xResumingThreadMutex ); + + PORT_ASSERT(xThreadId->threadStatus == THREAD_SLEEPING); + + /** + * Unfortunately "is supposed to" does not hold on all Posix-ish systems + * but sending the cond_signal again doesn't hurt anyone. + */ + while ( xThreadId->threadStatus != THREAD_WAKING ) { + pthread_cond_signal(& xThreadId->threadSleepCond); + sched_yield(); + } + + PORT_UNLOCK( xResumingThreadMutex ); + +} +/*-----------------------------------------------------------*/ + +/** + * this is init code executed the first time a thread is created + */ +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; + + pxThreads = ( xThreadState *)pvPortMalloc( sizeof( xThreadState ) * MAX_NUMBER_OF_TASKS ); + + const pthread_cond_t cinit = PTHREAD_COND_INITIALIZER; + const pthread_mutex_t minit = PTHREAD_MUTEX_INITIALIZER; + for ( lIndex = 0; lIndex < MAX_NUMBER_OF_TASKS; lIndex++ ) + { + pxThreads[ lIndex ].hThread = ( pthread_t )NULL; + pxThreads[ lIndex ].hTask = ( xTaskHandle )NULL; + pxThreads[ lIndex ].uxCriticalNesting = 0; + pxThreads[ lIndex ].threadSleepMutex = minit; + pxThreads[ lIndex ].threadSleepCond = cinit; + } + + sigsuspendself.sa_flags = 0; + sigsuspendself.sa_handler = prvSuspendSignalHandler; + sigfillset( &sigsuspendself.sa_mask ); + + if ( 0 != sigaction( SIG_SUSPEND, &sigsuspendself, NULL ) ) + { + PORT_PRINT( "Problem installing SIG_SUSPEND_SELF\n" ); + } + PORT_PRINT( "Running as PID: %d\n", getpid() ); + + /* When scheduler is set up main thread first claims the running thread mutex */ + PORT_LOCK( xRunningThreadMutex ); + +} +/*-----------------------------------------------------------*/ + +/** + * get a thread handle based on a task handle + */ +xThreadState* prvGetThreadHandle( xTaskHandle hTask ) +{ +portLONG lIndex; +if (!pxThreads) return NULL; + for ( lIndex = 0; lIndex < MAX_NUMBER_OF_TASKS; lIndex++ ) + { + if ( pxThreads[ lIndex ].hTask == hTask ) + { + return &pxThreads[ lIndex ]; + break; + } + } + return NULL; +} +/*-----------------------------------------------------------*/ + +/** + * get a thread handle based on a posix thread handle + */ +xThreadState* prvGetThreadHandleByThread( pthread_t hThread ) +{ +portLONG lIndex; + /** + * if the scheduler is NOT yet started, we can give back a dummy thread handle + * to allow keeping track of interrupt nesting. + * However once the scheduler is started we return a NULL, + * so any misbehaving code can nicely segfault. + */ + if (!xSchedulerStarted && !pxThreads) return &xDummyThread; + if (!pxThreads) return NULL; + for ( lIndex = 0; lIndex < MAX_NUMBER_OF_TASKS; lIndex++ ) + { + if ( pxThreads[ lIndex ].hThread == hThread ) + { + return &pxThreads[ lIndex ]; + } + } + if (!xSchedulerStarted) return &xDummyThread; + return NULL; +} +/*-----------------------------------------------------------*/ + +/* next free task handle */ +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 ) + { + PORT_PRINT( "No more free threads, please increase the maximum.\n" ); + lIndex = 0; + vPortEndScheduler(); + } + + return lIndex; +} + +/*-----------------------------------------------------------*/ + +/** + * delete a thread from the list + */ +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 ) + { + //vPortEnableInterrupts(); + xInterruptsEnabled = pdTRUE; + } + pxThreads[ lIndex ].uxCriticalNesting = 0; + break; + } + } +} +/*-----------------------------------------------------------*/ + +/** + * add a thread to the list + */ +void vPortAddTaskHandle( void *pxTaskHandle ) +{ +portLONG lIndex; + + 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; + } + } + } +} +/*-----------------------------------------------------------*/ + +/** + * find out system speed + */ +void vPortFindTicksPerSecond( void ) +{ + /* Needs to be reasonably high for accuracy. */ + unsigned long ulTicksPerSecond = sysconf(_SC_CLK_TCK); + PORT_PRINT( "Timer Resolution for Run TimeStats is %ld ticks per second.\n", ulTicksPerSecond ); +} +/*-----------------------------------------------------------*/ + +/** + * timer stuff + */ +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; +} +/*-----------------------------------------------------------*/ + diff --git a/flight/PiOS.posix/posix/Libraries/FreeRTOS/Source/portable/GCC/Posix/port_linux.c b/flight/PiOS.posix/posix/Libraries/FreeRTOS/Source/portable/GCC/Posix/port_linux.c deleted file mode 100644 index 639dd1d33..000000000 --- a/flight/PiOS.posix/posix/Libraries/FreeRTOS/Source/portable/GCC/Posix/port_linux.c +++ /dev/null @@ -1,774 +0,0 @@ -/* - 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 -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -/* Scheduler includes. */ -#include "FreeRTOS.h" -#include "task.h" -/*-----------------------------------------------------------*/ - -#define MAX_NUMBER_OF_TASKS ( _POSIX_THREAD_THREADS_MAX ) -/*-----------------------------------------------------------*/ - -/* 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; - xTaskHandle hTask; - unsigned portBASE_TYPE uxCriticalNesting; -} xThreadState; -/*-----------------------------------------------------------*/ - -static xThreadState *pxThreads; -static pthread_once_t hSigSetupThread = PTHREAD_ONCE_INIT; -static pthread_attr_t xThreadAttributes; -static pthread_mutex_t xSuspendResumeThreadMutex = PTHREAD_MUTEX_INITIALIZER; -static pthread_mutex_t xSingleThreadMutex = PTHREAD_MUTEX_INITIALIZER; -static pthread_t hMainThread = ( pthread_t )NULL; -/*-----------------------------------------------------------*/ - -static volatile portBASE_TYPE xSentinel = 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 prvSetupTimerInterrupt( void ); -static void *prvWaitForStart( void * pvParams ); -static void prvSuspendSignalHandler(int sig); -static void prvResumeSignalHandler(int sig); -static void prvSetupSignalsAndSchedulerPolicy( void ); -static void prvSuspendThread( pthread_t xThreadId ); -static void prvResumeThread( pthread_t xThreadId ); -static pthread_t prvGetThreadHandle( xTaskHandle hTask ); -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 ); - -/* - * Start first task is a separate function so it can be tested in isolation. - */ -void vPortStartFirstTask( void ); -/*-----------------------------------------------------------*/ - -/* - * 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 ) ); - - (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(); - - /* Create the new pThread. */ - if ( 0 == pthread_mutex_lock( &xSingleThreadMutex ) ) - { - xSentinel = 0; - if ( 0 != pthread_create( &( pxThreads[ lIndexOfLastAddedTask ].hThread ), &xThreadAttributes, prvWaitForStart, (void *)pxThisThreadParams ) ) - { - /* Thread create failed, signal the failure */ - pxTopOfStack = 0; - } - - /* Wait until the task suspends. */ - (void)pthread_mutex_unlock( &xSingleThreadMutex ); - while ( xSentinel == 0 ); - vPortExitCritical(); - } - - return pxTopOfStack; -} -/*-----------------------------------------------------------*/ - -void vPortStartFirstTask( void ) -{ - /* Initialise the critical nesting count ready for the first task. */ - uxCriticalNesting = 0; - - /* Start the first task. */ - vPortEnableInterrupts(); - - /* Start the first task. */ - prvResumeThread( prvGetThreadHandle( xTaskGetCurrentTaskHandle() ) ); -} -/*-----------------------------------------------------------*/ - -/* - * See header file for description. - */ -portBASE_TYPE xPortStartScheduler( void ) -{ -portBASE_TYPE xResult; -int iSignal; -sigset_t xSignals; -sigset_t xSignalToBlock; -sigset_t xSignalsBlocked; -portLONG lIndex; - - /* Establish the signals to block before they are needed. */ - sigfillset( &xSignalToBlock ); - - /* Block until the end */ - (void)pthread_sigmask( SIG_SETMASK, &xSignalToBlock, &xSignalsBlocked ); - - for ( lIndex = 0; lIndex < MAX_NUMBER_OF_TASKS; lIndex++ ) - { - pxThreads[ lIndex ].uxCriticalNesting = 0; - } - - /* Start the timer that generates the tick ISR. Interrupts are disabled - here already. */ - prvSetupTimerInterrupt(); - - /* Start the first task. Will not return unless all threads are killed. */ - vPortStartFirstTask(); - - /* This is the end signal we are looking for. */ - sigemptyset( &xSignals ); - sigaddset( &xSignals, SIG_RESUME ); - - while ( pdTRUE != xSchedulerEnd ) - { - if ( 0 != sigwait( &xSignals, &iSignal ) ) - { - printf( "Main thread spurious signal: %d\n", iSignal ); - } - } - - printf( "Cleaning Up, Exiting.\n" ); - /* Cleanup the mutexes */ - xResult = pthread_mutex_destroy( &xSuspendResumeThreadMutex ); - xResult = pthread_mutex_destroy( &xSingleThreadMutex ); - 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 - * xSingleThreadMutex 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; - - if ( 0 == pthread_mutex_lock( &xSingleThreadMutex ) ) - { - xTaskToSuspend = prvGetThreadHandle( xTaskGetCurrentTaskHandle() ); - - vTaskSwitchContext(); - - xTaskToResume = prvGetThreadHandle( xTaskGetCurrentTaskHandle() ); - if ( xTaskToSuspend != xTaskToResume ) - { - /* Remember and switch the critical nesting. */ - prvSetTaskCriticalNesting( xTaskToSuspend, uxCriticalNesting ); - uxCriticalNesting = prvGetTaskCriticalNesting( xTaskToResume ); - /* Switch tasks. */ - prvResumeThread( xTaskToResume ); - prvSuspendThread( xTaskToSuspend ); - } - else - { - /* Yielding to self */ - (void)pthread_mutex_unlock( &xSingleThreadMutex ); - } - } -} -/*-----------------------------------------------------------*/ - -void vPortDisableInterrupts( void ) -{ - xInterruptsEnabled = pdFALSE; -} -/*-----------------------------------------------------------*/ - -void vPortEnableInterrupts( void ) -{ - xInterruptsEnabled = pdTRUE; -} -/*-----------------------------------------------------------*/ - -portBASE_TYPE xPortSetInterruptMask( void ) -{ -portBASE_TYPE xReturn = xInterruptsEnabled; - xInterruptsEnabled = pdFALSE; - return xReturn; -} -/*-----------------------------------------------------------*/ - -void vPortClearInterruptMask( portBASE_TYPE xMask ) -{ - xInterruptsEnabled = xMask; -} -/*-----------------------------------------------------------*/ - -/* - * Setup the systick timer to generate the tick interrupts at the required - * frequency. - */ -void prvSetupTimerInterrupt( void ) -{ -struct itimerval itimer, oitimer; -portTickType xMicroSeconds = portTICK_RATE_MICROSECONDS; - - /* Initialise the structure with the current timer information. */ - if ( 0 == getitimer( TIMER_TYPE, &itimer ) ) - { - /* Set the interval between timer events. */ - itimer.it_interval.tv_sec = 0; - itimer.it_interval.tv_usec = xMicroSeconds; - - /* Set the current count-down. */ - itimer.it_value.tv_sec = 0; - itimer.it_value.tv_usec = xMicroSeconds; - - /* Set-up the timer interrupt. */ - if ( 0 != setitimer( TIMER_TYPE, &itimer, &oitimer ) ) - { - printf( "Set Timer problem.\n" ); - } - } - else - { - printf( "Get Timer problem.\n" ); - } -} -/*-----------------------------------------------------------*/ - -void vPortSystemTickHandler( int sig ) -{ -pthread_t xTaskToSuspend; -pthread_t xTaskToResume; - - if ( ( pdTRUE == xInterruptsEnabled ) && ( pdTRUE != xServicingTick ) ) - { - if ( 0 == pthread_mutex_trylock( &xSingleThreadMutex ) ) - { - xServicingTick = pdTRUE; - - xTaskToSuspend = prvGetThreadHandle( xTaskGetCurrentTaskHandle() ); - /* Tick Increment. */ - vTaskIncrementTick(); - - /* Select Next Task. */ -#if ( configUSE_PREEMPTION == 1 ) - vTaskSwitchContext(); -#endif - xTaskToResume = prvGetThreadHandle( xTaskGetCurrentTaskHandle() ); - - /* The only thread that can process this tick is the running thread. */ - if ( xTaskToSuspend != xTaskToResume ) - { - /* Remember and switch the critical nesting. */ - prvSetTaskCriticalNesting( xTaskToSuspend, uxCriticalNesting ); - uxCriticalNesting = prvGetTaskCriticalNesting( xTaskToResume ); - /* Resume next task. */ - prvResumeThread( xTaskToResume ); - /* Suspend the current task. */ - prvSuspendThread( xTaskToSuspend ); - } - else - { - /* Release the lock as we are Resuming. */ - (void)pthread_mutex_unlock( &xSingleThreadMutex ); - } - xServicingTick = pdFALSE; - } - else - { - xPendYield = pdTRUE; - } - } - else - { - xPendYield = pdTRUE; - } -} -/*-----------------------------------------------------------*/ - -void vPortForciblyEndThread( void *pxTaskToDelete ) -{ -xTaskHandle hTaskToDelete = ( xTaskHandle )pxTaskToDelete; -pthread_t xTaskToDelete; -pthread_t xTaskToResume; -portBASE_TYPE xResult; - - if ( 0 == pthread_mutex_lock( &xSingleThreadMutex ) ) - { - 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( &xSingleThreadMutex ); - } - else - { - /* Resume the other thread. */ - prvResumeThread( xTaskToResume ); - /* Pthread Clean-up function will note the cancellation. */ - /* Release the execution. */ - uxCriticalNesting = 0; - vPortEnableInterrupts(); - (void)pthread_mutex_unlock( &xSingleThreadMutex ); - /* 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() ); - - if ( 0 == pthread_mutex_lock( &xSingleThreadMutex ) ) - { - prvSuspendThread( pthread_self() ); - } - - pvCode( pParams ); - - pthread_cleanup_pop( 1 ); - return (void *)NULL; -} -/*-----------------------------------------------------------*/ - -void prvSuspendSignalHandler(int sig) -{ -sigset_t xSignals; - - /* Only interested in the resume signal. */ - sigemptyset( &xSignals ); - sigaddset( &xSignals, SIG_RESUME ); - xSentinel = 1; - - /* Unlock the Single thread mutex to allow the resumed task to continue. */ - if ( 0 != pthread_mutex_unlock( &xSingleThreadMutex ) ) - { - printf( "Releasing someone else's lock.\n" ); - } - - /* Wait on the resume signal. */ - if ( 0 != sigwait( &xSignals, &sig ) ) - { - printf( "SSH: Sw %d\n", 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(); - } -} -/*-----------------------------------------------------------*/ - -void prvSuspendThread( pthread_t xThreadId ) -{ -portBASE_TYPE xResult = pthread_mutex_lock( &xSuspendResumeThreadMutex ); - if ( 0 == xResult ) - { - /* Set-up for the Suspend Signal handler? */ - xSentinel = 0; - xResult = pthread_mutex_unlock( &xSuspendResumeThreadMutex ); - xResult = pthread_kill( xThreadId, SIG_SUSPEND ); - while ( ( xSentinel == 0 ) && ( pdTRUE != xServicingTick ) ) - { - sched_yield(); - } - } -} -/*-----------------------------------------------------------*/ - -void prvResumeSignalHandler(int sig) -{ - /* Yield the Scheduler to ensure that the yielding thread completes. */ - if ( 0 == pthread_mutex_lock( &xSingleThreadMutex ) ) - { - (void)pthread_mutex_unlock( &xSingleThreadMutex ); - } -} -/*-----------------------------------------------------------*/ - -void prvResumeThread( pthread_t xThreadId ) -{ -portBASE_TYPE xResult; - if ( 0 == pthread_mutex_lock( &xSuspendResumeThreadMutex ) ) - { - if ( pthread_self() != xThreadId ) - { - xResult = pthread_kill( xThreadId, SIG_RESUME ); - } - xResult = pthread_mutex_unlock( &xSuspendResumeThreadMutex ); - } -} -/*-----------------------------------------------------------*/ - -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, sigresume, sigtick; -portLONG lIndex; - - 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 ); - - sigresume.sa_flags = 0; - sigresume.sa_handler = prvResumeSignalHandler; - sigfillset( &sigresume.sa_mask ); - - sigtick.sa_flags = 0; - sigtick.sa_handler = vPortSystemTickHandler; - sigfillset( &sigtick.sa_mask ); - - if ( 0 != sigaction( SIG_SUSPEND, &sigsuspendself, NULL ) ) - { - printf( "Problem installing SIG_SUSPEND_SELF\n" ); - } - if ( 0 != sigaction( SIG_RESUME, &sigresume, NULL ) ) - { - printf( "Problem installing SIG_RESUME\n" ); - } - if ( 0 != sigaction( SIG_TICK, &sigtick, NULL ) ) - { - printf( "Problem installing SIG_TICK\n" ); - } - printf( "Running as PID: %d\n", getpid() ); -} -/*-----------------------------------------------------------*/ - -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; - - 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; - } - } - } -} -/*-----------------------------------------------------------*/ - -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; -} -/*-----------------------------------------------------------*/ diff --git a/flight/PiOS.posix/posix/Libraries/FreeRTOS/Source/portable/GCC/Posix/port_posix.c b/flight/PiOS.posix/posix/Libraries/FreeRTOS/Source/portable/GCC/Posix/port_posix.c deleted file mode 100644 index db0e4d71e..000000000 --- a/flight/PiOS.posix/posix/Libraries/FreeRTOS/Source/portable/GCC/Posix/port_posix.c +++ /dev/null @@ -1,1258 +0,0 @@ -/* - 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 -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - - -/* Scheduler includes. */ -#include "FreeRTOS.h" -#include "task.h" -/*-----------------------------------------------------------*/ - -#define MAX_NUMBER_OF_TASKS ( _POSIX_THREAD_THREADS_MAX ) -/*-----------------------------------------------------------*/ - -/* 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_t hMainThread = ( pthread_t )NULL; -/*-----------------------------------------------------------*/ - -static volatile portBASE_TYPE xSentinel = pdFALSE; -static volatile portBASE_TYPE xRunning = pdFALSE; -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 -#ifdef CHECK_TASK_RESUMES -static portBASE_TYPE prvGetTaskState( xTaskHandle hTask ); -#endif -static void prvSetTaskState( xTaskHandle hTask, portBASE_TYPE state ); -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 - -#define THREAD_STATE_PAUSE 1 -#define THREAD_STATE_RUNNING 2 - -//#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( stderr, "%20s(%li)\t%20s\t%i: ",debug_task_handle->pcTaskName,(long)pthread_self(),__func__,__LINE__)): \ - (fprintf( stderr, "%20s(%li)\t%20s\t%i: ","__unknown__",(long)pthread_self(),__func__,__LINE__)) \ - |1)?( \ - ((fprintf( stderr, __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_trylock(...) ( (debug_printf(" -!- pthread_mutex_trylock(%s)\n",#__VA_ARGS__)|1)?pthread_mutex_trylock(__VA_ARGS__):0 ) - #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( stderr, "%20s(%li)\t%20s\t%i: ",debug_task_handle->pcTaskName,(long)pthread_self(),__func__,__LINE__)): \ - (fprintf( stderr, "%20s(%li)\t%20s\t%i: ","__unknown__",(long)pthread_self(),__func__,__LINE__)) \ - |1)?( \ - ((fprintf( stderr, __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 */ -// pthread_condattr_t condAttr; -// assert( 0 == pthread_condattr_init( &condAttr ) ); - 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 */ -// pthread_mutexattr_t mutexAttr; -// assert( 0 == pthread_mutexattr_init( &mutexAttr ) ); -// assert( 0 == pthread_mutexattr_settype( &mutexAttr, PTHREAD_MUTEX_ERRORCHECK ) ); - 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() ); -// careful! race condition? if u mutex lock here, could u start the tick handler more early? - 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. */ - sigemptyset( &xSignalToBlock ); - sigaddset( &xSignalToBlock, SIG_SUSPEND ); - sigaddset( &xSignalToBlock, SIG_TICK ); - (void)pthread_sigmask( SIG_SETMASK, &xSignalToBlock, NULL ); - - for ( lIndex = 0; lIndex < MAX_NUMBER_OF_TASKS; lIndex++ ) - { - pxThreads[ lIndex ].uxCriticalNesting = 0; - } - - /* Start the first task. Will not return unless all threads are killed. */ - vPortStartFirstTask(); - - /* Unfortunately things are stable if we start ticking during setup. This need to be */ - /* checked careful in startup on hardware */ - usleep(1000000); - -#if defined(TICK_SIGNAL) || defined(TICK_SIGWAIT) - - struct itimerval itimer; - portTickType xMicroSeconds = portTICK_RATE_MICROSECONDS; - - debug_printf("init %li microseconds\n",(long)xMicroSeconds); - /* Initialise the structure with the current timer information. */ - assert ( 0 == getitimer( TIMER_TYPE, &itimer ) ); - - /* Set the interval between timer events. */ - itimer.it_interval.tv_sec = 0; - itimer.it_interval.tv_usec = xMicroSeconds; - - /* Set the current count-down. */ - itimer.it_value.tv_sec = 0; - itimer.it_value.tv_usec = xMicroSeconds; - -#endif - -#ifdef TICK_SIGNAL - struct sigaction sigtick; - sigtick.sa_flags = 0; - sigtick.sa_handler = vPortSystemTickHandler; - sigfillset( &sigtick.sa_mask ); - assert ( 0 == sigaction( SIG_TICK, &sigtick, NULL ) ); - - /* Set-up the timer interrupt. */ - assert ( 0 == setitimer( TIMER_TYPE, &itimer, NULL ) ); - - sigemptyset( &xSignalToBlock ); - sigaddset( &xSignalToBlock, SIG_SUSPEND ); - (void)pthread_sigmask( SIG_SETMASK, &xSignalToBlock, NULL ); - - while(1) - { - usleep(1000); - sched_yield(); - } -#endif - -#ifdef TICK_SIGWAIT - /* Tick signal already blocked */ - sigset_t xSignalsToWait; - sigemptyset( &xSignalsToWait ); - sigaddset( &xSignalsToWait, SIG_TICK ); - - /* Set-up the timer interrupt. */ - assert ( 0 == setitimer( TIMER_TYPE, &itimer, NULL ) ); - - while( pdTRUE != xSchedulerEnd ) { - int xResult; - assert( 0 == sigwait( &xSignalsToWait, &xResult ) ); -// assert( xResult == SIG_TICK ); - vPortSystemTickHandler(SIG_TICK); - } -#endif - -#if !defined(TICK_SIGNAL) && !defined(TICK_SIGWAIT) - - struct timespec x; - while( pdTRUE != xSchedulerEnd ) { - x.tv_sec=0; - x.tv_nsec=portTICK_RATE_MICROSECONDS * 1000; - nanosleep(&x,NULL); -// careful - on some systems a signal to ANY thread in the process will -// end nanosleeps immediately - better sleep with pselect() and set the -// wakeup sigmask to all blocked (see test_case_x_pselect.c) -// printf("."); fflush(stdout); - vPortSystemTickHandler(SIG_TICK); -// printf("*"); fflush(stdout); - } - -#endif - 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 ) - { -// careful - race condition possible? - 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; -int retVal; -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" ); - - vPortEnterCritical(); - - retVal = pthread_mutex_trylock( &xSwappingThreadMutex ); - while( retVal != 0 ) { - - assert( retVal == EBUSY ); - - /* If we can't get the mutex, that means an interrupt is running and we */ - /* should keep an eye out if this task should suspend so the interrupt */ - /* routine doesn't stall waiting for this task to pause */ - debug_printf( "Waiting to get swapping mutex from ISR\r\n" ); - - assert( xTaskGetCurrentTaskHandle() != NULL ); - xTaskToSuspend = prvGetThreadHandle( xTaskGetCurrentTaskHandle() ); -// careful! race condition!!!! unprotected by mutex - - if( prvGetThreadHandle( xTaskGetCurrentTaskHandle() ) != pthread_self() ) { -// careful! race condition!!!! unprotected by mutex - debug_printf( "The current task isn't even us. Pausing now, deal with possible interrupt later.\r\n" ); - vPortExitCritical(); - pauseThread( THREAD_PAUSE_YIELD ); - - return; - } - sched_yield(); - retVal = pthread_mutex_trylock( &xSwappingThreadMutex ); - } - - /* At this point we have the lock, active task shouldn't change */ - oldTask = xTaskGetCurrentTaskHandle(); - assert( oldTask != NULL ); - xTaskToSuspend = prvGetThreadHandle( xTaskGetCurrentTaskHandle() ); - - if(xTaskToSuspend != pthread_self() ) { - debug_printf( "The current task isn't even us, letting interrupt happen. Watch for swap.\r\n" ); - - assert( pthread_mutex_unlock( &xSwappingThreadMutex ) == 0); - vPortExitCritical(); - pauseThread( THREAD_PAUSE_YIELD ); - - return; - } - - assert( xTaskToSuspend == pthread_self() ); // race condition I didn't account for - - /* Get new task then release the task switching mutex */ - vTaskSwitchContext(); - newTask = xTaskGetCurrentTaskHandle(); - assert( newTask != NULL ); - 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( prvGetTaskState( oldTask ) != THREAD_STATE_RUNNING ) - { - usleep(100); - sched_yield(); - 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 */ - vPortExitCritical(); - -} -/*-----------------------------------------------------------*/ - -void vPortDisableInterrupts( void ) -{ - //debug_printf("\r\n"); - sigset_t xSignals; - sigemptyset( &xSignals ); - sigaddset( &xSignals, SIG_SUSPEND ); - pthread_sigmask( SIG_BLOCK, &xSignals, NULL ); - - xInterruptsEnabled = pdFALSE; -} -/*-----------------------------------------------------------*/ - -void vPortEnableInterrupts( void ) -{ - - xInterruptsEnabled = pdTRUE; - //debug_printf("\r\n"); - sigset_t xSignals; - sigemptyset( &xSignals ); - sigaddset( &xSignals, SIG_SUSPEND ); - pthread_sigmask( SIG_UNBLOCK, &xSignals, NULL ); -} -/*-----------------------------------------------------------*/ - -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; - -/* assert( SIG_TICK == sig ); - assert( prvGetThreadHandle( xTaskGetCurrentTaskHandle() ) != NULL ); - assert( pthread_self() != prvGetThreadHandle( xTaskGetCurrentTaskHandle() ) ); */ - - 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(); - assert( oldTask != NULL ); - xTaskToSuspend = prvGetThreadHandle( xTaskGetCurrentTaskHandle() ); - - /* Tick Increment. */ - vTaskIncrementTick(); - - /* Select Next Task. */ -#if ( configUSE_PREEMPTION == 1 ) - vTaskSwitchContext(); -#endif - - newTask = xTaskGetCurrentTaskHandle(); - assert( newTask != NULL ); - 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 ) - { - /* 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); - - assert( pthread_kill( xTaskToSuspend, SIG_SUSPEND ) == 0); - -#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( prvGetTaskState( oldTask ) != THREAD_STATE_PAUSE ) -#endif - { - usleep(100); - debug_printf( "Waiting for old task to suspend\r\n" ); - debug_printf( "Sent signal\r\n" ); - sched_yield(); - } - debug_printf( "Suspended\r\n" ); - -#ifdef CHECK_TASK_RESUMES - while( prvGetTaskState( newTask ) != THREAD_STATE_RUNNING ) -#endif - { - debug_printf( "Waiting for new task to resume\r\n" ); -#ifdef COND_SIGNALING - // Set resume condition for specific thread - pthread_cond_t * hCond = prvGetConditionHandle( xTaskGetCurrentTaskHandle() ); - assert( pthread_cond_signal( hCond ) == 0 ); -#endif - - 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; - } - debug_printf("Exiting\r\n"); -} -/*-----------------------------------------------------------*/ - -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 ) ) -// careful! windows bug - this thread won't be suspendable while waiting for mutex! -// so tick handler will wait forever for this thread to go to sleep -// might want to put a try_lock() - sched_yield() loop when on cygwin! - { - 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 ); -// careful! will be hit every time a thread exits itself gracefully - better fix this, we might need -// it - - /* 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 ); - sigaddset( &xSignals, SIG_TICK ); - assert( pthread_sigmask( SIG_SETMASK, &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. Order is strange but because of how this is hacked onto the trace */ - /*handling code in tasks.c */ - 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"); - - /* Since all starting tasks have the critical nesting at zero, just enable interrupts */ - vPortEnableInterrupts(); - - pvCode( pParams ); - - pthread_cleanup_pop( 1 ); - return (void *)NULL; -} -/*-----------------------------------------------------------*/ - -void pauseThread( portBASE_TYPE pauseMode ) -{ - xTaskHandle hTask = prvGetTaskHandle( pthread_self() ); - - debug_printf( "Pausing thread %li. Set state to suspended\r\n", (long int) pthread_self() ); - prvSetTaskState( hTask, THREAD_STATE_PAUSE ); - -#ifdef RUNNING_THREAD_MUTEX - if( pauseMode != THREAD_PAUSE_CREATED ) - assert( 0 == pthread_mutex_unlock( &xRunningThread ) ); -#endif - -#ifdef COND_SIGNALING - int xResult; - 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 - - while (1) { - assert( xTaskGetCurrentTaskHandle() != NULL ); - if( pthread_self() == prvGetThreadHandle(xTaskGetCurrentTaskHandle() ) && xRunning ) -// careful! race condition!!!! possibly unprotected by mutex when CHECK_TASK_RESUMES is not set? - { - - /* Must do this before trying to lock the mutex, because if CHECK_TASK_RESUMES */ - /* is defined then the mutex not unlocked until this is changed */ - debug_printf( "Resuming. Marking task as running\r\n" ); - prvSetTaskState( hTask, THREAD_STATE_RUNNING ); - -#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(1000); - 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 ); - -#ifdef CHECK_TASK_RESUMES - /* This would seem like a major bug, but can happen because now we send extra suspend signals */ - /* if they aren't caught */ - assert( xTaskGetCurrentTaskHandle() != NULL ); - if( pthread_self() == prvGetThreadHandle( xTaskGetCurrentTaskHandle() ) ) { -// careful! race condition? Or does the tick handler wait for us to sleep before unlocking? - debug_printf( "Marked as current task, resuming\r\n" ); - return; - } -#endif - - /* Check that we aren't suspending when we should be running. This bug would need tracking down */ -// assert( pthread_self() != prvGetThreadHandle(xTaskGetCurrentTaskHandle() ) ); - - /* 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); - - assert( xTaskGetCurrentTaskHandle() != NULL ); - while( pthread_self() != prvGetThreadHandle( xTaskGetCurrentTaskHandle() ) ) -// careful! race condition? could a port_yield mess with this? - { - debug_printf( "Incorrectly woke up. Repausing\r\n" ); */ - pauseThread( THREAD_PAUSE_INTERRUPT ); -/* } - - assert( xTaskGetCurrentTaskHandle() != NULL ); - 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 ); - sigaddset( &xBlockSignals, SIG_SUSPEND ); - assert( 0 == pthread_sigmask( SIG_UNBLOCK, &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 - { - debug_printf( "Not reenabling interrupts\r\n" ); - 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; - pxThreads[ lIndex ].xThreadState = 0; - } - - sigsuspendself.sa_flags = 0; - sigsuspendself.sa_handler = prvSuspendSignalHandler; - sigemptyset( &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 ) -{ -portLONG lIndex; - - /* If not initialized yet */ - if( pxThreads == NULL ) return NULL; - assert( hThread != (pthread_t) NULL ); - for ( lIndex = 0; lIndex < MAX_NUMBER_OF_TASKS; lIndex++ ) - { - if ( pxThreads[ lIndex ].hThread == hThread ) - { - return pxThreads[ lIndex ].hTask; - } - } -// assert( 0 ); - return NULL; -} - -/*-----------------------------------------------------------*/ -pthread_cond_t * prvGetConditionHandle( xTaskHandle hTask ) -{ -pthread_cond_t * hCond = NULL; -portLONG lIndex; - - assert( hTask != NULL ); - for ( lIndex = 0; lIndex < MAX_NUMBER_OF_TASKS; lIndex++ ) - { - if ( pxThreads[ lIndex ].hTask == hTask ) - { - debug_printf( "Found condition on %i task\r\n", lIndex ); - hCond = pxThreads[ lIndex ].hCond; - break; - } - } - assert( hCond != NULL ); - return hCond; - printf( "Failed to get handle, pausing then recursing\r\n" ); - usleep(1000); - return prvGetConditionHandle( hTask ); - assert(0); - return hCond; -} - -/*-----------------------------------------------------------*/ -#ifdef CHECK_TASK_RESUMES -static portBASE_TYPE prvGetTaskState( xTaskHandle hTask ) -{ -portLONG lIndex; - assert( hTask != NULL ); - for ( lIndex = 0; lIndex < MAX_NUMBER_OF_TASKS; lIndex++ ) - { - if ( pxThreads[ lIndex ].hTask == hTask ) - { - debug_printf( "Found state (%li) on %i task\r\n",pxThreads[ lIndex ].xThreadState, lIndex ); - return pxThreads[ lIndex ].xThreadState; - } - } - assert(0); - return 0; -} -#endif - -void prvSetTaskState( xTaskHandle hTask, portBASE_TYPE state ) -{ -portLONG lIndex; - assert( hTask != NULL ); - for ( lIndex = 0; lIndex < MAX_NUMBER_OF_TASKS; lIndex++ ) - { - if ( pxThreads[ lIndex ].hTask == hTask ) - { - pxThreads[ lIndex ].xThreadState = state; - return; - } - } - assert(0); - return; -} - - -/*-----------------------------------------------------------*/ -pthread_t prvGetThreadHandle( xTaskHandle hTask ) -{ - pthread_t hThread = ( pthread_t )NULL; - portLONG lIndex; - - assert( hTask != NULL ); - - for ( lIndex = 0; lIndex < MAX_NUMBER_OF_TASKS; lIndex++ ) - { - if ( pxThreads[ lIndex ].hTask == hTask ) - { - hThread = pxThreads[ lIndex ].hThread; - break; - } - } - - assert( hThread != (pthread_t) NULL ); - 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; -} -/*-----------------------------------------------------------*/ diff --git a/flight/PiOS.posix/posix/Libraries/FreeRTOS/Source/portable/GCC/Posix/portmacro.h b/flight/PiOS.posix/posix/Libraries/FreeRTOS/Source/portable/GCC/Posix/portmacro.h index 4da6b124b..775c2bac9 100644 --- a/flight/PiOS.posix/posix/Libraries/FreeRTOS/Source/portable/GCC/Posix/portmacro.h +++ b/flight/PiOS.posix/posix/Libraries/FreeRTOS/Source/portable/GCC/Posix/portmacro.h @@ -142,17 +142,6 @@ extern void vPortAddTaskHandle( void *pxTaskHandle ); /* 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 ); diff --git a/flight/PiOS.posix/posix/Libraries/FreeRTOS/Source/portable/GCC/Posix/corvuscorax/tasks.c b/flight/PiOS.posix/posix/Libraries/FreeRTOS/Source/tasks.c similarity index 100% rename from flight/PiOS.posix/posix/Libraries/FreeRTOS/Source/portable/GCC/Posix/corvuscorax/tasks.c rename to flight/PiOS.posix/posix/Libraries/FreeRTOS/Source/tasks.c diff --git a/flight/PiOS.posix/posix/Libraries/FreeRTOS/Source/tasks_linux.c b/flight/PiOS.posix/posix/Libraries/FreeRTOS/Source/tasks_linux.c deleted file mode 100644 index 9b06c3f89..000000000 --- a/flight/PiOS.posix/posix/Libraries/FreeRTOS/Source/tasks_linux.c +++ /dev/null @@ -1,2323 +0,0 @@ -/* - 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 -#include -#include -#include - -/* Defining MPU_WRAPPERS_INCLUDED_FROM_API_FILE prevents task.h from redefining -all the API functions to use the MPU wrappers. That should only be done when -task.h is included from an application file. */ -#define MPU_WRAPPERS_INCLUDED_FROM_API_FILE - -#include "FreeRTOS.h" -#include "task.h" -#include "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 -/*-----------------------------------------------------------*/ - - - - diff --git a/flight/PiOS.posix/posix/Libraries/FreeRTOS/Source/tasks_posix.c b/flight/PiOS.posix/posix/Libraries/FreeRTOS/Source/tasks_posix.c deleted file mode 100644 index f9fb0dcc0..000000000 --- a/flight/PiOS.posix/posix/Libraries/FreeRTOS/Source/tasks_posix.c +++ /dev/null @@ -1,2333 +0,0 @@ -/* - 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 -#include -#include -#include -#include -#include - -/* Defining MPU_WRAPPERS_INCLUDED_FROM_API_FILE prevents task.h from redefining -all the API functions to use the MPU wrappers. That should only be done when -task.h is included from an application file. */ -#define MPU_WRAPPERS_INCLUDED_FROM_API_FILE - -#include "FreeRTOS.h" -#include "task.h" -#include "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 -#ifdef IDLE_SLEEPS - 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 ); - sigaddset( &xSignals, SIG_TICK ); - 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 -/*-----------------------------------------------------------*/ - - - - diff --git a/flight/PiOS.posix/posix/Libraries/FreeRTOS/library.mk b/flight/PiOS.posix/posix/Libraries/FreeRTOS/library.mk new file mode 100644 index 000000000..ae65aff82 --- /dev/null +++ b/flight/PiOS.posix/posix/Libraries/FreeRTOS/library.mk @@ -0,0 +1,11 @@ +# +# Rules to add FreeRTOS to a PiOS target +# +# Note that the PIOS target-specific makefile will detect that FREERTOS_DIR +# has been defined and add in the target-specific pieces separately. +# + +FREERTOS_DIR := $(dir $(lastword $(MAKEFILE_LIST)))/Source +SRC += $(wildcard $(FREERTOS_DIR)/*.c) +EXTRAINCDIRS += $(FREERTOS_DIR)/include + diff --git a/flight/PiOS.posix/posix/library.mk b/flight/PiOS.posix/posix/library.mk new file mode 100644 index 000000000..530431210 --- /dev/null +++ b/flight/PiOS.posix/posix/library.mk @@ -0,0 +1,76 @@ +# +# Rules to (help) build the F4xx device support. +# + +# +# Directory containing this makefile +# +PIOS_DEVLIB := $(dir $(lastword $(MAKEFILE_LIST))) + +# +# Hardcoded linker script names for now +# +#LINKER_SCRIPTS_APP = $(PIOS_DEVLIB)/link_STM32F4xx_OP_memory.ld \ + $(PIOS_DEVLIB)/link_STM32F4xx_sections.ld + +#LINKER_SCRIPTS_BL = $(PIOS_DEVLIB)/link_STM32F4xx_BL_memory.ld \ + $(PIOS_DEVLIB)/link_STM32F4xx_sections.ld + +# +# Compiler options implied by the F4xx +# +#CDEFS += -DSTM32F4XX +#CDEFS += -DHSE_VALUE=$(OSCILLATOR_FREQ) +#CDEFS += -DUSE_STDPERIPH_DRIVER +ARCHFLAGS += -DARCH_POSIX + +# +# PIOS device library source and includes +# +SRC += $(wildcard $(PIOS_DEVLIB)*.c) +EXTRAINCDIRS += $(PIOS_DEVLIB)/inc + +# +# CMSIS for the F4 +# +#include $(PIOSCOMMONLIB)/CMSIS2/library.mk +#CMSIS2_DEVICEDIR := $(PIOS_DEVLIB)/Libraries/CMSIS2/Device/ST/STM32F4xx +#SRC += $(wildcard $(CMSIS2_DEVICEDIR)/Source/*.c) +#EXTRAINCDIRS += $(CMSIS2_DEVICEDIR)/Include + +# +# ST Peripheral library +# +#PERIPHLIB = $(PIOS_DEVLIB)/Libraries/STM32F4xx_StdPeriph_Driver +#SRC += $(wildcard $(PERIPHLIB)/src/*.c) +#EXTRAINCDIRS += $(PERIPHLIB)/inc + +# +# ST USB OTG library +# +#USBOTGLIB = $(PIOS_DEVLIB)/Libraries/STM32_USB_OTG_Driver +#USBOTGLIB_SRC = usb_core.c usb_dcd.c usb_dcd_int.c +#SRC += $(addprefix $(USBOTGLIB)/src/,$(USBOTGLIB_SRC)) +#EXTRAINCDIRS += $(USBOTGLIB)/inc + +# +# ST USB Device library +# +#USBDEVLIB = $(PIOS_DEVLIB)/Libraries/STM32_USB_Device_Library +#SRC += $(wildcard $(USBDEVLIB)/Core/src/*.c) +#EXTRAINCDIRS += $(USBDEVLIB)/Core/inc + +# +# FreeRTOS +# +# If the application has included the generic FreeRTOS support, then add in +# the device-specific pieces of the code. +# +ifneq ($(FREERTOS_DIR),) +FREERTOS_PORTDIR := $(PIOS_DEVLIB)/Libraries/FreeRTOS/Source +SRC += $(wildcard $(FREERTOS_PORTDIR)/portable/GCC/Posix/*.c) +SRC += $(wildcard $(FREERTOS_PORTDIR)/portable/MemMang/*.c) + +EXTRAINCDIRS += $(FREERTOS_PORTDIR)/portable/GCC/Posix +endif + diff --git a/flight/PiOS.posix/posix/pios_debug.c b/flight/PiOS.posix/posix/pios_debug.c index 7f3dc99da..02d41ee64 100644 --- a/flight/PiOS.posix/posix/pios_debug.c +++ b/flight/PiOS.posix/posix/pios_debug.c @@ -72,11 +72,10 @@ void PIOS_DEBUG_PinValue4BitL(uint8_t value) /** * Report a serious error and halt */ -void PIOS_DEBUG_Panic(const char *msg) __attribute__ ((noreturn)) +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); +#ifdef PIOS_COM_AUX + PIOS_COM_SendFormattedStringNonBlocking(PIOS_COM_DEBUG, "\r%s\r", msg); #endif // tell the user whats going on on commandline too diff --git a/flight/PiOS.posix/posix/pios_delay.c b/flight/PiOS.posix/posix/pios_delay.c index cec10467c..386e2bb2f 100644 --- a/flight/PiOS.posix/posix/pios_delay.c +++ b/flight/PiOS.posix/posix/pios_delay.c @@ -59,7 +59,7 @@ int32_t PIOS_DELAY_Init(void) * \param[in] uS delay (1..65535 microseconds) * \return < 0 on errors */ -int32_t PIOS_DELAY_WaituS(uint16_t uS) +int32_t PIOS_DELAY_WaituS(uint32_t uS) { static struct timespec wait,rest; wait.tv_sec=0; @@ -83,7 +83,7 @@ int32_t PIOS_DELAY_WaituS(uint16_t uS) * \param[in] mS delay (1..65535 milliseconds) * \return < 0 on errors */ -int32_t PIOS_DELAY_WaitmS(uint16_t mS) +int32_t PIOS_DELAY_WaitmS(uint32_t mS) { //for(int i = 0; i < mS; i++) { // PIOS_DELAY_WaituS(1000); @@ -99,4 +99,44 @@ int32_t PIOS_DELAY_WaitmS(uint16_t mS) return 0; } +/** + * @brief Query the Delay timer for the current uS + * @return A microsecond value + */ +uint32_t PIOS_DELAY_GetuS() +{ + static struct timespec current; + clock_gettime(CLOCK_REALTIME, ¤t); + return ((current.tv_sec * 1000000) + (current.tv_nsec / 1000)); +} + +/** + * @brief Calculate time in microseconds since a previous time + * @param[in] t previous time + * @return time in us since previous time t. + */ +uint32_t PIOS_DELAY_GetuSSince(uint32_t t) +{ + return (PIOS_DELAY_GetuS() - t); +} + +/** + * @brief Get the raw delay timer, useful for timing + * @return Unitless value (uint32 wrap around) + */ +uint32_t PIOS_DELAY_GetRaw() +{ + return (PIOS_DELAY_GetuS()); +} + +/** + * @brief Compare to raw times to and convert to us + * @return A microsecond value + */ +uint32_t PIOS_DELAY_DiffuS(uint32_t raw) +{ + return ( PIOS_DELAY_GetuS() - raw ); +} + + #endif diff --git a/flight/PiOS.posix/posix/pios_led.c b/flight/PiOS.posix/posix/pios_led.c index b35477d45..8e0776883 100644 --- a/flight/PiOS.posix/posix/pios_led.c +++ b/flight/PiOS.posix/posix/pios_led.c @@ -41,7 +41,7 @@ static uint8_t LED_GPIO[PIOS_LED_NUM]; -static inline void PIOS_SetLED(LedTypeDef LED,uint8_t stat) { +static inline void PIOS_SetLED(uint32_t LED,uint8_t stat) { printf("PIOS: LED %i status %i\n",LED,stat); LED_GPIO[LED]=stat; } @@ -71,7 +71,7 @@ void PIOS_LED_Init(void) * Turn on LED * \param[in] LED LED Name (LED1, LED2) */ -void PIOS_LED_On(LedTypeDef LED) +void PIOS_LED_On(uint32_t LED) { //LED_GPIO_PORT[LED]->BRR = LED_GPIO_PIN[LED]; PIOS_SetLED(LED,1); @@ -82,7 +82,7 @@ void PIOS_LED_On(LedTypeDef LED) * Turn off LED * \param[in] LED LED Name (LED1, LED2) */ -void PIOS_LED_Off(LedTypeDef LED) +void PIOS_LED_Off(uint32_t LED) { //LED_GPIO_PORT[LED]->BSRR = LED_GPIO_PIN[LED]; PIOS_SetLED(LED,0); @@ -93,7 +93,7 @@ void PIOS_LED_Off(LedTypeDef LED) * Toggle LED on/off * \param[in] LED LED Name (LED1, LED2) */ -void PIOS_LED_Toggle(LedTypeDef LED) +void PIOS_LED_Toggle(uint32_t LED) { //LED_GPIO_PORT[LED]->ODR ^= LED_GPIO_PIN[LED]; PIOS_SetLED(LED,LED_GPIO[LED]?0:1); diff --git a/flight/PiOS.posix/posix/pios_udp.c b/flight/PiOS.posix/posix/pios_udp.c index 5ccbae767..2c98c42ee 100644 --- a/flight/PiOS.posix/posix/pios_udp.c +++ b/flight/PiOS.posix/posix/pios_udp.c @@ -78,11 +78,6 @@ static pios_udp_dev * find_udp_dev_by_id (uint8_t udp) 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; /** @@ -151,7 +146,13 @@ int32_t PIOS_UDP_Init(uint32_t * udp_id, const struct pios_udp_cfg * cfg) int res= bind(udp_dev->socket, (struct sockaddr *)&udp_dev->server,sizeof(udp_dev->server)); /* Create transmit thread for this connection */ +#if defined(PIOS_INCLUDE_FREERTOS) +//( pdTASK_CODE pvTaskCode, const portCHAR * const pcName, unsigned portSHORT usStackDepth, void *pvParameters, unsigned portBASE_TYPE uxPriority, xTaskHandle *pvCreatedTask ); + xTaskCreate((pdTASK_CODE)PIOS_UDP_RxThread, (const signed char *)"UDP_Rx_Thread",1024,(void*)udp_dev,(tskIDLE_PRIORITY + 1),&udp_dev->rxThread); +#else pthread_create(&udp_dev->rxThread, NULL, PIOS_UDP_RxThread, (void*)udp_dev); +#endif + printf("udp dev %i - socket %i opened - result %i\n",pios_udp_num_devices-1,udp_dev->socket,res); diff --git a/flight/PiOS/Boards/STM32103CB_CC_Rev1.h b/flight/PiOS/Boards/STM32103CB_CC_Rev1.h index fd391c46c..18d977cf4 100644 --- a/flight/PiOS/Boards/STM32103CB_CC_Rev1.h +++ b/flight/PiOS/Boards/STM32103CB_CC_Rev1.h @@ -215,6 +215,7 @@ extern uint32_t pios_com_telem_usb_id; //------------------------ #define PIOS_RCVR_MAX_DEVS 3 #define PIOS_RCVR_MAX_CHANNELS 12 +#define PIOS_GCSRCVR_TIMEOUT_MS 100 //------------------------- // Receiver PPM input diff --git a/flight/PiOS/Boards/STM32103CB_PIPXTREME_Rev1.h b/flight/PiOS/Boards/STM32103CB_PIPXTREME_Rev1.h old mode 100644 new mode 100755 index 8d04e05a4..868bba722 --- a/flight/PiOS/Boards/STM32103CB_PIPXTREME_Rev1.h +++ b/flight/PiOS/Boards/STM32103CB_PIPXTREME_Rev1.h @@ -23,20 +23,22 @@ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ -#ifndef PIOS_BOARD_H -#define PIOS_BOARD_H +#ifndef STM32103CB_PIPXTREME_H_ +#define STM32103CB_PIPXTREME_H_ -// ***************************************************************** +#define ADD_ONE_ADC + +//------------------------ // Timers and Channels Used - +//------------------------ /* -Timer | Channel 1 | Channel 2 | Channel 3 | Channel 4 -------+------------+------------+------------+------------ -TIM1 | DELAY | -TIM2 | | PPM Output | PPM Input | -TIM3 | TIMER INTERRUPT | -TIM4 | STOPWATCH | -------+------------+------------+------------+------------ +Timer | Channel 1 | Channel 2 | Channel 3 | Channel 4 +------+-----------+-----------+-----------+---------- +TIM1 | Servo 4 | | | +TIM2 | RC In 5 | RC In 6 | Servo 6 | +TIM3 | Servo 5 | RC In 2 | RC In 3 | RC In 4 +TIM4 | RC In 1 | Servo 3 | Servo 2 | Servo 1 +------+-----------+-----------+-----------+---------- */ //------------------------ @@ -55,6 +57,7 @@ TIM4 | STOPWATCH | /* Channel 11 - */ /* Channel 12 - */ + //------------------------ // BOOTLOADER_SETTINGS //------------------------ @@ -63,23 +66,26 @@ TIM4 | STOPWATCH | #define MAX_DEL_RETRYS 3 -// ***************************************************************** -// System Settings +//------------------------ +// WATCHDOG_SETTINGS +//------------------------ +#define PIOS_WATCHDOG_TIMEOUT 500 +#define PIOS_WDG_REGISTER BKP_DR4 +#define PIOS_WDG_COMUAVTALK 0x0001 +#define PIOS_WDG_RADIORECEIVE 0x0002 +#define PIOS_WDG_SENDPACKET 0x0004 +#define PIOS_WDG_SENDDATA 0x0008 +#define PIOS_WDG_TRANSCOMM 0x0010 +#define PIOS_WDG_PPMINPUT 0x0020 -#define PIOS_MASTER_CLOCK 72000000ul -#define PIOS_PERIPHERAL_CLOCK (PIOS_MASTER_CLOCK / 2) +//------------------------ +// TELEMETRY +//------------------------ +#define TELEM_QUEUE_SIZE 20 -// ***************************************************************** -// Interrupt Priorities - -#define PIOS_IRQ_PRIO_LOW 12 // lower than RTOS -#define PIOS_IRQ_PRIO_MID 8 // higher than RTOS -#define PIOS_IRQ_PRIO_HIGH 5 // for SPI, ADC, I2C etc... -#define PIOS_IRQ_PRIO_HIGHEST 4 // for USART etc... - -// ***************************************************************** +//------------------------ // PIOS_LED - +//------------------------ #define PIOS_LED_USB 0 #define PIOS_LED_LINK 1 #define PIOS_LED_RX 2 @@ -104,17 +110,27 @@ TIM4 | STOPWATCH | #define TX_LED_OFF PIOS_LED_Off(PIOS_LED_TX) #define TX_LED_TOGGLE PIOS_LED_Toggle(PIOS_LED_TX) -// ***************************************************************** -// Timer interrupt +//------------------------- +// System Settings +//------------------------- +#define PIOS_MASTER_CLOCK 72000000 +#define PIOS_PERIPHERAL_CLOCK (PIOS_MASTER_CLOCK / 2) -#define TIMER_INT_TIMER TIM3 -#define TIMER_INT_FUNC TIM3_IRQHandler -#define TIMER_INT_PRIORITY 2 +//------------------------- +// Interrupt Priorities +//------------------------- +#define PIOS_IRQ_PRIO_LOW 12 // lower than RTOS +#define PIOS_IRQ_PRIO_MID 8 // higher than RTOS +#define PIOS_IRQ_PRIO_HIGH 5 // for SPI, ADC, I2C etc... +#define PIOS_IRQ_PRIO_HIGHEST 4 // for USART etc... -// ***************************************************************** -// Stop watch timer - -#define STOPWATCH_TIMER TIM4 +//------------------------ +// PIOS_I2C +// See also pios_board.c +//------------------------ +#define PIOS_I2C_MAX_DEVS 1 +extern uint32_t pios_i2c_flexi_adapter_id; +#define PIOS_I2C_MAIN_ADAPTER (pios_i2c_flexi_adapter_id) //------------------------ // PIOS_SPI @@ -126,286 +142,170 @@ extern uint32_t pios_spi_port_id; //------------------------- // PIOS_USART -// -// See also pios_board.c //------------------------- -#define PIOS_USART_MAX_DEVS 1 +#define PIOS_USART_MAX_DEVS 3 //------------------------- // PIOS_COM // // See also pios_board.c //------------------------- -#define PIOS_COM_MAX_DEVS 2 +#define PIOS_COM_MAX_DEVS 5 -extern uint32_t pios_com_serial_id; -#define PIOS_COM_SERIAL (pios_com_serial_id) -//#define PIOS_COM_DEBUG PIOS_COM_SERIAL // uncomment this to send debug info out the serial port - -#if defined(PIOS_INCLUDE_USB_HID) extern uint32_t pios_com_telem_usb_id; -#define PIOS_COM_TELEM_USB (pios_com_telem_usb_id) -#endif +extern uint32_t pios_com_telemetry_id; +extern uint32_t pios_com_flexi_id; +extern uint32_t pios_com_vcp_id; +extern uint32_t pios_com_uavtalk_com_id; +extern uint32_t pios_com_trans_com_id; +extern uint32_t pios_com_debug_id; +extern uint32_t pios_com_rfm22b_id; +extern uint32_t pios_ppm_rcvr_id; +#define PIOS_COM_USB_HID (pios_com_telem_usb_id) +#define PIOS_COM_TELEMETRY (pios_com_telemetry_id) +#define PIOS_COM_FLEXI (pios_com_flexi_id) +#define PIOS_COM_VCP (pios_com_vcp_id) +#define PIOS_COM_UAVTALK (pios_com_uavtalk_com_id) +#define PIOS_COM_TRANS_COM (pios_com_trans_com_id) +#define PIOS_COM_DEBUG (pios_com_debug_id) +#define PIOS_COM_RADIO (pios_com_rfm22b_id) +#define PIOS_COM_TELEM_USB PIOS_COM_USB_HID +#define PIOS_PPM_RECEIVER (pios_ppm_rcvr_id) -#if defined(PIOS_COM_DEBUG) -// #define DEBUG_PRINTF(...) PIOS_COM_SendFormattedString(PIOS_COM_DEBUG, __VA_ARGS__) - #define DEBUG_PRINTF(...) PIOS_COM_SendFormattedStringNonBlocking(PIOS_COM_DEBUG, __VA_ARGS__) +#define DEBUG_LEVEL 2 +#if DEBUG_LEVEL > 0 +#define DEBUG_PRINTF(level, ...) {if(level <= DEBUG_LEVEL && PIOS_COM_DEBUG > 0) { PIOS_COM_SendFormattedStringNonBlocking(PIOS_COM_DEBUG, __VA_ARGS__); }} #else - #define DEBUG_PRINTF(...) +#define DEBUG_PRINTF(...) #endif +#define RFM22_DEBUG 1 //------------------------- -// PPM input/output -//------------------------- -#define PIOS_PPM_IN_GPIO_PORT GPIOB -#define PIOS_PPM_IN_GPIO_PIN GPIO_Pin_11 -#define PIOS_PPM_IN_TIM_CHANNEL TIM_Channel_4 -#define PIOS_PPM_IN_TIM_CCR TIM_IT_CC4 -#define PIOS_PPM_IN_TIM_GETCAP_FUNC TIM_GetCapture4 - -#define PIOS_PPM_OUT_GPIO_PORT GPIOB -#define PIOS_PPM_OUT_GPIO_PIN GPIO_Pin_10 -#define PIOS_PPM_OUT_TIM_CHANNEL TIM_Channel_3 -#define PIOS_PPM_OUT_TIM_CCR TIM_IT_CC3 - -#define PIOS_PPM_MAX_CHANNELS 7 -#define PIOS_PPM_TIM_PORT TIM2 -#define PIOS_PPM_TIM TIM2 -#define PIOS_PPM_TIM_IRQ TIM2_IRQn -#define PIOS_PPM_CC_IRQ_FUNC TIM2_IRQHandler -#define PIOS_PPM_TIMER_EN_RCC_FUNC RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2, ENABLE) -#define PIOS_PPM_TIMER_DIS_RCC_FUNC RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2, DISABLE) - -// ***************************************************************** // ADC +// None +//------------------------- +//#define PIOS_ADC_OVERSAMPLING_RATE 1 +#define PIOS_ADC_USE_TEMP_SENSOR 0 +#define PIOS_ADC_TEMP_SENSOR_ADC ADC1 +#define PIOS_ADC_TEMP_SENSOR_ADC_CHANNEL 1 -// PIOS_ADC_PinGet(0) = Temperature Sensor (On-board) -// PIOS_ADC_PinGet(1) = PSU Voltage +#define PIOS_ADC_NUM_PINS 0 -#define PIOS_ADC_OVERSAMPLING_RATE 2 +#define PIOS_ADC_PORTS { } +#define PIOS_ADC_PINS { } +#define PIOS_ADC_CHANNELS { } +#define PIOS_ADC_MAPPING { } +#define PIOS_ADC_CHANNEL_MAPPING { } +#define PIOS_ADC_NUM_CHANNELS (PIOS_ADC_NUM_PINS + PIOS_ADC_USE_TEMP_SENSOR) +#define PIOS_ADC_NUM_ADC_CHANNELS 0 +#define PIOS_ADC_USE_ADC2 0 +#define PIOS_ADC_CLOCK_FUNCTION RCC_APB2PeriphClockCmd(RCC_APB2Periph_ADC1 | RCC_APB2Periph_ADC2, ENABLE) +#define PIOS_ADC_ADCCLK RCC_PCLK2_Div8 +/* RCC_PCLK2_Div2: ADC clock = PCLK2/2 */ +/* RCC_PCLK2_Div4: ADC clock = PCLK2/4 */ +/* RCC_PCLK2_Div6: ADC clock = PCLK2/6 */ +/* RCC_PCLK2_Div8: ADC clock = PCLK2/8 */ +#define PIOS_ADC_SAMPLE_TIME ADC_SampleTime_239Cycles5 +/* Sample time: */ +/* With an ADCCLK = 14 MHz and a sampling time of 239.5 cycles: */ +/* Tconv = 239.5 + 12.5 = 252 cycles = 18�s */ +/* (1 / (ADCCLK / CYCLES)) = Sample Time (�S) */ +#define PIOS_ADC_IRQ_PRIO PIOS_IRQ_PRIO_LOW -#define PIOS_ADC_USE_TEMP_SENSOR 1 -#define PIOS_ADC_TEMP_SENSOR_ADC ADC1 -#define PIOS_ADC_TEMP_SENSOR_ADC_CHANNEL 16 // Temperature sensor channel -//#define PIOS_ADC_TEMP_SENSOR_ADC_CHANNEL 17 // VREF channel +// Currently analog acquistion hard coded at 480 Hz +// PCKL2 = HCLK / 16 +// ADCCLK = PCLK2 / 2 +#define PIOS_ADC_RATE (72.0e6 / 1.0 / 8.0 / 252.0 / (PIOS_ADC_NUM_CHANNELS >> PIOS_ADC_USE_ADC2)) +#define PIOS_ADC_MAX_OVERSAMPLING 36 -#define PIOS_ADC_PIN1_GPIO_PORT GPIOB // Port B (PSU Voltage) -#define PIOS_ADC_PIN1_GPIO_PIN GPIO_Pin_1 // PB1 .. ADC12_IN9 -#define PIOS_ADC_PIN1_GPIO_CHANNEL ADC_Channel_9 -#define PIOS_ADC_PIN1_ADC ADC2 -#define PIOS_ADC_PIN1_ADC_NUMBER 1 +//------------------------ +// PIOS_RCVR +// See also pios_board.c +//------------------------ +#define PIOS_RCVR_MAX_DEVS 3 +#define PIOS_RCVR_MAX_CHANNELS 12 +#define PIOS_GCSRCVR_TIMEOUT_MS 100 -#define PIOS_ADC_NUM_PINS 1 +//------------------------- +// Receiver PPM input +//------------------------- +#define PIOS_PPM_MAX_DEVS 1 +#define PIOS_PPM_NUM_INPUTS 12 +#define PIOS_PPM_PACKET_UPDATE_PERIOD_MS 25 -#define PIOS_ADC_PORTS { PIOS_ADC_PIN1_GPIO_PORT } -#define PIOS_ADC_PINS { PIOS_ADC_PIN1_GPIO_PIN } -#define PIOS_ADC_CHANNELS { PIOS_ADC_PIN1_GPIO_CHANNEL } -#define PIOS_ADC_MAPPING { PIOS_ADC_PIN1_ADC } -#define PIOS_ADC_CHANNEL_MAPPING { PIOS_ADC_PIN1_ADC_NUMBER } +//------------------------- +// Servo outputs +//------------------------- +#define PIOS_SERVO_UPDATE_HZ 50 +#define PIOS_SERVOS_INITIAL_POSITION 0 /* dont want to start motors, have no pulse till settings loaded */ -#define PIOS_ADC_NUM_CHANNELS (PIOS_ADC_NUM_PINS + PIOS_ADC_USE_TEMP_SENSOR) -#define PIOS_ADC_NUM_ADC_CHANNELS 2 -#define PIOS_ADC_USE_ADC2 1 -#define PIOS_ADC_CLOCK_FUNCTION RCC_APB2PeriphClockCmd(RCC_APB2Periph_ADC1 | RCC_APB2Periph_ADC2, ENABLE) -//#define PIOS_ADC_ADCCLK RCC_PCLK2_Div2 // ADC clock = PCLK2/2 -//#define PIOS_ADC_ADCCLK RCC_PCLK2_Div4 // ADC clock = PCLK2/4 -//#define PIOS_ADC_ADCCLK RCC_PCLK2_Div6 // ADC clock = PCLK2/6 -#define PIOS_ADC_ADCCLK RCC_PCLK2_Div8 // ADC clock = PCLK2/8 -//#define PIOS_ADC_SAMPLE_TIME ADC_SampleTime_1Cycles5 -//#define PIOS_ADC_SAMPLE_TIME ADC_SampleTime_7Cycles5 -//#define PIOS_ADC_SAMPLE_TIME ADC_SampleTime_13Cycles5 -//#define PIOS_ADC_SAMPLE_TIME ADC_SampleTime_28Cycles5 -//#define PIOS_ADC_SAMPLE_TIME ADC_SampleTime_41Cycles5 -//#define PIOS_ADC_SAMPLE_TIME ADC_SampleTime_55Cycles5 -//#define PIOS_ADC_SAMPLE_TIME ADC_SampleTime_71Cycles5 -#define PIOS_ADC_SAMPLE_TIME ADC_SampleTime_239Cycles5 - /* Sample time: */ - /* With an ADCCLK = 14 MHz and a sampling time of 293.5 cycles: */ - /* Tconv = 239.5 + 12.5 = 252 cycles = 18�s */ - /* (1 / (ADCCLK / CYCLES)) = Sample Time (�S) */ -#define PIOS_ADC_IRQ_PRIO 3 -#define PIOS_ADC_MAX_OVERSAMPLING 1 -#define PIOS_ADC_RATE (72.0e6 / 1 / 8 / 252 / (PIOS_ADC_NUM_ADC_CHANNELS >> PIOS_ADC_USE_ADC2)) +//-------------------------- +// Timer controller settings +//-------------------------- +#define PIOS_TIM_MAX_DEVS 3 -// ***************************************************************** -// GPIO output pins +//------------------------- +// GPIO +//------------------------- +#define PIOS_GPIO_PORTS { } +#define PIOS_GPIO_PINS { } +#define PIOS_GPIO_CLKS { } +#define PIOS_GPIO_NUM 0 -// GPIO_Mode_Out_OD Open Drain Output -// GPIO_Mode_Out_PP Push-Pull Output -// GPIO_Mode_AF_OD Open Drain Output Alternate-Function -// GPIO_Mode_AF_PP Push-Pull Output Alternate-Function - -// Serial port RTS line -#define PIOS_GPIO_OUT_0_PORT GPIOB -#define PIOS_GPIO_OUT_0_PIN GPIO_Pin_15 -#define PIOS_GPIO_OUT_0_GPIO_CLK RCC_APB2Periph_GPIOB - -// RF module chip-select line -#define PIOS_GPIO_OUT_1_PORT GPIOA -#define PIOS_GPIO_OUT_1_PIN GPIO_Pin_4 -#define PIOS_GPIO_OUT_1_GPIO_CLK RCC_APB2Periph_GPIOA - -// PPM OUT line -#define PIOS_GPIO_OUT_2_PORT GPIOB -#define PIOS_GPIO_OUT_2_PIN GPIO_Pin_10 -#define PIOS_GPIO_OUT_2_GPIO_CLK RCC_APB2Periph_GPIOB - -// spare pin -#define PIOS_GPIO_OUT_3_PORT GPIOA -#define PIOS_GPIO_OUT_3_PIN GPIO_Pin_0 -#define PIOS_GPIO_OUT_3_GPIO_CLK RCC_APB2Periph_GPIOA - -// spare pin -#define PIOS_GPIO_OUT_4_PORT GPIOA -#define PIOS_GPIO_OUT_4_PIN GPIO_Pin_1 -#define PIOS_GPIO_OUT_4_GPIO_CLK RCC_APB2Periph_GPIOA - -// spare pin -#define PIOS_GPIO_OUT_5_PORT GPIOC -#define PIOS_GPIO_OUT_5_PIN GPIO_Pin_13 -#define PIOS_GPIO_OUT_5_GPIO_CLK RCC_APB2Periph_GPIOC - -// spare pin -#define PIOS_GPIO_OUT_6_PORT GPIOC -#define PIOS_GPIO_OUT_6_PIN GPIO_Pin_14 -#define PIOS_GPIO_OUT_6_GPIO_CLK RCC_APB2Periph_GPIOC - -// spare pin -#define PIOS_GPIO_OUT_7_PORT GPIOC -#define PIOS_GPIO_OUT_7_PIN GPIO_Pin_15 -#define PIOS_GPIO_OUT_7_GPIO_CLK RCC_APB2Periph_GPIOC - -#define PIOS_GPIO_NUM 8 -#define PIOS_GPIO_PORTS {PIOS_GPIO_OUT_0_PORT, PIOS_GPIO_OUT_1_PORT, PIOS_GPIO_OUT_2_PORT, PIOS_GPIO_OUT_3_PORT, PIOS_GPIO_OUT_4_PORT, PIOS_GPIO_OUT_5_PORT, PIOS_GPIO_OUT_6_PORT, PIOS_GPIO_OUT_7_PORT} -#define PIOS_GPIO_PINS {PIOS_GPIO_OUT_0_PIN, PIOS_GPIO_OUT_1_PIN, PIOS_GPIO_OUT_2_PIN, PIOS_GPIO_OUT_3_PIN, PIOS_GPIO_OUT_4_PIN, PIOS_GPIO_OUT_5_PIN, PIOS_GPIO_OUT_6_PIN, PIOS_GPIO_OUT_7_PIN} -#define PIOS_GPIO_CLKS {PIOS_GPIO_OUT_0_GPIO_CLK, PIOS_GPIO_OUT_1_GPIO_CLK, PIOS_GPIO_OUT_2_GPIO_CLK, PIOS_GPIO_OUT_3_GPIO_CLK, PIOS_GPIO_OUT_4_GPIO_CLK, PIOS_GPIO_OUT_5_GPIO_CLK, PIOS_GPIO_OUT_6_GPIO_CLK, PIOS_GPIO_OUT_7_GPIO_CLK} - -#define SERIAL_RTS_ENABLE PIOS_GPIO_Enable(0) -#define SERIAL_RTS_SET PIOS_GPIO_Off(0) -#define SERIAL_RTS_CLEAR PIOS_GPIO_On(0) - -#define RF_CS_ENABLE PIOS_GPIO_Enable(1) -#define RF_CS_HIGH PIOS_GPIO_Off(1) -#define RF_CS_LOW PIOS_GPIO_On(1) - -#define PPM_OUT_PIN PIOS_GPIO_OUT_2_PIN -#define PPM_OUT_PORT PIOS_GPIO_OUT_2_PORT -#define PPM_OUT_ENABLE PIOS_GPIO_Enable(2) -#define PPM_OUT_HIGH PIOS_GPIO_Off(2) -#define PPM_OUT_LOW PIOS_GPIO_On(2) - -#define SPARE1_ENABLE PIOS_GPIO_Enable(3) -#define SPARE1_HIGH PIOS_GPIO_Off(3) -#define SPARE1_LOW PIOS_GPIO_On(3) - -#define SPARE2_ENABLE PIOS_GPIO_Enable(4) -#define SPARE2_HIGH PIOS_GPIO_Off(4) -#define SPARE2_LOW PIOS_GPIO_On(4) - -#define SPARE3_ENABLE PIOS_GPIO_Enable(5) -#define SPARE3_HIGH PIOS_GPIO_Off(5) -#define SPARE3_LOW PIOS_GPIO_On(5) - -#define SPARE4_ENABLE PIOS_GPIO_Enable(6) -#define SPARE4_HIGH PIOS_GPIO_Off(6) -#define SPARE4_LOW PIOS_GPIO_On(6) - -#define SPARE5_ENABLE PIOS_GPIO_Enable(7) -#define SPARE5_HIGH PIOS_GPIO_Off(7) -#define SPARE5_LOW PIOS_GPIO_On(7) - -// ***************************************************************** -// GPIO input pins - -// GPIO_Mode_AIN Analog Input -// GPIO_Mode_IN_FLOATING Input Floating -// GPIO_Mode_IPD Input Pull-Down -// GPIO_Mode_IPU Input Pull-up - -// API mode line -#define GPIO_IN_0_PORT GPIOB -#define GPIO_IN_0_PIN GPIO_Pin_13 -#define GPIO_IN_0_MODE GPIO_Mode_IPU - -// Serial port CTS line -#define GPIO_IN_1_PORT GPIOB -#define GPIO_IN_1_PIN GPIO_Pin_14 -#define GPIO_IN_1_MODE GPIO_Mode_IPU - -// VBUS sense line -#define GPIO_IN_2_PORT GPIOA -#define GPIO_IN_2_PIN GPIO_Pin_8 -#define GPIO_IN_2_MODE GPIO_Mode_IN_FLOATING - -// 868MHz jumper option -#define GPIO_IN_3_PORT GPIOB -#define GPIO_IN_3_PIN GPIO_Pin_8 -#define GPIO_IN_3_MODE GPIO_Mode_IPU - -// 915MHz jumper option -#define GPIO_IN_4_PORT GPIOB -#define GPIO_IN_4_PIN GPIO_Pin_9 -#define GPIO_IN_4_MODE GPIO_Mode_IPU - -// RF INT line -#define GPIO_IN_5_PORT GPIOA -#define GPIO_IN_5_PIN GPIO_Pin_2 -#define GPIO_IN_5_MODE GPIO_Mode_IN_FLOATING - -// RF misc line -#define GPIO_IN_6_PORT GPIOB -#define GPIO_IN_6_PIN GPIO_Pin_0 -#define GPIO_IN_6_MODE GPIO_Mode_IN_FLOATING - -// PPM IN line -#define PPM_IN_PORT GPIOB -#define PPM_IN_PIN GPIO_Pin_11 -#define PPM_IN_MODE GPIO_Mode_IPD - -#define GPIO_IN_NUM 8 -#define GPIO_IN_PORTS { GPIO_IN_0_PORT, GPIO_IN_1_PORT, GPIO_IN_2_PORT, GPIO_IN_3_PORT, GPIO_IN_4_PORT, GPIO_IN_5_PORT, GPIO_IN_6_PORT, PPM_IN_PORT } -#define GPIO_IN_PINS { GPIO_IN_0_PIN, GPIO_IN_1_PIN, GPIO_IN_2_PIN, GPIO_IN_3_PIN, GPIO_IN_4_PIN, GPIO_IN_5_PIN, GPIO_IN_6_PIN, PPM_IN_PIN } -#define GPIO_IN_MODES { GPIO_IN_0_MODE, GPIO_IN_1_MODE, GPIO_IN_2_MODE, GPIO_IN_3_MODE, GPIO_IN_4_MODE, GPIO_IN_5_MODE, GPIO_IN_6_MODE, PPM_IN_MODE } - -#define API_MODE_PIN 0 -#define SERIAL_CTS_PIN 1 -#define VBUS_SENSE_PIN 2 -#define _868MHz_PIN 3 -#define _915MHz_PIN 4 -#define RF_INT_PIN 5 -#define RF_MISC_PIN 6 - -// ***************************************************************** +//------------------------- // USB +//------------------------- +#define PIOS_USB_HID_MAX_DEVS 1 +#define PIOS_USB_ENABLED 1 +#define PIOS_USB_HID_MAX_DEVS 1 +#define PIOS_USB_MAX_DEVS 1 +#define PIOS_USB_DETECT_GPIO_PORT GPIOC +#define PIOS_USB_DETECT_GPIO_PIN GPIO_Pin_15 +#define PIOS_USB_DETECT_EXTI_LINE EXTI_Line15 -#if defined(PIOS_INCLUDE_USB_HID) - #define PIOS_USB_ENABLED 1 - #define PIOS_USB_MAX_DEVS 1 - #define PIOS_USB_DETECT_GPIO_PORT GPIO_IN_2_PORT - #define PIOS_USB_DETECT_GPIO_PIN GPIO_IN_2_PIN - #define PIOS_USB_DETECT_EXTI_LINE EXTI_Line4 - #define PIOS_IRQ_USB_PRIORITY 8 -#endif -#define PIOS_USB_HID_MAX_DEVS 1 - -// ***************************************************************** +//------------------------- // RFM22 +//------------------------- -//#define RFM22_EXT_INT_USE - -#define RFM22_PIOS_SPI PIOS_SPI_PORT // SPIx +extern uint32_t pios_rfm22b_id; +#define RFM22_EXT_INT_USE +#define RFM22_PIOS_SPI PIOS_SPI_PORT // SPIx #if defined(RFM22_EXT_INT_USE) - #define RFM22_EXT_INT_PORT_SOURCE GPIO_PortSourceGPIOA - #define RFM22_EXT_INT_PIN_SOURCE GPIO_PinSource2 - - #define RFM22_EXT_INT_LINE EXTI_Line2 - #define RFM22_EXT_INT_IRQn EXTI2_IRQn - #define RFM22_EXT_INT_FUNC EXTI2_IRQHandler - - #define RFM22_EXT_INT_PRIORITY 1 +#define PIOS_RFM22_EXTI_GPIO_PORT GPIOA +#define PIOS_RFM22_EXTI_GPIO_PIN GPIO_Pin_2 +#define PIOS_RFM22_EXTI_PORT_SOURCE GPIO_PortSourceGPIOA +#define PIOS_RFM22_EXTI_PIN_SOURCE GPIO_PinSource2 +#define PIOS_RFM22_EXTI_CLK RCC_APB2Periph_GPIOA +#define PIOS_RFM22_EXTI_LINE EXTI_Line2 +#define PIOS_RFM22_EXTI_IRQn EXTI2_IRQn +#define PIOS_RFM22_EXTI_PRIO PIOS_IRQ_PRIO_LOW #endif -// ***************************************************************** +//------------------------- +// Packet Handler +//------------------------- -#endif /* PIOS_BOARD_H */ +uint32_t pios_packet_handler; +#define PIOS_INCLUDE_PACKET_HANDLER +#define PIOS_PH_MAX_PACKET 255 +#define PIOS_PH_WIN_SIZE 3 +#define PIOS_PH_MAX_CONNECTIONS 1 + +//------------------------- +// Reed-Solomon ECC +//------------------------- + +#define RS_ECC_NPARITY 4 + +//------------------------- +// Flash EEPROM Emulation +//------------------------- + +#define PIOS_FLASH_SIZE 0x20000 +#define PIOS_FLASH_EEPROM_START_ADDR 0x08000000 +#define PIOS_FLASH_PAGE_SIZE 1024 +#define PIOS_FLASH_EEPROM_ADDR (PIOS_FLASH_EEPROM_START_ADDR + PIOS_FLASH_SIZE - PIOS_FLASH_PAGE_SIZE) +#define PIOS_FLASH_EEPROM_LEN PIOS_FLASH_PAGE_SIZE + +#endif /* STM32103CB_PIPXTREME_H_ */ diff --git a/flight/PiOS/Common/pios_crc.c b/flight/PiOS/Common/pios_crc.c index 548ba2648..dcd8c80c7 100644 --- a/flight/PiOS/Common/pios_crc.c +++ b/flight/PiOS/Common/pios_crc.c @@ -29,6 +29,76 @@ static const uint8_t crc_table[256] = { 0xde, 0xd9, 0xd0, 0xd7, 0xc2, 0xc5, 0xcc, 0xcb, 0xe6, 0xe1, 0xe8, 0xef, 0xfa, 0xfd, 0xf4, 0xf3 }; +static const uint16_t CRC_Table16[] = { // HDLC polynomial + 0x0000, 0x1189, 0x2312, 0x329b, 0x4624, 0x57ad, 0x6536, 0x74bf, + 0x8c48, 0x9dc1, 0xaf5a, 0xbed3, 0xca6c, 0xdbe5, 0xe97e, 0xf8f7, + 0x1081, 0x0108, 0x3393, 0x221a, 0x56a5, 0x472c, 0x75b7, 0x643e, + 0x9cc9, 0x8d40, 0xbfdb, 0xae52, 0xdaed, 0xcb64, 0xf9ff, 0xe876, + 0x2102, 0x308b, 0x0210, 0x1399, 0x6726, 0x76af, 0x4434, 0x55bd, + 0xad4a, 0xbcc3, 0x8e58, 0x9fd1, 0xeb6e, 0xfae7, 0xc87c, 0xd9f5, + 0x3183, 0x200a, 0x1291, 0x0318, 0x77a7, 0x662e, 0x54b5, 0x453c, + 0xbdcb, 0xac42, 0x9ed9, 0x8f50, 0xfbef, 0xea66, 0xd8fd, 0xc974, + 0x4204, 0x538d, 0x6116, 0x709f, 0x0420, 0x15a9, 0x2732, 0x36bb, + 0xce4c, 0xdfc5, 0xed5e, 0xfcd7, 0x8868, 0x99e1, 0xab7a, 0xbaf3, + 0x5285, 0x430c, 0x7197, 0x601e, 0x14a1, 0x0528, 0x37b3, 0x263a, + 0xdecd, 0xcf44, 0xfddf, 0xec56, 0x98e9, 0x8960, 0xbbfb, 0xaa72, + 0x6306, 0x728f, 0x4014, 0x519d, 0x2522, 0x34ab, 0x0630, 0x17b9, + 0xef4e, 0xfec7, 0xcc5c, 0xddd5, 0xa96a, 0xb8e3, 0x8a78, 0x9bf1, + 0x7387, 0x620e, 0x5095, 0x411c, 0x35a3, 0x242a, 0x16b1, 0x0738, + 0xffcf, 0xee46, 0xdcdd, 0xcd54, 0xb9eb, 0xa862, 0x9af9, 0x8b70, + 0x8408, 0x9581, 0xa71a, 0xb693, 0xc22c, 0xd3a5, 0xe13e, 0xf0b7, + 0x0840, 0x19c9, 0x2b52, 0x3adb, 0x4e64, 0x5fed, 0x6d76, 0x7cff, + 0x9489, 0x8500, 0xb79b, 0xa612, 0xd2ad, 0xc324, 0xf1bf, 0xe036, + 0x18c1, 0x0948, 0x3bd3, 0x2a5a, 0x5ee5, 0x4f6c, 0x7df7, 0x6c7e, + 0xa50a, 0xb483, 0x8618, 0x9791, 0xe32e, 0xf2a7, 0xc03c, 0xd1b5, + 0x2942, 0x38cb, 0x0a50, 0x1bd9, 0x6f66, 0x7eef, 0x4c74, 0x5dfd, + 0xb58b, 0xa402, 0x9699, 0x8710, 0xf3af, 0xe226, 0xd0bd, 0xc134, + 0x39c3, 0x284a, 0x1ad1, 0x0b58, 0x7fe7, 0x6e6e, 0x5cf5, 0x4d7c, + 0xc60c, 0xd785, 0xe51e, 0xf497, 0x8028, 0x91a1, 0xa33a, 0xb2b3, + 0x4a44, 0x5bcd, 0x6956, 0x78df, 0x0c60, 0x1de9, 0x2f72, 0x3efb, + 0xd68d, 0xc704, 0xf59f, 0xe416, 0x90a9, 0x8120, 0xb3bb, 0xa232, + 0x5ac5, 0x4b4c, 0x79d7, 0x685e, 0x1ce1, 0x0d68, 0x3ff3, 0x2e7a, + 0xe70e, 0xf687, 0xc41c, 0xd595, 0xa12a, 0xb0a3, 0x8238, 0x93b1, + 0x6b46, 0x7acf, 0x4854, 0x59dd, 0x2d62, 0x3ceb, 0x0e70, 0x1ff9, + 0xf78f, 0xe606, 0xd49d, 0xc514, 0xb1ab, 0xa022, 0x92b9, 0x8330, + 0x7bc7, 0x6a4e, 0x58d5, 0x495c, 0x3de3, 0x2c6a, 0x1ef1, 0x0f78 +}; + +static const uint32_t CRC_Table32[] = { + 0x00000000, 0x04c11db7, 0x09823b6e, 0x0d4326d9, 0x130476dc, 0x17c56b6b, 0x1a864db2, 0x1e475005, + 0x2608edb8, 0x22c9f00f, 0x2f8ad6d6, 0x2b4bcb61, 0x350c9b64, 0x31cd86d3, 0x3c8ea00a, 0x384fbdbd, + 0x4c11db70, 0x48d0c6c7, 0x4593e01e, 0x4152fda9, 0x5f15adac, 0x5bd4b01b, 0x569796c2, 0x52568b75, + 0x6a1936c8, 0x6ed82b7f, 0x639b0da6, 0x675a1011, 0x791d4014, 0x7ddc5da3, 0x709f7b7a, 0x745e66cd, + 0x9823b6e0, 0x9ce2ab57, 0x91a18d8e, 0x95609039, 0x8b27c03c, 0x8fe6dd8b, 0x82a5fb52, 0x8664e6e5, + 0xbe2b5b58, 0xbaea46ef, 0xb7a96036, 0xb3687d81, 0xad2f2d84, 0xa9ee3033, 0xa4ad16ea, 0xa06c0b5d, + 0xd4326d90, 0xd0f37027, 0xddb056fe, 0xd9714b49, 0xc7361b4c, 0xc3f706fb, 0xceb42022, 0xca753d95, + 0xf23a8028, 0xf6fb9d9f, 0xfbb8bb46, 0xff79a6f1, 0xe13ef6f4, 0xe5ffeb43, 0xe8bccd9a, 0xec7dd02d, + 0x34867077, 0x30476dc0, 0x3d044b19, 0x39c556ae, 0x278206ab, 0x23431b1c, 0x2e003dc5, 0x2ac12072, + 0x128e9dcf, 0x164f8078, 0x1b0ca6a1, 0x1fcdbb16, 0x018aeb13, 0x054bf6a4, 0x0808d07d, 0x0cc9cdca, + 0x7897ab07, 0x7c56b6b0, 0x71159069, 0x75d48dde, 0x6b93dddb, 0x6f52c06c, 0x6211e6b5, 0x66d0fb02, + 0x5e9f46bf, 0x5a5e5b08, 0x571d7dd1, 0x53dc6066, 0x4d9b3063, 0x495a2dd4, 0x44190b0d, 0x40d816ba, + 0xaca5c697, 0xa864db20, 0xa527fdf9, 0xa1e6e04e, 0xbfa1b04b, 0xbb60adfc, 0xb6238b25, 0xb2e29692, + 0x8aad2b2f, 0x8e6c3698, 0x832f1041, 0x87ee0df6, 0x99a95df3, 0x9d684044, 0x902b669d, 0x94ea7b2a, + 0xe0b41de7, 0xe4750050, 0xe9362689, 0xedf73b3e, 0xf3b06b3b, 0xf771768c, 0xfa325055, 0xfef34de2, + 0xc6bcf05f, 0xc27dede8, 0xcf3ecb31, 0xcbffd686, 0xd5b88683, 0xd1799b34, 0xdc3abded, 0xd8fba05a, + 0x690ce0ee, 0x6dcdfd59, 0x608edb80, 0x644fc637, 0x7a089632, 0x7ec98b85, 0x738aad5c, 0x774bb0eb, + 0x4f040d56, 0x4bc510e1, 0x46863638, 0x42472b8f, 0x5c007b8a, 0x58c1663d, 0x558240e4, 0x51435d53, + 0x251d3b9e, 0x21dc2629, 0x2c9f00f0, 0x285e1d47, 0x36194d42, 0x32d850f5, 0x3f9b762c, 0x3b5a6b9b, + 0x0315d626, 0x07d4cb91, 0x0a97ed48, 0x0e56f0ff, 0x1011a0fa, 0x14d0bd4d, 0x19939b94, 0x1d528623, + 0xf12f560e, 0xf5ee4bb9, 0xf8ad6d60, 0xfc6c70d7, 0xe22b20d2, 0xe6ea3d65, 0xeba91bbc, 0xef68060b, + 0xd727bbb6, 0xd3e6a601, 0xdea580d8, 0xda649d6f, 0xc423cd6a, 0xc0e2d0dd, 0xcda1f604, 0xc960ebb3, + 0xbd3e8d7e, 0xb9ff90c9, 0xb4bcb610, 0xb07daba7, 0xae3afba2, 0xaafbe615, 0xa7b8c0cc, 0xa379dd7b, + 0x9b3660c6, 0x9ff77d71, 0x92b45ba8, 0x9675461f, 0x8832161a, 0x8cf30bad, 0x81b02d74, 0x857130c3, + 0x5d8a9099, 0x594b8d2e, 0x5408abf7, 0x50c9b640, 0x4e8ee645, 0x4a4ffbf2, 0x470cdd2b, 0x43cdc09c, + 0x7b827d21, 0x7f436096, 0x7200464f, 0x76c15bf8, 0x68860bfd, 0x6c47164a, 0x61043093, 0x65c52d24, + 0x119b4be9, 0x155a565e, 0x18197087, 0x1cd86d30, 0x029f3d35, 0x065e2082, 0x0b1d065b, 0x0fdc1bec, + 0x3793a651, 0x3352bbe6, 0x3e119d3f, 0x3ad08088, 0x2497d08d, 0x2056cd3a, 0x2d15ebe3, 0x29d4f654, + 0xc5a92679, 0xc1683bce, 0xcc2b1d17, 0xc8ea00a0, 0xd6ad50a5, 0xd26c4d12, 0xdf2f6bcb, 0xdbee767c, + 0xe3a1cbc1, 0xe760d676, 0xea23f0af, 0xeee2ed18, 0xf0a5bd1d, 0xf464a0aa, 0xf9278673, 0xfde69bc4, + 0x89b8fd09, 0x8d79e0be, 0x803ac667, 0x84fbdbd0, 0x9abc8bd5, 0x9e7d9662, 0x933eb0bb, 0x97ffad0c, + 0xafb010b1, 0xab710d06, 0xa6322bdf, 0xa2f33668, 0xbcb4666d, 0xb8757bda, 0xb5365d03, 0xb1f740b4 + }; + /** * Update the crc value with new data. * @@ -52,7 +122,7 @@ 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 @@ -72,3 +142,58 @@ uint8_t PIOS_CRC_updateCRC(uint8_t crc, const uint8_t* data, int32_t length) return crc8; } +/** + * Update the crc value with new data. + * \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. + */ +uint16_t PIOS_CRC16_updateByte(uint16_t crc, const uint8_t data) +{ + return ((crc >> 8) ^ CRC_Table16[(crc & 0xff) ^ 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 + */ +uint16_t PIOS_CRC16_updateCRC(uint16_t crc, const uint8_t* data, int32_t length) +{ + register uint8_t *p = (uint8_t *)data; + register uint16_t _crc = crc; + for (register uint32_t i = length; i > 0; i--) + _crc = (_crc >> 8) ^ CRC_Table16[(_crc ^ *p++) & 0xff]; + return _crc; +} + +/** + * Update the crc value with new data. + * \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. + */ +uint32_t PIOS_CRC32_updateByte(uint32_t crc, const uint8_t data) +{ + return ((crc << 8) ^ CRC_Table32[(crc >> 24) ^ 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 + */ +uint32_t PIOS_CRC32_updateCRC(uint32_t crc, const uint8_t* data, int32_t length) +{ + register uint8_t *p = (uint8_t *)data; + register uint32_t _crc = crc; + for (register uint32_t i = length; i > 0; i--) + _crc = (_crc << 8) ^ CRC_Table32[(_crc >> 24) ^ *p++]; + return _crc; +} diff --git a/flight/PiOS/Common/pios_gcsrcvr.c b/flight/PiOS/Common/pios_gcsrcvr.c index ad34b5c20..eda2a94ed 100644 --- a/flight/PiOS/Common/pios_gcsrcvr.c +++ b/flight/PiOS/Common/pios_gcsrcvr.c @@ -152,10 +152,9 @@ static void PIOS_gcsrcvr_Supervisor(uint32_t gcsrcvr_id) { } /* - * RTC runs at 625Hz so divide down the base rate so - * that this loop runs at 25Hz. + * RTC runs at 625Hz. */ - if(++(gcsrcvr_dev->supv_timer) < 25) { + if(++(gcsrcvr_dev->supv_timer) < (PIOS_GCSRCVR_TIMEOUT_MS * 1000 / 625)) { return; } gcsrcvr_dev->supv_timer = 0; diff --git a/flight/PiOS/Common/pios_rfm22b.c b/flight/PiOS/Common/pios_rfm22b.c new file mode 100644 index 000000000..872ddbb96 --- /dev/null +++ b/flight/PiOS/Common/pios_rfm22b.c @@ -0,0 +1,2407 @@ +/** +****************************************************************************** +* @addtogroup PIOS PIOS Core hardware abstraction layer +* @{ +* @addtogroup PIOS_RFM22B Radio Functions +* @brief PIOS interface for for the RFM22B radio +* @{ +* +* @file pios_rfm22b.c +* @author The OpenPilot Team, http://www.openpilot.org Copyright (C) 2012. +* @brief Implements a driver the the RFM22B driver +* @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 + */ + +// ***************************************************************** +// RFM22B hardware layer +// +// This module uses the RFM22B's internal packet handling hardware to +// encapsulate our own packet data. +// +// The RFM22B internal hardware packet handler configuration is as follows .. +// +// 4-byte (32-bit) preamble .. alternating 0's & 1's +// 4-byte (32-bit) sync +// 1-byte packet length (number of data bytes to follow) +// 0 to 255 user data bytes +// +// Our own packet data will also contain it's own header and 32-bit CRC +// as a single 16-bit CRC is not sufficient for wireless comms. +// +// ***************************************************************** + +/* Project Includes */ +#include "pios.h" + +#if defined(PIOS_INCLUDE_RFM22B) + +#include // memmove + +#include +#include + +#include + +#include + +/* Local Defines */ +#define STACK_SIZE_BYTES 200 + +// RTC timer is running at 625Hz (1.6ms or 5 ticks == 8ms). +// A 256 byte message at 56kbps should take less than 40ms +// Note: This timeout should be rate dependent. +#define PIOS_RFM22B_SUPERVISOR_TIMEOUT 65 // ~100ms + +// this is too adjust the RF module so that it is on frequency +#define OSC_LOAD_CAP 0x7F // cap = 12.5pf .. default +#define OSC_LOAD_CAP_1 0x7D // board 1 +#define OSC_LOAD_CAP_2 0x7B // board 2 +#define OSC_LOAD_CAP_3 0x7E // board 3 +#define OSC_LOAD_CAP_4 0x7F // board 4 + +// ************************************ + +#define TX_TEST_MODE_TIMELIMIT_MS 30000 // TX test modes time limit (in ms) + +//#define TX_PREAMBLE_NIBBLES 8 // 7 to 511 (number of nibbles) +//#define RX_PREAMBLE_NIBBLES 5 // 5 to 31 (number of nibbles) +#define TX_PREAMBLE_NIBBLES 12 // 7 to 511 (number of nibbles) +#define RX_PREAMBLE_NIBBLES 6 // 5 to 31 (number of nibbles) + +// the size of the rf modules internal transmit buffers. +#define TX_BUFFER_SIZE 256 +// the size of the rf modules internal FIFO buffers +#define FIFO_SIZE 64 + +#define TX_FIFO_HI_WATERMARK 62 // 0-63 +#define TX_FIFO_LO_WATERMARK 32 // 0-63 + +#define RX_FIFO_HI_WATERMARK 32 // 0-63 + +#define PREAMBLE_BYTE 0x55 // preamble byte (preceeds SYNC_BYTE's) + +#define SYNC_BYTE_1 0x2D // RF sync bytes (32-bit in all) +#define SYNC_BYTE_2 0xD4 // +#define SYNC_BYTE_3 0x4B // +#define SYNC_BYTE_4 0x59 // + +// ************************************ +// the default TX power level + +#define RFM22_DEFAULT_RF_POWER RFM22_tx_pwr_txpow_0 // +1dBm ... 1.25mW +//#define RFM22_DEFAULT_RF_POWER RFM22_tx_pwr_txpow_1 // +2dBm ... 1.6mW +//#define RFM22_DEFAULT_RF_POWER RFM22_tx_pwr_txpow_2 // +5dBm ... 3.16mW +//#define RFM22_DEFAULT_RF_POWER RFM22_tx_pwr_txpow_3 // +8dBm ... 6.3mW +//#define RFM22_DEFAULT_RF_POWER RFM22_tx_pwr_txpow_4 // +11dBm .. 12.6mW +//#define RFM22_DEFAULT_RF_POWER RFM22_tx_pwr_txpow_5 // +14dBm .. 25mW +//#define RFM22_DEFAULT_RF_POWER RFM22_tx_pwr_txpow_6 // +17dBm .. 50mW +//#define RFM22_DEFAULT_RF_POWER RFM22_tx_pwr_txpow_7 // +20dBm .. 100mW + +// ************************************ +// the default RF datarate + +//#define RFM22_DEFAULT_RF_DATARATE 500 // 500 bits per sec +//#define RFM22_DEFAULT_RF_DATARATE 1000 // 1k bits per sec +//#define RFM22_DEFAULT_RF_DATARATE 2000 // 2k bits per sec +//#define RFM22_DEFAULT_RF_DATARATE 4000 // 4k bits per sec +//#define RFM22_DEFAULT_RF_DATARATE 8000 // 8k bits per sec +//#define RFM22_DEFAULT_RF_DATARATE 9600 // 9.6k bits per sec +//#define RFM22_DEFAULT_RF_DATARATE 16000 // 16k bits per sec +//#define RFM22_DEFAULT_RF_DATARATE 19200 // 19k2 bits per sec +//#define RFM22_DEFAULT_RF_DATARATE 24000 // 24k bits per sec +//#define RFM22_DEFAULT_RF_DATARATE 32000 // 32k bits per sec +//#define RFM22_DEFAULT_RF_DATARATE 64000 // 64k bits per sec +#define RFM22_DEFAULT_RF_DATARATE 128000 // 128k bits per sec +//#define RFM22_DEFAULT_RF_DATARATE 192000 // 192k bits per sec +//#define RFM22_DEFAULT_RF_DATARATE 256000 // 256k bits per sec .. NOT YET WORKING + +// ************************************ + +#define RFM22_DEFAULT_SS_RF_DATARATE 125 // 128bps + +// ************************************ +// Normal data streaming +// GFSK modulation +// no manchester encoding +// data whitening +// FIFO mode +// 5-nibble rx preamble length detection +// 10-nibble tx preamble length +// AFC enabled + +/* Local type definitions */ +enum pios_rfm22b_dev_magic { + PIOS_RFM22B_DEV_MAGIC = 0x68e971b6, +}; + +struct pios_rfm22b_dev { + enum pios_rfm22b_dev_magic magic; + struct pios_rfm22b_cfg cfg; + + uint32_t deviceID; + + // The COM callback functions. + pios_com_callback rx_in_cb; + uint32_t rx_in_context; + pios_com_callback tx_out_cb; + uint32_t tx_out_context; + + // The supervisor countdown timer. + uint16_t supv_timer; + uint16_t resets; +}; + +uint32_t random32 = 0x459ab8d8; + +/* Local function forwared declarations */ +static void PIOS_RFM22B_Supervisor(uint32_t ppm_id); +static void rfm22_processInt(void); +static void PIOS_RFM22_EXT_Int(void); +static void rfm22_setTxMode(uint8_t mode); + +// SPI read/write functions +void rfm22_startBurstWrite(uint8_t addr); +inline void rfm22_burstWrite(uint8_t data) +{ + PIOS_SPI_TransferByte(RFM22_PIOS_SPI, data); +} +void rfm22_endBurstWrite(void); +void rfm22_write(uint8_t addr, uint8_t data); +void rfm22_startBurstRead(uint8_t addr); +inline uint8_t rfm22_burstRead(void) +{ + return PIOS_SPI_TransferByte(RFM22_PIOS_SPI, 0xff); +} +void rfm22_endBurstRead(void); +uint8_t rfm22_read(uint8_t addr); +uint8_t rfm22_txStart(); + +/* Provide a COM driver */ +static void PIOS_RFM22B_ChangeBaud(uint32_t rfm22b_id, uint32_t baud); +static void PIOS_RFM22B_RegisterRxCallback(uint32_t rfm22b_id, pios_com_callback rx_in_cb, uint32_t context); +static void PIOS_RFM22B_RegisterTxCallback(uint32_t rfm22b_id, pios_com_callback tx_out_cb, uint32_t context); +static void PIOS_RFM22B_TxStart(uint32_t rfm22b_id, uint16_t tx_bytes_avail); +static void PIOS_RFM22B_RxStart(uint32_t rfm22b_id, uint16_t rx_bytes_avail); + +/* Local variables */ +const struct pios_com_driver pios_rfm22b_com_driver = { + .set_baud = PIOS_RFM22B_ChangeBaud, + .tx_start = PIOS_RFM22B_TxStart, + .rx_start = PIOS_RFM22B_RxStart, + .bind_tx_cb = PIOS_RFM22B_RegisterTxCallback, + .bind_rx_cb = PIOS_RFM22B_RegisterRxCallback, +}; + +// External interrupt configuration +static const struct pios_exti_cfg pios_exti_rfm22b_cfg __exti_config = { + .vector = PIOS_RFM22_EXT_Int, + .line = PIOS_RFM22_EXTI_LINE, + .pin = { + .gpio = PIOS_RFM22_EXTI_GPIO_PORT, + .init = { + .GPIO_Pin = PIOS_RFM22_EXTI_GPIO_PIN, + .GPIO_Mode = GPIO_Mode_IN_FLOATING, + }, + }, + .irq = { + .init = { + .NVIC_IRQChannel = PIOS_RFM22_EXTI_IRQn, + .NVIC_IRQChannelPreemptionPriority = PIOS_RFM22_EXTI_PRIO, + .NVIC_IRQChannelSubPriority = 0, + .NVIC_IRQChannelCmd = ENABLE, + }, + }, + .exti = { + .init = { + .EXTI_Line = PIOS_RFM22_EXTI_LINE, + .EXTI_Mode = EXTI_Mode_Interrupt, + .EXTI_Trigger = EXTI_Trigger_Falling, + .EXTI_LineCmd = ENABLE, + }, + }, +}; + +// xtal 10 ppm, 434MHz +#define LOOKUP_SIZE 14 +const uint32_t data_rate[] = { 500, 1000, 2000, 4000, 8000, 9600, 16000, 19200, 24000, 32000, 64000, 128000, 192000, 256000}; +const uint8_t modulation_index[] = { 16, 8, 4, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1}; +const uint32_t freq_deviation[] = { 4000, 4000, 4000, 4000, 4000, 4800, 8000, 9600, 12000, 16000, 32000, 64000, 96000, 128000}; +const uint32_t rx_bandwidth[] = { 17500, 17500, 17500, 17500, 17500, 19400, 32200, 38600, 51200, 64100, 137900, 269300, 420200, 518800}; +const int8_t est_rx_sens_dBm[] = { -118, -118, -117, -116, -115, -115, -112, -112, -110, -109, -106, -103, -101, -100}; // estimated receiver sensitivity for BER = 1E-3 + +const uint8_t reg_1C[] = { 0x37, 0x37, 0x37, 0x37, 0x3A, 0x3B, 0x26, 0x28, 0x2E, 0x16, 0x07, 0x83, 0x8A, 0x8C}; // rfm22_if_filter_bandwidth + +const uint8_t reg_1D[] = { 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44}; // rfm22_afc_loop_gearshift_override +const uint8_t reg_1E[] = { 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x02}; // rfm22_afc_timing_control + +const uint8_t reg_1F[] = { 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03}; // rfm22_clk_recovery_gearshift_override +const uint8_t reg_20[] = { 0xE8, 0xF4, 0xFA, 0x70, 0x3F, 0x34, 0x3F, 0x34, 0x2A, 0x3F, 0x3F, 0x5E, 0x3F, 0x2F}; // rfm22_clk_recovery_oversampling_ratio +const uint8_t reg_21[] = { 0x60, 0x20, 0x00, 0x01, 0x02, 0x02, 0x02, 0x02, 0x03, 0x02, 0x02, 0x01, 0x02, 0x02}; // rfm22_clk_recovery_offset2 +const uint8_t reg_22[] = { 0x20, 0x41, 0x83, 0x06, 0x0C, 0x75, 0x0C, 0x75, 0x12, 0x0C, 0x0C, 0x5D, 0x0C, 0xBB}; // rfm22_clk_recovery_offset1 +const uint8_t reg_23[] = { 0xC5, 0x89, 0x12, 0x25, 0x4A, 0x25, 0x4A, 0x25, 0x6F, 0x4A, 0x4A, 0x86, 0x4A, 0x0D}; // rfm22_clk_recovery_offset0 +const uint8_t reg_24[] = { 0x00, 0x00, 0x00, 0x02, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x05, 0x07, 0x07}; // rfm22_clk_recovery_timing_loop_gain1 +const uint8_t reg_25[] = { 0x0A, 0x23, 0x85, 0x0E, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x74, 0xFF, 0xFF}; // rfm22_clk_recovery_timing_loop_gain0 + +const uint8_t reg_2A[] = { 0x0E, 0x0E, 0x0E, 0x0E, 0x0E, 0x0D, 0x0D, 0x0E, 0x12, 0x17, 0x31, 0x50, 0x50, 0x50}; // rfm22_afc_limiter .. AFC_pull_in_range = ±AFCLimiter[7:0] x (hbsel+1) x 625 Hz + +const uint8_t reg_6E[] = { 0x04, 0x08, 0x10, 0x20, 0x41, 0x4E, 0x83, 0x9D, 0xC4, 0x08, 0x10, 0x20, 0x31, 0x41}; // rfm22_tx_data_rate1 +const uint8_t reg_6F[] = { 0x19, 0x31, 0x62, 0xC5, 0x89, 0xA5, 0x12, 0x49, 0x9C, 0x31, 0x62, 0xC5, 0x27, 0x89}; // rfm22_tx_data_rate0 + +const uint8_t reg_70[] = { 0x2D, 0x2D, 0x2D, 0x2D, 0x2D, 0x2D, 0x2D, 0x2D, 0x2D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D}; // rfm22_modulation_mode_control1 +const uint8_t reg_71[] = { 0x23, 0x23, 0x23, 0x23, 0x23, 0x23, 0x23, 0x23, 0x23, 0x23, 0x23, 0x23, 0x23, 0x23}; // rfm22_modulation_mode_control2 + +const uint8_t reg_72[] = { 0x06, 0x06, 0x06, 0x06, 0x06, 0x08, 0x0D, 0x0F, 0x13, 0x1A, 0x33, 0x66, 0x9A, 0xCD}; // rfm22_frequency_deviation + +// ************************************ +// Scan Spectrum settings +// GFSK modulation +// no manchester encoding +// data whitening +// FIFO mode +// 5-nibble rx preamble length detection +// 10-nibble tx preamble length +#define SS_LOOKUP_SIZE 2 + +// xtal 1 ppm, 434MHz +const uint32_t ss_rx_bandwidth[] = { 2600, 10600}; + +const uint8_t ss_reg_1C[] = { 0x51, 0x32}; // rfm22_if_filter_bandwidth +const uint8_t ss_reg_1D[] = { 0x00, 0x00}; // rfm22_afc_loop_gearshift_override + +const uint8_t ss_reg_20[] = { 0xE8, 0x38}; // rfm22_clk_recovery_oversampling_ratio +const uint8_t ss_reg_21[] = { 0x60, 0x02}; // rfm22_clk_recovery_offset2 +const uint8_t ss_reg_22[] = { 0x20, 0x4D}; // rfm22_clk_recovery_offset1 +const uint8_t ss_reg_23[] = { 0xC5, 0xD3}; // rfm22_clk_recovery_offset0 +const uint8_t ss_reg_24[] = { 0x00, 0x07}; // rfm22_clk_recovery_timing_loop_gain1 +const uint8_t ss_reg_25[] = { 0x0F, 0xFF}; // rfm22_clk_recovery_timing_loop_gain0 + +const uint8_t ss_reg_2A[] = { 0xFF, 0xFF}; // rfm22_afc_limiter .. AFC_pull_in_range = ±AFCLimiter[7:0] x (hbsel+1) x 625 Hz + +const uint8_t ss_reg_70[] = { 0x24, 0x2D}; // rfm22_modulation_mode_control1 +const uint8_t ss_reg_71[] = { 0x2B, 0x23}; // rfm22_modulation_mode_control2 + +// ************************************ + +volatile bool initialized = false; + +struct pios_rfm22b_dev * rfm22b_dev; + +#if defined(RFM22_EXT_INT_USE) +volatile bool exec_using_spi; // set this if you want to access the SPI bus outside of the interrupt +#endif + +uint8_t device_type; // the RF chips device ID number +uint8_t device_version; // the RF chips revision number + +volatile uint8_t rf_mode; // holds our current RF mode + +uint32_t lower_carrier_frequency_limit_Hz; // the minimum RF frequency we can use +uint32_t upper_carrier_frequency_limit_Hz; // the maximum RF frequency we can use +uint32_t carrier_frequency_hz; // the current RF frequency we are on + +uint32_t carrier_datarate_bps; // the RF data rate we are using + +uint32_t rf_bandwidth_used; // the RF bandwidth currently used +uint32_t ss_rf_bandwidth_used; // the RF bandwidth currently used + +uint8_t hbsel; // holds the hbsel (1 or 2) +float frequency_step_size; // holds the minimum frequency step size + +uint8_t frequency_hop_channel; // current frequency hop channel + +uint8_t frequency_hop_step_size_reg; // + +uint8_t adc_config; // holds the adc config reg value + +volatile uint8_t device_status; // device status register +volatile uint8_t int_status1; // interrupt status register 1 +volatile uint8_t int_status2; // interrupt status register 2 +volatile uint8_t ezmac_status; // ezmac status register + +volatile int16_t afc_correction; // afc correction reading +volatile int32_t afc_correction_Hz; // afc correction reading (in Hz) + +volatile int16_t temperature_reg; // the temperature sensor reading + +#if defined(RFM22_DEBUG) +volatile uint8_t prev_device_status; // just for debugging +volatile uint8_t prev_int_status1; // " " +volatile uint8_t prev_int_status2; // " " +volatile uint8_t prev_ezmac_status; // " " + +const char *debug_msg = NULL; +const char *error_msg = NULL; +static uint32_t debug_val = 0; +#endif + +volatile uint8_t osc_load_cap; // xtal frequency calibration value + +volatile uint8_t rssi; // the current RSSI (register value) +volatile int8_t rssi_dBm; // dBm value + +// the transmit power to use for data transmissions +uint8_t tx_power; +// the tx power register read back +volatile uint8_t tx_pwr; + +// The transmit buffer. Holds data that is being transmitted. +uint8_t tx_buffer[TX_BUFFER_SIZE] __attribute__ ((aligned(4))); +// The transmit buffer. Hosts data that is wating to be transmitted. +uint8_t tx_pre_buffer[TX_BUFFER_SIZE] __attribute__ ((aligned(4))); +// The tx pre-buffer write index. +uint16_t tx_pre_buffer_size; +// the tx data read index +volatile uint16_t tx_data_rd; +// the tx data write index +volatile uint16_t tx_data_wr; + +// the current receive buffer in use (double buffer) +volatile uint8_t rx_buffer_current; +// the receive buffer .. received packet data is saved here +volatile uint8_t rx_buffer[258] __attribute__ ((aligned(4))); +// the receive buffer write index +volatile uint16_t rx_buffer_wr; + +// the received packet +volatile int8_t rx_packet_start_rssi_dBm; // +volatile int8_t rx_packet_start_afc_Hz; // +volatile int8_t rx_packet_rssi_dBm; // the received packet signal strength +volatile int8_t rx_packet_afc_Hz; // the receive packet frequency offset + +int lookup_index; +int ss_lookup_index; + +volatile bool power_on_reset; // set if the RF module has reset itself + +volatile uint16_t rfm22_int_timer; // used to detect if the RF module stops responding. thus act accordingly if it does stop responding. +volatile uint16_t rfm22_int_time_outs; // counter +volatile uint16_t prev_rfm22_int_time_outs; // + +uint16_t timeout_ms = 20000; // +uint16_t timeout_sync_ms = 3; // +uint16_t timeout_data_ms = 20; // + +struct pios_rfm22b_dev * rfm22b_dev_g; + + +static bool PIOS_RFM22B_validate(struct pios_rfm22b_dev * rfm22b_dev) +{ + return (rfm22b_dev->magic == PIOS_RFM22B_DEV_MAGIC); +} + +#if defined(PIOS_INCLUDE_FREERTOS) +static struct pios_rfm22b_dev * PIOS_RFM22B_alloc(void) +{ + struct pios_rfm22b_dev * rfm22b_dev; + + rfm22b_dev = (struct pios_rfm22b_dev *)pvPortMalloc(sizeof(*rfm22b_dev)); + if (!rfm22b_dev) return(NULL); + rfm22b_dev_g = rfm22b_dev; + + rfm22b_dev->magic = PIOS_RFM22B_DEV_MAGIC; + return(rfm22b_dev); +} +#else +static struct pios_rfm22b_dev pios_rfm22b_devs[PIOS_RFM22B_MAX_DEVS]; +static uint8_t pios_rfm22b_num_devs; +static struct pios_rfm22b_dev * PIOS_RFM22B_alloc(void) +{ + struct pios_rfm22b_dev * rfm22b_dev; + + if (pios_rfm22b_num_devs >= PIOS_RFM22B_MAX_DEVS) + return NULL; + + rfm22b_dev = &pios_rfm22b_devs[pios_rfm22b_num_devs++]; + rfm22b_dev->magic = PIOS_RFM22B_DEV_MAGIC; + + return (rfm22b_dev); +} +#endif + +/** + * Initialise an RFM22B device + */ +int32_t PIOS_RFM22B_Init(uint32_t *rfm22b_id, const struct pios_rfm22b_cfg *cfg) +{ + PIOS_DEBUG_Assert(rfm22b_id); + PIOS_DEBUG_Assert(cfg); + + // Allocate the device structure. + rfm22b_dev = (struct pios_rfm22b_dev *) PIOS_RFM22B_alloc(); + if (!rfm22b_dev) + return(-1); + + // Bind the configuration to the device instance + rfm22b_dev->cfg = *cfg; + + *rfm22b_id = (uint32_t)rfm22b_dev; + + // Initialize the TX pre-buffer pointer. + tx_pre_buffer_size = 0; + + // Create our (hopefully) unique 32 bit id from the processor serial number. + uint8_t crcs[] = { 0, 0, 0, 0 }; + { + char serial_no_str[33]; + PIOS_SYS_SerialNumberGet(serial_no_str); + // Create a 32 bit value using 4 8 bit CRC values. + for (uint8_t i = 0; serial_no_str[i] != 0; ++i) + crcs[i % 4] = PIOS_CRC_updateByte(crcs[i % 4], serial_no_str[i]); + } + rfm22b_dev->deviceID = crcs[0] | crcs[1] << 8 | crcs[2] << 16 | crcs[3] << 24; + DEBUG_PRINTF(2, "RF device ID: %x\n\r", rfm22b_dev->deviceID); + + // Initialize the supervisor timer. + rfm22b_dev->supv_timer = PIOS_RFM22B_SUPERVISOR_TIMEOUT; + rfm22b_dev->resets = 0; + + // Initialize the radio device. + int initval = rfm22_init_normal(rfm22b_dev->deviceID, cfg->minFrequencyHz, cfg->maxFrequencyHz, 50000); + + if (initval < 0) + { + + // RF module error .. flash the LED's +#if defined(PIOS_COM_DEBUG) + DEBUG_PRINTF(2, "RF ERROR res: %d\n\r\n\r", initval); +#endif + + for(unsigned int j = 0; j < 16; j++) + { + USB_LED_ON; + LINK_LED_ON; + RX_LED_OFF; + TX_LED_OFF; + + PIOS_DELAY_WaitmS(200); + + USB_LED_OFF; + LINK_LED_OFF; + RX_LED_ON; + TX_LED_ON; + + PIOS_DELAY_WaitmS(200); + } + + PIOS_DELAY_WaitmS(1000); + + return initval; + } + + rfm22_setFreqCalibration(cfg->RFXtalCap); + rfm22_setNominalCarrierFrequency(cfg->frequencyHz); + rfm22_setDatarate(cfg->maxRFBandwidth, TRUE); + rfm22_setTxPower(cfg->maxTxPower); + + DEBUG_PRINTF(2, "\n\r"); + DEBUG_PRINTF(2, "RF device ID: %x\n\r", rfm22b_dev->deviceID); + DEBUG_PRINTF(2, "RF datarate: %dbps\n\r", rfm22_getDatarate()); + DEBUG_PRINTF(2, "RF frequency: %dHz\n\r", rfm22_getNominalCarrierFrequency()); + DEBUG_PRINTF(2, "RF TX power: %d\n\r", rfm22_getTxPower()); + + // Setup a real-time clock callback to kickstart the radio if a transfer lock sup. + if (!PIOS_RTC_RegisterTickCallback(PIOS_RFM22B_Supervisor, *rfm22b_id)) { + PIOS_DEBUG_Assert(0); + } + + return(0); +} + +uint32_t PIOS_RFM22B_DeviceID(uint32_t rfm22b_id) +{ + struct pios_rfm22b_dev *rfm22b_dev = (struct pios_rfm22b_dev *)rfm22b_id; + + return rfm22b_dev->deviceID; +} + +int8_t PIOS_RFM22B_RSSI(uint32_t rfm22b_id) +{ + return rfm22_receivedRSSI(); +} + +int16_t PIOS_RFM22B_Resets(uint32_t rfm22b_id) +{ + struct pios_rfm22b_dev *rfm22b_dev = (struct pios_rfm22b_dev *)rfm22b_id; + + return rfm22b_dev->resets; +} + +static void PIOS_RFM22B_RxStart(uint32_t rfm22b_id, uint16_t rx_bytes_avail) +{ + struct pios_rfm22b_dev * rfm22b_dev = (struct pios_rfm22b_dev *)rfm22b_id; + + bool valid = PIOS_RFM22B_validate(rfm22b_dev); + PIOS_Assert(valid); + +} + +static void PIOS_RFM22B_TxStart(uint32_t rfm22b_id, uint16_t tx_bytes_avail) +{ + struct pios_rfm22b_dev * rfm22b_dev = (struct pios_rfm22b_dev *)rfm22b_id; + bool valid = PIOS_RFM22B_validate(rfm22b_dev); + PIOS_Assert(valid); + + // Get some data to send + bool need_yield = false; + if(tx_pre_buffer_size== 0) + tx_pre_buffer_size = (rfm22b_dev->tx_out_cb)(rfm22b_dev->tx_out_context, tx_pre_buffer, + TX_BUFFER_SIZE, NULL, &need_yield); + + if(tx_pre_buffer_size > 0) + { + + // already have data to be sent + if (tx_data_wr > 0) + return; + + // we are currently transmitting or scanning the spectrum + if (rf_mode == TX_DATA_MODE || rf_mode == TX_STREAM_MODE || rf_mode == TX_CARRIER_MODE || + rf_mode == TX_PN_MODE || rf_mode == RX_SCAN_SPECTRUM) + return; + + // is the channel clear to transmit on? + if (!rfm22_channelIsClear()) + return; + + // Start the transmit + rfm22_txStart(); + } +} + +/** + * Changes the baud rate of the RFM22B peripheral without re-initialising. + * \param[in] rfm22b_id RFM22B name (GPS, TELEM, AUX) + * \param[in] baud Requested baud rate + */ +static void PIOS_RFM22B_ChangeBaud(uint32_t rfm22b_id, uint32_t baud) +{ + struct pios_rfm22b_dev * rfm22b_dev = (struct pios_rfm22b_dev *)rfm22b_id; + + bool valid = PIOS_RFM22B_validate(rfm22b_dev); + PIOS_Assert(valid); + +} + +static void PIOS_RFM22B_RegisterRxCallback(uint32_t rfm22b_id, pios_com_callback rx_in_cb, uint32_t context) +{ + struct pios_rfm22b_dev * rfm22b_dev = (struct pios_rfm22b_dev *)rfm22b_id; + + bool valid = PIOS_RFM22B_validate(rfm22b_dev); + PIOS_Assert(valid); + + /* + * Order is important in these assignments since ISR uses _cb + * field to determine if it's ok to dereference _cb and _context + */ + rfm22b_dev->rx_in_context = context; + rfm22b_dev->rx_in_cb = rx_in_cb; +} + +static void PIOS_RFM22B_RegisterTxCallback(uint32_t rfm22b_id, pios_com_callback tx_out_cb, uint32_t context) +{ + struct pios_rfm22b_dev * rfm22b_dev = (struct pios_rfm22b_dev *)rfm22b_id; + + bool valid = PIOS_RFM22B_validate(rfm22b_dev); + PIOS_Assert(valid); + + /* + * Order is important in these assignments since ISR uses _cb + * field to determine if it's ok to dereference _cb and _context + */ + rfm22b_dev->tx_out_context = context; + rfm22b_dev->tx_out_cb = tx_out_cb; +} + +static void PIOS_RFM22B_Supervisor(uint32_t rfm22b_id) +{ + /* Recover our device context */ + struct pios_rfm22b_dev * rfm22b_dev = (struct pios_rfm22b_dev *)rfm22b_id; + + if (!PIOS_RFM22B_validate(rfm22b_dev)) { + /* Invalid device specified */ + return; + } + + /* Not a problem if we're waiting for a packet. */ + if(rf_mode == RX_WAIT_SYNC_MODE) + return; + + /* The radio must be locked up if the timer reaches 0 */ + if(--(rfm22b_dev->supv_timer) != 0) + return; + ++(rfm22b_dev->resets); + + /* Start a packet transfer if one is available. */ + if(!rfm22_txStart()) + { + /* Otherwise, switch to RX mode */ + rfm22_setRxMode(RX_WAIT_PREAMBLE_MODE, false); + } +} + +static void rfm22_setDebug(const char* msg) +{ + debug_msg = msg; +} + +static void rfm22_setError(const char* msg) +{ + error_msg = msg; +} + +// ************************************ +// SPI read/write + +void rfm22_startBurstWrite(uint8_t addr) +{ + // wait 1us .. so we don't toggle the CS line to quickly + PIOS_DELAY_WaituS(1); + + // chip select line LOW + PIOS_SPI_RC_PinSet(RFM22_PIOS_SPI, 0, 0); + + PIOS_SPI_TransferByte(RFM22_PIOS_SPI, 0x80 | addr); +} + +void rfm22_endBurstWrite(void) +{ + // chip select line HIGH + PIOS_SPI_RC_PinSet(RFM22_PIOS_SPI, 0, 1); +} + +void rfm22_write(uint8_t addr, uint8_t data) +{ + // wait 1us .. so we don't toggle the CS line to quickly + PIOS_DELAY_WaituS(1); + + // chip select line LOW + PIOS_SPI_RC_PinSet(RFM22_PIOS_SPI, 0, 0); + + PIOS_SPI_TransferByte(RFM22_PIOS_SPI, 0x80 | addr); + PIOS_SPI_TransferByte(RFM22_PIOS_SPI, data); + + // chip select line HIGH + PIOS_SPI_RC_PinSet(RFM22_PIOS_SPI, 0, 1); +} + +void rfm22_startBurstRead(uint8_t addr) +{ + // wait 1us .. so we don't toggle the CS line to quickly + PIOS_DELAY_WaituS(1); + + // chip select line LOW + PIOS_SPI_RC_PinSet(RFM22_PIOS_SPI, 0, 0); + + PIOS_SPI_TransferByte(RFM22_PIOS_SPI, addr & 0x7f); +} + +void rfm22_endBurstRead(void) +{ + // chip select line HIGH + PIOS_SPI_RC_PinSet(RFM22_PIOS_SPI, 0, 1); +} + +uint8_t rfm22_read(uint8_t addr) +{ + uint8_t rdata; + + // wait 1us .. so we don't toggle the CS line to quickly + PIOS_DELAY_WaituS(1); + + // chip select line LOW + PIOS_SPI_RC_PinSet(RFM22_PIOS_SPI, 0, 0); + + PIOS_SPI_TransferByte(RFM22_PIOS_SPI, addr & 0x7f); + rdata = PIOS_SPI_TransferByte(RFM22_PIOS_SPI, 0xff); + + // chip select line HIGH + PIOS_SPI_RC_PinSet(RFM22_PIOS_SPI, 0, 1); + + return rdata; +} + +// ************************************ +// external interrupt + + +static void PIOS_RFM22_EXT_Int(void) +{ + rfm22_setDebug("Ext Int"); + if (!exec_using_spi) + rfm22_processInt(); + rfm22_setDebug("Ext Done"); +} + +void rfm22_disableExtInt(void) +{ +#if defined(RFM22_EXT_INT_USE) + rfm22_setDebug("Disable Int"); + // Configure the external interrupt + GPIO_EXTILineConfig(PIOS_RFM22_EXTI_PORT_SOURCE, PIOS_RFM22_EXTI_PIN_SOURCE); + EXTI_InitTypeDef EXTI_InitStructure = pios_exti_rfm22b_cfg.exti.init; + EXTI_InitStructure.EXTI_LineCmd = DISABLE; + EXTI_Init(&EXTI_InitStructure); + + EXTI_ClearFlag(PIOS_RFM22_EXTI_LINE); + rfm22_setDebug("Disable Int done"); +#endif +} + +void rfm22_enableExtInt(void) +{ +#if defined(RFM22_EXT_INT_USE) + rfm22_setDebug("Ensable Int"); + if (PIOS_EXTI_Init(&pios_exti_rfm22b_cfg)) + PIOS_Assert(0); + rfm22_setDebug("Ensable Int done"); +#endif +} + + +// ************************************ +// set/get the current tx power setting + +void rfm22_setTxPower(uint8_t tx_pwr) +{ + switch (tx_pwr) + { + case 0: tx_power = RFM22_tx_pwr_txpow_0; break; // +1dBm ... 1.25mW + case 1: tx_power = RFM22_tx_pwr_txpow_1; break; // +2dBm ... 1.6mW + case 2: tx_power = RFM22_tx_pwr_txpow_2; break; // +5dBm ... 3.16mW + case 3: tx_power = RFM22_tx_pwr_txpow_3; break; // +8dBm ... 6.3mW + case 4: tx_power = RFM22_tx_pwr_txpow_4; break; // +11dBm .. 12.6mW + case 5: tx_power = RFM22_tx_pwr_txpow_5; break; // +14dBm .. 25mW + case 6: tx_power = RFM22_tx_pwr_txpow_6; break; // +17dBm .. 50mW + case 7: tx_power = RFM22_tx_pwr_txpow_7; break; // +20dBm .. 100mW + default: break; + } +} + +uint8_t rfm22_getTxPower(void) +{ + return tx_power; +} + +// ************************************ + +uint32_t rfm22_minFrequency(void) +{ + return lower_carrier_frequency_limit_Hz; +} +uint32_t rfm22_maxFrequency(void) +{ + return upper_carrier_frequency_limit_Hz; +} + +void rfm22_setNominalCarrierFrequency(uint32_t frequency_hz) +{ + + exec_using_spi = TRUE; + + // ******* + + if (frequency_hz < lower_carrier_frequency_limit_Hz) frequency_hz = lower_carrier_frequency_limit_Hz; + else + if (frequency_hz > upper_carrier_frequency_limit_Hz) frequency_hz = upper_carrier_frequency_limit_Hz; + + if (frequency_hz < 480000000) + hbsel = 1; + else + hbsel = 2; + uint8_t fb = (uint8_t)(frequency_hz / (10000000 * hbsel)); + + uint32_t fc = (uint32_t)(frequency_hz - (10000000 * hbsel * fb)); + + fc = (fc * 64u) / (10000ul * hbsel); + fb -= 24; + + // carrier_frequency_hz = frequency_hz; + carrier_frequency_hz = ((uint32_t)fb + 24 + ((float)fc / 64000)) * 10000000 * hbsel; + + if (hbsel > 1) + fb |= RFM22_fbs_hbsel; + + fb |= RFM22_fbs_sbse; // is this the RX LO polarity? + + frequency_step_size = 156.25f * hbsel; + + rfm22_write(RFM22_frequency_hopping_channel_select, frequency_hop_channel); // frequency hopping channel (0-255) + + rfm22_write(RFM22_frequency_offset1, 0); // no frequency offset + rfm22_write(RFM22_frequency_offset2, 0); // no frequency offset + + rfm22_write(RFM22_frequency_band_select, fb); // set the carrier frequency + rfm22_write(RFM22_nominal_carrier_frequency1, fc >> 8); // " " + rfm22_write(RFM22_nominal_carrier_frequency0, fc & 0xff); // " " + + // ******* + +#if defined(RFM22_DEBUG) + //DEBUG_PRINTF(2, "rf setFreq: %u\n\r", carrier_frequency_hz); + // DEBUG_PRINTF(2, "rf setFreq frequency_step_size: %0.2f\n\r", frequency_step_size); +#endif + + exec_using_spi = FALSE; +} + +uint32_t rfm22_getNominalCarrierFrequency(void) +{ + return carrier_frequency_hz; +} + +float rfm22_getFrequencyStepSize(void) +{ + return frequency_step_size; +} + +void rfm22_setFreqHopChannel(uint8_t channel) +{ // set the frequency hopping channel + frequency_hop_channel = channel; + rfm22_write(RFM22_frequency_hopping_channel_select, frequency_hop_channel); +} + +uint8_t rfm22_freqHopChannel(void) +{ // return the current frequency hopping channel + return frequency_hop_channel; +} + +uint32_t rfm22_freqHopSize(void) +{ // return the frequency hopping step size + return ((uint32_t)frequency_hop_step_size_reg * 10000); +} + +// ************************************ +// radio datarate about 19200 Baud +// radio frequency deviation 45kHz +// radio receiver bandwidth 67kHz. +// +// Carson's rule: +// The signal bandwidth is about 2(Delta-f + fm) .. +// +// Delta-f = frequency deviation +// fm = maximum frequency of the signal +// +// This gives 2(45 + 9.6) = 109.2kHz. + +void rfm22_setDatarate(uint32_t datarate_bps, bool data_whitening) +{ + + exec_using_spi = TRUE; + + lookup_index = 0; + while (lookup_index < (LOOKUP_SIZE - 1) && data_rate[lookup_index] < datarate_bps) + lookup_index++; + + carrier_datarate_bps = datarate_bps = data_rate[lookup_index]; + + rf_bandwidth_used = rx_bandwidth[lookup_index]; + + // rfm22_if_filter_bandwidth + rfm22_write(0x1C, reg_1C[lookup_index]); + + // rfm22_afc_loop_gearshift_override + rfm22_write(0x1D, reg_1D[lookup_index]); + // RFM22_afc_timing_control + rfm22_write(0x1E, reg_1E[lookup_index]); + + // RFM22_clk_recovery_gearshift_override + rfm22_write(0x1F, reg_1F[lookup_index]); + // rfm22_clk_recovery_oversampling_ratio + rfm22_write(0x20, reg_20[lookup_index]); + // rfm22_clk_recovery_offset2 + rfm22_write(0x21, reg_21[lookup_index]); + // rfm22_clk_recovery_offset1 + rfm22_write(0x22, reg_22[lookup_index]); + // rfm22_clk_recovery_offset0 + rfm22_write(0x23, reg_23[lookup_index]); + // rfm22_clk_recovery_timing_loop_gain1 + rfm22_write(0x24, reg_24[lookup_index]); + // rfm22_clk_recovery_timing_loop_gain0 + rfm22_write(0x25, reg_25[lookup_index]); + + // rfm22_afc_limiter + rfm22_write(0x2A, reg_2A[lookup_index]); + + if (carrier_datarate_bps < 100000) + // rfm22_chargepump_current_trimming_override + rfm22_write(0x58, 0x80); + else + // rfm22_chargepump_current_trimming_override + rfm22_write(0x58, 0xC0); + + // rfm22_tx_data_rate1 + rfm22_write(0x6E, reg_6E[lookup_index]); + // rfm22_tx_data_rate0 + rfm22_write(0x6F, reg_6F[lookup_index]); + + // Enable data whitening + // uint8_t txdtrtscale_bit = rfm22_read(RFM22_modulation_mode_control1) & RFM22_mmc1_txdtrtscale; + // rfm22_write(RFM22_modulation_mode_control1, txdtrtscale_bit | RFM22_mmc1_enwhite); + + if (!data_whitening) + // rfm22_modulation_mode_control1 + rfm22_write(0x70, reg_70[lookup_index] & ~RFM22_mmc1_enwhite); + else + // rfm22_modulation_mode_control1 + rfm22_write(0x70, reg_70[lookup_index] | RFM22_mmc1_enwhite); + + // rfm22_modulation_mode_control2 + rfm22_write(0x71, reg_71[lookup_index]); + + // rfm22_frequency_deviation + rfm22_write(0x72, reg_72[lookup_index]); + + rfm22_write(RFM22_ook_counter_value1, 0x00); + rfm22_write(RFM22_ook_counter_value2, 0x00); + + // ******************************** + // calculate the TX register values + /* + uint16_t fd = frequency_deviation / 625; + + uint8_t mmc1 = RFM22_mmc1_enphpwdn | RFM22_mmc1_manppol; + uint16_t txdr; + if (datarate_bps < 30000) + { + txdr = (datarate_bps * 20972) / 10000; + mmc1 |= RFM22_mmc1_txdtrtscale; + } + else + txdr = (datarate_bps * 6553) / 100000; + + uint8_t mmc2 = RFM22_mmc2_dtmod_fifo | RFM22_mmc2_modtyp_gfsk; // FIFO mode, GFSK + // uint8_t mmc2 = RFM22_mmc2_dtmod_pn9 | RFM22_mmc2_modtyp_gfsk; // PN9 mode, GFSK .. TX TEST MODE + if (fd & 0x100) mmc2 |= RFM22_mmc2_fd; + + rfm22_write(RFM22_frequency_deviation, fd); // set the TX peak frequency deviation + + rfm22_write(RFM22_modulation_mode_control1, mmc1); + rfm22_write(RFM22_modulation_mode_control2, mmc2); + + rfm22_write(RFM22_tx_data_rate1, txdr >> 8); // set the TX data rate + rfm22_write(RFM22_tx_data_rate0, txdr); // " " + */ + // ******************************** + // determine a clear channel time + + // initialise the stopwatch with a suitable resolution for the datarate + //STOPWATCH_init(4000000ul / carrier_datarate_bps); // set resolution to the time for 1 nibble (4-bits) at rf datarate + + // ******************************** + // determine suitable time-out periods + + // milliseconds + timeout_sync_ms = (8000ul * 16) / carrier_datarate_bps; + if (timeout_sync_ms < 3) + // because out timer resolution is only 1ms + timeout_sync_ms = 3; + + // milliseconds + timeout_data_ms = (8000ul * 100) / carrier_datarate_bps; + if (timeout_data_ms < 3) + // because out timer resolution is only 1ms + timeout_data_ms = 3; + + // ******************************** + +#if defined(RFM22_DEBUG) +/* + DEBUG_PRINTF(2, "rf datarate_bps: %d\n\r", datarate_bps); + DEBUG_PRINTF(2, "rf frequency_deviation: %d\n\r", frequency_deviation); + uint32_t frequency_deviation = freq_deviation[lookup_index]; // Hz + uint32_t modulation_bandwidth = datarate_bps + (2 * frequency_deviation); + DEBUG_PRINTF(2, "rf modulation_bandwidth: %u\n\r", modulation_bandwidth); + DEBUG_PRINTF(2, "rf_rx_bandwidth[%u]: %u\n\r", lookup_index, rx_bandwidth[lookup_index]); + DEBUG_PRINTF(2, "rf est rx sensitivity[%u]: %ddBm\n\r", lookup_index, est_rx_sens_dBm[lookup_index]); +*/ +#endif + + // ******* + + exec_using_spi = FALSE; +} + +uint32_t rfm22_getDatarate(void) +{ + return carrier_datarate_bps; +} + +// ************************************ + +void rfm22_setSSBandwidth(uint32_t bandwidth_index) +{ + + exec_using_spi = TRUE; + + ss_lookup_index = bandwidth_index; + + ss_rf_bandwidth_used = ss_rx_bandwidth[lookup_index]; + + // ******************************** + + rfm22_write(0x1C, ss_reg_1C[ss_lookup_index]); // rfm22_if_filter_bandwidth + rfm22_write(0x1D, ss_reg_1D[ss_lookup_index]); // rfm22_afc_loop_gearshift_override + + rfm22_write(0x20, ss_reg_20[ss_lookup_index]); // rfm22_clk_recovery_oversampling_ratio + rfm22_write(0x21, ss_reg_21[ss_lookup_index]); // rfm22_clk_recovery_offset2 + rfm22_write(0x22, ss_reg_22[ss_lookup_index]); // rfm22_clk_recovery_offset1 + rfm22_write(0x23, ss_reg_23[ss_lookup_index]); // rfm22_clk_recovery_offset0 + rfm22_write(0x24, ss_reg_24[ss_lookup_index]); // rfm22_clk_recovery_timing_loop_gain1 + rfm22_write(0x25, ss_reg_25[ss_lookup_index]); // rfm22_clk_recovery_timing_loop_gain0 + + rfm22_write(0x2A, ss_reg_2A[ss_lookup_index]); // rfm22_afc_limiter + + rfm22_write(0x58, 0x80); // rfm22_chargepump_current_trimming_override + + rfm22_write(0x70, ss_reg_70[ss_lookup_index]); // rfm22_modulation_mode_control1 + rfm22_write(0x71, ss_reg_71[ss_lookup_index]); // rfm22_modulation_mode_control2 + + rfm22_write(RFM22_ook_counter_value1, 0x00); + rfm22_write(RFM22_ook_counter_value2, 0x00); + + // ******************************** + +#if defined(RFM22_DEBUG) + DEBUG_PRINTF(2, "ss_rf_rx_bandwidth[%u]: %u\n\r", ss_lookup_index, ss_rx_bandwidth[ss_lookup_index]); +#endif + + // ******* + + exec_using_spi = FALSE; +} + +// ************************************ + +void rfm22_setRxMode(uint8_t mode, bool multi_packet_mode) +{ + exec_using_spi = TRUE; + + // disable interrupts + rfm22_write(RFM22_interrupt_enable1, 0x00); + rfm22_write(RFM22_interrupt_enable2, 0x00); + + // Switch to TUNE mode + rfm22_write(RFM22_op_and_func_ctrl1, RFM22_opfc1_pllon); + + RX_LED_OFF; + TX_LED_OFF; + + if (rf_mode == TX_CARRIER_MODE || rf_mode == TX_PN_MODE) + { + // FIFO mode, GFSK modulation + uint8_t fd_bit = rfm22_read(RFM22_modulation_mode_control2) & RFM22_mmc2_fd; + rfm22_write(RFM22_modulation_mode_control2, fd_bit | RFM22_mmc2_dtmod_fifo | + RFM22_mmc2_modtyp_gfsk); + } + + // empty the rx buffer + rx_buffer_wr = 0; + // reset the timer + rfm22_int_timer = 0; + rf_mode = mode; + + // Clear the TX buffer. + tx_data_rd = tx_data_wr = 0; + + // clear FIFOs + if (!multi_packet_mode) + { + rfm22_write(RFM22_op_and_func_ctrl2, RFM22_opfc2_ffclrrx | RFM22_opfc2_ffclrtx); + rfm22_write(RFM22_op_and_func_ctrl2, 0x00); + } else { + rfm22_write(RFM22_op_and_func_ctrl2, RFM22_opfc2_rxmpk | RFM22_opfc2_ffclrrx | + RFM22_opfc2_ffclrtx); + rfm22_write(RFM22_op_and_func_ctrl2, RFM22_opfc2_rxmpk); + } + + // enable RX interrupts + rfm22_write(RFM22_interrupt_enable1, RFM22_ie1_encrcerror | RFM22_ie1_enpkvalid | + RFM22_ie1_enrxffafull | RFM22_ie1_enfferr); + rfm22_write(RFM22_interrupt_enable2, RFM22_ie2_enpreainval | RFM22_ie2_enpreaval | + RFM22_ie2_enswdet); + + // enable the receiver + // rfm22_write(RFM22_op_and_func_ctrl1, RFM22_opfc1_xton | RFM22_opfc1_rxon); + rfm22_write(RFM22_op_and_func_ctrl1, RFM22_opfc1_pllon | RFM22_opfc1_rxon); + + exec_using_spi = FALSE; +} + +// ************************************ + +uint16_t rfm22_addHeader() +{ + uint16_t i = 0; + + for (uint16_t j = (TX_PREAMBLE_NIBBLES + 1) / 2; j > 0; j--) + { + rfm22_burstWrite(PREAMBLE_BYTE); + i++; + } + rfm22_burstWrite(SYNC_BYTE_1); i++; + rfm22_burstWrite(SYNC_BYTE_2); i++; + + return i; +} + +// ************************************ + +uint8_t rfm22_txStart() +{ + if((tx_pre_buffer_size == 0) || (exec_using_spi == TRUE)) + { + // Clear the TX buffer. + tx_data_rd = tx_data_wr = 0; + return 0; + } + + exec_using_spi = TRUE; + + // Disable interrrupts. + PIOS_IRQ_Disable(); + + // Initialize the supervisor timer. + rfm22b_dev->supv_timer = PIOS_RFM22B_SUPERVISOR_TIMEOUT; + + // disable interrupts + rfm22_write(RFM22_interrupt_enable1, 0x00); + rfm22_write(RFM22_interrupt_enable2, 0x00); + + // TUNE mode + rfm22_write(RFM22_op_and_func_ctrl1, RFM22_opfc1_pllon); + + // Queue the data up for sending + memcpy(tx_buffer, tx_pre_buffer, tx_pre_buffer_size); + tx_data_rd = 0; + tx_data_wr = tx_pre_buffer_size; + tx_pre_buffer_size = 0; + + RX_LED_OFF; + + // Set the destination address in the transmit header. + // The destination address is the first 4 bytes of the message. + rfm22_write(RFM22_transmit_header0, tx_buffer[0]); + rfm22_write(RFM22_transmit_header1, tx_buffer[1]); + rfm22_write(RFM22_transmit_header2, tx_buffer[2]); + rfm22_write(RFM22_transmit_header3, tx_buffer[3]); + + // FIFO mode, GFSK modulation + uint8_t fd_bit = rfm22_read(RFM22_modulation_mode_control2) & RFM22_mmc2_fd; + rfm22_write(RFM22_modulation_mode_control2, fd_bit | RFM22_mmc2_dtmod_fifo | + RFM22_mmc2_modtyp_gfsk); + + // set the tx power + rfm22_write(RFM22_tx_power, RFM22_tx_pwr_papeaken | RFM22_tx_pwr_papeaklvl_1 | + RFM22_tx_pwr_papeaklvl_0 | RFM22_tx_pwr_lna_sw | tx_power); + + // clear FIFOs + rfm22_write(RFM22_op_and_func_ctrl2, RFM22_opfc2_ffclrrx | RFM22_opfc2_ffclrtx); + rfm22_write(RFM22_op_and_func_ctrl2, 0x00); + + // ******************* + // add some data to the chips TX FIFO before enabling the transmitter + + // set the total number of data bytes we are going to transmit + rfm22_write(RFM22_transmit_packet_length, tx_data_wr); + + // add some data + rfm22_startBurstWrite(RFM22_fifo_access); + for (uint16_t i = 0; (tx_data_rd < tx_data_wr) && (i < FIFO_SIZE); ++tx_data_rd, ++i) + rfm22_burstWrite(tx_buffer[tx_data_rd]); + rfm22_endBurstWrite(); + + // ******************* + + // reset the timer + rfm22_int_timer = 0; + + rf_mode = TX_DATA_MODE; + + // enable TX interrupts + // rfm22_write(RFM22_interrupt_enable1, RFM22_ie1_enpksent | RFM22_ie1_entxffaem | RFM22_ie1_enfferr); + rfm22_write(RFM22_interrupt_enable1, RFM22_ie1_enpksent | RFM22_ie1_entxffaem); + + // read interrupt status - clear interrupts + //rfm22_read(RFM22_interrupt_status1); + //rfm22_read(RFM22_interrupt_status2); + + // enable the transmitter + // rfm22_write(RFM22_op_and_func_ctrl1, RFM22_opfc1_xton | RFM22_opfc1_txon); + rfm22_write(RFM22_op_and_func_ctrl1, RFM22_opfc1_pllon | RFM22_opfc1_txon); + + // Re-ensable interrrupts. + PIOS_IRQ_Enable(); + + TX_LED_ON; + + exec_using_spi = FALSE; + return 1; +} + + +static void rfm22_setTxMode(uint8_t mode) +{ + rfm22_setDebug("setTxMode"); + if (mode != TX_DATA_MODE && mode != TX_STREAM_MODE && mode != TX_CARRIER_MODE && mode != TX_PN_MODE) + return; // invalid mode + + exec_using_spi = TRUE; + + // ******************* + + // disable interrupts + rfm22_write(RFM22_interrupt_enable1, 0x00); + rfm22_write(RFM22_interrupt_enable2, 0x00); + + // rfm22_write(RFM22_op_and_func_ctrl1, RFM22_opfc1_xton); // READY mode + rfm22_write(RFM22_op_and_func_ctrl1, RFM22_opfc1_pllon); // TUNE mode + + RX_LED_OFF; + + // set the tx power + rfm22_write(RFM22_tx_power, RFM22_tx_pwr_papeaken | RFM22_tx_pwr_papeaklvl_1 | + RFM22_tx_pwr_papeaklvl_0 | RFM22_tx_pwr_lna_sw | tx_power); + + uint8_t fd_bit = rfm22_read(RFM22_modulation_mode_control2) & RFM22_mmc2_fd; + if (mode == TX_CARRIER_MODE) + // blank carrier mode - for testing + rfm22_write(RFM22_modulation_mode_control2, fd_bit | RFM22_mmc2_dtmod_pn9 | + RFM22_mmc2_modtyp_none); // FIFO mode, Blank carrier + else if (mode == TX_PN_MODE) + // psuedo random data carrier mode - for testing + rfm22_write(RFM22_modulation_mode_control2, fd_bit | RFM22_mmc2_dtmod_pn9 | + RFM22_mmc2_modtyp_gfsk); // FIFO mode, PN9 carrier + else + // data transmission + // FIFO mode, GFSK modulation + rfm22_write(RFM22_modulation_mode_control2, fd_bit | RFM22_mmc2_dtmod_fifo | + RFM22_mmc2_modtyp_gfsk); + + // rfm22_write(0x72, reg_72[lookup_index]); // rfm22_frequency_deviation + + // clear FIFOs + rfm22_write(RFM22_op_and_func_ctrl2, RFM22_opfc2_ffclrrx | RFM22_opfc2_ffclrtx); + rfm22_write(RFM22_op_and_func_ctrl2, 0x00); + + // ******************* + // add some data to the chips TX FIFO before enabling the transmitter + { + uint16_t rd = 0; + uint16_t wr = tx_data_wr; + + if (mode == TX_DATA_MODE) + // set the total number of data bytes we are going to transmit + rfm22_write(RFM22_transmit_packet_length, wr); + + uint16_t max_bytes = FIFO_SIZE - 1; + uint16_t i = 0; + rfm22_startBurstWrite(RFM22_fifo_access); + if (mode == TX_STREAM_MODE) { + if (rd >= wr) { + // no data to send - yet .. just send preamble pattern + while (true) { + rfm22_burstWrite(PREAMBLE_BYTE); + if (++i >= max_bytes) break; + } + } else // add the RF heaader + i += rfm22_addHeader(); + } + + // add some data + for (uint16_t j = wr - rd; j > 0; j--) { + rfm22_burstWrite(tx_buffer[rd++]); + if (++i >= max_bytes) + break; + } + + rfm22_endBurstWrite(); + + tx_data_rd = rd; + } + + // ******************* + + // reset the timer + rfm22_int_timer = 0; + + rf_mode = mode; + + // enable TX interrupts + // rfm22_write(RFM22_interrupt_enable1, RFM22_ie1_enpksent | RFM22_ie1_entxffaem | RFM22_ie1_enfferr); + rfm22_write(RFM22_interrupt_enable1, RFM22_ie1_enpksent | RFM22_ie1_entxffaem); + + // read interrupt status - clear interrupts + rfm22_read(RFM22_interrupt_status1); + rfm22_read(RFM22_interrupt_status2); + + // enable the transmitter + // rfm22_write(RFM22_op_and_func_ctrl1, RFM22_opfc1_xton | RFM22_opfc1_txon); + rfm22_write(RFM22_op_and_func_ctrl1, RFM22_opfc1_pllon | RFM22_opfc1_txon); + + TX_LED_ON; + + // ******************* + + exec_using_spi = FALSE; + + rfm22_setDebug("setTxMode end"); +} + +// ************************************ +// external interrupt line triggered (or polled) from the rf chip + +void rfm22_processRxInt(void) +{ + register uint8_t int_stat1 = int_status1; + register uint8_t int_stat2 = int_status2; + rfm22_setDebug("processRxInt"); + + // FIFO under/over flow error. Restart RX mode. + if (device_status & (RFM22_ds_ffunfl | RFM22_ds_ffovfl)) + { + rfm22_setError("R_UNDER/OVERRUN"); + rfm22_setRxMode(RX_WAIT_PREAMBLE_MODE, false); + return; + } + + // Sync timeout. Restart RX mode. + if (rf_mode == RX_WAIT_SYNC_MODE && rfm22_int_timer >= timeout_sync_ms) + { + rfm22_int_time_outs++; + rfm22_setError("R_SYNC_TIMEOUT"); + rfm22_setRxMode(RX_WAIT_PREAMBLE_MODE, false); + return; + } + + // RX timeout. Restart RX mode. + if (rf_mode == RX_DATA_MODE && rfm22_int_timer >= timeout_data_ms) + { + rfm22_setError("MISSING_INTERRUPTS"); + rfm22_int_time_outs++; + rfm22_setRxMode(RX_WAIT_PREAMBLE_MODE, false); + return; + } + + // The module is not in RX mode. Restart RX mode. + if ((device_status & RFM22_ds_cps_mask) != RFM22_ds_cps_rx) + { + // the rf module is not in rx mode + if (rfm22_int_timer >= 100) + { + rfm22_int_time_outs++; + // reset the receiver + rfm22_setRxMode(RX_WAIT_PREAMBLE_MODE, false); + return; + } + } + + // Valid preamble detected + if (int_stat2 & RFM22_is2_ipreaval) + { + if (rf_mode == RX_WAIT_PREAMBLE_MODE) + { + rfm22_int_timer = 0; // reset the timer + rf_mode = RX_WAIT_SYNC_MODE; + RX_LED_ON; + rfm22_setDebug("pream_det"); + } + } + + // Sync word detected + if (int_stat2 & RFM22_is2_iswdet) + { + if (rf_mode == RX_WAIT_PREAMBLE_MODE || rf_mode == RX_WAIT_SYNC_MODE) + { + rfm22_int_timer = 0; // reset the timer + rf_mode = RX_DATA_MODE; + RX_LED_ON; + rfm22_setDebug("sync_det"); + + // read the 10-bit signed afc correction value + // bits 9 to 2 + afc_correction = (uint16_t)rfm22_read(RFM22_afc_correction_read) << 8; + // bits 1 & 0 + afc_correction |= (uint16_t)rfm22_read(RFM22_ook_counter_value1) & 0x00c0; + afc_correction >>= 6; + // convert the afc value to Hz + afc_correction_Hz = (int32_t)(frequency_step_size * afc_correction + 0.5f); + + // remember the rssi for this packet + rx_packet_start_rssi_dBm = rssi_dBm; + // remember the afc value for this packet + rx_packet_start_afc_Hz = afc_correction_Hz; + } + } + + // RX FIFO almost full, it needs emptying + if (int_stat1 & RFM22_is1_irxffafull) + { + if (rf_mode == RX_DATA_MODE) + { + // read data from the rf chips FIFO buffer + rfm22_int_timer = 0; // reset the timer + + // read the total length of the packet data + uint16_t len = rfm22_read(RFM22_received_packet_length); + + // The received packet is going to be larger than the specified length + if ((rx_buffer_wr + RX_FIFO_HI_WATERMARK) > len) + { + rfm22_setError("r_size_error1"); + rfm22_setRxMode(RX_WAIT_PREAMBLE_MODE, false); + return; + } + + // Another packet length error. + if (((rx_buffer_wr + RX_FIFO_HI_WATERMARK) >= len) && !(int_stat1 & RFM22_is1_ipkvalid)) + { + rfm22_setError("r_size_error2"); + rfm22_setRxMode(RX_WAIT_PREAMBLE_MODE, false); + return; + } + + // Fetch the data from the RX FIFO + rfm22_startBurstRead(RFM22_fifo_access); + for (uint8_t i = 0; i < RX_FIFO_HI_WATERMARK; ++i) + rx_buffer[rx_buffer_wr++] = rfm22_burstRead(); + rfm22_endBurstRead(); + } + else + { // just clear the RX FIFO + rfm22_startBurstRead(RFM22_fifo_access); + for (register uint16_t i = RX_FIFO_HI_WATERMARK; i > 0; i--) + rfm22_burstRead(); // read a byte from the rf modules RX FIFO buffer + rfm22_endBurstRead(); + } + } + + // CRC error .. discard the received data + if (int_stat1 & RFM22_is1_icrerror) + { + rfm22_int_timer = 0; // reset the timer + rfm22_setError("CRC_ERR"); + rfm22_setRxMode(RX_WAIT_PREAMBLE_MODE, false); + return; + } + + // if (int_stat2 & RFM22_is2_irssi) + // { // RSSI level is >= the set threshold + // } + + // if (device_status & RFM22_ds_rxffem) + // { // RX FIFO empty + // } + + // if (device_status & RFM22_ds_headerr) + // { // Header check error + // } + + // Valid packet received + if (int_stat1 & RFM22_is1_ipkvalid) + { + // reset the timer + rfm22_int_timer = 0; + + // read the total length of the packet data + register uint16_t len = rfm22_read(RFM22_received_packet_length); + + // their must still be data in the RX FIFO we need to get + if (rx_buffer_wr < len) + { + // Fetch the data from the RX FIFO + rfm22_startBurstRead(RFM22_fifo_access); + while (rx_buffer_wr < len) + rx_buffer[rx_buffer_wr++] = rfm22_burstRead(); + rfm22_endBurstRead(); + } + + if (rx_buffer_wr != len) + { + // we have a packet length error .. discard the packet + rfm22_setError("r_pack_len_error"); + debug_val = len; + return; + } + + // we have a valid received packet + rfm22_setDebug("VALID_R_PACKET"); + + if (rx_buffer_wr > 0) + { + // remember the rssi for this packet + rx_packet_rssi_dBm = rx_packet_start_rssi_dBm; + // remember the afc offset for this packet + rx_packet_afc_Hz = rx_packet_start_afc_Hz; + // Add the rssi and afc to the end of the packet. + rx_buffer[rx_buffer_wr++] = rx_packet_start_rssi_dBm; + rx_buffer[rx_buffer_wr++] = rx_packet_start_afc_Hz; + // Pass this packet on + bool need_yield = false; + if (rfm22b_dev_g->rx_in_cb) + (rfm22b_dev_g->rx_in_cb)(rfm22b_dev_g->rx_in_context, (uint8_t*)rx_buffer, + rx_buffer_wr, NULL, &need_yield); + rx_buffer_wr = 0; + } + + // Send a packet if it's available. + if(!rfm22_txStart()) + { + // Switch to RX mode + rfm22_setDebug(" Set RX"); + rfm22_setRxMode(RX_WAIT_PREAMBLE_MODE, false); + } + } + + rfm22_setDebug("processRxInt end"); +} + +void rfm22_processTxInt(void) +{ + register uint8_t int_stat1 = int_status1; + + // reset the timer + rfm22_int_timer = 0; + + // FIFO under/over flow error. Back to RX mode. + if (device_status & (RFM22_ds_ffunfl | RFM22_ds_ffovfl)) + { + rfm22_setError("T_UNDER/OVERRUN"); + rfm22_setRxMode(RX_WAIT_PREAMBLE_MODE, false); + return; + } + + // Transmit timeout. Abort the transmit. + if (rfm22_int_timer >= timeout_data_ms) + { + rfm22_int_time_outs++; + rfm22_setRxMode(RX_WAIT_PREAMBLE_MODE, false); + return; + } + + // the rf module is not in tx mode + if ((device_status & RFM22_ds_cps_mask) != RFM22_ds_cps_tx) + { + if (rfm22_int_timer >= 100) + { + rfm22_int_time_outs++; + rfm22_setError("T_TIMEOUT"); + rfm22_setRxMode(RX_WAIT_PREAMBLE_MODE, false); // back to rx mode + return; + } + } + + // TX FIFO almost empty, it needs filling up + if (int_stat1 & RFM22_is1_ixtffaem) + { + // top-up the rf chips TX FIFO buffer + uint16_t max_bytes = FIFO_SIZE - TX_FIFO_LO_WATERMARK - 1; + rfm22_startBurstWrite(RFM22_fifo_access); + for (uint16_t i = 0; (tx_data_rd < tx_data_wr) && (i < max_bytes); ++i, ++tx_data_rd) + rfm22_burstWrite(tx_buffer[tx_data_rd]); + rfm22_endBurstWrite(); + } + + // Packet has been sent + if (int_stat1 & RFM22_is1_ipksent) + { + rfm22_setDebug(" T_Sent"); + + // Send another packet if it's available. + if(!rfm22_txStart()) + { + // Switch to RX mode + rfm22_setDebug(" Set RX"); + rfm22_setRxMode(RX_WAIT_PREAMBLE_MODE, false); + return; + } + } + + rfm22_setDebug("ProcessTxInt done"); +} + +static void rfm22_processInt(void) +{ + rfm22_setDebug("ProcessInt"); + // this is called from the external interrupt handler + + if (!initialized || power_on_reset) + // we haven't yet been initialized + return; + + exec_using_spi = TRUE; + + // Reset the supervisor timer. + rfm22b_dev->supv_timer = PIOS_RFM22B_SUPERVISOR_TIMEOUT; + + // ******************************** + // read the RF modules current status registers + + // read interrupt status registers - clears the interrupt line + int_status1 = rfm22_read(RFM22_interrupt_status1); + int_status2 = rfm22_read(RFM22_interrupt_status2); + + // read device status register + device_status = rfm22_read(RFM22_device_status); + + // read ezmac status register + ezmac_status = rfm22_read(RFM22_ezmac_status); + + // Read the RSSI if we're in RX mode + if (rf_mode != TX_DATA_MODE && rf_mode != TX_STREAM_MODE && + rf_mode != TX_CARRIER_MODE && rf_mode != TX_PN_MODE) + { + // read rx signal strength .. 45 = -100dBm, 205 = -20dBm + rssi = rfm22_read(RFM22_rssi); + // convert to dBm + rssi_dBm = (int8_t)(rssi >> 1) - 122; + + // calibrate the RSSI value (rf bandwidth appears to affect it) + // if (rf_bandwidth_used > 0) + // rssi_dBm -= 10000 / rf_bandwidth_used; + } + else + { + // read the tx power register + tx_pwr = rfm22_read(RFM22_tx_power); + } + + // the RF module has gone and done a reset - we need to re-initialize the rf module + if (int_status2 & RFM22_is2_ipor) + { + initialized = FALSE; + power_on_reset = TRUE; + rfm22_setError("Reset"); + // Need to do something here! + return; + } + + switch (rf_mode) + { + case RX_SCAN_SPECTRUM: + break; + + case RX_WAIT_PREAMBLE_MODE: + case RX_WAIT_SYNC_MODE: + case RX_DATA_MODE: + + rfm22_processRxInt(); + break; + + case TX_DATA_MODE: + case TX_STREAM_MODE: + + rfm22_processTxInt(); + break; + + case TX_CARRIER_MODE: + case TX_PN_MODE: + + // if (rfm22_int_timer >= TX_TEST_MODE_TIMELIMIT_MS) // 'nn'ms limit + // { + // rfm22_setRxMode(RX_WAIT_PREAMBLE_MODE, false); // back to rx mode + // tx_data_rd = tx_data_wr = 0; // wipe TX buffer + // break; + // } + + break; + + default: // unknown mode - this should NEVER happen, maybe we should do a complete CPU reset here + rfm22_setRxMode(RX_WAIT_PREAMBLE_MODE, false); // to rx mode + break; + } + + exec_using_spi = FALSE; + + rfm22_setDebug("ProcessInt done"); +} + +// ************************************ + +int8_t rfm22_getRSSI(void) +{ + exec_using_spi = TRUE; + + rssi = rfm22_read(RFM22_rssi); // read rx signal strength .. 45 = -100dBm, 205 = -20dBm + rssi_dBm = (int8_t)(rssi >> 1) - 122; // convert to dBm + + exec_using_spi = FALSE; + return rssi_dBm; +} + +int8_t rfm22_receivedRSSI(void) +{ // return the packets signal strength + if (!initialized) + return -127; + else + return rx_packet_rssi_dBm; +} + +int32_t rfm22_receivedAFCHz(void) +{ // return the packets offset frequency + if (!initialized) + return 0; + else + return rx_packet_afc_Hz; +} + +// ************************************ + +// ************************************ + +void rfm22_setTxStream(void) // TEST ONLY +{ + if (!initialized) + return; + + tx_data_rd = tx_data_wr = 0; + + rfm22_setTxMode(TX_STREAM_MODE); +} + +// ************************************ + +void rfm22_setTxNormal(void) +{ + if (!initialized) + return; + + // if (rf_mode == TX_CARRIER_MODE || rf_mode == TX_PN_MODE) + if (rf_mode != RX_SCAN_SPECTRUM) + { + rfm22_setRxMode(RX_WAIT_PREAMBLE_MODE, false); + tx_data_rd = tx_data_wr = 0; + + rx_packet_start_rssi_dBm = 0; + rx_packet_start_afc_Hz = 0; + rx_packet_rssi_dBm = 0; + rx_packet_afc_Hz = 0; + } +} + +// enable a blank tx carrier (for frequency alignment) +void rfm22_setTxCarrierMode(void) +{ + if (!initialized) + return; + + if (rf_mode != TX_CARRIER_MODE && rf_mode != RX_SCAN_SPECTRUM) + rfm22_setTxMode(TX_CARRIER_MODE); +} + +// enable a psuedo random data tx carrier (for spectrum inspection) +void rfm22_setTxPNMode(void) +{ + if (!initialized) + return; + + if (rf_mode != TX_PN_MODE && rf_mode != RX_SCAN_SPECTRUM) + rfm22_setTxMode(TX_PN_MODE); +} + +// ************************************ + +// return the current mode +int8_t rfm22_currentMode(void) +{ + return rf_mode; +} + +// return TRUE if we are transmitting +bool rfm22_transmitting(void) +{ + return (rf_mode == TX_DATA_MODE || rf_mode == TX_STREAM_MODE || rf_mode == TX_CARRIER_MODE || rf_mode == TX_PN_MODE); +} + +// return TRUE if the channel is clear to transmit on +bool rfm22_channelIsClear(void) +{ + if (!initialized) + // we haven't yet been initialized + return FALSE; + + if (rf_mode != RX_WAIT_PREAMBLE_MODE && rf_mode != RX_WAIT_SYNC_MODE) + // we are receiving something or we are transmitting or we are scanning the spectrum + return FALSE; + + return TRUE; +} + +// return TRUE if the transmiter is ready for use +bool rfm22_txReady(void) +{ + if (!initialized) + // we haven't yet been initialized + return FALSE; + + return (tx_data_rd == 0 && tx_data_wr == 0 && rf_mode != TX_DATA_MODE && + rf_mode != TX_STREAM_MODE && rf_mode != TX_CARRIER_MODE && rf_mode != TX_PN_MODE && + rf_mode != RX_SCAN_SPECTRUM); +} + +// ************************************ +// set/get the frequency calibration value + +void rfm22_setFreqCalibration(uint8_t value) +{ + osc_load_cap = value; + + if (!initialized || power_on_reset) + return; // we haven't yet been initialized + + uint8_t prev_rf_mode = rf_mode; + + if (rf_mode == TX_CARRIER_MODE || rf_mode == TX_PN_MODE) + { + rfm22_setRxMode(RX_WAIT_PREAMBLE_MODE, false); + tx_data_rd = tx_data_wr = 0; + } + + exec_using_spi = TRUE; + + rfm22_write(RFM22_xtal_osc_load_cap, osc_load_cap); + + exec_using_spi = FALSE; + + if (prev_rf_mode == TX_CARRIER_MODE || prev_rf_mode == TX_PN_MODE) + rfm22_setTxMode(prev_rf_mode); +} + +uint8_t rfm22_getFreqCalibration(void) +{ + return osc_load_cap; +} + +// ************************************ +// can be called from an interrupt if you wish + +void rfm22_1ms_tick(void) +{ // call this once every ms + if (!initialized) return; // we haven't yet been initialized + + if (rf_mode != RX_SCAN_SPECTRUM) + { + if (rfm22_int_timer < 0xffff) rfm22_int_timer++; + } +} + +// ************************************ +// reset the RF module + +int rfm22_resetModule(uint8_t mode, uint32_t min_frequency_hz, uint32_t max_frequency_hz) +{ + initialized = false; + +#if defined(RFM22_EXT_INT_USE) + rfm22_disableExtInt(); +#endif + + power_on_reset = false; + + // **************** + + exec_using_spi = TRUE; + + // **************** + // setup the SPI port + + // chip select line HIGH + PIOS_SPI_RC_PinSet(RFM22_PIOS_SPI, 0, 1); + + // set SPI port SCLK frequency .. 4.5MHz + PIOS_SPI_SetClockSpeed(RFM22_PIOS_SPI, PIOS_SPI_PRESCALER_16); + // set SPI port SCLK frequency .. 2.25MHz + // PIOS_SPI_SetClockSpeed(RFM22_PIOS_SPI, PIOS_SPI_PRESCALER_32); + + // set SPI port SCLK frequency .. 285kHz .. purely for hardware fault finding + // PIOS_SPI_SetClockSpeed(RFM22_PIOS_SPI, PIOS_SPI_PRESCALER_256); + + // **************** + // software reset the RF chip .. following procedure according to Si4x3x Errata (rev. B) + + rfm22_write(RFM22_op_and_func_ctrl1, RFM22_opfc1_swres); // software reset the radio + + PIOS_DELAY_WaitmS(26); // wait 26ms + + for (int i = 50; i > 0; i--) + { + PIOS_DELAY_WaitmS(1); // wait 1ms + + // read the status registers + int_status1 = rfm22_read(RFM22_interrupt_status1); + int_status2 = rfm22_read(RFM22_interrupt_status2); + if (int_status2 & RFM22_is2_ichiprdy) break; + } + + // **************** + + // read status - clears interrupt + device_status = rfm22_read(RFM22_device_status); + int_status1 = rfm22_read(RFM22_interrupt_status1); + int_status2 = rfm22_read(RFM22_interrupt_status2); + ezmac_status = rfm22_read(RFM22_ezmac_status); + + // disable all interrupts + rfm22_write(RFM22_interrupt_enable1, 0x00); + rfm22_write(RFM22_interrupt_enable2, 0x00); + + // **************** + + exec_using_spi = FALSE; + + // **************** + + rf_mode = mode; + + device_status = int_status1 = int_status2 = ezmac_status = 0; + + rssi = 0; + rssi_dBm = -127; + + rx_buffer_current = 0; + rx_buffer_wr = 0; + rx_packet_rssi_dBm = -127; + rx_packet_afc_Hz = 0; + + tx_data_rd = tx_data_wr = 0; + + lookup_index = 0; + ss_lookup_index = 0; + + rf_bandwidth_used = 0; + ss_rf_bandwidth_used = 0; + + rfm22_int_timer = 0; + rfm22_int_time_outs = 0; + prev_rfm22_int_time_outs = 0; + + hbsel = 0; + frequency_step_size = 0.0f; + + frequency_hop_channel = 0; + + afc_correction = 0; + afc_correction_Hz = 0; + + temperature_reg = 0; + + // set the TX power + tx_power = RFM22_DEFAULT_RF_POWER; + + tx_pwr = 0; + + // **************** + // read the RF chip ID bytes + + device_type = rfm22_read(RFM22_DEVICE_TYPE) & RFM22_DT_MASK; // read the device type + device_version = rfm22_read(RFM22_DEVICE_VERSION) & RFM22_DV_MASK; // read the device version + +#if defined(RFM22_DEBUG) + DEBUG_PRINTF(2, "rf device type: %d\n\r", device_type); + DEBUG_PRINTF(2, "rf device version: %d\n\r", device_version); +#endif + + if (device_type != 0x08) + { +#if defined(RFM22_DEBUG) + DEBUG_PRINTF(2, "rf device type: INCORRECT - should be 0x08\n\r"); +#endif + return -1; // incorrect RF module type + } + + // if (device_version != RFM22_DEVICE_VERSION_V2) // V2 + // return -2; // incorrect RF module version + // if (device_version != RFM22_DEVICE_VERSION_A0) // A0 + // return -2; // incorrect RF module version + if (device_version != RFM22_DEVICE_VERSION_B1) // B1 + { +#if defined(RFM22_DEBUG) + DEBUG_PRINTF(2, "rf device version: INCORRECT\n\r"); +#endif + return -2; // incorrect RF module version + } + + // **************** + // set the minimum and maximum carrier frequency allowed + + if (min_frequency_hz < RFM22_MIN_CARRIER_FREQUENCY_HZ) min_frequency_hz = RFM22_MIN_CARRIER_FREQUENCY_HZ; + else + if (min_frequency_hz > RFM22_MAX_CARRIER_FREQUENCY_HZ) min_frequency_hz = RFM22_MAX_CARRIER_FREQUENCY_HZ; + + if (max_frequency_hz < RFM22_MIN_CARRIER_FREQUENCY_HZ) max_frequency_hz = RFM22_MIN_CARRIER_FREQUENCY_HZ; + else + if (max_frequency_hz > RFM22_MAX_CARRIER_FREQUENCY_HZ) max_frequency_hz = RFM22_MAX_CARRIER_FREQUENCY_HZ; + + if (min_frequency_hz > max_frequency_hz) + { // swap them over + uint32_t tmp = min_frequency_hz; + min_frequency_hz = max_frequency_hz; + max_frequency_hz = tmp; + } + + lower_carrier_frequency_limit_Hz = min_frequency_hz; + upper_carrier_frequency_limit_Hz = max_frequency_hz; + + // **************** + // calibrate our RF module to be exactly on frequency .. different for every module + + osc_load_cap = OSC_LOAD_CAP; // default + rfm22_write(RFM22_xtal_osc_load_cap, osc_load_cap); + + // **************** + + // disable Low Duty Cycle Mode + rfm22_write(RFM22_op_and_func_ctrl2, 0x00); + + rfm22_write(RFM22_cpu_output_clk, RFM22_coc_1MHz); // 1MHz clock output + + rfm22_write(RFM22_op_and_func_ctrl1, RFM22_opfc1_xton); // READY mode + // rfm22_write(RFM22_op_and_func_ctrl1, RFM22_opfc1_pllon); // TUNE mode + + // choose the 3 GPIO pin functions + rfm22_write(RFM22_io_port_config, RFM22_io_port_default); // GPIO port use default value + rfm22_write(RFM22_gpio0_config, RFM22_gpio0_config_drv3 | RFM22_gpio0_config_txstate); // GPIO0 = TX State (to control RF Switch) + rfm22_write(RFM22_gpio1_config, RFM22_gpio1_config_drv3 | RFM22_gpio1_config_rxstate); // GPIO1 = RX State (to control RF Switch) + rfm22_write(RFM22_gpio2_config, RFM22_gpio2_config_drv3 | RFM22_gpio2_config_cca); // GPIO2 = Clear Channel Assessment + + // **************** + + return 0; // OK +} + +// ************************************ + +int rfm22_init_scan_spectrum(uint32_t min_frequency_hz, uint32_t max_frequency_hz) +{ +#if defined(RFM22_DEBUG) + DEBUG_PRINTF(2, "\n\rRF init scan spectrum\n\r"); +#endif + + int res = rfm22_resetModule(RX_SCAN_SPECTRUM, min_frequency_hz, max_frequency_hz); + if (res < 0) + return res; + + // rfm22_setSSBandwidth(0); + rfm22_setSSBandwidth(1); + + // FIFO mode, GFSK modulation + uint8_t fd_bit = rfm22_read(RFM22_modulation_mode_control2) & RFM22_mmc2_fd; + rfm22_write(RFM22_modulation_mode_control2, RFM22_mmc2_trclk_clk_none | RFM22_mmc2_dtmod_fifo | fd_bit | RFM22_mmc2_modtyp_gfsk); + + rfm22_write(RFM22_cpu_output_clk, RFM22_coc_1MHz); // 1MHz clock output + + rfm22_write(RFM22_rssi_threshold_clear_chan_indicator, 0); + + rfm22_write(RFM22_preamble_detection_ctrl1, 31 << 3); // 31-nibbles rx preamble detection + + // avoid packet detection + rfm22_write(RFM22_data_access_control, RFM22_dac_enpacrx | RFM22_dac_encrc); + rfm22_write(RFM22_header_control1, 0x0f); + rfm22_write(RFM22_header_control2, 0x77); + + rfm22_write(RFM22_sync_word3, SYNC_BYTE_1); + rfm22_write(RFM22_sync_word2, SYNC_BYTE_2); + rfm22_write(RFM22_sync_word1, SYNC_BYTE_3 ^ 0xff); + rfm22_write(RFM22_sync_word0, SYNC_BYTE_4 ^ 0xff); + + // all the bits to be checked + rfm22_write(RFM22_header_enable3, 0xff); + rfm22_write(RFM22_header_enable2, 0xff); + rfm22_write(RFM22_header_enable1, 0xff); + rfm22_write(RFM22_header_enable0, 0xff); + + // set frequency hopping channel step size (multiples of 10kHz) + // rfm22_write(RFM22_frequency_hopping_step_size, 0); + + // set our nominal carrier frequency + rfm22_setNominalCarrierFrequency(min_frequency_hz); + + // set minimum tx power + rfm22_write(RFM22_tx_power, RFM22_tx_pwr_lna_sw | 0); + + rfm22_write(RFM22_agc_override1, RFM22_agc_ovr1_sgi | RFM22_agc_ovr1_agcen); + + // rfm22_write(RFM22_vco_current_trimming, 0x7f); + // rfm22_write(RFM22_vco_calibration_override, 0x40); + // rfm22_write(RFM22_chargepump_current_trimming_override, 0x80); + + // Enable RF module external interrupt + rfm22_enableExtInt(); + + rfm22_setRxMode(RX_SCAN_SPECTRUM, true); + + initialized = true; + + return 0; // OK +} + +// ************************************ + +int rfm22_init_tx_stream(uint32_t min_frequency_hz, uint32_t max_frequency_hz) +{ +#if defined(RFM22_DEBUG) + DEBUG_PRINTF(2, "\n\rRF init TX stream\n\r"); +#endif + + int res = rfm22_resetModule(TX_STREAM_MODE, min_frequency_hz, max_frequency_hz); + if (res < 0) + return res; + + frequency_hop_step_size_reg = 0; + + // set the RF datarate + rfm22_setDatarate(RFM22_DEFAULT_RF_DATARATE, FALSE); + + // FIFO mode, GFSK modulation + uint8_t fd_bit = rfm22_read(RFM22_modulation_mode_control2) & RFM22_mmc2_fd; + rfm22_write(RFM22_modulation_mode_control2, RFM22_mmc2_trclk_clk_none | RFM22_mmc2_dtmod_fifo | fd_bit | RFM22_mmc2_modtyp_gfsk); + + // disable the internal Tx & Rx packet handlers (without CRC) + rfm22_write(RFM22_data_access_control, 0); + + rfm22_write(RFM22_preamble_length, TX_PREAMBLE_NIBBLES); // x-nibbles tx preamble + rfm22_write(RFM22_preamble_detection_ctrl1, RX_PREAMBLE_NIBBLES << 3); // x-nibbles rx preamble detection + + rfm22_write(RFM22_header_control1, RFM22_header_cntl1_bcen_none | RFM22_header_cntl1_hdch_none); // header control - we are not using the header + rfm22_write(RFM22_header_control2, RFM22_header_cntl2_fixpklen | RFM22_header_cntl2_hdlen_none | RFM22_header_cntl2_synclen_32 | ((TX_PREAMBLE_NIBBLES >> 8) & 0x01)); // no header bytes, synchronization word length 3, 2 used, packet length not included in header (fixed packet length). + + rfm22_write(RFM22_sync_word3, SYNC_BYTE_1); // sync word + rfm22_write(RFM22_sync_word2, SYNC_BYTE_2); // + + // rfm22_write(RFM22_modem_test, 0x01); + + rfm22_write(RFM22_agc_override1, RFM22_agc_ovr1_agcen); + // rfm22_write(RFM22_agc_override1, RFM22_agc_ovr1_sgi | RFM22_agc_ovr1_agcen); + + rfm22_write(RFM22_frequency_hopping_step_size, frequency_hop_step_size_reg); // set frequency hopping channel step size (multiples of 10kHz) + + rfm22_setNominalCarrierFrequency((min_frequency_hz + max_frequency_hz) / 2); // set our nominal carrier frequency + + rfm22_write(RFM22_tx_power, RFM22_tx_pwr_papeaken | RFM22_tx_pwr_papeaklvl_0 | RFM22_tx_pwr_lna_sw | tx_power); // set the tx power + // rfm22_write(RFM22_tx_power, RFM22_tx_pwr_lna_sw | tx_power); // set the tx power + + // rfm22_write(RFM22_vco_current_trimming, 0x7f); + // rfm22_write(RFM22_vco_calibration_override, 0x40); + // rfm22_write(RFM22_chargepump_current_trimming_override, 0x80); + + rfm22_write(RFM22_tx_fifo_control1, TX_FIFO_HI_WATERMARK); // TX FIFO Almost Full Threshold (0 - 63) + rfm22_write(RFM22_tx_fifo_control2, TX_FIFO_LO_WATERMARK); // TX FIFO Almost Empty Threshold (0 - 63) + + // Enable RF module external interrupt + rfm22_enableExtInt(); + + initialized = true; + + return 0; // OK +} + +// ************************************ + +int rfm22_init_rx_stream(uint32_t min_frequency_hz, uint32_t max_frequency_hz) +{ +#if defined(RFM22_DEBUG) + DEBUG_PRINTF(2, "\n\rRF init RX stream\n\r"); +#endif + + int res = rfm22_resetModule(RX_WAIT_PREAMBLE_MODE, min_frequency_hz, max_frequency_hz); + if (res < 0) + return res; + + frequency_hop_step_size_reg = 0; + + // set the RF datarate + rfm22_setDatarate(RFM22_DEFAULT_RF_DATARATE, FALSE); + + // FIFO mode, GFSK modulation + uint8_t fd_bit = rfm22_read(RFM22_modulation_mode_control2) & RFM22_mmc2_fd; + rfm22_write(RFM22_modulation_mode_control2, RFM22_mmc2_trclk_clk_none | RFM22_mmc2_dtmod_fifo | fd_bit | RFM22_mmc2_modtyp_gfsk); + + // disable the internal Tx & Rx packet handlers (without CRC) + rfm22_write(RFM22_data_access_control, 0); + + rfm22_write(RFM22_preamble_length, TX_PREAMBLE_NIBBLES); // x-nibbles tx preamble + rfm22_write(RFM22_preamble_detection_ctrl1, RX_PREAMBLE_NIBBLES << 3); // x-nibbles rx preamble detection + + rfm22_write(RFM22_header_control1, RFM22_header_cntl1_bcen_none | RFM22_header_cntl1_hdch_none); // header control - we are not using the header + rfm22_write(RFM22_header_control2, RFM22_header_cntl2_fixpklen | RFM22_header_cntl2_hdlen_none | RFM22_header_cntl2_synclen_32 | ((TX_PREAMBLE_NIBBLES >> 8) & 0x01)); // no header bytes, synchronization word length 3, 2 used, packet length not included in header (fixed packet length). + + rfm22_write(RFM22_sync_word3, SYNC_BYTE_1); // sync word + rfm22_write(RFM22_sync_word2, SYNC_BYTE_2); // + + // no header bits to be checked + rfm22_write(RFM22_header_enable3, 0x00); + rfm22_write(RFM22_header_enable2, 0x00); + rfm22_write(RFM22_header_enable1, 0x00); + rfm22_write(RFM22_header_enable0, 0x00); + + // rfm22_write(RFM22_modem_test, 0x01); + + rfm22_write(RFM22_agc_override1, RFM22_agc_ovr1_agcen); + // rfm22_write(RFM22_agc_override1, RFM22_agc_ovr1_sgi | RFM22_agc_ovr1_agcen); + + rfm22_write(RFM22_frequency_hopping_step_size, frequency_hop_step_size_reg); // set frequency hopping channel step size (multiples of 10kHz) + + rfm22_setNominalCarrierFrequency((min_frequency_hz + max_frequency_hz) / 2); // set our nominal carrier frequency + + // rfm22_write(RFM22_vco_current_trimming, 0x7f); + // rfm22_write(RFM22_vco_calibration_override, 0x40); + // rfm22_write(RFM22_chargepump_current_trimming_override, 0x80); + + // RX FIFO Almost Full Threshold (0 - 63) + rfm22_write(RFM22_rx_fifo_control, RX_FIFO_HI_WATERMARK); + + // Enable RF module external interrupt + rfm22_enableExtInt(); + + rfm22_setRxMode(RX_WAIT_PREAMBLE_MODE, false); + + initialized = true; + + return 0; // OK +} + +// ************************************ +// Initialise this hardware layer module and the rf module + +int rfm22_init_normal(uint32_t id, uint32_t min_frequency_hz, uint32_t max_frequency_hz, uint32_t freq_hop_step_size) +{ + int res = rfm22_resetModule(RX_WAIT_PREAMBLE_MODE, min_frequency_hz, max_frequency_hz); + if (res < 0) + return res; + + // initialize the frequency hopping step size + freq_hop_step_size /= 10000; // in 10kHz increments + if (freq_hop_step_size > 255) freq_hop_step_size = 255; + frequency_hop_step_size_reg = freq_hop_step_size; + + // set the RF datarate + rfm22_setDatarate(RFM22_DEFAULT_RF_DATARATE, TRUE); + + // FIFO mode, GFSK modulation + uint8_t fd_bit = rfm22_read(RFM22_modulation_mode_control2) & RFM22_mmc2_fd; + rfm22_write(RFM22_modulation_mode_control2, RFM22_mmc2_trclk_clk_none | RFM22_mmc2_dtmod_fifo | fd_bit | RFM22_mmc2_modtyp_gfsk); + + // setup to read the internal temperature sensor + + // ADC used to sample the temperature sensor + adc_config = RFM22_ac_adcsel_temp_sensor | RFM22_ac_adcref_bg; + rfm22_write(RFM22_adc_config, adc_config); + + // adc offset + rfm22_write(RFM22_adc_sensor_amp_offset, 0); + + // temp sensor calibration .. –40C to +64C 0.5C resolution + rfm22_write(RFM22_temp_sensor_calib, RFM22_tsc_tsrange0 | RFM22_tsc_entsoffs); + + // temp sensor offset + rfm22_write(RFM22_temp_value_offset, 0); + + // start an ADC conversion + rfm22_write(RFM22_adc_config, adc_config | RFM22_ac_adcstartbusy); + + // set the RSSI threshold interrupt to about -90dBm + rfm22_write(RFM22_rssi_threshold_clear_chan_indicator, (-90 + 122) * 2); + + // enable the internal Tx & Rx packet handlers (without CRC) + rfm22_write(RFM22_data_access_control, RFM22_dac_enpacrx | RFM22_dac_enpactx); + + // x-nibbles tx preamble + rfm22_write(RFM22_preamble_length, TX_PREAMBLE_NIBBLES); + // x-nibbles rx preamble detection + rfm22_write(RFM22_preamble_detection_ctrl1, RX_PREAMBLE_NIBBLES << 3); + +#ifdef PIOS_RFM22_NO_HEADER + // header control - we are not using the header + rfm22_write(RFM22_header_control1, RFM22_header_cntl1_bcen_none | RFM22_header_cntl1_hdch_none); + + // no header bytes, synchronization word length 3, 2, 1 & 0 used, packet length included in header. + rfm22_write(RFM22_header_control2, RFM22_header_cntl2_hdlen_none | + RFM22_header_cntl2_synclen_3210 | ((TX_PREAMBLE_NIBBLES >> 8) & 0x01)); +#else + // header control - using a 4 by header with broadcast of 0xffffffff + rfm22_write(RFM22_header_control1, + RFM22_header_cntl1_bcen_0 | + RFM22_header_cntl1_bcen_1 | + RFM22_header_cntl1_bcen_2 | + RFM22_header_cntl1_bcen_3 | + RFM22_header_cntl1_hdch_0 | + RFM22_header_cntl1_hdch_1 | + RFM22_header_cntl1_hdch_2 | + RFM22_header_cntl1_hdch_3); + // Check all bit of all bytes of the header + rfm22_write(RFM22_header_enable0, 0xff); + rfm22_write(RFM22_header_enable1, 0xff); + rfm22_write(RFM22_header_enable2, 0xff); + rfm22_write(RFM22_header_enable3, 0xff); + // Set the ID to be checked + rfm22_write(RFM22_check_header0, id & 0xff); + rfm22_write(RFM22_check_header1, (id >> 8) & 0xff); + rfm22_write(RFM22_check_header2, (id >> 16) & 0xff); + rfm22_write(RFM22_check_header3, (id >> 24) & 0xff); + // 4 header bytes, synchronization word length 3, 2, 1 & 0 used, packet length included in header. + rfm22_write(RFM22_header_control2, + RFM22_header_cntl2_hdlen_3210 | + RFM22_header_cntl2_synclen_3210 | + ((TX_PREAMBLE_NIBBLES >> 8) & 0x01)); +#endif + + // sync word + rfm22_write(RFM22_sync_word3, SYNC_BYTE_1); + rfm22_write(RFM22_sync_word2, SYNC_BYTE_2); + rfm22_write(RFM22_sync_word1, SYNC_BYTE_3); + rfm22_write(RFM22_sync_word0, SYNC_BYTE_4); + + rfm22_write(RFM22_agc_override1, RFM22_agc_ovr1_agcen); + + // set frequency hopping channel step size (multiples of 10kHz) + rfm22_write(RFM22_frequency_hopping_step_size, frequency_hop_step_size_reg); + + // set our nominal carrier frequency + rfm22_setNominalCarrierFrequency((min_frequency_hz + max_frequency_hz) / 2); + + // set the tx power + rfm22_write(RFM22_tx_power, RFM22_tx_pwr_papeaken | RFM22_tx_pwr_papeaklvl_0 | + RFM22_tx_pwr_lna_sw | tx_power); + + // TX FIFO Almost Full Threshold (0 - 63) + rfm22_write(RFM22_tx_fifo_control1, TX_FIFO_HI_WATERMARK); + + // TX FIFO Almost Empty Threshold (0 - 63) + rfm22_write(RFM22_tx_fifo_control2, TX_FIFO_LO_WATERMARK); + + // RX FIFO Almost Full Threshold (0 - 63) + rfm22_write(RFM22_rx_fifo_control, RX_FIFO_HI_WATERMARK); + + // Enable RF module external interrupt + rfm22_enableExtInt(); + + rfm22_setRxMode(RX_WAIT_PREAMBLE_MODE, false); + + initialized = true; + + return 0; // ok +} + +// ************************************ + +#endif + +/** + * @} + * @} + */ diff --git a/flight/PiOS/Common/pios_usb_desc_hid_cdc.c b/flight/PiOS/Common/pios_usb_desc_hid_cdc.c index 13fd988f2..1d4f0a9b2 100644 --- a/flight/PiOS/Common/pios_usb_desc_hid_cdc.c +++ b/flight/PiOS/Common/pios_usb_desc_hid_cdc.c @@ -38,9 +38,9 @@ static const struct usb_device_desc device_desc = { .bLength = sizeof(struct usb_device_desc), .bDescriptorType = USB_DESC_TYPE_DEVICE, .bcdUSB = htousbs(0x0200), - .bDeviceClass = 0x02, - .bDeviceSubClass = 0x00, - .bDeviceProtocol = 0x00, + .bDeviceClass = 0xef, + .bDeviceSubClass = 0x02, + .bDeviceProtocol = 0x01, .bMaxPacketSize0 = 64, /* Must be 64 for high-speed devices */ .idVendor = htousbs(USB_VENDOR_ID_OPENPILOT), .idProduct = htousbs(PIOS_USB_BOARD_PRODUCT_ID), @@ -98,10 +98,6 @@ static const uint8_t hid_report_desc[36] = { struct usb_config_hid_cdc { struct usb_configuration_desc config; struct usb_interface_association_desc iad; - struct usb_interface_desc hid_if; - struct usb_hid_desc hid; - struct usb_endpoint_desc hid_in; - struct usb_endpoint_desc hid_out; struct usb_interface_desc cdc_control_if; struct usb_cdc_header_func_desc cdc_header; struct usb_cdc_callmgmt_func_desc cdc_callmgmt; @@ -111,6 +107,10 @@ struct usb_config_hid_cdc { struct usb_interface_desc cdc_data_if; struct usb_endpoint_desc cdc_in; struct usb_endpoint_desc cdc_out; + struct usb_interface_desc hid_if; + struct usb_hid_desc hid; + struct usb_endpoint_desc hid_in; + struct usb_endpoint_desc hid_out; } __attribute__((packed)); static const struct usb_config_hid_cdc config_hid_cdc = { @@ -129,15 +129,87 @@ static const struct usb_config_hid_cdc config_hid_cdc = { .bDescriptorType = USB_DESC_TYPE_IAD, .bFirstInterface = 0, .bInterfaceCount = 2, - .bFunctionClass = 2, /* Communication */ - .bFunctionSubClass = 2, /* Abstract Control Model */ - .bFunctionProtocol = 0, /* V.25ter, Common AT commands */ + .bFunctionClass = USB_INTERFACE_CLASS_CDC, /* Communication */ + .bFunctionSubClass = USB_CDC_DESC_SUBTYPE_ABSTRACT_CTRL, /* Abstract Control Model */ + .bFunctionProtocol = 1, /* V.25ter, Common AT commands */ .iInterface = 0, }, + .cdc_control_if = { + .bLength = sizeof(struct usb_interface_desc), + .bDescriptorType = USB_DESC_TYPE_INTERFACE, + .bInterfaceNumber = 0, + .bAlternateSetting = 0, + .bNumEndpoints = 1, + .bInterfaceClass = USB_INTERFACE_CLASS_CDC, + .bInterfaceSubClass = USB_CDC_DESC_SUBTYPE_ABSTRACT_CTRL, /* Abstract Control Model */ + .nInterfaceProtocol = 1, /* V.25ter, Common AT commands */ + .iInterface = 0, + }, + .cdc_header = { + .bLength = sizeof(struct usb_cdc_header_func_desc), + .bDescriptorType = USB_DESC_TYPE_CLASS_SPECIFIC, + .bDescriptorSubType = USB_CDC_DESC_SUBTYPE_HEADER, + .bcdCDC = htousbs(0x0110), + }, + .cdc_callmgmt = { + .bLength = sizeof(struct usb_cdc_callmgmt_func_desc), + .bDescriptorType = USB_DESC_TYPE_CLASS_SPECIFIC, + .bDescriptorSubType = USB_CDC_DESC_SUBTYPE_CALLMGMT, + .bmCapabilities = 0x00, /* No call handling */ + .bDataInterface = 1, + }, + .cdc_acm = { + .bLength = sizeof(struct usb_cdc_acm_func_desc), + .bDescriptorType = USB_DESC_TYPE_CLASS_SPECIFIC, + .bDescriptorSubType = USB_CDC_DESC_SUBTYPE_ABSTRACT_CTRL, + .bmCapabilities = 0x00, + }, + .cdc_union = { + .bLength = sizeof(struct usb_cdc_union_func_desc), + .bDescriptorType = USB_DESC_TYPE_CLASS_SPECIFIC, + .bDescriptorSubType = USB_CDC_DESC_SUBTYPE_UNION, + .bMasterInterface = 0, + .bSlaveInterface = 1, + }, + .cdc_mgmt_in = { + .bLength = sizeof(struct usb_endpoint_desc), + .bDescriptorType = USB_DESC_TYPE_ENDPOINT, + .bEndpointAddress = USB_EP_IN(2), + .bmAttributes = USB_EP_ATTR_TT_INTERRUPT, + .wMaxPacketSize = htousbs(PIOS_USB_BOARD_CDC_MGMT_LENGTH), + .bInterval = 4, /* ms */ + }, + .cdc_data_if = { + .bLength = sizeof(struct usb_interface_desc), + .bDescriptorType = USB_DESC_TYPE_INTERFACE, + .bInterfaceNumber = 1, + .bAlternateSetting = 0, + .bNumEndpoints = 2, + .bInterfaceClass = USB_INTERFACE_CLASS_DATA, + .bInterfaceSubClass = 0, + .nInterfaceProtocol = 0, /* No class specific protocol */ + .iInterface = 0, + }, + .cdc_in = { + .bLength = sizeof(struct usb_endpoint_desc), + .bDescriptorType = USB_DESC_TYPE_ENDPOINT, + .bEndpointAddress = USB_EP_IN(3), + .bmAttributes = USB_EP_ATTR_TT_BULK, + .wMaxPacketSize = htousbs(PIOS_USB_BOARD_CDC_DATA_LENGTH), + .bInterval = 0, /* ms */ + }, + .cdc_out = { + .bLength = sizeof(struct usb_endpoint_desc), + .bDescriptorType = USB_DESC_TYPE_ENDPOINT, + .bEndpointAddress = USB_EP_OUT(3), + .bmAttributes = USB_EP_ATTR_TT_BULK, /* Bulk */ + .wMaxPacketSize = htousbs(PIOS_USB_BOARD_CDC_DATA_LENGTH), + .bInterval = 0, /* ms */ + }, .hid_if = { .bLength = sizeof(struct usb_interface_desc), .bDescriptorType = USB_DESC_TYPE_INTERFACE, - .bInterfaceNumber = 0, + .bInterfaceNumber = 2, .bAlternateSetting = 0, .bNumEndpoints = 2, .bInterfaceClass = USB_INTERFACE_CLASS_HID, @@ -170,78 +242,6 @@ static const struct usb_config_hid_cdc config_hid_cdc = { .wMaxPacketSize = htousbs(PIOS_USB_BOARD_HID_DATA_LENGTH), .bInterval = 4, /* ms */ }, - .cdc_control_if = { - .bLength = sizeof(struct usb_interface_desc), - .bDescriptorType = USB_DESC_TYPE_INTERFACE, - .bInterfaceNumber = 1, - .bAlternateSetting = 0, - .bNumEndpoints = 1, - .bInterfaceClass = USB_INTERFACE_CLASS_CDC, - .bInterfaceSubClass = 2, /* Abstract Control Model */ - .nInterfaceProtocol = 1, /* V.25ter, Common AT commands */ - .iInterface = 0, - }, - .cdc_header = { - .bLength = sizeof(struct usb_cdc_header_func_desc), - .bDescriptorType = USB_DESC_TYPE_CLASS_SPECIFIC, - .bDescriptorSubType = USB_CDC_DESC_SUBTYPE_HEADER, - .bcdCDC = htousbs(0x0110), - }, - .cdc_callmgmt = { - .bLength = sizeof(struct usb_cdc_callmgmt_func_desc), - .bDescriptorType = USB_DESC_TYPE_CLASS_SPECIFIC, - .bDescriptorSubType = USB_CDC_DESC_SUBTYPE_CALLMGMT, - .bmCapabilities = 0x00, /* No call handling */ - .bDataInterface = 2, - }, - .cdc_acm = { - .bLength = sizeof(struct usb_cdc_acm_func_desc), - .bDescriptorType = USB_DESC_TYPE_CLASS_SPECIFIC, - .bDescriptorSubType = USB_CDC_DESC_SUBTYPE_ABSTRACT_CTRL, - .bmCapabilities = 0, - }, - .cdc_union = { - .bLength = sizeof(struct usb_cdc_union_func_desc), - .bDescriptorType = USB_DESC_TYPE_CLASS_SPECIFIC, - .bDescriptorSubType = USB_CDC_DESC_SUBTYPE_UNION, - .bMasterInterface = 1, - .bSlaveInterface = 2, - }, - .cdc_mgmt_in = { - .bLength = sizeof(struct usb_endpoint_desc), - .bDescriptorType = USB_DESC_TYPE_ENDPOINT, - .bEndpointAddress = USB_EP_IN(2), - .bmAttributes = USB_EP_ATTR_TT_INTERRUPT, - .wMaxPacketSize = htousbs(PIOS_USB_BOARD_CDC_MGMT_LENGTH), - .bInterval = 4, /* ms */ - }, - .cdc_data_if = { - .bLength = sizeof(struct usb_interface_desc), - .bDescriptorType = USB_DESC_TYPE_INTERFACE, - .bInterfaceNumber = 2, - .bAlternateSetting = 0, - .bNumEndpoints = 2, - .bInterfaceClass = USB_INTERFACE_CLASS_DATA, - .bInterfaceSubClass = 0, - .nInterfaceProtocol = 0, /* No class specific protocol */ - .iInterface = 0, - }, - .cdc_in = { - .bLength = sizeof(struct usb_endpoint_desc), - .bDescriptorType = USB_DESC_TYPE_ENDPOINT, - .bEndpointAddress = USB_EP_IN(3), - .bmAttributes = USB_EP_ATTR_TT_BULK, - .wMaxPacketSize = htousbs(PIOS_USB_BOARD_CDC_DATA_LENGTH), - .bInterval = 0, /* ms */ - }, - .cdc_out = { - .bLength = sizeof(struct usb_endpoint_desc), - .bDescriptorType = USB_DESC_TYPE_ENDPOINT, - .bEndpointAddress = USB_EP_OUT(3), - .bmAttributes = USB_EP_ATTR_TT_BULK, /* Bulk */ - .wMaxPacketSize = htousbs(PIOS_USB_BOARD_CDC_DATA_LENGTH), - .bInterval = 0, /* ms */ - }, }; int32_t PIOS_USB_DESC_HID_CDC_Init(void) diff --git a/flight/PipXtreme/inc/ppm.h b/flight/PiOS/Common/pios_usb_util.c similarity index 67% rename from flight/PipXtreme/inc/ppm.h rename to flight/PiOS/Common/pios_usb_util.c index a2163292a..6949bd004 100644 --- a/flight/PipXtreme/inc/ppm.h +++ b/flight/PiOS/Common/pios_usb_util.c @@ -1,9 +1,14 @@ /** ****************************************************************************** + * @addtogroup PIOS PIOS Core hardware abstraction layer + * @{ + * @addtogroup PIOS_USB_UTIL USB utility functions + * @brief USB utility functions + * @{ * - * @file ppm.h - * @author The OpenPilot Team, http://www.openpilot.org Copyright (C) 2010. - * @brief Sends or Receives the ppm values to/from the remote unit + * @file pios_usb_util.c + * @author The OpenPilot Team, http://www.openpilot.org Copyright (C) 2012. + * @brief USB utility functions * @see The GNU Public License (GPL) Version 3 * *****************************************************************************/ @@ -23,18 +28,15 @@ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ -#ifndef PPM_H_ -#define PPM_H_ +#include "pios_usb_util.h" -#include "stdint.h" +uint8_t * PIOS_USB_UTIL_AsciiToUtf8(uint8_t * dst, uint8_t * src, uint16_t srclen) +{ + for (uint8_t i = 0; i < srclen; i++) { + *dst = *src; + dst += 2; + src += 1; + } -// ************************************************************* - -void ppm_1ms_tick(void); -void ppm_process(void); -void ppm_deinit(void); -void ppm_init(uint32_t our_sn); - -// ************************************************************* - -#endif + return dst; +} diff --git a/flight/PiOS/STM32F10x/link_STM32103CB_PIPXTREME_BL_sections.ld b/flight/PiOS/STM32F10x/link_STM32103CB_PIPXTREME_BL_sections.ld index 69eaadb8c..777e09aa6 100644 --- a/flight/PiOS/STM32F10x/link_STM32103CB_PIPXTREME_BL_sections.ld +++ b/flight/PiOS/STM32F10x/link_STM32103CB_PIPXTREME_BL_sections.ld @@ -3,7 +3,8 @@ PROVIDE ( vPortSVCHandler = 0 ) ; PROVIDE ( xPortPendSVHandler = 0 ) ; PROVIDE ( xPortSysTickHandler = 0 ) ; -_estack = 0x20004FF0; +/* This is the size of the stack for early init and for all FreeRTOS IRQs */ +_irq_stack_size = 0x400; /* Section Definitions */ SECTIONS @@ -49,6 +50,24 @@ SECTIONS _ebss = . ; } > SRAM + /* + * This stack is used both as the initial sp during early init as well as ultimately + * being used as the STM32's MSP (Main Stack Pointer) which is the same stack that + * is used for _all_ interrupt handlers. The end of this stack should be placed + * against the lowest address in RAM so that a stack overrun results in a hard fault + * at the first access beyond the end of the stack. + */ + .irq_stack : + { + . = ALIGN(4); + _irq_stack_end = . ; + . = . + _irq_stack_size ; + . = ALIGN(4); + _irq_stack_top = . - 4 ; + _init_stack_top = _irq_stack_top; + . = ALIGN(4); + } > SRAM + . = ALIGN(4); _end = . ; @@ -56,6 +75,39 @@ SECTIONS { . = ALIGN(4); KEEP(*(.boardinfo)) - . = ALIGN(4); } > BD_INFO + + /* Stabs debugging sections. */ + .stab 0 : { *(.stab) } + .stabstr 0 : { *(.stabstr) } + .stab.excl 0 : { *(.stab.excl) } + .stab.exclstr 0 : { *(.stab.exclstr) } + .stab.index 0 : { *(.stab.index) } + .stab.indexstr 0 : { *(.stab.indexstr) } + .comment 0 : { *(.comment) } + /* DWARF debug sections. + Symbols in the DWARF debugging sections are relative to the beginning + of the section so we begin them at 0. */ + /* DWARF 1 */ + .debug 0 : { *(.debug) } + .line 0 : { *(.line) } + /* GNU DWARF 1 extensions */ + .debug_srcinfo 0 : { *(.debug_srcinfo) } + .debug_sfnames 0 : { *(.debug_sfnames) } + /* DWARF 1.1 and DWARF 2 */ + .debug_aranges 0 : { *(.debug_aranges) } + .debug_pubnames 0 : { *(.debug_pubnames) } + /* DWARF 2 */ + .debug_info 0 : { *(.debug_info .gnu.linkonce.wi.*) } + .debug_abbrev 0 : { *(.debug_abbrev) } + .debug_line 0 : { *(.debug_line) } + .debug_frame 0 : { *(.debug_frame) } + .debug_str 0 : { *(.debug_str) } + .debug_loc 0 : { *(.debug_loc) } + .debug_macinfo 0 : { *(.debug_macinfo) } + /* SGI/MIPS DWARF 2 extensions */ + .debug_weaknames 0 : { *(.debug_weaknames) } + .debug_funcnames 0 : { *(.debug_funcnames) } + .debug_typenames 0 : { *(.debug_typenames) } + .debug_varnames 0 : { *(.debug_varnames) } } diff --git a/flight/PiOS/STM32F10x/link_STM32103CB_PIPXTREME_sections.ld b/flight/PiOS/STM32F10x/link_STM32103CB_PIPXTREME_sections.ld index badf5f986..568dddffa 100644 --- a/flight/PiOS/STM32F10x/link_STM32103CB_PIPXTREME_sections.ld +++ b/flight/PiOS/STM32F10x/link_STM32103CB_PIPXTREME_sections.ld @@ -1,3 +1,8 @@ +/* This is the size of the stack for all FreeRTOS IRQs */ +_irq_stack_size = 0x1A0; +/* This is the size of the stack for early init: life span is until scheduler starts */ +_init_stack_size = 0x100; + /* Stub out these functions since we don't use them anyway */ PROVIDE ( vPortSVCHandler = 0 ) ; PROVIDE ( xPortPendSVHandler = 0 ) ; @@ -5,8 +10,6 @@ PROVIDE ( xPortSysTickHandler = 0 ) ; PROVIDE(pios_board_info_blob = ORIGIN(BD_INFO)); -_estack = 0x20004FF0; - /* Section Definitions */ SECTIONS { @@ -19,6 +22,16 @@ SECTIONS *(.rodata .rodata* .gnu.linkonce.r.*) } > FLASH + /* module sections */ + .initcallmodule.init : + { + . = ALIGN(4); + __module_initcall_start = .; + KEEP(*(.initcallmodule.init)) + . = ALIGN(4); + __module_initcall_end = .; + } >FLASH + .ARM.extab : { *(.ARM.extab* .gnu.linkonce.armextab.*) @@ -33,6 +46,23 @@ SECTIONS _etext = .; _sidata = .; + /* + * This stack is used both as the initial sp during early init as well as ultimately + * being used as the STM32's MSP (Main Stack Pointer) which is the same stack that + * is used for _all_ interrupt handlers. The end of this stack should be placed + * against the lowest address in RAM so that a stack overrun results in a hard fault + * at the first access beyond the end of the stack. + */ + .irq_stack : + { + . = ALIGN(4); + _irq_stack_end = . ; + . = . + _irq_stack_size ; + . = ALIGN(4); + _irq_stack_top = . - 4 ; + . = ALIGN(4); + } > SRAM + .data : AT (_etext) { _sdata = .; @@ -41,16 +71,81 @@ SECTIONS _edata = . ; } > SRAM + + /* .bss section which is used for uninitialized data */ .bss (NOLOAD) : { _sbss = . ; *(.bss .bss.*) *(COMMON) - . = ALIGN(4); - _ebss = . ; } > SRAM - . = ALIGN(4); - _end = . ; + .heap (NOLOAD) : + { + . = ALIGN(4); + _sheap = . ; + _sheap_pre_rtos = . ; + *(.heap) + . = ALIGN(4); + _eheap = . ; + _eheap_pre_rtos = . ; + _init_stack_end = . ; + _sheap_post_rtos = . ; + . = . + _init_stack_size ; + . = ALIGN(4); + _eheap_post_rtos = . ; + _init_stack_top = . - 4 ; + } > SRAM + + + _free_ram = . ; + .free_ram (NOLOAD) : + { + . = ORIGIN(SRAM) + LENGTH(SRAM) - _free_ram ; + /* This is used by the startup in order to initialize the .bss section */ + _ebss = . ; + _eram = . ; + } > SRAM + + /* keep the heap section at the end of the SRAM + * this will allow to claim the remaining bytes not used + * at run time! (done by the reset vector). + */ + + PROVIDE ( _end = _ebss ) ; + + /* Stabs debugging sections. */ + .stab 0 : { *(.stab) } + .stabstr 0 : { *(.stabstr) } + .stab.excl 0 : { *(.stab.excl) } + .stab.exclstr 0 : { *(.stab.exclstr) } + .stab.index 0 : { *(.stab.index) } + .stab.indexstr 0 : { *(.stab.indexstr) } + .comment 0 : { *(.comment) } + /* DWARF debug sections. + Symbols in the DWARF debugging sections are relative to the beginning + of the section so we begin them at 0. */ + /* DWARF 1 */ + .debug 0 : { *(.debug) } + .line 0 : { *(.line) } + /* GNU DWARF 1 extensions */ + .debug_srcinfo 0 : { *(.debug_srcinfo) } + .debug_sfnames 0 : { *(.debug_sfnames) } + /* DWARF 1.1 and DWARF 2 */ + .debug_aranges 0 : { *(.debug_aranges) } + .debug_pubnames 0 : { *(.debug_pubnames) } + /* DWARF 2 */ + .debug_info 0 : { *(.debug_info .gnu.linkonce.wi.*) } + .debug_abbrev 0 : { *(.debug_abbrev) } + .debug_line 0 : { *(.debug_line) } + .debug_frame 0 : { *(.debug_frame) } + .debug_str 0 : { *(.debug_str) } + .debug_loc 0 : { *(.debug_loc) } + .debug_macinfo 0 : { *(.debug_macinfo) } + /* SGI/MIPS DWARF 2 extensions */ + .debug_weaknames 0 : { *(.debug_weaknames) } + .debug_funcnames 0 : { *(.debug_funcnames) } + .debug_typenames 0 : { *(.debug_typenames) } + .debug_varnames 0 : { *(.debug_varnames) } } diff --git a/flight/PiOS/STM32F10x/pios_eeprom.c b/flight/PiOS/STM32F10x/pios_eeprom.c new file mode 100644 index 000000000..f604f417b --- /dev/null +++ b/flight/PiOS/STM32F10x/pios_eeprom.c @@ -0,0 +1,155 @@ +/** +****************************************************************************** +* @addtogroup PIOS PIOS Core hardware abstraction layer +* @{ +* @addtogroup PIOS_EEPROM EEPROM reading/writing functions +* @brief PIOS EEPROM reading/writing functions +* @{ +* +* @file pios_eeprom.c +* @author The OpenPilot Team, http://www.openpilot.org Copyright (C) 2012. +* @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 +#include +#include +#include + +#include + +static struct pios_eeprom_cfg config; + +/** + * Initialize the flash eeprom device + * \param cfg The configuration structure. + */ +void PIOS_EEPROM_Init(const struct pios_eeprom_cfg *cfg) +{ + config = *cfg; +} + +/** + * Save a block of data to the flash eeprom device. + * \param data A pointer to the data to write. + * \param len The length of data to write. + * \return 0 on sucess + */ +int32_t PIOS_EEPROM_Save(uint8_t *data, uint32_t len) +{ + + // We need to write 32 bit words, so extend the length to be an even multiple of 4 bytes, + // and include 4 bytes for the 32 bit CRC. + uint32_t nwords = (len / 4) + 1 + (len % 4 ? 1 : 0); + uint32_t size = nwords * 4; + + // Ensure that the length is not longer than the max size. + if (size > config.max_size) + return -1; + + // Calculate a 32 bit CRC of the data. + uint32_t crc = PIOS_CRC32_updateCRC(0xffffffff, data, len); + + // Unlock the Flash Program Erase controller + FLASH_Unlock(); + + // See if we have to write the data. + if ((memcmp(data, (uint8_t*)config.base_address, len) == 0) && + (memcmp((uint8_t*)&crc, (uint8_t*)config.base_address + size - 4, 4) == 0)) + return 0; + + // TODO: Check that the area isn't already erased + + // Erase page + FLASH_Status fs = FLASH_ErasePage(config.base_address); + if (fs != FLASH_COMPLETE) + { // error + FLASH_Lock(); + return -2; + } + + // write 4 bytes at a time into program flash area (emulated EEPROM area) + uint8_t *p1 = data; + uint32_t *p3 = (uint32_t *)config.base_address; + for (int32_t i = 0; i < size; p3++) + { + uint32_t value = 0; + + if (i == (size - 4)) + { + // write the CRC. + value = crc; + i += 4; + } + else + { + if (i < len) value |= (uint32_t)*p1++ << 0; else value |= 0x000000ff; i++; + if (i < len) value |= (uint32_t)*p1++ << 8; else value |= 0x0000ff00; i++; + if (i < len) value |= (uint32_t)*p1++ << 16; else value |= 0x00ff0000; i++; + if (i < len) value |= (uint32_t)*p1++ << 24; else value |= 0xff000000; i++; + } + + // write a 32-bit value + fs = FLASH_ProgramWord((uint32_t)p3, value); + if (fs != FLASH_COMPLETE) + { + FLASH_Lock(); + return -3; + } + } + + // Lock the Flash Program Erase controller + FLASH_Lock(); + + return 0; +} + +/** + * Reads a block of data from the flash eeprom device. + * \param data A pointer to the output data buffer. + * \param len The length of data to read. + * \return 0 on sucess + */ +int32_t PIOS_EEPROM_Load(uint8_t *data, uint32_t len) +{ + + // We need to write 32 bit words, so the length should have been extended + // to an even multiple of 4 bytes, and should include 4 bytes for the 32 bit CRC. + uint32_t nwords = (len / 4) + 1 + (len % 4 ? 1 : 0); + uint32_t size = nwords * 4; + + // Ensure that the length is not longer than the max size. + if (size > config.max_size) + return -1; + + // Read the data from flash. + memcpy(data, (uint8_t*)config.base_address, len); + + // Read the CRC. + uint32_t crc_flash = *((uint32_t*)(config.base_address + size - 4)); + + // Calculate a 32 bit CRC of the data. + uint32_t crc = PIOS_CRC32_updateCRC(0xffffffff, data, len); + if(crc != crc_flash) + return -2; + + return 0; +} diff --git a/flight/PiOS/STM32F10x/pios_sys.c b/flight/PiOS/STM32F10x/pios_sys.c index 04d79c45b..6b59afbad 100644 --- a/flight/PiOS/STM32F10x/pios_sys.c +++ b/flight/PiOS/STM32F10x/pios_sys.c @@ -118,8 +118,8 @@ uint32_t PIOS_SYS_getCPUFlashSize(void) /** * 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) +* param[out] uint8_t pointer to a string which can store at least 12 bytes +* (12 bytes returned for STM32) * return < 0 if feature not supported */ int32_t PIOS_SYS_SerialNumberGetBinary(uint8_t *array) @@ -127,7 +127,7 @@ int32_t PIOS_SYS_SerialNumberGetBinary(uint8_t *array) int i; /* Stored in the so called "electronic signature" */ - for (i = 0; i < 12; ++i) { + for (i = 0; i < PIOS_SYS_SERIAL_NUM_BINARY_LEN; ++i) { uint8_t b = MEM8(0x1ffff7e8 + i); array[i] = b; @@ -148,7 +148,7 @@ int32_t PIOS_SYS_SerialNumberGet(char *str) int i; /* Stored in the so called "electronic signature" */ - for (i = 0; i < 24; ++i) { + for (i = 0; i < PIOS_SYS_SERIAL_NUM_ASCII_LEN; ++i) { uint8_t b = MEM8(0x1ffff7e8 + (i / 2)); if (!(i & 1)) b >>= 4; diff --git a/flight/PiOS/STM32F10x/pios_usb.c b/flight/PiOS/STM32F10x/pios_usb.c index c7b2855da..edac4611a 100644 --- a/flight/PiOS/STM32F10x/pios_usb.c +++ b/flight/PiOS/STM32F10x/pios_usb.c @@ -40,7 +40,7 @@ #if defined(PIOS_INCLUDE_USB_HID) /* Rx/Tx status */ -static uint8_t transfer_possible = 0; +static bool transfer_possible = false; enum pios_usb_dev_magic { PIOS_USB_DEV_MAGIC = 0x17365904, @@ -152,7 +152,7 @@ int32_t PIOS_USB_ChangeConnectionState(bool Connected) { // In all cases: re-initialise USB HID driver if (Connected) { - transfer_possible = 1; + transfer_possible = true; //TODO: Check SetEPRxValid(ENDP1); @@ -161,7 +161,7 @@ int32_t PIOS_USB_ChangeConnectionState(bool Connected) #endif } else { // Cable disconnected: disable transfers - transfer_possible = 0; + transfer_possible = false; #if defined(USB_LED_OFF) USB_LED_OFF; // turn the USB led off @@ -207,23 +207,30 @@ int32_t PIOS_USB_Reenumerate() return 0; } +bool PIOS_USB_CableConnected(uint8_t id) +{ + struct pios_usb_dev * usb_dev = (struct pios_usb_dev *) pios_usb_com_id; + + if (PIOS_USB_validate(usb_dev) != 0) + return false; + + return usb_dev->cfg->vsense.gpio->IDR & usb_dev->cfg->vsense.init.GPIO_Pin; +} + /** * This function returns the connection status of the USB HID interface * \return 1: interface available * \return 0: interface not available * \note Applications shouldn't call this function directly, instead please use \ref PIOS_COM layer functions */ -uint32_t usb_found; bool PIOS_USB_CheckAvailable(uint8_t id) { struct pios_usb_dev * usb_dev = (struct pios_usb_dev *) pios_usb_com_id; - if(PIOS_USB_validate(usb_dev) != 0) - return 0; + if (PIOS_USB_validate(usb_dev) != 0) + return false; - usb_found = (usb_dev->cfg->vsense.gpio->IDR & usb_dev->cfg->vsense.init.GPIO_Pin); - return usb_found; - return usb_found != 0 && transfer_possible ? 1 : 0; + return PIOS_USB_CableConnected(id) && transfer_possible; } #endif diff --git a/flight/PiOS/STM32F10x/pios_usbhook.c b/flight/PiOS/STM32F10x/pios_usbhook.c index c6a952498..cb3220227 100644 --- a/flight/PiOS/STM32F10x/pios_usbhook.c +++ b/flight/PiOS/STM32F10x/pios_usbhook.c @@ -304,7 +304,11 @@ static RESULT PIOS_USBHOOK_Data_Setup(uint8_t RequestNo) switch (Type_Recipient) { case (STANDARD_REQUEST | INTERFACE_RECIPIENT): switch (pInformation->USBwIndex0) { +#if defined(PIOS_INCLUDE_USB_CDC) + case 2: /* HID Interface */ +#else case 0: /* HID Interface */ +#endif switch (RequestNo) { case GET_DESCRIPTOR: switch (pInformation->USBwValue1) { @@ -321,7 +325,11 @@ static RESULT PIOS_USBHOOK_Data_Setup(uint8_t RequestNo) case (CLASS_REQUEST | INTERFACE_RECIPIENT): switch (pInformation->USBwIndex0) { +#if defined(PIOS_INCLUDE_USB_CDC) + case 2: /* HID Interface */ +#else case 0: /* HID Interface */ +#endif switch (RequestNo) { case USB_HID_REQ_GET_PROTOCOL: CopyRoutine = PIOS_USBHOOK_GetProtocolValue; @@ -330,16 +338,16 @@ static RESULT PIOS_USBHOOK_Data_Setup(uint8_t RequestNo) break; #if defined(PIOS_INCLUDE_USB_CDC) - case 1: /* CDC Call Control Interface */ + case 0: /* CDC Call Control Interface */ switch (RequestNo) { case USB_CDC_REQ_GET_LINE_CODING: - CopyRoutine = PIOS_USB_CDC_GetLineCoding; + //CopyRoutine = PIOS_USB_CDC_GetLineCoding; break; } break; - case 2: /* CDC Data Interface */ + case 1: /* CDC Data Interface */ switch (RequestNo) { case 0: break; @@ -376,7 +384,11 @@ static RESULT PIOS_USBHOOK_NoData_Setup(uint8_t RequestNo) switch (Type_Recipient) { case (CLASS_REQUEST | INTERFACE_RECIPIENT): switch (pInformation->USBwIndex0) { +#if defined(PIOS_INCLUDE_USB_CDC) + case 2: /* HID */ +#else case 0: /* HID */ +#endif switch (RequestNo) { case USB_HID_REQ_SET_PROTOCOL: return PIOS_USBHOOK_SetProtocol(); @@ -386,7 +398,7 @@ static RESULT PIOS_USBHOOK_NoData_Setup(uint8_t RequestNo) break; #if defined(PIOS_INCLUDE_USB_CDC) - case 1: /* CDC Call Control Interface */ + case 0: /* CDC Call Control Interface */ switch (RequestNo) { case USB_CDC_REQ_SET_LINE_CODING: return PIOS_USB_CDC_SetLineCoding(); diff --git a/flight/PiOS/STM32F10x/startup_stm32f10x_MD_PX.S b/flight/PiOS/STM32F10x/startup_stm32f10x_MD_PX.S new file mode 100644 index 000000000..828462ab6 --- /dev/null +++ b/flight/PiOS/STM32F10x/startup_stm32f10x_MD_PX.S @@ -0,0 +1,427 @@ +/** + ****************************************************************************** + * @file startup_stm32f10x_md.s + * @author MCD Application Team / Angus Peart + * @version V3.1.2 + * @date 09/28/2009 + * @brief STM32F10x Medium Density Devices vector table for RIDE7 toolchain. + * This module performs: + * - Set the initial SP + * - Set the initial PC == Reset_Handler, + * - Set the vector table entries with the exceptions ISR address + * - Branches to main in the C library (which eventually + * calls main()). + * After Reset the Cortex-M3 processor is in Thread mode, + * priority is Privileged, and the Stack is set to Main. + ******************************************************************************* + * @copy + * + * THE PRESENT FIRMWARE WHICH IS FOR GUIDANCE ONLY AIMS AT PROVIDING CUSTOMERS + * WITH CODING INFORMATION REGARDING THEIR PRODUCTS IN ORDER FOR THEM TO SAVE + * TIME. AS A RESULT, STMICROELECTRONICS SHALL NOT BE HELD LIABLE FOR ANY + * DIRECT, INDIRECT OR CONSEQUENTIAL DAMAGES WITH RESPECT TO ANY CLAIMS ARISING + * FROM THE CONTENT OF SUCH FIRMWARE AND/OR THE USE MADE BY CUSTOMERS OF THE + * CODING INFORMATION CONTAINED HEREIN IN CONNECTION WITH THEIR PRODUCTS. + * + *

© COPYRIGHT 2009 STMicroelectronics

+ */ + + .syntax unified + .cpu cortex-m3 + .fpu softvfp + .thumb + +.global g_pfnVectors +.global Default_Handler +.global xPortIncreaseHeapSize +.global Stack_Change + +/* start address for the initialization values of the .data section. +defined in linker script */ +.word _sidata +/* start address for the .data section. defined in linker script */ +.word _sdata +/* end address for the .data section. defined in linker script */ +.word _edata +/* start address for the .bss section. defined in linker script */ +.word _sbss +/* end address for the .bss section. defined in linker script */ +.word _ebss + +.equ BootRAM, 0xF108F85F +/** + * @brief This is the code that gets called when the processor first + * starts execution following a reset event. Only the absolutely + * necessary set is performed, after which the application + * supplied main() routine is called. + * @param None + * @retval : None +*/ + + .section .text.Reset_Handler + .weak Reset_Handler + .type Reset_Handler, %function +Reset_Handler: + +/* + * From COrtex-M3 reference manual: + * - Handler IRQ always use SP_main + * - Process use SP_main or SP_process + * Here, we will use beginning of SRAM for IRQ (SP_main) + * and end of heap for initialization (SP_process). + * Once the schedule starts, all threads will use their own stack + * from heap and NOBOBY should use SP_process again. + */ + /* Do set/reset the stack pointers */ + LDR r0, =_irq_stack_top + MSR msp, r0 + LDR r2, =_init_stack_top + MSR psp, r2 + /* check if irq and init stack are the same */ + /* if they are, we don't do stack swap */ + /* and lets bypass the monitoring as well for now */ + cmp r0, r2 + beq SectionBssInit +/* DO + * - stay in thread process mode + * - stay in privilege level + * - use process stack + */ + movs r0, #2 + MSR control, r0 + ISB +/* Fill IRQ stack for watermark monitoring */ + ldr r2, =_irq_stack_end + b LoopFillIRQStack + +FillIRQStack: + movw r3, #0xA5A5 + str r3, [r2], #4 + +LoopFillIRQStack: + ldr r3, = _irq_stack_top + cmp r2, r3 + bcc FillIRQStack + +SectionBssInit: +/* Copy the data segment initializers from flash to SRAM */ + movs r1, #0 + b LoopCopyDataInit + +CopyDataInit: + ldr r3, =_sidata + ldr r3, [r3, r1] + str r3, [r0, r1] + adds r1, r1, #4 + +LoopCopyDataInit: + ldr r0, =_sdata + ldr r3, =_edata + adds r2, r0, r1 + cmp r2, r3 + bcc CopyDataInit + ldr r2, =_sbss + b LoopFillZerobss +/* Zero fill the bss segment. */ +FillZerobss: + movs r3, #0 + str r3, [r2], #4 + +LoopFillZerobss: + ldr r3, = _ebss + cmp r2, r3 + bcc FillZerobss +/* Call the application's entry point.*/ + bl main +/* will never return here */ + bx lr +.size Reset_Handler, .-Reset_Handler + +/** + * @brief This is the code that swaps stack (from end of heap to irq_stack). + * Also reclaim the heap that was used as a stack. + * @param None + * @retval : None +*/ + .section .text.Stack_Change + .weak Stack_Change + .type Stack_Change, %function +Stack_Change: + mov r4, lr +/* Switches stack back momentarily to MSP */ + movs r0, #0 + msr control, r0 +Heap_Reclaim: +/* add heap_post_rtos to the heap (if the capability/function exist) */ +/* Also claim the unused memory (between end of heap to end of memory */ +/* CAREFULL: the heap section must be the last section in RAM in order this to work */ + ldr r0, = _init_stack_size + ldr r1, = _eheap_post_rtos + ldr r2, = _eram + subs r2, r2, r1 + adds r0, r0, r2 + bl xPortIncreaseHeapSize + bx r4 + .size Stack_Change, .-Stack_Change + + +/** + * @brief This is the code that gets called when the processor receives an + * unexpected interrupt. This simply enters an infinite loop, preserving + * the system state for examination by a debugger. + * + * @param None + * @retval : None +*/ + .section .text.Default_Handler,"ax",%progbits +Default_Handler: +Infinite_Loop: + b Infinite_Loop + .size Default_Handler, .-Default_Handler +/****************************************************************************** +* +* The minimal vector table for a Cortex M3. Note that the proper constructs +* must be placed on this to ensure that it ends up at physical address +* 0x0000.0000. +* +******************************************************************************/ + .section .isr_vector,"a",%progbits + .type g_pfnVectors, %object + .size g_pfnVectors, .-g_pfnVectors + + +g_pfnVectors: + .word _irq_stack_top + .word Reset_Handler + .word NMI_Handler + .word HardFault_Handler + .word MemManage_Handler + .word BusFault_Handler + .word UsageFault_Handler + .word 0 + .word 0 + .word 0 + .word 0 + .word vPortSVCHandler + .word DebugMon_Handler + .word 0 + .word xPortPendSVHandler + .word xPortSysTickHandler + .word WWDG_IRQHandler + .word PVD_IRQHandler + .word TAMPER_IRQHandler + .word RTC_IRQHandler + .word FLASH_IRQHandler + .word RCC_IRQHandler + .word EXTI0_IRQHandler + .word EXTI1_IRQHandler + .word EXTI2_IRQHandler + .word EXTI3_IRQHandler + .word EXTI4_IRQHandler + .word DMA1_Channel1_IRQHandler + .word DMA1_Channel2_IRQHandler + .word DMA1_Channel3_IRQHandler + .word DMA1_Channel4_IRQHandler + .word DMA1_Channel5_IRQHandler + .word DMA1_Channel6_IRQHandler + .word DMA1_Channel7_IRQHandler + .word ADC1_2_IRQHandler + .word USB_HP_CAN1_TX_IRQHandler + .word USB_LP_CAN1_RX0_IRQHandler + .word CAN1_RX1_IRQHandler + .word CAN1_SCE_IRQHandler + .word EXTI9_5_IRQHandler + .word TIM1_BRK_IRQHandler + .word TIM1_UP_IRQHandler + .word TIM1_TRG_COM_IRQHandler + .word TIM1_CC_IRQHandler + .word TIM2_IRQHandler + .word TIM3_IRQHandler + .word TIM4_IRQHandler + .word I2C1_EV_IRQHandler + .word I2C1_ER_IRQHandler + .word I2C2_EV_IRQHandler + .word I2C2_ER_IRQHandler + .word SPI1_IRQHandler + .word SPI2_IRQHandler + .word USART1_IRQHandler + .word USART2_IRQHandler + .word USART3_IRQHandler + .word EXTI15_10_IRQHandler + .word RTCAlarm_IRQHandler + .word USBWakeUp_IRQHandler + .word 0 + .word 0 + .word 0 + .word 0 + .word 0 + .word 0 + .word 0 + .word BootRAM /* @0x108. This is for boot in RAM mode for + STM32F10x Medium Density devices. */ + +/******************************************************************************* +* +* Provide weak aliases for each Exception handler to the Default_Handler. +* As they are weak aliases, any function with the same name will override +* this definition. +* +*******************************************************************************/ + + .weak NMI_Handler + .thumb_set NMI_Handler,Default_Handler + + .weak HardFault_Handler + .thumb_set HardFault_Handler,Default_Handler + + .weak MemManage_Handler + .thumb_set MemManage_Handler,Default_Handler + + .weak BusFault_Handler + .thumb_set BusFault_Handler,Default_Handler + + .weak UsageFault_Handler + .thumb_set UsageFault_Handler,Default_Handler + + .weak SVC_Handler + .thumb_set SVC_Handler,Default_Handler + + .weak DebugMon_Handler + .thumb_set DebugMon_Handler,Default_Handler + + .weak PendSV_Handler + .thumb_set PendSV_Handler,Default_Handler + + .weak SysTick_Handler + .thumb_set SysTick_Handler,Default_Handler + + .weak WWDG_IRQHandler + .thumb_set WWDG_IRQHandler,Default_Handler + + .weak PVD_IRQHandler + .thumb_set PVD_IRQHandler,Default_Handler + + .weak TAMPER_IRQHandler + .thumb_set TAMPER_IRQHandler,Default_Handler + + .weak RTC_IRQHandler + .thumb_set RTC_IRQHandler,Default_Handler + + .weak FLASH_IRQHandler + .thumb_set FLASH_IRQHandler,Default_Handler + + .weak RCC_IRQHandler + .thumb_set RCC_IRQHandler,Default_Handler + + .weak EXTI0_IRQHandler + .thumb_set EXTI0_IRQHandler,Default_Handler + + .weak EXTI1_IRQHandler + .thumb_set EXTI1_IRQHandler,Default_Handler + + .weak EXTI2_IRQHandler + .thumb_set EXTI2_IRQHandler,Default_Handler + + .weak EXTI3_IRQHandler + .thumb_set EXTI3_IRQHandler,Default_Handler + + .weak EXTI4_IRQHandler + .thumb_set EXTI4_IRQHandler,Default_Handler + + .weak DMA1_Channel1_IRQHandler + .thumb_set DMA1_Channel1_IRQHandler,Default_Handler + + .weak DMA1_Channel2_IRQHandler + .thumb_set DMA1_Channel2_IRQHandler,Default_Handler + + .weak DMA1_Channel3_IRQHandler + .thumb_set DMA1_Channel3_IRQHandler,Default_Handler + + .weak DMA1_Channel4_IRQHandler + .thumb_set DMA1_Channel4_IRQHandler,Default_Handler + + .weak DMA1_Channel5_IRQHandler + .thumb_set DMA1_Channel5_IRQHandler,Default_Handler + + .weak DMA1_Channel6_IRQHandler + .thumb_set DMA1_Channel6_IRQHandler,Default_Handler + + .weak DMA1_Channel7_IRQHandler + .thumb_set DMA1_Channel7_IRQHandler,Default_Handler + + .weak ADC1_2_IRQHandler + .thumb_set ADC1_2_IRQHandler,Default_Handler + + .weak USB_HP_CAN1_TX_IRQHandler + .thumb_set USB_HP_CAN1_TX_IRQHandler,Default_Handler + + .weak USB_LP_CAN1_RX0_IRQHandler + .thumb_set USB_LP_CAN1_RX0_IRQHandler,Default_Handler + + .weak CAN1_RX1_IRQHandler + .thumb_set CAN1_RX1_IRQHandler,Default_Handler + + .weak CAN1_SCE_IRQHandler + .thumb_set CAN1_SCE_IRQHandler,Default_Handler + + .weak EXTI9_5_IRQHandler + .thumb_set EXTI9_5_IRQHandler,Default_Handler + + .weak TIM1_BRK_IRQHandler + .thumb_set TIM1_BRK_IRQHandler,Default_Handler + + .weak TIM1_UP_IRQHandler + .thumb_set TIM1_UP_IRQHandler,Default_Handler + + .weak TIM1_TRG_COM_IRQHandler + .thumb_set TIM1_TRG_COM_IRQHandler,Default_Handler + + .weak TIM1_CC_IRQHandler + .thumb_set TIM1_CC_IRQHandler,Default_Handler + + .weak TIM2_IRQHandler + .thumb_set TIM2_IRQHandler,Default_Handler + + .weak TIM3_IRQHandler + .thumb_set TIM3_IRQHandler,Default_Handler + + .weak TIM4_IRQHandler + .thumb_set TIM4_IRQHandler,Default_Handler + + .weak I2C1_EV_IRQHandler + .thumb_set I2C1_EV_IRQHandler,Default_Handler + + .weak I2C1_ER_IRQHandler + .thumb_set I2C1_ER_IRQHandler,Default_Handler + + .weak I2C2_EV_IRQHandler + .thumb_set I2C2_EV_IRQHandler,Default_Handler + + .weak I2C2_ER_IRQHandler + .thumb_set I2C2_ER_IRQHandler,Default_Handler + + .weak SPI1_IRQHandler + .thumb_set SPI1_IRQHandler,Default_Handler + + .weak SPI2_IRQHandler + .thumb_set SPI2_IRQHandler,Default_Handler + + .weak USART1_IRQHandler + .thumb_set USART1_IRQHandler,Default_Handler + + .weak USART2_IRQHandler + .thumb_set USART2_IRQHandler,Default_Handler + + .weak USART3_IRQHandler + .thumb_set USART3_IRQHandler,Default_Handler + + .weak EXTI15_10_IRQHandler + .thumb_set EXTI15_10_IRQHandler,Default_Handler + + .weak RTCAlarm_IRQHandler + .thumb_set RTCAlarm_IRQHandler,Default_Handler + + .weak USBWakeUp_IRQHandler + .thumb_set USBWakeUp_IRQHandler,Default_Handler + + diff --git a/flight/PiOS/inc/pios_board_info.h b/flight/PiOS/inc/pios_board_info.h index f2ff58fb4..3ff7aa886 100644 --- a/flight/PiOS/inc/pios_board_info.h +++ b/flight/PiOS/inc/pios_board_info.h @@ -1,3 +1,8 @@ +#ifndef PIOS_BOARD_INFO_H +#define PIOS_BOARD_INFO_H + +#include /* uint* */ + #define PIOS_BOARD_INFO_BLOB_MAGIC 0xBDBDBDBD struct pios_board_info { @@ -15,3 +20,5 @@ struct pios_board_info { } __attribute__((packed)); extern const struct pios_board_info pios_board_info_blob; + +#endif /* PIOS_BOARD_INFO_H */ diff --git a/flight/PiOS/inc/pios_crc.h b/flight/PiOS/inc/pios_crc.h index 3a64f8bab..612c89e49 100644 --- a/flight/PiOS/inc/pios_crc.h +++ b/flight/PiOS/inc/pios_crc.h @@ -29,3 +29,9 @@ 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); + +uint16_t PIOS_CRC16_updateByte(uint16_t crc, const uint8_t data); +uint16_t PIOS_CRC16_updateCRC(uint16_t crc, const uint8_t* data, int32_t length); + +uint32_t PIOS_CRC32_updateByte(uint32_t crc, const uint8_t data); +uint32_t PIOS_CRC32_updateCRC(uint32_t crc, const uint8_t* data, int32_t length); diff --git a/flight/PiOS/inc/pios_eeprom.h b/flight/PiOS/inc/pios_eeprom.h new file mode 100644 index 000000000..14acc595e --- /dev/null +++ b/flight/PiOS/inc/pios_eeprom.h @@ -0,0 +1,50 @@ +/** + ****************************************************************************** + * @addtogroup PIOS PIOS Core hardware abstraction layer + * @{ + * @addtogroup PIOS_EEPROM EEPROM reading/writing functions + * @brief PIOS EEPROM reading/writing functions + * @{ + * + * @file pios_eeprom.c + * @author The OpenPilot Team, http://www.openpilot.org Copyright (C) 2012. + * @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 + */ + +#ifndef PIOS_EEPROM_H +#define PIOS_EEPROM_H + +/* Public Structures */ +struct pios_eeprom_cfg { + uint32_t base_address; + uint32_t max_size; +}; + +/* Public Functions */ +extern void PIOS_EEPROM_Init(const struct pios_eeprom_cfg *cfg); +extern int32_t PIOS_EEPROM_Save(uint8_t *data, uint32_t len); +extern int32_t PIOS_EEPROM_Load(uint8_t *data, uint32_t len); + +#endif /* PIOS_EEPROM_H */ + +/** + * @} + * @} + */ diff --git a/flight/PiOS/inc/pios_rfm22b.h b/flight/PiOS/inc/pios_rfm22b.h new file mode 100644 index 000000000..aa00a835e --- /dev/null +++ b/flight/PiOS/inc/pios_rfm22b.h @@ -0,0 +1,55 @@ +/** + ****************************************************************************** + * @addtogroup PIOS PIOS Core hardware abstraction layer + * @{ + * @addtogroup PIOS_RFM22B Radio Functions + * @brief PIOS interface for RFM22B Radio + * @{ + * + * @file pios_rfm22b.h + * @author The OpenPilot Team, http://www.openpilot.org Copyright (C) 2012. + * @brief RFM22B 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_RFM22B_H +#define PIOS_RFM22B_H + +/* Global Types */ +struct pios_rfm22b_cfg { + uint32_t frequencyHz; + uint32_t minFrequencyHz; + uint32_t maxFrequencyHz; + uint8_t RFXtalCap; + uint32_t maxRFBandwidth; + uint8_t maxTxPower; +}; + +/* Public Functions */ +extern int32_t PIOS_RFM22B_Init(uint32_t *rfb22b_id, const struct pios_rfm22b_cfg *cfg); +extern uint32_t PIOS_RFM22B_DeviceID(uint32_t rfb22b_id); +extern int8_t PIOS_RFM22B_RSSI(uint32_t rfm22b_id); +extern int16_t PIOS_RFM22B_Resets(uint32_t rfm22b_id); + +#endif /* PIOS_RFM22B_H */ + +/** + * @} + * @} + */ diff --git a/flight/PipXtreme/inc/rfm22b.h b/flight/PiOS/inc/pios_rfm22b_priv.h similarity index 95% rename from flight/PipXtreme/inc/rfm22b.h rename to flight/PiOS/inc/pios_rfm22b_priv.h index 25ef47e96..792915546 100644 --- a/flight/PipXtreme/inc/rfm22b.h +++ b/flight/PiOS/inc/pios_rfm22b_priv.h @@ -1,9 +1,14 @@ /** ****************************************************************************** + * @addtogroup PIOS PIOS Core hardware abstraction layer + * @{ + * @addtogroup PIOS_RFM22B Radio Functions + * @brief PIOS interface for RFM22B Radio + * @{ * - * @file rfm22b.h - * @author The OpenPilot Team, http://www.openpilot.org Copyright (C) 2010. - * @brief RF Module hardware layer + * @file pios_rfm22b_priv.h + * @author The OpenPilot Team, http://www.openpilot.org Copyright (C) 2012. + * @brief RFM22B private definitions. * @see The GNU Public License (GPL) Version 3 * *****************************************************************************/ @@ -23,10 +28,14 @@ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ -#ifndef __RFM22B_H__ -#define __RFM22B_H__ +#ifndef PIOS_RFM22B_PRIV_H +#define PIOS_RFM22B_PRIV_H -#include "stdint.h" +#include +#include "fifo_buffer.h" +#include "pios_rfm22b.h" + +extern const struct pios_com_driver pios_rfm22b_com_driver; // ************************************ @@ -386,11 +395,13 @@ enum { RX_SCAN_SPECTRUM = 0, #define RFM22_header_cntl1_bcen_none 0x00 // No broadcast address enable. #define RFM22_header_cntl1_bcen_0 0x10 // Broadcast address enable for header byte 0. #define RFM22_header_cntl1_bcen_1 0x20 // Broadcast address enable for header byte 1. -#define RFM22_header_cntl1_bcen_01 0x30 // Broadcast address enable for header bytes 0 & 1. +#define RFM22_header_cntl1_bcen_2 0x40 // Broadcast address enable for header byte 2. +#define RFM22_header_cntl1_bcen_3 0x80 // Broadcast address enable for header byte 3. #define RFM22_header_cntl1_hdch_none 0x00 // No Received Header check #define RFM22_header_cntl1_hdch_0 0x01 // Received Header check for byte 0. #define RFM22_header_cntl1_hdch_1 0x02 // Received Header check for byte 1. -#define RFM22_header_cntl1_hdch_01 0x03 // Received Header check for bytes 0 & 1. +#define RFM22_header_cntl1_hdch_2 0x04 // Received Header check for byte 2. +#define RFM22_header_cntl1_hdch_3 0x08 // Received Header check for byte 3. #define RFM22_header_control2 0x33 // R/W #define RFM22_header_cntl2_prealen 0x01 // MSB of Preamble Length. See register Preamble Length. @@ -598,9 +609,9 @@ uint32_t rfm22_getDatarate(void); void rfm22_setRxMode(uint8_t mode, bool multi_packet_mode); -int16_t rfm22_getRSSI(void); +int8_t rfm22_getRSSI(void); -int16_t rfm22_receivedRSSI(void); +int8_t rfm22_receivedRSSI(void); int32_t rfm22_receivedAFCHz(void); uint16_t rfm22_receivedLength(void); uint8_t * rfm22_receivedPointer(void); @@ -628,7 +639,6 @@ bool rfm22_channelIsClear(void); bool rfm22_txReady(void); void rfm22_1ms_tick(void); -void rfm22_process(void); void rfm22_TxDataByte_SetCallback(t_rfm22_TxDataByteCallback new_function); void rfm22_RxData_SetCallback(t_rfm22_RxDataCallback new_function); @@ -636,8 +646,11 @@ void rfm22_RxData_SetCallback(t_rfm22_RxDataCallback new_function); int rfm22_init_scan_spectrum(uint32_t min_frequency_hz, uint32_t max_frequency_hz); int rfm22_init_tx_stream(uint32_t min_frequency_hz, uint32_t max_frequency_hz); int rfm22_init_rx_stream(uint32_t min_frequency_hz, uint32_t max_frequency_hz); -int rfm22_init_normal(uint32_t min_frequency_hz, uint32_t max_frequency_hz, uint32_t freq_hop_step_size); +int rfm22_init_normal(uint32_t id, uint32_t min_frequency_hz, uint32_t max_frequency_hz, uint32_t freq_hop_step_size); -// ************************************ +#endif /* PIOS_RFM22B_PRIV_H */ -#endif +/** + * @} + * @} + */ diff --git a/flight/PiOS/inc/pios_sys.h b/flight/PiOS/inc/pios_sys.h index 9407fa720..7f183a892 100644 --- a/flight/PiOS/inc/pios_sys.h +++ b/flight/PiOS/inc/pios_sys.h @@ -32,12 +32,15 @@ #ifndef PIOS_SYS_H #define PIOS_SYS_H +#define PIOS_SYS_SERIAL_NUM_BINARY_LEN 12 +#define PIOS_SYS_SERIAL_NUM_ASCII_LEN (PIOS_SYS_SERIAL_NUM_BINARY_LEN * 2) + /* Public Functions */ extern void PIOS_SYS_Init(void); extern int32_t PIOS_SYS_Reset(void); extern uint32_t PIOS_SYS_getCPUFlashSize(void); -extern int32_t PIOS_SYS_SerialNumberGetBinary(uint8_t *array); -extern int32_t PIOS_SYS_SerialNumberGet(char *str); +extern int32_t PIOS_SYS_SerialNumberGetBinary(uint8_t array[PIOS_SYS_SERIAL_NUM_BINARY_LEN]); +extern int32_t PIOS_SYS_SerialNumberGet(char str[PIOS_SYS_SERIAL_NUM_ASCII_LEN+1]); #endif /* PIOS_SYS_H */ diff --git a/flight/PiOS/inc/pios_usb.h b/flight/PiOS/inc/pios_usb.h index 76b8f01b4..ad63ae3a8 100644 --- a/flight/PiOS/inc/pios_usb.h +++ b/flight/PiOS/inc/pios_usb.h @@ -35,6 +35,7 @@ /* Global functions */ extern int32_t PIOS_USB_Reenumerate(); extern int32_t PIOS_USB_ChangeConnectionState(bool connected); +extern bool PIOS_USB_CableConnected(uint8_t id); extern bool PIOS_USB_CheckAvailable(uint8_t id); #endif /* PIOS_USB_H */ diff --git a/flight/PiOS/inc/pios_usb_defs.h b/flight/PiOS/inc/pios_usb_defs.h index f0352333f..be827a494 100644 --- a/flight/PiOS/inc/pios_usb_defs.h +++ b/flight/PiOS/inc/pios_usb_defs.h @@ -300,7 +300,7 @@ struct usb_cdc_union_func_desc { uint8_t bSlaveInterface; } __attribute__((packed)); -#define USB_LANGID_ENGLISH_UK 0x0809 +#define USB_LANGID_ENGLISH_US 0x0409 struct usb_string_langid { uint8_t bLength; diff --git a/flight/PipXtreme/inc/api_config.h b/flight/PiOS/inc/pios_usb_util.h similarity index 68% rename from flight/PipXtreme/inc/api_config.h rename to flight/PiOS/inc/pios_usb_util.h index 5fcc2e064..114cd9a70 100644 --- a/flight/PipXtreme/inc/api_config.h +++ b/flight/PiOS/inc/pios_usb_util.h @@ -1,9 +1,14 @@ /** ****************************************************************************** + * @addtogroup PIOS PIOS Core hardware abstraction layer + * @{ + * @addtogroup PIOS_USB_UTIL USB utility functions + * @brief USB utility functions + * @{ * - * @file api_config.h - * @author The OpenPilot Team, http://www.openpilot.org Copyright (C) 2010. - * @brief RF Module hardware layer + * @file pios_usb_util.h + * @author The OpenPilot Team, http://www.openpilot.org Copyright (C) 2012. + * @brief USB utility functions * @see The GNU Public License (GPL) Version 3 * *****************************************************************************/ @@ -23,18 +28,11 @@ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ -#ifndef __API_CONFIG_H__ -#define __API_CONFIG_H__ +#ifndef PIOS_USB_UTIL_H +#define PIOS_USB_UTIL_H -#include "stdint.h" +#include /* uint8_t */ -// ***************************************************************************** +uint8_t * PIOS_USB_UTIL_AsciiToUtf8(uint8_t * dst, uint8_t * src, uint16_t srclen); -void apiconfig_1ms_tick(void); -void apiconfig_process(void); - -void apiconfig_init(void); - -// ***************************************************************************** - -#endif +#endif /* PIOS_USB_UTIL_H */ diff --git a/flight/PipXtreme/Makefile b/flight/PipXtreme/Makefile index 8c18afcbd..9ef5e9842 100644 --- a/flight/PipXtreme/Makefile +++ b/flight/PipXtreme/Makefile @@ -1,24 +1,24 @@ ##### - # Project: OpenPilot Pip Modems - # - # - # Makefile for OpenPilot Pip Modem project + # Project: OpenPilot + # + # + # Makefile for OpenPilot project build PiOS and the AP. # # The OpenPilot Team, http://www.openpilot.org, Copyright (C) 2009. - # + # # - # 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 + # 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 + # + # 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., + # + # 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 ##### @@ -33,12 +33,29 @@ TARGET := fw_$(BOARD_NAME) # Directory for output files (lst, obj, dep, elf, sym, map, hex, bin etc.) OUTDIR := $(TOP)/build/$(TARGET) -# Debugging (YES/NO) ? +# Set developer code and compile options +# Set to YES to compile for debugging DEBUG ?= NO -# Use Code Sourcery toolchain (YES/NO) ? +# Include objects that are just nice information to show +DIAGNOSTICS ?= NO + +# Set to YES to build a FW version that will erase all flash memory +ERASE_FLASH ?= NO +# 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_GPS ?= NO + +USE_I2C ?= YES + +# Set to YES when using Code Sourcery toolchain CODE_SOURCERY ?= YES +# Remove command is different for Code Sourcery on Windows ifeq ($(CODE_SOURCERY), YES) REMOVE_CMD = cs-rm else @@ -47,56 +64,85 @@ endif FLASH_TOOL = OPENOCD -# Include the USB files (YES/NO) ? -USE_USB = YES +# List of modules to include +OPTMODULES = +MODULES = RadioComBridge # Paths -HOME_DIR = ./ -HOME_DIR_INC = $(HOME_DIR)/inc -PIOS = ../PiOS -PIOSINC = $(PIOS)/inc +OPSYSTEM = ./System +OPSYSTEMINC = $(OPSYSTEM)/inc +OPUAVTALK = ../UAVTalk +OPUAVTALKINC = $(OPUAVTALK)/inc +OPUAVOBJ = ../UAVObjects +OPUAVOBJINC = $(OPUAVOBJ)/inc +OPTESTS = ./Tests +OPMODULEDIR = ../Modules FLIGHTLIB = ../Libraries FLIGHTLIBINC = $(FLIGHTLIB)/inc +RSCODEINC = $(FLIGHTLIB)/rscode +PIOS = ../PiOS +PIOSINC = $(PIOS)/inc PIOSSTM32F10X = $(PIOS)/STM32F10x PIOSCOMMON = $(PIOS)/Common PIOSBOARDS = $(PIOS)/Boards APPLIBDIR = $(PIOSSTM32F10X)/Libraries STMLIBDIR = $(APPLIBDIR) STMSPDDIR = $(STMLIBDIR)/STM32F10x_StdPeriph_Driver -ifeq ($(USE_USB), YES) - STMUSBDIR = $(STMLIBDIR)/STM32_USB-FS-Device_Driver -endif +STMUSBDIR = $(STMLIBDIR)/STM32_USB-FS-Device_Driver STMSPDSRCDIR = $(STMSPDDIR)/src STMSPDINCDIR = $(STMSPDDIR)/inc -ifeq ($(USE_USB), YES) - STMUSBSRCDIR = $(STMUSBDIR)/src - STMUSBINCDIR = $(STMUSBDIR)/inc -endif +STMUSBSRCDIR = $(STMUSBDIR)/src +STMUSBINCDIR = $(STMUSBDIR)/inc CMSISDIR = $(STMLIBDIR)/CMSIS/Core/CM3 -BOOT = ../Bootloaders/AHRS -BOOTINC = $(BOOT)/inc +DOSFSDIR = $(APPLIBDIR)/dosfs +MSDDIR = $(APPLIBDIR)/msd +RTOSDIR = $(APPLIBDIR)/FreeRTOS +RTOSSRCDIR = $(RTOSDIR)/Source +RTOSINCDIR = $(RTOSSRCDIR)/include +DOXYGENDIR = ../Doc/Doxygen +AHRSBOOTLOADER = ../Bootloaders/AHRS/ +AHRSBOOTLOADERINC = $(AHRSBOOTLOADER)/inc +PYMITE = $(FLIGHTLIB)/PyMite +PYMITELIB = $(PYMITE)/lib +PYMITEPLAT = $(PYMITE)/platform/openpilot +PYMITETOOLS = $(PYMITE)/tools +PYMITEVM = $(PYMITE)/vm +PYMITEINC = $(PYMITEVM) +PYMITEINC += $(PYMITEPLAT) +PYMITEINC += $(OUTDIR) +FLIGHTPLANLIB = $(OPMODULEDIR)/FlightPlan/lib +FLIGHTPLANS = $(OPMODULEDIR)/FlightPlan/flightplans HWDEFSINC = ../board_hw_defs/$(BOARD_NAME) +OPUAVSYNTHDIR = $(OUTDIR)/../uavobject-synthetics/flight + # List C source files here. (C dependencies are automatically generated.) # use file-extension c for "c-only"-files -## Core: -SRC += $(HOME_DIR)/main.c -SRC += $(HOME_DIR)/pios_board.c -SRC += $(HOME_DIR)/crc.c -SRC += $(HOME_DIR)/aes.c -SRC += $(HOME_DIR)/rfm22b.c -SRC += $(HOME_DIR)/packet_handler.c -SRC += $(HOME_DIR)/stream.c -SRC += $(HOME_DIR)/ppm.c -SRC += $(HOME_DIR)/transparent_comms.c -#SRC += $(HOME_DIR)/api_comms.c -SRC += $(HOME_DIR)/api_config.c -SRC += $(HOME_DIR)/saved_settings.c -SRC += $(HOME_DIR)/gpio_in.c -SRC += $(HOME_DIR)/stopwatch.c -SRC += $(HOME_DIR)/watchdog.c -SRC += $(FLIGHTLIB)/fifo_buffer.c +ifndef TESTAPP +## MODULES +SRC += ${foreach MOD, ${MODULES}, ${wildcard ${OPMODULEDIR}/${MOD}/*.c}} +## OPENPILOT CORE: +SRC += ${OPMODULEDIR}/PipXtreme/pipxtrememod.c +SRC += $(OPSYSTEM)/pipxtreme.c +SRC += $(OPSYSTEM)/pios_board.c +SRC += $(OPUAVTALK)/uavtalk.c +SRC += $(OPUAVOBJ)/uavobjectmanager.c +SRC += $(OPUAVOBJ)/eventdispatcher.c +else +## TESTCODE +SRC += $(OPTESTS)/test_common.c +SRC += $(OPTESTS)/$(TESTAPP).c +endif + +## UAVOBJECTS +ifndef TESTAPP +SRC += $(OPUAVSYNTHDIR)/gcsreceiver.c +SRC += $(OPUAVSYNTHDIR)/pipxstatus.c +SRC += $(OPUAVSYNTHDIR)/pipxsettings.c +SRC += $(OPUAVSYNTHDIR)/objectpersistence.c + +endif ## PIOS Hardware (STM32F10x) SRC += $(PIOSSTM32F10X)/pios_sys.c @@ -104,41 +150,60 @@ SRC += $(PIOSSTM32F10X)/pios_led.c SRC += $(PIOSSTM32F10X)/pios_delay.c SRC += $(PIOSSTM32F10X)/pios_usart.c SRC += $(PIOSSTM32F10X)/pios_irq.c -SRC += $(PIOSSTM32F10X)/pios_adc.c -SRC += $(PIOSSTM32F10X)/pios_gpio.c SRC += $(PIOSSTM32F10X)/pios_spi.c SRC += $(PIOSSTM32F10X)/pios_ppm.c +SRC += $(PIOSSTM32F10X)/pios_debug.c +SRC += $(PIOSSTM32F10X)/pios_gpio.c +SRC += $(PIOSSTM32F10X)/pios_exti.c +SRC += $(PIOSSTM32F10X)/pios_rtc.c +SRC += $(PIOSSTM32F10X)/pios_wdg.c +SRC += $(PIOSSTM32F10X)/pios_tim.c +SRC += $(PIOSSTM32F10X)/pios_pwm.c +SRC += $(PIOSSTM32F10X)/pios_eeprom.c +SRC += $(PIOSSTM32F10X)/pios_bl_helper.c # PIOS USB related files (seperated to make code maintenance more easy) -ifeq ($(USE_USB), YES) - SRC += $(PIOSSTM32F10X)/pios_usb.c - SRC += $(PIOSSTM32F10X)/pios_usbhook.c - SRC += $(PIOSSTM32F10X)/pios_usb_hid.c - SRC += $(PIOSSTM32F10X)/pios_usb_hid_istr.c - SRC += $(PIOSSTM32F10X)/pios_usb_hid_pwr.c - SRC += $(HOME_DIR)/pios_usb_board_data.c - SRC += $(PIOSCOMMON)/pios_usb_desc_hid_only.c -endif +SRC += $(PIOSSTM32F10X)/pios_usb.c +SRC += $(PIOSSTM32F10X)/pios_usbhook.c +SRC += $(PIOSSTM32F10X)/pios_usb_hid.c +SRC += $(PIOSSTM32F10X)/pios_usb_cdc.c +SRC += $(PIOSSTM32F10X)/pios_usb_hid_istr.c +SRC += $(PIOSSTM32F10X)/pios_usb_hid_pwr.c +SRC += $(OPSYSTEM)/pios_usb_board_data.c +SRC += $(PIOSCOMMON)/pios_usb_desc_hid_cdc.c +SRC += $(PIOSCOMMON)/pios_usb_desc_hid_only.c +SRC += $(PIOSCOMMON)/pios_usb_util.c ## PIOS Hardware (Common) +SRC += $(PIOSCOMMON)/pios_crc.c SRC += $(PIOSCOMMON)/pios_com.c +SRC += $(PIOSCOMMON)/pios_i2c_esc.c +SRC += $(PIOSCOMMON)/pios_rcvr.c SRC += $(PIOSCOMMON)/printf-stdarg.c +SRC += $(PIOSCOMMON)/pios_rfm22b.c +## Libraries for flight calculations +SRC += $(FLIGHTLIB)/fifo_buffer.c +SRC += $(FLIGHTLIB)/CoordinateConversions.c +SRC += $(FLIGHTLIB)/taskmonitor.c +SRC += $(FLIGHTLIB)/aes.c +SRC += $(FLIGHTLIB)/packet_handler.c +## The Reed-Solomon FEC library +SRC += $(FLIGHTLIB)/rscode/rs.c +SRC += $(FLIGHTLIB)/rscode/berlekamp.c +SRC += $(FLIGHTLIB)/rscode/galois.c ## CMSIS for STM32 SRC += $(CMSISDIR)/core_cm3.c SRC += $(CMSISDIR)/system_stm32f10x.c ## Used parts of the STM-Library -SRC += $(STMSPDSRCDIR)/stm32f10x_adc.c SRC += $(STMSPDSRCDIR)/stm32f10x_bkp.c SRC += $(STMSPDSRCDIR)/stm32f10x_crc.c SRC += $(STMSPDSRCDIR)/stm32f10x_dac.c -SRC += $(STMSPDSRCDIR)/stm32f10x_dbgmcu.c SRC += $(STMSPDSRCDIR)/stm32f10x_dma.c SRC += $(STMSPDSRCDIR)/stm32f10x_exti.c SRC += $(STMSPDSRCDIR)/stm32f10x_flash.c SRC += $(STMSPDSRCDIR)/stm32f10x_gpio.c -SRC += $(STMSPDSRCDIR)/stm32f10x_iwdg.c SRC += $(STMSPDSRCDIR)/stm32f10x_i2c.c SRC += $(STMSPDSRCDIR)/stm32f10x_pwr.c SRC += $(STMSPDSRCDIR)/stm32f10x_rcc.c @@ -146,31 +211,40 @@ SRC += $(STMSPDSRCDIR)/stm32f10x_rtc.c SRC += $(STMSPDSRCDIR)/stm32f10x_spi.c SRC += $(STMSPDSRCDIR)/stm32f10x_tim.c SRC += $(STMSPDSRCDIR)/stm32f10x_usart.c +SRC += $(STMSPDSRCDIR)/stm32f10x_iwdg.c +SRC += $(STMSPDSRCDIR)/stm32f10x_dbgmcu.c SRC += $(STMSPDSRCDIR)/misc.c ## STM32 USB Library -ifeq ($(USE_USB), YES) - SRC += $(STMUSBSRCDIR)/usb_core.c - SRC += $(STMUSBSRCDIR)/usb_init.c - SRC += $(STMUSBSRCDIR)/usb_int.c - SRC += $(STMUSBSRCDIR)/usb_mem.c - SRC += $(STMUSBSRCDIR)/usb_regs.c - SRC += $(STMUSBSRCDIR)/usb_sil.c -endif +SRC += $(STMUSBSRCDIR)/usb_core.c +SRC += $(STMUSBSRCDIR)/usb_init.c +SRC += $(STMUSBSRCDIR)/usb_int.c +SRC += $(STMUSBSRCDIR)/usb_mem.c +SRC += $(STMUSBSRCDIR)/usb_regs.c +SRC += $(STMUSBSRCDIR)/usb_sil.c + +## RTOS +SRC += $(RTOSSRCDIR)/list.c +SRC += $(RTOSSRCDIR)/queue.c +SRC += $(RTOSSRCDIR)/tasks.c + +## RTOS Portable +SRC += $(RTOSSRCDIR)/portable/GCC/ARM_CM3/port.c +SRC += $(RTOSSRCDIR)/portable/MemMang/heap_1.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 = +SRCARM = # List C++ source files here. # use file-extension .cpp for C++-files (not .C) -CPPSRC = +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 = +CPPSRCARM = # List Assembler source files here. # Make them always end in a capital .S. Files ending in a lowercase .s @@ -182,35 +256,48 @@ CPPSRCARM = ASRC = $(PIOSSTM32F10X)/startup_stm32f10x_$(MODEL)$(MODEL_SUFFIX).S # List Assembler source files here which must be assembled in ARM-Mode.. -ASRCARM = +ASRCARM = # List any extra directories to look for include files here. # Each directory must be seperated by a space. -EXTRAINCDIRS += $(HOME_DIR) -EXTRAINCDIRS += $(HOME_DIR_INC) +EXTRAINCDIRS = $(OPSYSTEM) +EXTRAINCDIRS += $(OPSYSTEMINC) +EXTRAINCDIRS += $(OPUAVTALK) +EXTRAINCDIRS += $(OPUAVTALKINC) +EXTRAINCDIRS += $(OPUAVOBJ) +EXTRAINCDIRS += $(OPUAVOBJINC) +EXTRAINCDIRS += $(OPUAVSYNTHDIR) EXTRAINCDIRS += $(PIOS) EXTRAINCDIRS += $(PIOSINC) EXTRAINCDIRS += $(FLIGHTLIBINC) +EXTRAINCDIRS += $(RSCODEINC) EXTRAINCDIRS += $(PIOSSTM32F10X) EXTRAINCDIRS += $(PIOSCOMMON) EXTRAINCDIRS += $(PIOSBOARDS) EXTRAINCDIRS += $(STMSPDINCDIR) -ifeq ($(USE_USB), YES) - EXTRAINCDIRS += $(STMUSBINCDIR) -endif +EXTRAINCDIRS += $(STMUSBINCDIR) EXTRAINCDIRS += $(CMSISDIR) -EXTRAINCDIRS += $(BOOTINC) +EXTRAINCDIRS += $(DOSFSDIR) +EXTRAINCDIRS += $(MSDDIR) +EXTRAINCDIRS += $(RTOSINCDIR) +EXTRAINCDIRS += $(APPLIBDIR) +EXTRAINCDIRS += $(RTOSSRCDIR)/portable/GCC/ARM_CM3 +EXTRAINCDIRS += $(AHRSBOOTLOADERINC) +EXTRAINCDIRS += $(PYMITEINC) EXTRAINCDIRS += $(HWDEFSINC) +EXTRAINCDIRS += ${foreach MOD, ${OPTMODULES} ${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_LIBDIRS = # Extra Libraries # Each library-name must be seperated by a space. -# i.e. to link with libxyz.a, libabc.a and libefsl.a: +# 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 @@ -219,19 +306,18 @@ EXTRA_LIBS = # Path to Linker-Scripts LINKERSCRIPTPATH = $(PIOSSTM32F10X) -# Optimization level, can be [0, 1, 2, 3, s]. +# 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 +OPT = 1 else OPT = s -#OPT = 2 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, +# 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 @@ -240,13 +326,30 @@ LOADFORMAT = both # Debugging format. DEBUGF = dwarf-2 -# Place project-specific -D (define) and/or +# Place project-specific -D (define) and/or # -U options for C here. CDEFS = -DSTM32F10X_$(MODEL) CDEFS += -DUSE_STDPERIPH_DRIVER CDEFS += -DUSE_$(BOARD) +ifeq ($(ENABLE_DEBUG_PINS), YES) +CDEFS += -DPIOS_ENABLE_DEBUG_PINS +endif +ifeq ($(ENABLE_AUX_UART), YES) +CDEFS += -DPIOS_ENABLE_AUX_UART +endif +ifeq ($(ERASE_FLASH), YES) +CDEFS += -DERASE_FLASH +endif -# Place project-specific -D and/or -U options for +ifneq ($(USE_GPS), NO) +CDEFS += -DUSE_GPS +endif + +ifeq ($(USE_I2C), YES) +CDEFS += -DUSE_I2C +endif + +# Place project-specific -D and/or -U options for # Assembler with preprocessor here. #ADEFS = -DUSE_IRQ_ASM_WRAPPER ADEFS = -D__ASSEMBLY__ @@ -272,18 +375,27 @@ CSTANDARD = -std=gnu99 # Flags for C and C++ (arm-elf-gcc/arm-elf-g++) ifeq ($(DEBUG),YES) -CFLAGS = -g$(DEBUGF) +CFLAGS = -DDEBUG endif -CFLAGS += -O$(OPT) -ifeq ($(DEBUG),NO) -CFLAGS += -fdata-sections -ffunction-sections +ifeq ($(DIAGNOSTICS),YES) +CFLAGS = -DDIAGNOSTICS endif + +CFLAGS += -g$(DEBUGF) +CFLAGS += -O$(OPT) CFLAGS += -mcpu=$(MCU) CFLAGS += $(CDEFS) CFLAGS += $(patsubst %,-I%,$(EXTRAINCDIRS)) -I. -CFLAGS += -mapcs-frame +#CFLAGS += -fno-cprop-registers -fno-defer-pop -fno-guess-branch-probability -fno-section-anchors +#CFLAGS += -fno-if-conversion -fno-if-conversion2 -fno-ipa-pure-const -fno-ipa-reference -fno-merge-constants +#CFLAGS += -fno-split-wide-types -fno-tree-ccp -fno-tree-ch -fno-tree-copy-prop -fno-tree-copyrename +#CFLAGS += -fno-tree-dce -fno-tree-dominator-opts -fno-tree-dse -fno-tree-fre -fno-tree-sink -fno-tree-sra +#CFLAGS += -fno-tree-ter +#CFLAGS += -g$(DEBUGF) -DDEBUG + +CFLAGS += -mapcs-frame CFLAGS += -fomit-frame-pointer ifeq ($(CODE_SOURCERY), YES) CFLAGS += -fpromote-loop-indices @@ -296,7 +408,7 @@ CFLAGS += -Wa,-adhlns=$(addprefix $(OUTDIR)/, $(notdir $(addsuffix .lst, $(basen CFLAGS += -MD -MP -MF $(OUTDIR)/dep/$(@F).d # flags only for C -#CONLYFLAGS += -Wnested-externs +#CONLYFLAGS += -Wnested-externs CONLYFLAGS += $(CSTANDARD) # Assembler flags. @@ -314,14 +426,11 @@ MATH_LIB = -lm # -Map: create map file # --cref: add cross reference to map file LDFLAGS = -nostartfiles -Wl,-Map=$(OUTDIR)/$(TARGET).map,--cref,--gc-sections -ifeq ($(DEBUG),NO) -LDFLAGS += -Wl,-static -Wl,-s -endif LDFLAGS += $(patsubst %,-L%,$(EXTRA_LIBDIRS)) LDFLAGS += -lc LDFLAGS += $(patsubst %,-l%,$(EXTRA_LIBS)) LDFLAGS += $(MATH_LIB) -LDFLAGS += -lc -lgcc +LDFLAGS += -lc -lgcc # Set linker-script name depending on selected submodel name LDFLAGS += -T$(LINKERSCRIPTPATH)/link_$(BOARD)_memory.ld @@ -329,6 +438,7 @@ LDFLAGS += -T$(LINKERSCRIPTPATH)/link_$(BOARD)_sections.ld # Define programs and commands. REMOVE = $(REMOVE_CMD) -f +PYTHON = python # List of all source files. ALLSRC = $(ASRCARM) $(ASRC) $(SRCARM) $(SRC) $(CPPSRCARM) $(CPPSRC) @@ -348,13 +458,13 @@ all: build ifeq ($(LOADFORMAT),ihex) build: elf hex lss sym -else +else ifeq ($(LOADFORMAT),binary) build: elf bin lss sym -else +else ifeq ($(LOADFORMAT),both) build: elf hex bin lss sym -else +else $(error "$(MSG_FORMATERROR) $(FORMAT)") endif endif @@ -364,22 +474,22 @@ endif $(eval $(call LINK_TEMPLATE, $(OUTDIR)/$(TARGET).elf, $(ALLOBJ))) # Assemble: create object files from assembler source files. -$(foreach src, $(ASRC), $(eval $(call ASSEMBLE_TEMPLATE, $(src)))) +$(foreach src, $(ASRC), $(eval $(call ASSEMBLE_TEMPLATE, $(src)))) # Assemble: create object files from assembler source files. ARM-only -$(foreach src, $(ASRCARM), $(eval $(call ASSEMBLE_ARM_TEMPLATE, $(src)))) +$(foreach src, $(ASRCARM), $(eval $(call ASSEMBLE_ARM_TEMPLATE, $(src)))) # Compile: create object files from C source files. -$(foreach src, $(SRC), $(eval $(call COMPILE_C_TEMPLATE, $(src)))) +$(foreach src, $(SRC), $(eval $(call COMPILE_C_TEMPLATE, $(src)))) # Compile: create object files from C source files. ARM-only -$(foreach src, $(SRCARM), $(eval $(call COMPILE_C_ARM_TEMPLATE, $(src)))) +$(foreach src, $(SRCARM), $(eval $(call COMPILE_C_ARM_TEMPLATE, $(src)))) # Compile: create object files from C++ source files. -$(foreach src, $(CPPSRC), $(eval $(call COMPILE_CPP_TEMPLATE, $(src)))) +$(foreach src, $(CPPSRC), $(eval $(call COMPILE_CPP_TEMPLATE, $(src)))) # Compile: create object files from C++ source files. ARM-only -$(foreach src, $(CPPSRCARM), $(eval $(call COMPILE_CPP_ARM_TEMPLATE, $(src)))) +$(foreach src, $(CPPSRCARM), $(eval $(call COMPILE_CPP_ARM_TEMPLATE, $(src)))) # Compile: create assembler files from C source files. ARM/Thumb $(eval $(call PARTIAL_COMPILE_TEMPLATE, SRC)) @@ -396,7 +506,7 @@ $(eval $(call JTAG_TEMPLATE,$(OUTDIR)/$(TARGET).bin,$(FW_BANK_BASE),$(FW_BANK_SI .PHONY: elf lss sym hex bin bino opfw elf: $(OUTDIR)/$(TARGET).elf -lss: $(OUTDIR)/$(TARGET).lss +lss: $(OUTDIR)/$(TARGET).lss sym: $(OUTDIR)/$(TARGET).sym hex: $(OUTDIR)/$(TARGET).hex bin: $(OUTDIR)/$(TARGET).bin @@ -432,6 +542,8 @@ clean_list : $(V1) $(REMOVE) $(OUTDIR)/$(TARGET).sym $(V1) $(REMOVE) $(OUTDIR)/$(TARGET).lss $(V1) $(REMOVE) $(OUTDIR)/$(TARGET).bin.o + $(V1) $(REMOVE) $(wildcard $(OUTDIR)/*.c) + $(V1) $(REMOVE) $(wildcard $(OUTDIR)/*.h) $(V1) $(REMOVE) $(ALLOBJ) $(V1) $(REMOVE) $(LSTFILES) $(V1) $(REMOVE) $(DEPFILES) diff --git a/flight/PipXtreme/System/alarms.c b/flight/PipXtreme/System/alarms.c new file mode 100755 index 000000000..01d79a1e5 --- /dev/null +++ b/flight/PipXtreme/System/alarms.c @@ -0,0 +1,214 @@ +/** + ****************************************************************************** + * @addtogroup OpenPilotSystem OpenPilot System + * @{ + * @addtogroup OpenPilotLibraries OpenPilot System Libraries + * @brief OpenPilot System libraries are available to all OP modules. + * @{ + * @file alarms.c + * @author The OpenPilot Team, http://www.openpilot.org Copyright (C) 2010. + * @brief Library for setting and clearing system alarms + * @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 "openpilot.h" +#include "alarms.h" + +// Private constants + +// Private types + +// Private variables +static xSemaphoreHandle lock; + +// Private functions +static int32_t hasSeverity(SystemAlarmsAlarmOptions severity); + +/** + * Initialize the alarms library + */ +int32_t AlarmsInitialize(void) +{ + SystemAlarmsInitialize(); + + lock = xSemaphoreCreateRecursiveMutex(); + //do not change the default states of the alarms, let the init code generated by the uavobjectgenerator handle that + //AlarmsClearAll(); + //AlarmsDefaultAll(); + return 0; +} + +/** + * Set an alarm + * @param alarm The system alarm to be modified + * @param severity The alarm severity + * @return 0 if success, -1 if an error + */ +int32_t AlarmsSet(SystemAlarmsAlarmElem alarm, SystemAlarmsAlarmOptions severity) +{ + SystemAlarmsData alarms; + + // Check that this is a valid alarm + if (alarm >= SYSTEMALARMS_ALARM_NUMELEM) + { + return -1; + } + + // Lock + xSemaphoreTakeRecursive(lock, portMAX_DELAY); + + // Read alarm and update its severity only if it was changed + SystemAlarmsGet(&alarms); + if ( alarms.Alarm[alarm] != severity ) + { + alarms.Alarm[alarm] = severity; + SystemAlarmsSet(&alarms); + } + + // Release lock + xSemaphoreGiveRecursive(lock); + return 0; + +} + +/** + * Get an alarm + * @param alarm The system alarm to be read + * @return Alarm severity + */ +SystemAlarmsAlarmOptions AlarmsGet(SystemAlarmsAlarmElem alarm) +{ + SystemAlarmsData alarms; + + // Check that this is a valid alarm + if (alarm >= SYSTEMALARMS_ALARM_NUMELEM) + { + return 0; + } + + // Read alarm + SystemAlarmsGet(&alarms); + return alarms.Alarm[alarm]; +} + +/** + * Set an alarm to it's default value + * @param alarm The system alarm to be modified + * @return 0 if success, -1 if an error + */ +int32_t AlarmsDefault(SystemAlarmsAlarmElem alarm) +{ + return AlarmsSet(alarm, SYSTEMALARMS_ALARM_DEFAULT); +} + +/** + * Default all alarms + */ +void AlarmsDefaultAll() +{ + uint32_t n; + for (n = 0; n < SYSTEMALARMS_ALARM_NUMELEM; ++n) + { + AlarmsDefault(n); + } +} + +/** + * Clear an alarm + * @param alarm The system alarm to be modified + * @return 0 if success, -1 if an error + */ +int32_t AlarmsClear(SystemAlarmsAlarmElem alarm) +{ + return AlarmsSet(alarm, SYSTEMALARMS_ALARM_OK); +} + +/** + * Clear all alarms + */ +void AlarmsClearAll() +{ + uint32_t n; + for (n = 0; n < SYSTEMALARMS_ALARM_NUMELEM; ++n) + { + AlarmsClear(n); + } +} + +/** + * Check if there are any alarms with the given or higher severity + * @return 0 if no alarms are found, 1 if at least one alarm is found + */ +int32_t AlarmsHasWarnings() +{ + return hasSeverity(SYSTEMALARMS_ALARM_WARNING); +} + +/** + * Check if there are any alarms with error or higher severity + * @return 0 if no alarms are found, 1 if at least one alarm is found + */ +int32_t AlarmsHasErrors() +{ + return hasSeverity(SYSTEMALARMS_ALARM_ERROR); +}; + +/** + * Check if there are any alarms with critical or higher severity + * @return 0 if no alarms are found, 1 if at least one alarm is found + */ +int32_t AlarmsHasCritical() +{ + return hasSeverity(SYSTEMALARMS_ALARM_CRITICAL); +}; + +/** + * Check if there are any alarms with the given or higher severity + * @return 0 if no alarms are found, 1 if at least one alarm is found + */ +static int32_t hasSeverity(SystemAlarmsAlarmOptions severity) +{ + SystemAlarmsData alarms; + uint32_t n; + + // Lock + xSemaphoreTakeRecursive(lock, portMAX_DELAY); + + // Read alarms + SystemAlarmsGet(&alarms); + + // Go through alarms and check if any are of the given severity or higher + for (n = 0; n < SYSTEMALARMS_ALARM_NUMELEM; ++n) + { + if ( alarms.Alarm[n] >= severity) + { + xSemaphoreGiveRecursive(lock); + return 1; + } + } + + // If this point is reached then no alarms found + xSemaphoreGiveRecursive(lock); + return 0; +} +/** + * @} + * @} + */ + diff --git a/flight/PipXtreme/System/inc/FreeRTOSConfig.h b/flight/PipXtreme/System/inc/FreeRTOSConfig.h new file mode 100755 index 000000000..994956008 --- /dev/null +++ b/flight/PipXtreme/System/inc/FreeRTOSConfig.h @@ -0,0 +1,99 @@ + +#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. + *----------------------------------------------------------*/ + +/** + * @addtogroup PIOS PIOS + * @{ + * @addtogroup FreeRTOS FreeRTOS + * @{ + */ + +/* Notes: We use 5 task priorities */ + +#define configUSE_PREEMPTION 1 +#define configUSE_IDLE_HOOK 1 +#define configUSE_TICK_HOOK 0 +#define configUSE_MALLOC_FAILED_HOOK 1 +#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 ) 48 ) +#define configTOTAL_HEAP_SIZE ( ( size_t ) ( 54 * 256) ) +#define configMAX_TASK_NAME_LEN ( 16 ) +#define configUSE_TRACE_FACILITY 0 +#define configUSE_16_BIT_TICKS 0 +#define configIDLE_SHOULD_YIELD 0 +#define configUSE_MUTEXES 1 +#define configUSE_RECURSIVE_MUTEXES 1 +#define configUSE_COUNTING_SEMAPHORES 0 +#define configUSE_ALTERNATIVE_API 0 +#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 1 + +/* 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 + +#if !defined(ARCH_POSIX) && !defined(ARCH_WIN32) +#define CHECK_IRQ_STACK +#endif + +/* Enable run time stats collection */ +#if defined(DIAGNOSTICS) +#define configCHECK_FOR_STACK_OVERFLOW 2 + +#define configGENERATE_RUN_TIME_STATS 1 +#define INCLUDE_uxTaskGetRunTime 1 +#define portCONFIGURE_TIMER_FOR_RUN_TIME_STATS()\ +do {\ +(*(unsigned long *)0xe000edfc) |= (1<<24);/* DEMCR |= DEMCR_TRCENA */\ +(*(unsigned long *)0xe0001000) |= 1; /* DWT_CTRL |= DWT_CYCCNT_ENA */\ +} while(0) +#define portGET_RUN_TIME_COUNTER_VALUE() (*(unsigned long *)0xe0001004)/* DWT_CYCCNT */ +#else +#define configCHECK_FOR_STACK_OVERFLOW 1 +#endif + + +/** + * @} + */ + +#endif /* FREERTOS_CONFIG_H */ diff --git a/flight/PipXtreme/System/inc/alarms.h b/flight/PipXtreme/System/inc/alarms.h new file mode 100755 index 000000000..9fb047dca --- /dev/null +++ b/flight/PipXtreme/System/inc/alarms.h @@ -0,0 +1,50 @@ +/** + ****************************************************************************** + * @addtogroup OpenPilotSystem OpenPilot System + * @{ + * @addtogroup OpenPilotLibraries OpenPilot System Libraries + * @{ + * @file alarms.h + * @author The OpenPilot Team, http://www.openpilot.org Copyright (C) 2010. + * @brief Include file of the alarm library + * @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 ALARMS_H +#define ALARMS_H + +#include "systemalarms.h" +#define SYSTEMALARMS_ALARM_DEFAULT SYSTEMALARMS_ALARM_UNINITIALISED + +int32_t AlarmsInitialize(void); +int32_t AlarmsSet(SystemAlarmsAlarmElem alarm, SystemAlarmsAlarmOptions severity); +SystemAlarmsAlarmOptions AlarmsGet(SystemAlarmsAlarmElem alarm); +int32_t AlarmsDefault(SystemAlarmsAlarmElem alarm); +void AlarmsDefaultAll(); +int32_t AlarmsClear(SystemAlarmsAlarmElem alarm); +void AlarmsClearAll(); +int32_t AlarmsHasWarnings(); +int32_t AlarmsHasErrors(); +int32_t AlarmsHasCritical(); + +#endif // ALARMS_H + +/** + * @} + * @} + */ diff --git a/flight/PipXtreme/reserved/api_comms.h b/flight/PipXtreme/System/inc/op_config.h old mode 100644 new mode 100755 similarity index 65% rename from flight/PipXtreme/reserved/api_comms.h rename to flight/PipXtreme/System/inc/op_config.h index 9f9cece0f..97910f392 --- a/flight/PipXtreme/reserved/api_comms.h +++ b/flight/PipXtreme/System/inc/op_config.h @@ -1,40 +1,39 @@ /** ****************************************************************************** + * @addtogroup OpenPilotSystem OpenPilot System + * @{ + * @addtogroup OpenPilotCore OpenPilot Core + * @{ * - * @file api_comms.h + * @file op_config.h * @author The OpenPilot Team, http://www.openpilot.org Copyright (C) 2010. - * @brief RF Module hardware layer + * @brief OpenPilot configuration header. + * Compile time config for OpenPilot Application * @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 +/* + * 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 + * + * 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., + * + * 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 __API_COMMS_H__ -#define __API_COMMS_H__ -#include "stdint.h" +#ifndef OP_CONFIG_H +#define OP_CONFIG_H -// ***************************************************************************** - -void api_1ms_tick(void); -void api_process(void); - -void api_init(void); - -// ***************************************************************************** - -#endif +#endif /* OP_CONFIG_H */ +/** + * @} + * @} + */ diff --git a/flight/PipXtreme/inc/crc.h b/flight/PipXtreme/System/inc/openpilot.h old mode 100644 new mode 100755 similarity index 57% rename from flight/PipXtreme/inc/crc.h rename to flight/PipXtreme/System/inc/openpilot.h index bb27dd5ad..59ae76fd4 --- a/flight/PipXtreme/inc/crc.h +++ b/flight/PipXtreme/System/inc/openpilot.h @@ -1,43 +1,53 @@ /** ****************************************************************************** - * - * @file crc.h + * @addtogroup OpenPilotSystem OpenPilot System + * @{ + * @addtogroup OpenPilotCore OpenPilot Core + * @{ + * @file openpilot.h * @author The OpenPilot Team, http://www.openpilot.org Copyright (C) 2010. - * @brief Serial communication port handling routines + * @brief Main OpenPilot 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 +/* + * 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 + * + * 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., + * + * 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 _CRC_H_ -#define _CRC_H_ -#include "stm32f10x.h" +#ifndef OPENPILOT_H +#define OPENPILOT_H -// ******************************************************************** -uint16_t updateCRC16(uint16_t crc, uint8_t b); -uint16_t updateCRC16Data(uint16_t crc, void *data, uint32_t len); +/* PIOS Includes */ +#include -uint32_t updateCRC32(uint32_t crc, uint8_t b); -uint32_t updateCRC32Data(uint32_t crc, void *data, uint32_t len); +/* OpenPilot Libraries */ +#include "op_config.h" +#include "utlist.h" +#include "uavobjectmanager.h" +#include "eventdispatcher.h" +#include "alarms.h" +#include "taskmonitor.h" +#include "uavtalk.h" -void CRC_init(void); +/* Global Functions */ +void OpenPilotInit(void); -// ******************************************************************** - -#endif +#endif /* OPENPILOT_H */ +/** + * @} + * @} + */ diff --git a/flight/PipXtreme/System/inc/pios_board_posix.h b/flight/PipXtreme/System/inc/pios_board_posix.h new file mode 100755 index 000000000..741f36ba7 --- /dev/null +++ b/flight/PipXtreme/System/inc/pios_board_posix.h @@ -0,0 +1,84 @@ +/** + ****************************************************************************** + * + * @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_LED1_GPIO_PORT GPIOC +//#define PIOS_LED_LED1_GPIO_PIN GPIO_Pin_12 +//#define PIOS_LED_LED1_GPIO_CLK RCC_APB2Periph_GPIOC +//#define PIOS_LED_LED2_GPIO_PORT GPIOC +//#define PIOS_LED_LED2_GPIO_PIN GPIO_Pin_13 +//#define PIOS_LED_LED2_GPIO_CLK RCC_APB2Periph_GPIOC +#define PIOS_LED_NUM 2 +//#define PIOS_LED_PORTS { PIOS_LED_LED1_GPIO_PORT, PIOS_LED_LED2_GPIO_PORT } +//#define PIOS_LED_PINS { PIOS_LED_LED1_GPIO_PIN, PIOS_LED_LED2_GPIO_PIN } +//#define PIOS_LED_CLKS { PIOS_LED_LED1_GPIO_CLK, PIOS_LED_LED2_GPIO_CLK } + + +//------------------------- +// COM +// +// See also pios_board_posix.c +//------------------------- +//#define PIOS_USART_TX_BUFFER_SIZE 256 +#define PIOS_COM_BUFFER_SIZE 1024 +#define PIOS_UDP_RX_BUFFER_SIZE PIOS_COM_BUFFER_SIZE + +#define PIOS_COM_TELEM_RF 0 +#define PIOS_COM_GPS 1 +#define PIOS_COM_TELEM_USB 2 + +#ifdef PIOS_ENABLE_AUX_UART +#define PIOS_COM_AUX 3 +#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 */ diff --git a/flight/PipXtreme/System/inc/pios_config.h b/flight/PipXtreme/System/inc/pios_config.h new file mode 100755 index 000000000..a94b2af89 --- /dev/null +++ b/flight/PipXtreme/System/inc/pios_config.h @@ -0,0 +1,103 @@ +/** + ****************************************************************************** + * @addtogroup OpenPilotSystem OpenPilot System + * @{ + * @addtogroup OpenPilotCore OpenPilot Core + * @{ + * + * @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. + * In particular, pios_config.h is where you define which PiOS libraries + * and features are included in the firmware. + * @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_H +#define PIOS_CONFIG_H + +/* Enable/Disable PiOS Modules */ +#define PIOS_INCLUDE_DELAY +#define PIOS_INCLUDE_IRQ +#define PIOS_INCLUDE_LED +#define PIOS_INCLUDE_IAP +#define PIOS_INCLUDE_RFM22B +#define PIOS_INCLUDE_RCVR +#define PIOS_INCLUDE_TIM + +/* Supported receiver interfaces */ +#define PIOS_INCLUDE_PPM + +/* Supported USART-based PIOS modules */ +#define PIOS_INCLUDE_SPI +#define PIOS_INCLUDE_SYS +#define PIOS_INCLUDE_USART +#define PIOS_INCLUDE_USB +#define PIOS_INCLUDE_USB_HID +#define PIOS_INCLUDE_USB_CDC +#define PIOS_INCLUDE_COM +#define PIOS_INCLUDE_SETTINGS +#define PIOS_INCLUDE_FREERTOS +#define PIOS_INCLUDE_GPIO +#define PIOS_INCLUDE_EXTI +#define PIOS_INCLUDE_RTC +#define PIOS_INCLUDE_WDG +#define PIOS_INCLUDE_BL_HELPER +#define PIOS_INCLUDE_FLASH_EEPROM + +/* 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 + +/* Alarm Thresholds */ +#define HEAP_LIMIT_WARNING 220 +#define HEAP_LIMIT_CRITICAL 40 +#define IRQSTACK_LIMIT_WARNING 100 +#define IRQSTACK_LIMIT_CRITICAL 60 +#define CPULOAD_LIMIT_WARNING 85 +#define CPULOAD_LIMIT_CRITICAL 95 + +/* Task stack sizes */ +#define PIOS_ACTUATOR_STACK_SIZE 1020 +#define PIOS_MANUAL_STACK_SIZE 724 +#define PIOS_SYSTEM_STACK_SIZE 460 +#define PIOS_STABILIZATION_STACK_SIZE 524 +#define PIOS_TELEM_STACK_SIZE 500 +#define PIOS_EVENTDISPATCHER_STACK_SIZE 130 +#define IDLE_COUNTS_PER_SEC_AT_NO_LOAD 1995998 +//#define PIOS_QUATERNION_STABILIZATION + +// This can't be too high to stop eventdispatcher thread overflowing +#define PIOS_EVENTDISAPTCHER_QUEUE 10 + +/* PIOS Initcall infrastructure */ +#define PIOS_INCLUDE_INITCALL + +#endif /* PIOS_CONFIG_H */ +/** + * @} + * @} + */ diff --git a/flight/PipXtreme/inc/pios_config.h b/flight/PipXtreme/System/inc/pios_config_posix.h old mode 100644 new mode 100755 similarity index 60% rename from flight/PipXtreme/inc/pios_config.h rename to flight/PipXtreme/System/inc/pios_config_posix.h index 46728b2cb..ddf7ee5d4 --- a/flight/PipXtreme/inc/pios_config.h +++ b/flight/PipXtreme/System/inc/pios_config_posix.h @@ -1,45 +1,54 @@ /** ****************************************************************************** * - * @file pios_config.h + * @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. + * @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 +/* + * 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 + * + * 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., + * + * 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_H -#define PIOS_CONFIG_H +#ifndef PIOS_CONFIG_POSIX_H +#define PIOS_CONFIG_POSIX_H + /* Enable/Disable PiOS Modules */ -#define PIOS_INCLUDE_ADC -#define PIOS_INCLUDE_DELAY -#define PIOS_INCLUDE_IRQ -#define PIOS_INCLUDE_LED -#define PIOS_INCLUDE_SPI #define PIOS_INCLUDE_SYS -#define PIOS_INCLUDE_USART +#define PIOS_INCLUDE_DELAY +#define PIOS_INCLUDE_LED +#define PIOS_INCLUDE_SDCARD +#define PIOS_INCLUDE_FREERTOS #define PIOS_INCLUDE_COM -#define PIOS_INCLUDE_GPIO -#define PIOS_INCLUDE_EXTI -#define PIOS_INCLUDE_USB -#define PIOS_INCLUDE_USB_HID +#define PIOS_INCLUDE_UDP +#define PIOS_INCLUDE_SERVO -#endif /* PIOS_CONFIG_H */ + +/* 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 + + +#endif /* PIOS_CONFIG_POSIX_H */ diff --git a/flight/PipXtreme/inc/pios_usb_board_data.h b/flight/PipXtreme/System/inc/pios_usb_board_data.h similarity index 88% rename from flight/PipXtreme/inc/pios_usb_board_data.h rename to flight/PipXtreme/System/inc/pios_usb_board_data.h index d4f4daf0a..4448831d8 100644 --- a/flight/PipXtreme/inc/pios_usb_board_data.h +++ b/flight/PipXtreme/System/inc/pios_usb_board_data.h @@ -31,13 +31,16 @@ #ifndef PIOS_USB_BOARD_DATA_H #define PIOS_USB_BOARD_DATA_H +#define PIOS_USB_BOARD_CDC_DATA_LENGTH 64 +#define PIOS_USB_BOARD_CDC_MGMT_LENGTH 32 #define PIOS_USB_BOARD_HID_DATA_LENGTH 64 -#define PIOS_USB_BOARD_EP_NUM 2 +#define PIOS_USB_BOARD_EP_NUM 4 -#include "pios_usb_defs.h" /* struct usb_* */ +#include "pios_usb_defs.h" /* USB_* macros */ #define PIOS_USB_BOARD_PRODUCT_ID USB_PRODUCT_ID_PIPXTREME #define PIOS_USB_BOARD_DEVICE_VER USB_OP_DEVICE_VER(USB_OP_BOARD_ID_PIPXTREME, USB_OP_BOARD_MODE_FW) +#define PIOS_USB_BOARD_SN_SUFFIX "+FW" #endif /* PIOS_USB_BOARD_DATA_H */ diff --git a/flight/PipXtreme/System/pios_board.c b/flight/PipXtreme/System/pios_board.c new file mode 100644 index 000000000..ab53d7611 --- /dev/null +++ b/flight/PipXtreme/System/pios_board.c @@ -0,0 +1,398 @@ +/* -*- Mode: c; c-basic-offset: 2; tab-width: 2; indent-tabs-mode: t -*- */ +/** + ****************************************************************************** + * @addtogroup OpenPilotSystem OpenPilot System + * @{ + * @addtogroup OpenPilotCore OpenPilot Core + * @{ + * + * @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 +#include +#include +#include + +#define PIOS_COM_SERIAL_RX_BUF_LEN 256 +#define PIOS_COM_SERIAL_TX_BUF_LEN 256 + +#define PIOS_COM_FLEXI_RX_BUF_LEN 256 +#define PIOS_COM_FLEXI_TX_BUF_LEN 256 + +#define PIOS_COM_TELEM_USB_RX_BUF_LEN 256 +#define PIOS_COM_TELEM_USB_TX_BUF_LEN 256 + +#define PIOS_COM_VCP_USB_RX_BUF_LEN 256 +#define PIOS_COM_VCP_USB_TX_BUF_LEN 256 + +#define PIOS_COM_RFM22B_RF_RX_BUF_LEN 256 +#define PIOS_COM_RFM22B_RF_TX_BUF_LEN 256 + +uint32_t pios_com_telem_usb_id = 0; +uint32_t pios_com_telemetry_id; +uint32_t pios_com_flexi_id; +uint32_t pios_com_vcp_id; +uint32_t pios_com_uavtalk_com_id = 0; +uint32_t pios_com_trans_com_id = 0; +uint32_t pios_com_debug_id = 0; +uint32_t pios_com_rfm22b_id = 0; +uint32_t pios_rfm22b_id = 0; +uint32_t pios_ppm_rcvr_id = 0; + +/** + * PIOS_Board_Init() + * initializes all the core subsystems on this specific hardware + * called from System/openpilot.c + */ +void PIOS_Board_Init(void) { + + /* Delay system */ + PIOS_DELAY_Init(); + + /* Set up the SPI interface to the serial flash */ + if (PIOS_SPI_Init(&pios_spi_port_id, &pios_spi_port_cfg)) { + PIOS_Assert(0); + } + + /* Initialize UAVObject libraries */ + EventDispatcherInitialize(); + UAVObjInitialize(); + +#ifdef PIOS_INCLUDE_WDG + /* Initialize watchdog as early as possible to catch faults during init */ + PIOS_WDG_Init(); +#endif /* PIOS_INCLUDE_WDG */ + +#if defined(PIOS_INCLUDE_RTC) + /* Initialize the real-time clock and its associated tick */ + PIOS_RTC_Init(&pios_rtc_main_cfg); +#endif /* PIOS_INCLUDE_RTC */ + + PipXSettingsInitialize(); + +#if defined(PIOS_INCLUDE_LED) + PIOS_LED_Init(&pios_led_cfg); +#endif /* PIOS_INCLUDE_LED */ + + PipXSettingsData pipxSettings; +#if defined(PIOS_INCLUDE_FLASH_EEPROM) + PIOS_EEPROM_Init(&pios_eeprom_cfg); + + /* Read the settings from flash. */ + /* NOTE: We probably need to save/restore the objID here incase the object changed but the size doesn't */ + if (PIOS_EEPROM_Load((uint8_t*)&pipxSettings, sizeof(PipXSettingsData)) == 0) + PipXSettingsSet(&pipxSettings); + else + PipXSettingsGet(&pipxSettings); +#else + PipXSettingsGet(&pipxSettings); +#endif /* PIOS_INCLUDE_FLASH_EEPROM */ + + /* Initialize the task monitor library */ + TaskMonitorInitialize(); + +#if defined(PIOS_INCLUDE_TIM) + /* Set up pulse timers */ + PIOS_TIM_InitClock(&tim_1_cfg); + PIOS_TIM_InitClock(&tim_2_cfg); + PIOS_TIM_InitClock(&tim_3_cfg); + PIOS_TIM_InitClock(&tim_4_cfg); +#endif /* PIOS_INCLUDE_TIM */ + +#if defined(PIOS_INCLUDE_PACKET_HANDLER) + pios_packet_handler = PHInitialize(&pios_ph_cfg); +#endif /* PIOS_INCLUDE_PACKET_HANDLER */ + +#if defined(PIOS_INCLUDE_USB) + /* Initialize board specific USB data */ + PIOS_USB_BOARD_DATA_Init(); + + + /* Flags to determine if various USB interfaces are advertised */ + bool usb_hid_present = false; + bool usb_cdc_present = false; + +#if defined(PIOS_INCLUDE_USB_CDC) + if (PIOS_USB_DESC_HID_CDC_Init()) { + PIOS_Assert(0); + } + usb_hid_present = true; + usb_cdc_present = true; +#else + if (PIOS_USB_DESC_HID_ONLY_Init()) { + PIOS_Assert(0); + } + usb_hid_present = true; +#endif + + uint32_t pios_usb_id; + PIOS_USB_Init(&pios_usb_id, &pios_usb_main_cfg); + +#if defined(PIOS_INCLUDE_USB_CDC) + if (!usb_cdc_present) { + /* Force VCP port function to disabled if we haven't advertised VCP in our USB descriptor */ + pipxSettings.VCPConfig = PIPXSETTINGS_VCPCONFIG_DISABLED; + } + + switch (pipxSettings.VCPConfig) + { + case PIPXSETTINGS_VCPCONFIG_SERIAL: + case PIPXSETTINGS_VCPCONFIG_DEBUG: + { + uint32_t pios_usb_cdc_id; + if (PIOS_USB_CDC_Init(&pios_usb_cdc_id, &pios_usb_cdc_cfg, pios_usb_id)) { + PIOS_Assert(0); + } + uint8_t * rx_buffer = (uint8_t *) pvPortMalloc(PIOS_COM_VCP_USB_RX_BUF_LEN); + uint8_t * tx_buffer = (uint8_t *) pvPortMalloc(PIOS_COM_VCP_USB_TX_BUF_LEN); + PIOS_Assert(rx_buffer); + PIOS_Assert(tx_buffer); + if (PIOS_COM_Init(&pios_com_vcp_id, &pios_usb_cdc_com_driver, pios_usb_cdc_id, + rx_buffer, PIOS_COM_VCP_USB_RX_BUF_LEN, + tx_buffer, PIOS_COM_VCP_USB_TX_BUF_LEN)) { + PIOS_Assert(0); + } + switch (pipxSettings.TelemetryConfig) + { + case PIPXSETTINGS_VCPCONFIG_SERIAL: + pios_com_trans_com_id = pios_com_vcp_id; + break; + case PIPXSETTINGS_VCPCONFIG_DEBUG: + pios_com_debug_id = pios_com_vcp_id; + break; + } + break; + } + case PIPXSETTINGS_VCPCONFIG_DISABLED: + break; + } +#endif + +#if defined(PIOS_INCLUDE_USB_HID) + + /* Configure the usb HID port */ +#if defined(PIOS_INCLUDE_COM) + { + uint32_t pios_usb_hid_id; + if (PIOS_USB_HID_Init(&pios_usb_hid_id, &pios_usb_hid_cfg, pios_usb_id)) { + PIOS_Assert(0); + } + uint8_t * rx_buffer = (uint8_t *) pvPortMalloc(PIOS_COM_TELEM_USB_RX_BUF_LEN); + uint8_t * tx_buffer = (uint8_t *) pvPortMalloc(PIOS_COM_TELEM_USB_TX_BUF_LEN); + PIOS_Assert(rx_buffer); + PIOS_Assert(tx_buffer); + if (PIOS_COM_Init(&pios_com_telem_usb_id, &pios_usb_hid_com_driver, pios_usb_hid_id, + rx_buffer, PIOS_COM_TELEM_USB_RX_BUF_LEN, + tx_buffer, PIOS_COM_TELEM_USB_TX_BUF_LEN)) { + PIOS_Assert(0); + } + } +#endif /* PIOS_INCLUDE_COM */ + +#endif /* PIOS_INCLUDE_USB_HID */ + +#endif /* PIOS_INCLUDE_USB */ + + /* Configure USART1 (telemetry port) */ + switch (pipxSettings.TelemetryConfig) + { + case PIPXSETTINGS_TELEMETRYCONFIG_SERIAL: + case PIPXSETTINGS_TELEMETRYCONFIG_UAVTALK: + case PIPXSETTINGS_TELEMETRYCONFIG_DEBUG: + { + uint32_t pios_usart1_id; + if (PIOS_USART_Init(&pios_usart1_id, &pios_usart_serial_cfg)) { + PIOS_Assert(0); + } + uint8_t * rx_buffer = (uint8_t *) pvPortMalloc(PIOS_COM_SERIAL_RX_BUF_LEN); + uint8_t * tx_buffer = (uint8_t *) pvPortMalloc(PIOS_COM_SERIAL_TX_BUF_LEN); + PIOS_Assert(rx_buffer); + PIOS_Assert(tx_buffer); + if (PIOS_COM_Init(&pios_com_telemetry_id, &pios_usart_com_driver, pios_usart1_id, + rx_buffer, PIOS_COM_SERIAL_RX_BUF_LEN, + tx_buffer, PIOS_COM_SERIAL_TX_BUF_LEN)) { + PIOS_Assert(0); + } + switch (pipxSettings.TelemetryConfig) + { + case PIPXSETTINGS_TELEMETRYCONFIG_SERIAL: + pios_com_trans_com_id = pios_com_telemetry_id; + break; + case PIPXSETTINGS_TELEMETRYCONFIG_UAVTALK: + pios_com_uavtalk_com_id = pios_com_telemetry_id; + break; + case PIPXSETTINGS_TELEMETRYCONFIG_DEBUG: + pios_com_debug_id = pios_com_telemetry_id; + break; + } + break; + } + case PIPXSETTINGS_TELEMETRYCONFIG_DISABLED: + break; + } + + /* Configure USART3 */ + switch (pipxSettings.FlexiConfig) + { + case PIPXSETTINGS_FLEXICONFIG_SERIAL: + case PIPXSETTINGS_FLEXICONFIG_UAVTALK: + case PIPXSETTINGS_FLEXICONFIG_DEBUG: + { + uint32_t pios_usart3_id; + if (PIOS_USART_Init(&pios_usart3_id, &pios_usart_telem_flexi_cfg)) { + PIOS_Assert(0); + } + uint8_t * rx_buffer = (uint8_t *) pvPortMalloc(PIOS_COM_FLEXI_RX_BUF_LEN); + uint8_t * tx_buffer = (uint8_t *) pvPortMalloc(PIOS_COM_FLEXI_TX_BUF_LEN); + PIOS_Assert(rx_buffer); + PIOS_Assert(tx_buffer); + if (PIOS_COM_Init(&pios_com_flexi_id, &pios_usart_com_driver, pios_usart3_id, + rx_buffer, PIOS_COM_FLEXI_RX_BUF_LEN, + tx_buffer, PIOS_COM_FLEXI_TX_BUF_LEN)) { + PIOS_Assert(0); + } + switch (pipxSettings.FlexiConfig) + { + case PIPXSETTINGS_FLEXICONFIG_SERIAL: + pios_com_trans_com_id = pios_com_flexi_id; + break; + case PIPXSETTINGS_FLEXICONFIG_UAVTALK: + pios_com_uavtalk_com_id = pios_com_flexi_id; + break; + case PIPXSETTINGS_FLEXICONFIG_DEBUG: + pios_com_debug_id = pios_com_flexi_id; + break; + } + break; + } + case PIPXSETTINGS_FLEXICONFIG_PPM_IN: +#if defined(PIOS_INCLUDE_PPM) + { + uint32_t pios_ppm_id; + PIOS_PPM_Init(&pios_ppm_id, &pios_ppm_cfg); + + if (PIOS_RCVR_Init(&pios_ppm_rcvr_id, &pios_ppm_rcvr_driver, pios_ppm_id)) { + PIOS_Assert(0); + } + } +#endif /* PIOS_INCLUDE_PPM */ + case PIPXSETTINGS_FLEXICONFIG_PPM_OUT: + case PIPXSETTINGS_FLEXICONFIG_RSSI: + case PIPXSETTINGS_FLEXICONFIG_DISABLED: + break; + } + +#if defined(PIOS_INCLUDE_RFM22B) + struct pios_rfm22b_cfg pios_rfm22b_cfg = { + .frequencyHz = 434000000, + .minFrequencyHz = 434000000 - 2000000, + .maxFrequencyHz = 434000000 + 2000000, + .RFXtalCap = 0x7f, + .maxRFBandwidth = 128000, + .maxTxPower = RFM22_tx_pwr_txpow_7, // +20dBm .. 100mW + }; + + /* Retrieve hardware settings. */ + pios_rfm22b_cfg.frequencyHz = pipxSettings.Frequency; + pios_rfm22b_cfg.RFXtalCap = pipxSettings.FrequencyCalibration; + switch (pipxSettings.RFSpeed) + { + case PIPXSETTINGS_RFSPEED_2400: + pios_rfm22b_cfg.maxRFBandwidth = 2000; + break; + case PIPXSETTINGS_RFSPEED_4800: + pios_rfm22b_cfg.maxRFBandwidth = 4000; + break; + case PIPXSETTINGS_RFSPEED_9600: + pios_rfm22b_cfg.maxRFBandwidth = 9600; + break; + case PIPXSETTINGS_RFSPEED_19200: + pios_rfm22b_cfg.maxRFBandwidth = 19200; + break; + case PIPXSETTINGS_RFSPEED_38400: + pios_rfm22b_cfg.maxRFBandwidth = 32000; + break; + case PIPXSETTINGS_RFSPEED_57600: + pios_rfm22b_cfg.maxRFBandwidth = 64000; + break; + case PIPXSETTINGS_RFSPEED_115200: + pios_rfm22b_cfg.maxRFBandwidth = 128000; + break; + } + switch (pipxSettings.RFSpeed) + { + case PIPXSETTINGS_MAXRFPOWER_125: + pios_rfm22b_cfg.maxTxPower = RFM22_tx_pwr_txpow_0; + break; + case PIPXSETTINGS_MAXRFPOWER_16: + pios_rfm22b_cfg.maxTxPower = RFM22_tx_pwr_txpow_1; + break; + case PIPXSETTINGS_MAXRFPOWER_316: + pios_rfm22b_cfg.maxTxPower = RFM22_tx_pwr_txpow_2; + break; + case PIPXSETTINGS_MAXRFPOWER_63: + pios_rfm22b_cfg.maxTxPower = RFM22_tx_pwr_txpow_3; + break; + case PIPXSETTINGS_MAXRFPOWER_126: + pios_rfm22b_cfg.maxTxPower = RFM22_tx_pwr_txpow_4; + break; + case PIPXSETTINGS_MAXRFPOWER_25: + pios_rfm22b_cfg.maxTxPower = RFM22_tx_pwr_txpow_5; + break; + case PIPXSETTINGS_MAXRFPOWER_50: + pios_rfm22b_cfg.maxTxPower = RFM22_tx_pwr_txpow_6; + break; + case PIPXSETTINGS_MAXRFPOWER_100: + pios_rfm22b_cfg.maxTxPower = RFM22_tx_pwr_txpow_7; + break; + } + + /* Initalize the RFM22B radio COM device. */ + { + if (PIOS_RFM22B_Init(&pios_rfm22b_id, &pios_rfm22b_cfg)) { + PIOS_Assert(0); + } + uint8_t * rx_buffer = (uint8_t *) pvPortMalloc(PIOS_COM_RFM22B_RF_RX_BUF_LEN); + uint8_t * tx_buffer = (uint8_t *) pvPortMalloc(PIOS_COM_RFM22B_RF_TX_BUF_LEN); + PIOS_Assert(rx_buffer); + PIOS_Assert(tx_buffer); + if (PIOS_COM_Init(&pios_com_rfm22b_id, &pios_rfm22b_com_driver, pios_rfm22b_id, + rx_buffer, PIOS_COM_RFM22B_RF_RX_BUF_LEN, + tx_buffer, PIOS_COM_RFM22B_RF_TX_BUF_LEN)) { + PIOS_Assert(0); + } + } +#endif /* PIOS_INCLUDE_RFM22B */ + + /* Remap AFIO pin */ + GPIO_PinRemapConfig( GPIO_Remap_SWJ_NoJTRST, ENABLE); + +#ifdef PIOS_INCLUDE_ADC + PIOS_ADC_Init(); +#endif + PIOS_GPIO_Init(); +} + +/** + * @} + */ diff --git a/flight/PipXtreme/System/pios_board_posix.c b/flight/PipXtreme/System/pios_board_posix.c new file mode 100755 index 000000000..30f949830 --- /dev/null +++ b/flight/PipXtreme/System/pios_board_posix.c @@ -0,0 +1,142 @@ +/** + ****************************************************************************** + * + * @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 +#include +#include +#include +#include + +/** + * 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(); + + /* Initialize the alarms library */ + AlarmsInitialize(); + + /* Initialize the task monitor library */ + TaskMonitorInitialize(); + + /* Initialize the PiOS library */ + PIOS_COM_Init(); + +} + + +const struct pios_udp_cfg pios_udp0_cfg = { + .ip = "0.0.0.0", + .port = 9000, +}; +const struct pios_udp_cfg pios_udp1_cfg = { + .ip = "0.0.0.0", + .port = 9001, +}; +const struct pios_udp_cfg pios_udp2_cfg = { + .ip = "0.0.0.0", + .port = 9002, +}; + +#ifdef PIOS_COM_AUX +/* + * AUX USART + */ +const struct pios_udp_cfg pios_udp3_cfg = { + .ip = "0.0.0.0", + .port = 9003, +}; +#endif + +/* + * 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; + +struct pios_com_dev pios_com_devs[] = { + { + .id = PIOS_UDP_TELEM, + .driver = &pios_udp_com_driver, + }, + { + .id = PIOS_UDP_GPS, + .driver = &pios_udp_com_driver, + }, + { + .id = PIOS_UDP_LOCAL, + .driver = &pios_udp_com_driver, + }, +#ifdef PIOS_COM_AUX + { + .id = PIOS_UDP_AUX, + .driver = &pios_udp_com_driver, + }, +#endif +}; + +const uint8_t pios_com_num_devices = NELEMENTS(pios_com_devs); + +/** + * @} + */ diff --git a/flight/PipXtreme/pios_usb_board_data.c b/flight/PipXtreme/System/pios_usb_board_data.c similarity index 80% rename from flight/PipXtreme/pios_usb_board_data.c rename to flight/PipXtreme/System/pios_usb_board_data.c index 3e41e5ac9..c2e0c8762 100644 --- a/flight/PipXtreme/pios_usb_board_data.c +++ b/flight/PipXtreme/System/pios_usb_board_data.c @@ -31,6 +31,7 @@ #include "pios_usb_board_data.h" /* struct usb_*, USB_* */ #include "pios_sys.h" /* PIOS_SYS_SerialNumberGet */ #include "pios_usbhook.h" /* PIOS_USBHOOK_* */ +#include "pios_usb_util.h" /* PIOS_USB_UTIL_AsciiToUtf8 */ static const uint8_t usb_product_id[20] = { sizeof(usb_product_id), @@ -46,40 +47,15 @@ static const uint8_t usb_product_id[20] = { 'e', 0, }; -static uint8_t usb_serial_number[52] = { +static uint8_t usb_serial_number[2 + PIOS_SYS_SERIAL_NUM_ASCII_LEN*2 + (sizeof(PIOS_USB_BOARD_SN_SUFFIX)-1)*2] = { sizeof(usb_serial_number), USB_DESC_TYPE_STRING, - 0, 0, - 0, 0, - 0, 0, - 0, 0, - 0, 0, - 0, 0, - 0, 0, - 0, 0, - 0, 0, - 0, 0, - 0, 0, - 0, 0, - 0, 0, - 0, 0, - 0, 0, - 0, 0, - 0, 0, - 0, 0, - 0, 0, - 0, 0, - 0, 0, - 0, 0, - 0, 0, - 0, 0, - 0, 0 }; static const struct usb_string_langid usb_lang_id = { .bLength = sizeof(usb_lang_id), .bDescriptorType = USB_DESC_TYPE_STRING, - .bLangID = htousbs(USB_LANGID_ENGLISH_UK), + .bLangID = htousbs(USB_LANGID_ENGLISH_US), }; static const uint8_t usb_vendor_id[28] = { @@ -103,11 +79,13 @@ static const uint8_t usb_vendor_id[28] = { int32_t PIOS_USB_BOARD_DATA_Init(void) { /* Load device serial number into serial number string */ - uint8_t sn[25]; + uint8_t sn[PIOS_SYS_SERIAL_NUM_ASCII_LEN + 1]; PIOS_SYS_SerialNumberGet((char *)sn); - for (uint8_t i = 0; sn[i] != '\0' && (2 * i) < usb_serial_number[0]; i++) { - usb_serial_number[2 + 2 * i] = sn[i]; - } + + /* Concatenate the device serial number and the appropriate suffix ("+BL" or "+FW") into the USB serial number */ + uint8_t * utf8 = &(usb_serial_number[2]); + utf8 = PIOS_USB_UTIL_AsciiToUtf8(utf8, sn, PIOS_SYS_SERIAL_NUM_ASCII_LEN); + utf8 = PIOS_USB_UTIL_AsciiToUtf8(utf8, (uint8_t *)PIOS_USB_BOARD_SN_SUFFIX, sizeof(PIOS_USB_BOARD_SN_SUFFIX)-1); PIOS_USBHOOK_RegisterString(USB_STRING_DESC_PRODUCT, (uint8_t *)&usb_product_id, sizeof(usb_product_id)); PIOS_USBHOOK_RegisterString(USB_STRING_DESC_SERIAL, (uint8_t *)&usb_serial_number, sizeof(usb_serial_number)); diff --git a/flight/PipXtreme/System/pipxtreme.c b/flight/PipXtreme/System/pipxtreme.c new file mode 100755 index 000000000..7dfd28a96 --- /dev/null +++ b/flight/PipXtreme/System/pipxtreme.c @@ -0,0 +1,99 @@ +/** + ****************************************************************************** + * @addtogroup OpenPilotSystem OpenPilot System + * @brief These files are the core system files of OpenPilot. + * They are the ground layer just above PiOS. In practice, OpenPilot actually starts + * in the main() function of openpilot.c + * @{ + * @addtogroup OpenPilotCore OpenPilot Core + * @brief This is where the OP firmware starts. Those files also define the compile-time + * options of the firmware. + * @{ + * @file openpilot.c + * @author The OpenPilot Team, http://www.openpilot.org Copyright (C) 2010. + * @brief Sets up and runs main OpenPilot tasks. + * @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 + */ + + +/* OpenPilot Includes */ +#include "openpilot.h" +#include "uavobjectsinit.h" +#include "hwsettings.h" +#include "systemmod.h" + +/* Task Priorities */ +#define PRIORITY_TASK_HOOKS (tskIDLE_PRIORITY + 3) + +/* Global Variables */ + +/* Prototype of PIOS_Board_Init() function */ +extern void PIOS_Board_Init(void); +extern void Stack_Change(void); + +/** +* OpenPilot Main function: +* +* Initialize PiOS
+* Create the "System" task (SystemModInitializein Modules/System/systemmod.c)
+* Start FreeRTOS Scheduler (vTaskStartScheduler) (Now handled by caller) +* If something goes wrong, blink LED1 and LED2 every 100ms +* +*/ +int main() +{ + /* NOTE: Do NOT modify the following start-up sequence */ + /* Any new initialization functions should be added in OpenPilotInit() */ + + /* Brings up System using CMSIS functions, enables the LEDs. */ + PIOS_SYS_Init(); + + /* Architecture dependant Hardware and + * core subsystem initialisation + * (see pios_board.c for your arch) + * */ + PIOS_Board_Init(); + + /* Initialize modules */ + MODULE_INITIALISE_ALL + + /* swap the stack to use the IRQ stack */ + Stack_Change(); + + /* Start the FreeRTOS scheduler which should never returns.*/ + vTaskStartScheduler(); + + /* If all is well we will never reach here as the scheduler will now be running. */ + + /* Do some indication to user that something bad just happened */ + while (1) { +#if defined(PIOS_LED_HEARTBEAT) + PIOS_LED_Toggle(PIOS_LED_HEARTBEAT); +#endif /* PIOS_LED_HEARTBEAT */ + PIOS_DELAY_WaitmS(100); + } + + return 0; +} + +/** + * @} + * @} + */ + diff --git a/flight/PipXtreme/api_config.c b/flight/PipXtreme/api_config.c deleted file mode 100644 index 5aa9fc6c0..000000000 --- a/flight/PipXtreme/api_config.c +++ /dev/null @@ -1,852 +0,0 @@ -/** - ****************************************************************************** - * - * @file apiconfig_config.h - * @author The OpenPilot Team, http://www.openpilot.org Copyright (C) 2010. - * @brief RF Module hardware layer - * @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 - -#include "stm32f10x.h" -#include "gpio_in.h" -#include "api_config.h" -#include "rfm22b.h" -#include "packet_handler.h" -#include "stream.h" -#include "ppm.h" -#include "saved_settings.h" -#include "crc.h" -#include "main.h" -#include "pios_usb.h" /* PIOS_USB_* */ - -#if defined(PIOS_COM_DEBUG) -// #define APICONFIG_DEBUG -#endif - -// ***************************************************************************** -// modem configuration packets - -#define PIPX_HEADER_MARKER 0x76b38a52 - -enum { - PIPX_PACKET_TYPE_REQ_DETAILS = 0, - PIPX_PACKET_TYPE_DETAILS, - PIPX_PACKET_TYPE_REQ_SETTINGS, - PIPX_PACKET_TYPE_SETTINGS, - PIPX_PACKET_TYPE_REQ_STATE, - PIPX_PACKET_TYPE_STATE, - PIPX_PACKET_TYPE_SPECTRUM -}; - -typedef struct -{ - uint32_t marker; - uint32_t serial_number; - uint8_t type; - uint8_t spare; - uint16_t data_size; - uint32_t header_crc; - uint32_t data_crc; -// uint8_t data[0]; -} __attribute__((__packed__)) t_pipx_config_header; - -typedef struct -{ - uint8_t major_version; - uint8_t minor_version; - uint32_t serial_number; - uint32_t min_frequency_Hz; - uint32_t max_frequency_Hz; - uint8_t frequency_band; - float frequency_step_size; -} __attribute__((__packed__)) t_pipx_config_details; - -typedef struct -{ - uint8_t mode; - uint8_t link_state; - int16_t rssi; - int32_t afc; - uint16_t retries; -} __attribute__((__packed__)) t_pipx_config_state; - -typedef struct -{ - uint8_t mode; - uint32_t serial_baudrate; // serial usart baudrate - uint32_t destination_id; - uint32_t frequency_Hz; - uint32_t max_rf_bandwidth; - uint8_t max_tx_power; - uint8_t rf_xtal_cap; - bool aes_enable; - uint8_t aes_key[16]; - uint8_t rts_time; - uint8_t spare[16]; -} __attribute__((__packed__)) t_pipx_config_settings; - -typedef struct -{ - uint32_t start_frequency; - uint16_t frequency_step_size; - uint16_t magnitudes; -// int8_t magnitude[0]; -} __attribute__((__packed__)) t_pipx_config_spectrum; - -// ***************************************************************************** -// local variables - -uint32_t apiconfig_previous_com_port = 0; - -volatile uint16_t apiconfig_rx_config_timer = 0; -volatile uint16_t apiconfig_rx_timer = 0; -volatile uint16_t apiconfig_tx_timer = 0; -volatile uint16_t apiconfig_ss_timer = 0; - -uint8_t apiconfig_rx_buffer[256] __attribute__ ((aligned(4))); -uint16_t apiconfig_rx_buffer_wr; - -uint8_t apiconfig_tx_buffer[256] __attribute__ ((aligned(4))); -uint16_t apiconfig_tx_buffer_wr; - -uint8_t apiconfig_tx_config_buffer[128] __attribute__ ((aligned(4))); -uint16_t apiconfig_tx_config_buffer_wr; - -// for scanning the spectrum -int8_t apiconfig_spec_buffer[64] __attribute__ ((aligned(4))); -uint16_t apiconfig_spec_buffer_wr; -uint32_t apiconfig_spec_start_freq; -uint32_t apiconfig_spec_freq; - -bool apiconfig_usb_comms; -uint32_t apiconfig_comm_port; - -uint16_t apiconfig_connection_index; // the RF connection we are using - -uint8_t led_counter; - -// ***************************************************************************** - -int apiconfig_sendDetailsPacket(void) -{ - if (sizeof(apiconfig_tx_config_buffer) - apiconfig_tx_config_buffer_wr < sizeof(t_pipx_config_header) + sizeof(t_pipx_config_details)) - return -1; // not enough room in the tx buffer for the packet we were going to send - - t_pipx_config_header *header = (t_pipx_config_header *)(apiconfig_tx_config_buffer + apiconfig_tx_config_buffer_wr); - t_pipx_config_details *details = (t_pipx_config_details *)((uint8_t *)header + sizeof(t_pipx_config_header)); - - header->marker = PIPX_HEADER_MARKER; - header->serial_number = serial_number_crc32; - header->type = PIPX_PACKET_TYPE_DETAILS; - header->spare = 0; - header->data_size = sizeof(t_pipx_config_details); - - details->major_version = VERSION_MAJOR; - details->minor_version = VERSION_MINOR; - details->serial_number = serial_number_crc32; - details->min_frequency_Hz = saved_settings.min_frequency_Hz; - details->max_frequency_Hz = saved_settings.max_frequency_Hz; - details->frequency_band = saved_settings.frequency_band; - details->frequency_step_size = rfm22_getFrequencyStepSize(); - - header->data_crc = updateCRC32Data(0xffffffff, details, header->data_size); - header->header_crc = 0; - header->header_crc = updateCRC32Data(0xffffffff, header, sizeof(t_pipx_config_header)); - - int total_packet_size = sizeof(t_pipx_config_header) + header->data_size; - - apiconfig_tx_config_buffer_wr += total_packet_size; - - #if defined(APICONFIG_DEBUG) - DEBUG_PRINTF("TX api config: details\r\n"); - #endif - - return total_packet_size; -} - -int apiconfig_sendStatePacket(void) -{ - if (sizeof(apiconfig_tx_config_buffer) - apiconfig_tx_config_buffer_wr < sizeof(t_pipx_config_header) + sizeof(t_pipx_config_state)) - return -1; // not enough room in the tx buffer for the packet we were going to send - - t_pipx_config_header *header = (t_pipx_config_header *)(apiconfig_tx_config_buffer + apiconfig_tx_config_buffer_wr); - t_pipx_config_state *state = (t_pipx_config_state *)((uint8_t *)header + sizeof(t_pipx_config_header)); - - header->marker = PIPX_HEADER_MARKER; - header->serial_number = serial_number_crc32; - header->type = PIPX_PACKET_TYPE_STATE; - header->spare = 0; - header->data_size = sizeof(t_pipx_config_state); - - state->mode = 0; - state->link_state = ph_getCurrentLinkState(0); - state->rssi = ph_getLastRSSI(0); - state->afc = ph_getLastAFC(0); - state->retries = ph_getRetries(0); - - header->data_crc = updateCRC32Data(0xffffffff, state, header->data_size); - header->header_crc = 0; - header->header_crc = updateCRC32Data(0xffffffff, header, sizeof(t_pipx_config_header)); - - int total_packet_size = sizeof(t_pipx_config_header) + header->data_size; - - apiconfig_tx_config_buffer_wr += total_packet_size; - - #if defined(APICONFIG_DEBUG) - DEBUG_PRINTF("TX api config: state\r\n"); - #endif - - return total_packet_size; -} - -int apiconfig_sendSettingsPacket(void) -{ - if (sizeof(apiconfig_tx_config_buffer) - apiconfig_tx_config_buffer_wr < sizeof(t_pipx_config_header) + sizeof(t_pipx_config_settings)) - return -1; // not enough room in the tx buffer for the packet we were going to send - - t_pipx_config_header *header = (t_pipx_config_header *)(apiconfig_tx_config_buffer + apiconfig_tx_config_buffer_wr); - t_pipx_config_settings *settings = (t_pipx_config_settings *)((uint8_t *)header + sizeof(t_pipx_config_header)); - - header->marker = PIPX_HEADER_MARKER; - header->serial_number = serial_number_crc32; - header->type = PIPX_PACKET_TYPE_SETTINGS; - header->spare = 0; - header->data_size = sizeof(t_pipx_config_settings); - - settings->mode = saved_settings.mode; - settings->destination_id = saved_settings.destination_id; - settings->frequency_Hz = saved_settings.frequency_Hz; - settings->max_rf_bandwidth = saved_settings.max_rf_bandwidth; - settings->max_tx_power = saved_settings.max_tx_power; - settings->rf_xtal_cap = saved_settings.rf_xtal_cap; - settings->serial_baudrate = saved_settings.serial_baudrate; - settings->aes_enable = saved_settings.aes_enable; - memcpy((char *)settings->aes_key, (char *)saved_settings.aes_key, sizeof(settings->aes_key)); - settings->rts_time = saved_settings.rts_time; - memset(settings->spare, 0xff, sizeof(settings->spare)); - - header->data_crc = updateCRC32Data(0xffffffff, settings, header->data_size); - header->header_crc = 0; - header->header_crc = updateCRC32Data(0xffffffff, header, sizeof(t_pipx_config_header)); - - int total_packet_size = sizeof(t_pipx_config_header) + header->data_size; - - apiconfig_tx_config_buffer_wr += total_packet_size; - - #if defined(APICONFIG_DEBUG) - DEBUG_PRINTF("TX api config: settings\r\n"); - #endif - - return total_packet_size; -} - -int apiconfig_sendSpectrumPacket(uint32_t start_frequency, uint16_t freq_step_size, void *spectrum_data, uint32_t spectrum_data_size) -{ - if (sizeof(apiconfig_tx_config_buffer) - apiconfig_tx_config_buffer_wr < sizeof(t_pipx_config_header) + sizeof(t_pipx_config_spectrum) + spectrum_data_size) - return -1; // not enough room in the tx buffer for the packet we were going to send - - if (!spectrum_data || spectrum_data_size <= 0) - return -2; // nothing to send - - t_pipx_config_header *header = (t_pipx_config_header *)(apiconfig_tx_config_buffer + apiconfig_tx_config_buffer_wr); - t_pipx_config_spectrum *spectrum = (t_pipx_config_spectrum *)((uint8_t *)header + sizeof(t_pipx_config_header)); - uint8_t *data = (uint8_t *)spectrum + sizeof(t_pipx_config_spectrum); - - header->marker = PIPX_HEADER_MARKER; - header->serial_number = serial_number_crc32; - header->type = PIPX_PACKET_TYPE_SPECTRUM; - header->spare = 0; - header->data_size = sizeof(t_pipx_config_spectrum) + spectrum_data_size; - - spectrum->start_frequency = start_frequency; - spectrum->frequency_step_size = freq_step_size; - spectrum->magnitudes = spectrum_data_size; - memmove(data, spectrum_data, spectrum_data_size); - - header->data_crc = updateCRC32Data(0xffffffff, spectrum, header->data_size); - header->header_crc = 0; - header->header_crc = updateCRC32Data(0xffffffff, header, sizeof(t_pipx_config_header)); - - int total_packet_size = sizeof(t_pipx_config_header) + header->data_size; - - apiconfig_tx_config_buffer_wr += total_packet_size; - - #if defined(APICONFIG_DEBUG) - DEBUG_PRINTF("TX api config: spectrum\r\n"); - #endif - - return total_packet_size; -} - -void apiconfig_processInputPacket(void *buf, uint16_t len) -{ - if (len <= 0) - return; - - t_pipx_config_header *header = (t_pipx_config_header *)buf; - uint8_t *data = (uint8_t *)header + sizeof(t_pipx_config_header); - - switch (header->type) - { - case PIPX_PACKET_TYPE_REQ_DETAILS: - - #if defined(APICONFIG_DEBUG) - DEBUG_PRINTF("RX api config: req_details\r\n"); - #endif - - if (header->serial_number == 0 || header->serial_number == 0xffffffff || header->serial_number == serial_number_crc32) - apiconfig_sendDetailsPacket(); - - break; - - case PIPX_PACKET_TYPE_REQ_STATE: - - #if defined(APICONFIG_DEBUG) - DEBUG_PRINTF("RX api config: req_state\r\n"); - #endif - - if (header->serial_number == serial_number_crc32) - apiconfig_sendStatePacket(); - - break; - - case PIPX_PACKET_TYPE_REQ_SETTINGS: // they are requesting our configuration - - #if defined(APICONFIG_DEBUG) - DEBUG_PRINTF("RX api config: req_settings\r\n"); - #endif - - if (header->serial_number == serial_number_crc32) - apiconfig_sendSettingsPacket(); - - break; - - case PIPX_PACKET_TYPE_SETTINGS: // they have sent us new configuration settings - #if defined(APICONFIG_DEBUG) - DEBUG_PRINTF("RX api config: settings\r\n"); - #endif - - if (header->serial_number == serial_number_crc32) - { // the packet is meant for us - - booting = true; - - ph_set_remote_serial_number(0, 0); // stop the packet handler trying to communicate - - // ****** - // save the new settings - - t_pipx_config_settings *settings = (t_pipx_config_settings *)data; - - saved_settings.mode = settings->mode; - saved_settings.destination_id = settings->destination_id; - saved_settings.frequency_Hz = settings->frequency_Hz; - saved_settings.max_tx_power = settings->max_tx_power; - saved_settings.max_rf_bandwidth = settings->max_rf_bandwidth; - saved_settings.rf_xtal_cap = settings->rf_xtal_cap; - saved_settings.serial_baudrate = settings->serial_baudrate; - saved_settings.aes_enable = settings->aes_enable; - memcpy((char *)saved_settings.aes_key, (char *)settings->aes_key, sizeof(saved_settings.aes_key)); - saved_settings.rts_time = settings->rts_time; - - saved_settings_save(); // save them into flash - - // ****** - - ph_deinit(); - stream_deinit(); - ppm_deinit(); - - PIOS_COM_ChangeBaud(PIOS_COM_SERIAL, saved_settings.serial_baudrate); - - switch (saved_settings.mode) - { - case MODE_NORMAL: // normal 2-way packet mode - case MODE_STREAM_TX: // 1-way continuous tx packet mode - case MODE_STREAM_RX: // 1-way continuous rx packet mode - case MODE_PPM_TX: // PPM tx mode - case MODE_PPM_RX: // PPM rx mode - case MODE_SCAN_SPECTRUM: // scan the receiver over the whole band - case MODE_TX_BLANK_CARRIER_TEST: // blank carrier Tx mode (for calibrating the carrier frequency say) - case MODE_TX_SPECTRUM_TEST: // pseudo random Tx data mode (for checking the Tx carrier spectrum) - break; - default: // unknown mode - saved_settings.mode = MODE_NORMAL; - break; - } - - switch (saved_settings.mode) - { - case MODE_NORMAL: // normal 2-way packet mode - ph_init(serial_number_crc32); // initialise the packet handler - break; - - case MODE_STREAM_TX: // 1-way continuous tx packet mode - case MODE_STREAM_RX: // 1-way continuous rx packet mode - stream_init(serial_number_crc32); // initialise the continuous packet stream module - break; - - case MODE_PPM_TX: // PPM tx mode - case MODE_PPM_RX: // PPM rx mode - ppm_init(serial_number_crc32); // initialise the PPM module - break; - - case MODE_SCAN_SPECTRUM: // scan the receiver over the whole band - rfm22_init_scan_spectrum(saved_settings.min_frequency_Hz, saved_settings.max_frequency_Hz); - rfm22_setFreqCalibration(saved_settings.rf_xtal_cap); - apiconfig_spec_start_freq = saved_settings.min_frequency_Hz; - apiconfig_spec_freq = apiconfig_spec_start_freq; - apiconfig_spec_buffer_wr = 0; - apiconfig_ss_timer = 0; - break; - - case MODE_TX_BLANK_CARRIER_TEST: // blank carrier Tx mode (for calibrating the carrier frequency say) - rfm22_init_normal(saved_settings.min_frequency_Hz, saved_settings.max_frequency_Hz, rfm22_freqHopSize()); - rfm22_setFreqCalibration(saved_settings.rf_xtal_cap); - rfm22_setNominalCarrierFrequency(saved_settings.frequency_Hz); - rfm22_setDatarate(saved_settings.max_rf_bandwidth, TRUE); - rfm22_setTxPower(saved_settings.max_tx_power); - rfm22_setTxCarrierMode(); - break; - - case MODE_TX_SPECTRUM_TEST: // pseudo random Tx data mode (for checking the Tx carrier spectrum) - rfm22_init_normal(saved_settings.min_frequency_Hz, saved_settings.max_frequency_Hz, rfm22_freqHopSize()); - rfm22_setFreqCalibration(saved_settings.rf_xtal_cap); - rfm22_setNominalCarrierFrequency(saved_settings.frequency_Hz); - rfm22_setDatarate(saved_settings.max_rf_bandwidth, TRUE); - rfm22_setTxPower(saved_settings.max_tx_power); - rfm22_setTxPNMode(); - break; - } - - // ****** - - booting = false; - } - - break; - - default: - #if defined(APICONFIG_DEBUG) - DEBUG_PRINTF("RX api config: unknown type [%u]\r\n", header->type); - #endif - break; - } -} - -uint16_t apiconfig_scanForConfigPacket(void *buf, uint16_t *len, bool rf_packet) -{ - uint16_t length = *len; - uint16_t i = 0; - - while (TRUE) - { - uint32_t crc1, crc2; - - t_pipx_config_header *header = (t_pipx_config_header *)buf + i; - uint8_t *data = (uint8_t *)header + sizeof(t_pipx_config_header); - - if (i + sizeof(t_pipx_config_header) > length) - { // not enough data for a packet - if (i >= sizeof(header->marker)) - i -= sizeof(header->marker); - else - i = 0; - break; - } - - if (header->marker != PIPX_HEADER_MARKER) - { // no packet marker found - i++; - continue; - } - - // check the header is error free - crc1 = header->header_crc; - header->header_crc = 0; - crc2 = updateCRC32Data(0xffffffff, header, sizeof(t_pipx_config_header)); - header->header_crc = crc1; - if (crc2 != crc1) - { // faulty header or not really a header - i++; - continue; - } - - // valid header found! - - #if defined(APICONFIG_DEBUG) - DEBUG_PRINTF("RX api config: header found\r\n"); - #endif - - if (!rf_packet) - { - apiconfig_rx_config_timer = 0; // reset timer - apiconfig_rx_timer = 0; // reset the timer - } - - int total_packet_size = sizeof(t_pipx_config_header) + header->data_size; - - if (i + total_packet_size > length) - { // not yet got a full packet - break; - } - - if (header->data_size > 0) - { // check the data is error free - crc1 = header->data_crc; - crc2 = updateCRC32Data(0xffffffff, data, header->data_size); - if (crc2 != crc1) - { // faulty data .. remove the entire packet - length -= total_packet_size; - if (length - i > 0) - memmove(buf + i, buf + i + total_packet_size, length - i); - continue; - } - } - - if (!rf_packet) - apiconfig_processInputPacket(buf + i, length - i); - - // remove the packet from the buffer - length -= total_packet_size; - if (length - i > 0) - memmove(buf + i, buf + i + total_packet_size, length - i); - - break; - } - - *len = length; - - return i; -} - -// ***************************************************************************** -// send the data received from the local comm-port to the RF packet handler TX buffer - -void apiconfig_processTx(void) -{ - while (TRUE) - { - // scan for a configuration packet in the rx buffer - uint16_t data_size = apiconfig_scanForConfigPacket(apiconfig_rx_buffer, &apiconfig_rx_buffer_wr, false); - - uint16_t time_out = 5; // ms - if (!apiconfig_usb_comms) time_out = (15000 * sizeof(t_pipx_config_header)) / saved_settings.serial_baudrate; // allow enough time to rx a config header - if (time_out < 5) time_out = 5; - - if (data_size == 0 && apiconfig_rx_timer >= time_out) - // no config packet found in the buffer within the timeout period, treat any data in the buffer as data to be sent over the air - data_size = apiconfig_rx_buffer_wr; - - if (data_size == 0) - break; // no data to send over the air - - if (saved_settings.mode == MODE_NORMAL || saved_settings.mode == MODE_STREAM_TX) - { - // free space size in the RF packet handler tx buffer - uint16_t ph_num = ph_putData_free(apiconfig_connection_index); - - // set the USART RTS handshaking line - if (!apiconfig_usb_comms && ph_connected(apiconfig_connection_index)) - { - if (ph_num < 32) - SERIAL_RTS_CLEAR; // lower the USART RTS line - we don't have space in the buffer for anymore bytes - else - SERIAL_RTS_SET; // release the USART RTS line - we have space in the buffer for now bytes - } - else - SERIAL_RTS_SET; // release the USART RTS line - - #if defined(APICONFIG_DEBUG) - DEBUG_PRINTF("RX api config: data size %u\r\n", data_size); - #endif - - if (ph_connected(apiconfig_connection_index)) - { // we have an RF link to a remote modem - - if (ph_num < data_size) - break; // not enough room in the RF packet handler TX buffer for the data - - // copy the data into the RF packet handler TX buffer for sending over the RF link - data_size = ph_putData(apiconfig_connection_index, apiconfig_rx_buffer, data_size); - } - } - else - { - SERIAL_RTS_SET; // release the USART RTS line - we have space in the buffer for now bytes - } - - // remove the data from our RX buffer - apiconfig_rx_buffer_wr -= data_size; - if (apiconfig_rx_buffer_wr > 0) - memmove(apiconfig_rx_buffer, apiconfig_rx_buffer + data_size, apiconfig_rx_buffer_wr); - } -} - -// ***************************************************************************** -// send data down the local comm port - -void apiconfig_processRx(void) -{ - if (apiconfig_tx_config_buffer_wr > 0) - { // send any config packets in the config buffer - - while (TRUE) - { - uint16_t data_size = apiconfig_tx_config_buffer_wr; - -// if (data_size > 32) -// data_size = 32; - - if (!apiconfig_usb_comms && !GPIO_IN(SERIAL_CTS_PIN)) - break; // we can't yet send data down the comm-port - - // send the data out the comm-port - int32_t res = PIOS_COM_SendBufferNonBlocking(apiconfig_comm_port, apiconfig_tx_config_buffer, data_size); - if (res < 0) - { // failed to send the data out the comm-port - - #if defined(APICONFIG_DEBUG) - DEBUG_PRINTF("PIOS_COM_SendBuffer %d %d\r\n", data_size, res); - #endif - - if (apiconfig_tx_timer >= 5000) - { // seems we can't send our data for at least the last 5 seconds - delete it - apiconfig_tx_config_buffer_wr = 0; - } - - break; - } - - // data was sent out the comm-port OK .. remove the sent data from our buffer - - #if defined(APICONFIG_DEBUG) - DEBUG_PRINTF("TX api config: data [%u]\r\n", data_size); - #endif - - apiconfig_tx_config_buffer_wr -= data_size; - if (apiconfig_tx_config_buffer_wr > 0) - memmove(apiconfig_tx_config_buffer, apiconfig_tx_config_buffer + data_size, apiconfig_tx_config_buffer_wr); - - apiconfig_tx_timer = 0; - - break; - } - - return; - } - - if (saved_settings.mode == MODE_NORMAL || saved_settings.mode == MODE_STREAM_RX) - { - // send the data received via the RF link out the comm-port - while (TRUE) - { - // get number of data bytes received via the RF link - uint16_t ph_num = ph_getData_used(apiconfig_connection_index); - - // limit to how much space we have in the temp TX buffer - if (ph_num > sizeof(apiconfig_tx_buffer) - apiconfig_tx_buffer_wr) - ph_num = sizeof(apiconfig_tx_buffer) - apiconfig_tx_buffer_wr; - - if (ph_num > 0) - { // fetch the data bytes received via the RF link and save into our temp buffer - ph_num = ph_getData(apiconfig_connection_index, apiconfig_tx_buffer + apiconfig_tx_buffer_wr, ph_num); - apiconfig_tx_buffer_wr += ph_num; - } - - uint16_t data_size = apiconfig_tx_buffer_wr; - if (data_size == 0) - break; // no data to send - - // we have data to send down the comm-port -/* - #if (defined(PIOS_COM_DEBUG) && (PIOS_COM_DEBUG == PIOS_COM_SERIAL)) - if (!apiconfig_usb_comms) - { // the serial-port is being used for debugging - don't send data down it - apiconfig_tx_buffer_wr = 0; - apiconfig_tx_timer = 0; - continue; - } - #endif -*/ - if (!apiconfig_usb_comms && !GPIO_IN(SERIAL_CTS_PIN)) - break; // we can't yet send data down the comm-port - - // send the data out the comm-port - int32_t res = PIOS_COM_SendBufferNonBlocking(apiconfig_comm_port, apiconfig_tx_buffer, data_size); - if (res < 0) - { // failed to send the data out the comm-port - - #if defined(APICONFIG_DEBUG) - DEBUG_PRINTF("PIOS_COM_SendBuffer %d %d\r\n", data_size, res); - #endif - - if (apiconfig_tx_timer >= 5000) - { // seems we can't send our data for at least the last 5 seconds - delete it - apiconfig_tx_buffer_wr = 0; - } - - break; - } - - // data was sent out the comm-port OK .. remove the sent data from our buffer - - apiconfig_tx_buffer_wr -= data_size; - if (apiconfig_tx_buffer_wr > 0) - memmove(apiconfig_tx_buffer, apiconfig_tx_buffer + data_size, apiconfig_tx_buffer_wr); - - apiconfig_tx_timer = 0; - } - } -} - -// ************************************************************* - -void apiconfig_process_scan_spectrum(void) -{ - if (saved_settings.mode != MODE_SCAN_SPECTRUM) - return; - - if (apiconfig_ss_timer < 1) return; // 1ms - apiconfig_ss_timer = 0; - - if (++led_counter >= 30) - { - led_counter = 0; -// RX_LED_TOGGLE; - LINK_LED_TOGGLE; - } - -// uint16_t freq_step_size = (uint16_t)(rfm22_getFrequencyStepSize() * 4 + 0.5f); - uint16_t freq_step_size = (uint16_t)(rfm22_getFrequencyStepSize() * 20 + 0.5f); - - // fetch the current rssi level - int16_t rssi_dbm = rfm22_getRSSI(); - if (rssi_dbm < -128) rssi_dbm = -128; - else - if (rssi_dbm > 0) rssi_dbm = 0; - - // onto next frequency - apiconfig_spec_freq += freq_step_size; - if (apiconfig_spec_freq >= rfm22_maxFrequency()) apiconfig_spec_freq = rfm22_minFrequency(); - rfm22_setNominalCarrierFrequency(apiconfig_spec_freq); -// rfm22_setRxMode(RX_SCAN_SPECTRUM, true); - - // add the RSSI value to the buffer - apiconfig_spec_buffer[apiconfig_spec_buffer_wr] = rssi_dbm; - if (++apiconfig_spec_buffer_wr >= sizeof(apiconfig_spec_buffer)) - { // send the buffer - apiconfig_sendSpectrumPacket(apiconfig_spec_start_freq, freq_step_size, apiconfig_spec_buffer, apiconfig_spec_buffer_wr); - - apiconfig_spec_buffer_wr = 0; - apiconfig_spec_start_freq = apiconfig_spec_freq; - } -} - -// ***************************************************************************** -// call this as often as possible - not from an interrupt - -void apiconfig_process(void) -{ // copy data from comm-port RX buffer to RF packet handler TX buffer, and from RF packet handler RX buffer to comm-port TX buffer - - apiconfig_process_scan_spectrum(); - - // ******************** - - // decide which comm-port we are using (usart or usb) - apiconfig_usb_comms = false; // TRUE if we are using the usb port for comms. - apiconfig_comm_port = PIOS_COM_SERIAL; // default to using the usart comm-port - #if defined(PIOS_INCLUDE_USB) - if (PIOS_USB_CheckAvailable(0)) - { // USB comms is up, use the USB comm-port instead of the USART comm-port - apiconfig_usb_comms = true; - apiconfig_comm_port = PIOS_COM_TELEM_USB; - } - #endif - - // check to see if the local communication port has changed (usart/usb) - if (apiconfig_previous_com_port == 0 && apiconfig_previous_com_port != apiconfig_comm_port) - { // the local communications port has changed .. remove any data in the buffers - apiconfig_rx_buffer_wr = 0; - apiconfig_tx_buffer_wr = 0; - apiconfig_tx_config_buffer_wr = 0; - } - else - if (apiconfig_usb_comms) - { // we're using the USB for comms - keep the USART rx buffer empty - uint8_t c; - while (PIOS_COM_ReceiveBuffer(PIOS_COM_SERIAL, &c, 1, 0) > 0); - } - apiconfig_previous_com_port = apiconfig_comm_port; // remember the current comm-port we are using - - apiconfig_connection_index = 0; // the RF connection we are using - - // ******************* - // fetch the data received via the comm-port - - // get the number of data bytes received down the comm-port - uint16_t buf_avail = sizeof(apiconfig_rx_buffer) - apiconfig_rx_buffer_wr; - - PIOS_COM_ReceiveBuffer(apiconfig_comm_port, &(apiconfig_rx_buffer[apiconfig_rx_buffer_wr]), buf_avail, 0); - - apiconfig_processTx(); - apiconfig_processRx(); - - // speed the pinging speed up if the GCS is connected and monitoring the signal level etc - ph_setFastPing(apiconfig_rx_config_timer < 2000); -} - -// ***************************************************************************** -// can be called from an interrupt if you wish - -void apiconfig_1ms_tick(void) -{ // call this once every 1ms - - if (apiconfig_rx_config_timer < 0xffff) apiconfig_rx_config_timer++; - if (apiconfig_rx_timer < 0xffff) apiconfig_rx_timer++; - if (apiconfig_tx_timer < 0xffff) apiconfig_tx_timer++; - if (apiconfig_ss_timer < 0xffff) apiconfig_ss_timer++; -} - -// ***************************************************************************** - -void apiconfig_init(void) -{ - apiconfig_previous_com_port = 0; - - apiconfig_rx_buffer_wr = 0; - - apiconfig_tx_buffer_wr = 0; - - apiconfig_tx_config_buffer_wr = 0; - - apiconfig_rx_config_timer = 0xffff; - apiconfig_rx_timer = 0; - apiconfig_tx_timer = 0; - apiconfig_ss_timer = 0; - - apiconfig_spec_buffer_wr = 0; - apiconfig_spec_start_freq = 0; - - led_counter = 0; -} - -// ***************************************************************************** diff --git a/flight/PipXtreme/crc.c b/flight/PipXtreme/crc.c deleted file mode 100644 index 1c297a165..000000000 --- a/flight/PipXtreme/crc.c +++ /dev/null @@ -1,189 +0,0 @@ -/** - ****************************************************************************** - * - * @file crc.c - * @author The OpenPilot Team, http://www.openpilot.org Copyright (C) 2010. - * @brief Serial communication port handling 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 - */ - -#include "crc.h" - -// ************************************************************************** - -#define Poly16 0x8408 // HDLC polynomial: 1 + x**5 + x**12 + x**16 -#define Poly32 0x04c11db7 // 32-bit polynomial .. this should produce the same as the STM32 hardware CRC - -static const uint16_t CRC_Table16[] = { // HDLC polynomial - 0x0000, 0x1189, 0x2312, 0x329b, 0x4624, 0x57ad, 0x6536, 0x74bf, - 0x8c48, 0x9dc1, 0xaf5a, 0xbed3, 0xca6c, 0xdbe5, 0xe97e, 0xf8f7, - 0x1081, 0x0108, 0x3393, 0x221a, 0x56a5, 0x472c, 0x75b7, 0x643e, - 0x9cc9, 0x8d40, 0xbfdb, 0xae52, 0xdaed, 0xcb64, 0xf9ff, 0xe876, - 0x2102, 0x308b, 0x0210, 0x1399, 0x6726, 0x76af, 0x4434, 0x55bd, - 0xad4a, 0xbcc3, 0x8e58, 0x9fd1, 0xeb6e, 0xfae7, 0xc87c, 0xd9f5, - 0x3183, 0x200a, 0x1291, 0x0318, 0x77a7, 0x662e, 0x54b5, 0x453c, - 0xbdcb, 0xac42, 0x9ed9, 0x8f50, 0xfbef, 0xea66, 0xd8fd, 0xc974, - 0x4204, 0x538d, 0x6116, 0x709f, 0x0420, 0x15a9, 0x2732, 0x36bb, - 0xce4c, 0xdfc5, 0xed5e, 0xfcd7, 0x8868, 0x99e1, 0xab7a, 0xbaf3, - 0x5285, 0x430c, 0x7197, 0x601e, 0x14a1, 0x0528, 0x37b3, 0x263a, - 0xdecd, 0xcf44, 0xfddf, 0xec56, 0x98e9, 0x8960, 0xbbfb, 0xaa72, - 0x6306, 0x728f, 0x4014, 0x519d, 0x2522, 0x34ab, 0x0630, 0x17b9, - 0xef4e, 0xfec7, 0xcc5c, 0xddd5, 0xa96a, 0xb8e3, 0x8a78, 0x9bf1, - 0x7387, 0x620e, 0x5095, 0x411c, 0x35a3, 0x242a, 0x16b1, 0x0738, - 0xffcf, 0xee46, 0xdcdd, 0xcd54, 0xb9eb, 0xa862, 0x9af9, 0x8b70, - 0x8408, 0x9581, 0xa71a, 0xb693, 0xc22c, 0xd3a5, 0xe13e, 0xf0b7, - 0x0840, 0x19c9, 0x2b52, 0x3adb, 0x4e64, 0x5fed, 0x6d76, 0x7cff, - 0x9489, 0x8500, 0xb79b, 0xa612, 0xd2ad, 0xc324, 0xf1bf, 0xe036, - 0x18c1, 0x0948, 0x3bd3, 0x2a5a, 0x5ee5, 0x4f6c, 0x7df7, 0x6c7e, - 0xa50a, 0xb483, 0x8618, 0x9791, 0xe32e, 0xf2a7, 0xc03c, 0xd1b5, - 0x2942, 0x38cb, 0x0a50, 0x1bd9, 0x6f66, 0x7eef, 0x4c74, 0x5dfd, - 0xb58b, 0xa402, 0x9699, 0x8710, 0xf3af, 0xe226, 0xd0bd, 0xc134, - 0x39c3, 0x284a, 0x1ad1, 0x0b58, 0x7fe7, 0x6e6e, 0x5cf5, 0x4d7c, - 0xc60c, 0xd785, 0xe51e, 0xf497, 0x8028, 0x91a1, 0xa33a, 0xb2b3, - 0x4a44, 0x5bcd, 0x6956, 0x78df, 0x0c60, 0x1de9, 0x2f72, 0x3efb, - 0xd68d, 0xc704, 0xf59f, 0xe416, 0x90a9, 0x8120, 0xb3bb, 0xa232, - 0x5ac5, 0x4b4c, 0x79d7, 0x685e, 0x1ce1, 0x0d68, 0x3ff3, 0x2e7a, - 0xe70e, 0xf687, 0xc41c, 0xd595, 0xa12a, 0xb0a3, 0x8238, 0x93b1, - 0x6b46, 0x7acf, 0x4854, 0x59dd, 0x2d62, 0x3ceb, 0x0e70, 0x1ff9, - 0xf78f, 0xe606, 0xd49d, 0xc514, 0xb1ab, 0xa022, 0x92b9, 0x8330, - 0x7bc7, 0x6a4e, 0x58d5, 0x495c, 0x3de3, 0x2c6a, 0x1ef1, 0x0f78 -}; - -static const uint32_t CRC_Table32[] = { - 0x00000000, 0x04c11db7, 0x09823b6e, 0x0d4326d9, 0x130476dc, 0x17c56b6b, 0x1a864db2, 0x1e475005, - 0x2608edb8, 0x22c9f00f, 0x2f8ad6d6, 0x2b4bcb61, 0x350c9b64, 0x31cd86d3, 0x3c8ea00a, 0x384fbdbd, - 0x4c11db70, 0x48d0c6c7, 0x4593e01e, 0x4152fda9, 0x5f15adac, 0x5bd4b01b, 0x569796c2, 0x52568b75, - 0x6a1936c8, 0x6ed82b7f, 0x639b0da6, 0x675a1011, 0x791d4014, 0x7ddc5da3, 0x709f7b7a, 0x745e66cd, - 0x9823b6e0, 0x9ce2ab57, 0x91a18d8e, 0x95609039, 0x8b27c03c, 0x8fe6dd8b, 0x82a5fb52, 0x8664e6e5, - 0xbe2b5b58, 0xbaea46ef, 0xb7a96036, 0xb3687d81, 0xad2f2d84, 0xa9ee3033, 0xa4ad16ea, 0xa06c0b5d, - 0xd4326d90, 0xd0f37027, 0xddb056fe, 0xd9714b49, 0xc7361b4c, 0xc3f706fb, 0xceb42022, 0xca753d95, - 0xf23a8028, 0xf6fb9d9f, 0xfbb8bb46, 0xff79a6f1, 0xe13ef6f4, 0xe5ffeb43, 0xe8bccd9a, 0xec7dd02d, - 0x34867077, 0x30476dc0, 0x3d044b19, 0x39c556ae, 0x278206ab, 0x23431b1c, 0x2e003dc5, 0x2ac12072, - 0x128e9dcf, 0x164f8078, 0x1b0ca6a1, 0x1fcdbb16, 0x018aeb13, 0x054bf6a4, 0x0808d07d, 0x0cc9cdca, - 0x7897ab07, 0x7c56b6b0, 0x71159069, 0x75d48dde, 0x6b93dddb, 0x6f52c06c, 0x6211e6b5, 0x66d0fb02, - 0x5e9f46bf, 0x5a5e5b08, 0x571d7dd1, 0x53dc6066, 0x4d9b3063, 0x495a2dd4, 0x44190b0d, 0x40d816ba, - 0xaca5c697, 0xa864db20, 0xa527fdf9, 0xa1e6e04e, 0xbfa1b04b, 0xbb60adfc, 0xb6238b25, 0xb2e29692, - 0x8aad2b2f, 0x8e6c3698, 0x832f1041, 0x87ee0df6, 0x99a95df3, 0x9d684044, 0x902b669d, 0x94ea7b2a, - 0xe0b41de7, 0xe4750050, 0xe9362689, 0xedf73b3e, 0xf3b06b3b, 0xf771768c, 0xfa325055, 0xfef34de2, - 0xc6bcf05f, 0xc27dede8, 0xcf3ecb31, 0xcbffd686, 0xd5b88683, 0xd1799b34, 0xdc3abded, 0xd8fba05a, - 0x690ce0ee, 0x6dcdfd59, 0x608edb80, 0x644fc637, 0x7a089632, 0x7ec98b85, 0x738aad5c, 0x774bb0eb, - 0x4f040d56, 0x4bc510e1, 0x46863638, 0x42472b8f, 0x5c007b8a, 0x58c1663d, 0x558240e4, 0x51435d53, - 0x251d3b9e, 0x21dc2629, 0x2c9f00f0, 0x285e1d47, 0x36194d42, 0x32d850f5, 0x3f9b762c, 0x3b5a6b9b, - 0x0315d626, 0x07d4cb91, 0x0a97ed48, 0x0e56f0ff, 0x1011a0fa, 0x14d0bd4d, 0x19939b94, 0x1d528623, - 0xf12f560e, 0xf5ee4bb9, 0xf8ad6d60, 0xfc6c70d7, 0xe22b20d2, 0xe6ea3d65, 0xeba91bbc, 0xef68060b, - 0xd727bbb6, 0xd3e6a601, 0xdea580d8, 0xda649d6f, 0xc423cd6a, 0xc0e2d0dd, 0xcda1f604, 0xc960ebb3, - 0xbd3e8d7e, 0xb9ff90c9, 0xb4bcb610, 0xb07daba7, 0xae3afba2, 0xaafbe615, 0xa7b8c0cc, 0xa379dd7b, - 0x9b3660c6, 0x9ff77d71, 0x92b45ba8, 0x9675461f, 0x8832161a, 0x8cf30bad, 0x81b02d74, 0x857130c3, - 0x5d8a9099, 0x594b8d2e, 0x5408abf7, 0x50c9b640, 0x4e8ee645, 0x4a4ffbf2, 0x470cdd2b, 0x43cdc09c, - 0x7b827d21, 0x7f436096, 0x7200464f, 0x76c15bf8, 0x68860bfd, 0x6c47164a, 0x61043093, 0x65c52d24, - 0x119b4be9, 0x155a565e, 0x18197087, 0x1cd86d30, 0x029f3d35, 0x065e2082, 0x0b1d065b, 0x0fdc1bec, - 0x3793a651, 0x3352bbe6, 0x3e119d3f, 0x3ad08088, 0x2497d08d, 0x2056cd3a, 0x2d15ebe3, 0x29d4f654, - 0xc5a92679, 0xc1683bce, 0xcc2b1d17, 0xc8ea00a0, 0xd6ad50a5, 0xd26c4d12, 0xdf2f6bcb, 0xdbee767c, - 0xe3a1cbc1, 0xe760d676, 0xea23f0af, 0xeee2ed18, 0xf0a5bd1d, 0xf464a0aa, 0xf9278673, 0xfde69bc4, - 0x89b8fd09, 0x8d79e0be, 0x803ac667, 0x84fbdbd0, 0x9abc8bd5, 0x9e7d9662, 0x933eb0bb, 0x97ffad0c, - 0xafb010b1, 0xab710d06, 0xa6322bdf, 0xa2f33668, 0xbcb4666d, 0xb8757bda, 0xb5365d03, 0xb1f740b4 - }; - -// ************************************************************************** -// 16-bit CRC - -inline uint16_t updateCRC16(uint16_t crc, uint8_t b) -{ // update the crc - table method - return ((crc >> 8) ^ CRC_Table16[(crc & 0xff) ^ b]); -} -/* -uint16_t updateCRC16(uint16_t crc, uint8_t b) -{ // update the fcs - bit band method - register uint8_t f = (uint8_t)(crc >> 8); - crc = (crc & 0x00ff) ^ b; - for (int i = 8; i > 0; i--) - crc = (crc & 1) ? (crc >> 1) ^ Poly16 : crc >> 1; - return (crc ^ f); -} -*/ -uint16_t updateCRC16Data(uint16_t crc, void *data, uint32_t len) -{ - register uint8_t *p = (uint8_t *)data; - register uint16_t _crc = crc; - for (register uint32_t i = len; i > 0; i--) - _crc = (_crc >> 8) ^ CRC_Table16[(_crc ^ *p++) & 0xff]; -// _crc = UpdateCRC16(_crc, *p++); - return _crc; -} -/* -// Generate the CRC table -void makeCRC_Table16(void) -{ - for (uint16_t i = 0; i < 256; i++) - { - uint16_t crc = i; - for (int j = 8; j > 0; j--) - crc = (crc & 1) ? (crc >> 1) ^ Poly16 : crc >> 1; - CRC_Table16[i] = crc; - } -} -*/ -// ************************************************************************** -// 32-bit CRC - -inline uint32_t updateCRC32(uint32_t crc, uint8_t b) -{ - return ((crc << 8) ^ CRC_Table32[(crc >> 24) ^ b]); -} -/* -uint32_t updateCRC32(uint32_t crc, uint8_t b) -{ // update the crc - bit bang method - register uint32_t f = crc << 8; - crc = (crc >> 24) ^ b; - for (int i = 8; i > 0; i--) - crc = (crc & 1) ? (crc << 1) ^ Poly32 : crc << 1; - return (crc ^ f); -} -*/ -uint32_t updateCRC32Data(uint32_t crc, void *data, uint32_t len) -{ - register uint8_t *p = (uint8_t *)data; - register uint32_t _crc = crc; - for (register uint32_t i = len; i > 0; i--) - _crc = (_crc << 8) ^ CRC_Table32[(_crc >> 24) ^ *p++]; -// _crc = UpdateCRC32(_crc, *p++); - return _crc; -} -/* -// Generate the CRC table -void makeCRC_Table32(void) -{ - for (uint32_t i = 0; i < 256; i++) - { - uint32_t crc = i; - for (int j = 8; j > 0; j--) - crc = (crc & 1) ? (crc << 1) ^ Poly32 : crc << 1; - CRC_Table32[i] = crc; - } -} -*/ -// ************************************************************************** - -void CRC_init(void) -{ -// MakeCRC_Table16(); -// MakeCRC_Table32(); -} - -// ************************************************************************** diff --git a/flight/PipXtreme/gpio_in.c b/flight/PipXtreme/gpio_in.c deleted file mode 100644 index b67989b34..000000000 --- a/flight/PipXtreme/gpio_in.c +++ /dev/null @@ -1,182 +0,0 @@ -/** - ****************************************************************************** - * - * @file gpio_in.c - * @author The OpenPilot Team, http://www.openpilot.org Copyright (C) 2010. - * @brief GPIO input 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 - */ - - - - - -/* ***************************************************************** -// Example pin definitions .. this would go into your pios_board.h file - -// GPIO_Mode_AIN Analog Input -// GPIO_Mode_IN_FLOATING Input Floating -// GPIO_Mode_IPD Input Pull-Down -// GPIO_Mode_IPU Input Pull-up - -// API mode line -#define GPIO_IN_0_PORT GPIOB -#define GPIO_IN_0_PIN GPIO_Pin_13 -#define GPIO_IN_0_MODE GPIO_Mode_IPU - -// Serial port CTS line -#define GPIO_IN_1_PORT GPIOB -#define GPIO_IN_1_PIN GPIO_Pin_14 -#define GPIO_IN_1_MODE GPIO_Mode_IPU - -#define GPIO_IN_NUM 2 -#define GPIO_IN_PORTS { GPIO_IN_0_PORT, GPIO_IN_1_PORT } -#define GPIO_IN_PINS { GPIO_IN_0_PIN, GPIO_IN_1_PIN } -#define GPIO_IN_MODES { GPIO_IN_0_MODE, GPIO_IN_1_MODE } - -#define API_MODE_PIN 0 -#define SERIAL_CTS_PIN 1 - -********************************************************************* -Example usage .. - -{ - - - - // setup all the GPIO input pins - GPIO_IN_Init(); - - - - - if (!GPIO_IN(API_MODE_PIN)) - { // pin is LOW - - - } - else - { // pin is HIGH - - - } - - - -} - -***************************************************************************** */ - - - - -#include - -#include "gpio_in.h" - -// ***************************************************************************** -// setup the GPIO input pins - -// PORT .. -// GPIOA -// GPIOB -// GPIOC -// GPIOD -// GPIOE -// GPIOF -// GPIOG - -// PIN .. -// GPIO_Pin_0 -// GPIO_Pin_1 -// GPIO_Pin_2 -// GPIO_Pin_3 -// GPIO_Pin_4 -// GPIO_Pin_5 -// GPIO_Pin_6 -// GPIO_Pin_7 -// GPIO_Pin_8 -// GPIO_Pin_9 -// GPIO_Pin_10 -// GPIO_Pin_11 -// GPIO_Pin_12 -// GPIO_Pin_13 -// GPIO_Pin_14 -// GPIO_Pin_15 - -// MODE .. -// GPIO_Mode_AIN Analog Input -// GPIO_Mode_IN_FLOATING Input Floating -// GPIO_Mode_IPD Input Pull-Down -// GPIO_Mode_IPU Input Pull-up - -#if defined(GPIO_IN_NUM) && defined(GPIO_IN_PORTS) && defined(GPIO_IN_PINS) && defined(GPIO_IN_MODES) -// #if defined(PIOS_INCLUDE_GPIO_IN) && defined(PIOS_GPIO_IN_NUM) && defined(PIOS_GPIO_IN_PORTS) && defined(PIOS_GPIO_IN_PINS) && defined(PIOS_GPIO_IN_MODES) - - // Local Variables - static GPIO_TypeDef *GPIO_IN_PORT[GPIO_IN_NUM] = GPIO_IN_PORTS; - static const uint32_t GPIO_IN_PIN[GPIO_IN_NUM] = GPIO_IN_PINS; - static const uint32_t GPIO_IN_MODE[GPIO_IN_NUM] = GPIO_IN_MODES; - - /** - * Initialises all the GPIO INPUT's - */ - void GPIO_IN_Init(void) - { - GPIO_InitTypeDef GPIO_InitStructure; - GPIO_InitStructure.GPIO_Speed = GPIO_Speed_2MHz; - - for (int i = 0; i < GPIO_IN_NUM; i++) - { - switch ((uint32_t)GPIO_IN_PORT[i]) - { - case (uint32_t)GPIOA: RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE); break; - case (uint32_t)GPIOB: RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE); break; - case (uint32_t)GPIOC: RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOC, ENABLE); break; - case (uint32_t)GPIOD: RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOD, ENABLE); break; - case (uint32_t)GPIOE: RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOE, ENABLE); break; - case (uint32_t)GPIOF: RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOF, ENABLE); break; - case (uint32_t)GPIOG: RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOG, ENABLE); break; - } - GPIO_InitStructure.GPIO_Pin = GPIO_IN_PIN[i]; - GPIO_InitStructure.GPIO_Mode = GPIO_IN_MODE[i]; - GPIO_Init(GPIO_IN_PORT[i], &GPIO_InitStructure); - } - } - - /** - * Read input pin level - * \param[num] Pin Pin Number - */ - bool GPIO_IN(uint8_t num) - { // return .. - // FALSE if the input pin is LOW - // TRUE if the input pin is HIGH - if (num >= GPIO_IN_NUM) return FALSE; - return ((GPIO_IN_PORT[num]->IDR & GPIO_IN_PIN[num]) != 0); - } - -#endif - -// *********************************************************************************** - -/** - * @} - * @} - */ diff --git a/flight/PipXtreme/inc/main.h b/flight/PipXtreme/inc/main.h deleted file mode 100644 index b1efc1fce..000000000 --- a/flight/PipXtreme/inc/main.h +++ /dev/null @@ -1,74 +0,0 @@ -/** - ****************************************************************************** - * - * @file main.h - * @author The OpenPilot Team, http://www.openpilot.org Copyright (C) 2010. - * @brief Main modem 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 __MAIN_H__ -#define __MAIN_H__ - -#include - -// ***************************************************************************** - -// firmware version -#define VERSION_MAJOR 0 // 0 to 255 -#define VERSION_MINOR 9 // 0 to 255 - -// macro's for reading internal flash memory -#define mem8(addr) (*((volatile uint8_t *)(addr))) -#define mem16(addr) (*((volatile uint16_t *)(addr))) -#define mem32(addr) (*((volatile uint32_t *)(addr))) - -enum { - FREQBAND_UNKNOWN = 0, - FREQBAND_434MHz, - FREQBAND_868MHz, - FREQBAND_915MHz -}; - -enum { - MODE_NORMAL = 0, // normal 2-way packet mode - MODE_STREAM_TX, // 1-way continuous tx packet mode - MODE_STREAM_RX, // 1-way continuous rx packet mode - MODE_PPM_TX, // PPM tx mode - MODE_PPM_RX, // PPM rx mode - MODE_SCAN_SPECTRUM, // scan the receiver over the whole band - MODE_TX_BLANK_CARRIER_TEST, // blank carrier Tx mode (for calibrating the carrier frequency say) - MODE_TX_SPECTRUM_TEST // pseudo random Tx data mode (for checking the Tx carrier spectrum) -}; - -// ***************************************************************************** - -extern volatile uint32_t random32; - -extern bool booting; - -extern uint32_t flash_size; - -extern char serial_number_str[25]; -extern uint32_t serial_number_crc32; - -// ***************************************************************************** - -#endif diff --git a/flight/PipXtreme/inc/packet_handler.h b/flight/PipXtreme/inc/packet_handler.h deleted file mode 100644 index b2753bca3..000000000 --- a/flight/PipXtreme/inc/packet_handler.h +++ /dev/null @@ -1,76 +0,0 @@ -/** - ****************************************************************************** - * - * @file packet_handler.h - * @author The OpenPilot Team, http://www.openpilot.org Copyright (C) 2010. - * @brief Modem packet handling 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 - */ - -#ifndef __PACKET_HANDLER_H__ -#define __PACKET_HANDLER_H__ - -#include "stdint.h" - -// ***************************************************************************** - -#define PH_MAX_CONNECTIONS 1 // maximum number of remote connections - -// ***************************************************************************** - -void ph_1ms_tick(void); -void ph_process(void); - -bool ph_connected(const int connection_index); - -uint16_t ph_putData_free(const int connection_index); -uint16_t ph_putData(const int connection_index, const void *data, uint16_t len); - -uint16_t ph_getData_used(const int connection_index); -uint16_t ph_getData(const int connection_index, void *data, uint16_t len); - -void ph_setFastPing(bool fast); - -uint16_t ph_getRetries(const int connection_index); - -uint8_t ph_getCurrentLinkState(const int connection_index); - -int16_t ph_getLastRSSI(const int connection_index); -int32_t ph_getLastAFC(const int connection_index); - -void ph_setNominalCarrierFrequency(uint32_t frequency_hz); -uint32_t ph_getNominalCarrierFrequency(void); - -void ph_setDatarate(uint32_t datarate_bps); -uint32_t ph_getDatarate(void); - -void ph_setTxPower(uint8_t tx_power); -uint8_t ph_getTxPower(void); - -void ph_set_AES128_key(const void *key); - -int ph_set_remote_serial_number(int connection_index, uint32_t sn); -void ph_set_remote_encryption(int connection_index, bool enabled, const void *key); - -void ph_deinit(void); -void ph_init(uint32_t our_sn); - -// ***************************************************************************** - -#endif diff --git a/flight/PipXtreme/inc/saved_settings.h b/flight/PipXtreme/inc/saved_settings.h deleted file mode 100644 index d174281fc..000000000 --- a/flight/PipXtreme/inc/saved_settings.h +++ /dev/null @@ -1,80 +0,0 @@ -/** - ****************************************************************************** - * - * @file saved_settings.h - * @author The OpenPilot Team, http://www.openpilot.org Copyright (C) 2010. - * @brief RF Module hardware layer - * @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 _SAVED_SETTINGS_H_ -#define _SAVED_SETTINGS_H_ - -// ***************************************************************** - -#include "stm32f10x.h" -#include "stm32f10x_flash.h" - -// ***************************************************************** - -typedef struct -{ - uint32_t serial_baudrate; // serial uart baudrate - - uint32_t destination_id; - - uint32_t min_frequency_Hz; - uint32_t max_frequency_Hz; - uint32_t frequency_Hz; - - uint32_t max_rf_bandwidth; - - uint8_t max_tx_power; - - uint8_t frequency_band; - - uint8_t rf_xtal_cap; - - bool aes_enable; - uint8_t aes_key[16]; - - uint8_t mode; - - uint8_t rts_time; - - uint8_t spare[30]; // allow for future unknown settings - - uint32_t crc; -} __attribute__((__packed__)) t_saved_settings; - -// ***************************************************************** -// public variables - -extern volatile t_saved_settings saved_settings __attribute__ ((aligned(4))); // a RAM copy of the settings stored in EEPROM - -// ***************************************************************** -// public functions - -int32_t saved_settings_save(void); - -void saved_settings_init(void); - -// ***************************************************************** - -#endif diff --git a/flight/PipXtreme/inc/stopwatch.h b/flight/PipXtreme/inc/stopwatch.h deleted file mode 100644 index efc8b4d86..000000000 --- a/flight/PipXtreme/inc/stopwatch.h +++ /dev/null @@ -1,40 +0,0 @@ -/** - ****************************************************************************** - * - * @file stopwatch.h - * @author The OpenPilot Team, http://www.openpilot.org Copyright (C) 2010. - * @brief Stop watch function - * @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 __STOPWATCH_H__ -#define __STOPWATCH_H__ - -#include "stm32f10x.h" - -// ***************************************************************************** - -void STOPWATCH_init(uint32_t resolution); -void STOPWATCH_reset(void); -uint32_t STOPWATCH_get_count(void); -uint32_t STOPWATCH_get_us(void); - -// ***************************************************************************** - -#endif diff --git a/flight/PipXtreme/inc/stream.h b/flight/PipXtreme/inc/stream.h deleted file mode 100644 index 60245c0a7..000000000 --- a/flight/PipXtreme/inc/stream.h +++ /dev/null @@ -1,40 +0,0 @@ -/** - ****************************************************************************** - * - * @file stream.h - * @author The OpenPilot Team, http://www.openpilot.org Copyright (C) 2010. - * @brief Sends or Receives a continuous packet stream to/from the remote unit - * @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 STREAM_H_ -#define STREAM_H_ - -#include "stdint.h" - -// ************************************************************* - -void stream_1ms_tick(void); -void stream_process(void); -void stream_deinit(void); -void stream_init(uint32_t our_sn); - -// ************************************************************* - -#endif diff --git a/flight/PipXtreme/inc/transparent_comms.h b/flight/PipXtreme/inc/transparent_comms.h deleted file mode 100644 index 7a174cbf2..000000000 --- a/flight/PipXtreme/inc/transparent_comms.h +++ /dev/null @@ -1,40 +0,0 @@ -/** - ****************************************************************************** - * - * @file transparent_comms.h - * @author The OpenPilot Team, http://www.openpilot.org Copyright (C) 2010. - * @brief Serial communication port handling 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 - */ - -#ifndef __TRANSPARENT_COMMS_H__ -#define __TRANSPARENT_COMMS_H__ - -#include "stdint.h" - -// ***************************************************************************** - -void trans_1ms_tick(void); -void trans_process(void); - -void trans_init(void); - -// ***************************************************************************** - -#endif diff --git a/flight/PipXtreme/main.c b/flight/PipXtreme/main.c deleted file mode 100644 index 46b9073ea..000000000 --- a/flight/PipXtreme/main.c +++ /dev/null @@ -1,939 +0,0 @@ - -/** - ****************************************************************************** - * - * @file main.c - * @author The OpenPilot Team, http://www.openpilot.org Copyright (C) 2010. - * @brief Main modem 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 - */ - - -// ***************************************************************************** - -#define USE_WATCHDOG // comment this out if you don't want to use the watchdog - -// ***************************************************************************** -// OpenPilot Includes - -#include - -#include "crc.h" -#include "aes.h" -#include "rfm22b.h" -#include "packet_handler.h" -#include "stream.h" -#include "ppm.h" -#include "transparent_comms.h" -//#include "api_comms.h" -#include "api_config.h" -#include "gpio_in.h" -#include "stopwatch.h" -#include "watchdog.h" -#include "saved_settings.h" - -#include "main.h" - -/* Prototype of PIOS_Board_Init() function */ -extern void PIOS_Board_Init(void); - -// ***************************************************************************** -// ADC data - -#define ADC_REF 3.3f // ADC reference voltage -#define ADC_FULL_RANGE 4096 // 12 bit ADC - -#define ADC_PSU_RESISTOR_TOP 10000.0f // 10k upper resistor -#define ADC_PSU_RESISTOR_BOTTOM 2700.0f // 2k7 lower resistor -#define ADC_PSU_RATIO (ADC_PSU_RESISTOR_BOTTOM / (ADC_PSU_RESISTOR_TOP + ADC_PSU_RESISTOR_BOTTOM)) -#define ADC_PSU_mV_SCALE ((ADC_REF * 1000) / (ADC_FULL_RANGE * ADC_PSU_RATIO)) - -// ***************************************************************************** -// Global Variables - -uint32_t flash_size; - -char serial_number_str[25]; -uint32_t serial_number_crc32; - -uint32_t reset_addr; - -bool API_Mode; - -bool booting; - -volatile uint32_t random32; - -// ***************************************************************************** -// Local Variables - -#if defined(USE_WATCHDOG) - volatile uint16_t watchdog_timer; - uint16_t watchdog_delay; -#endif - -volatile bool inside_timer_int; -volatile uint32_t uptime_ms; - -volatile uint16_t second_tick_timer; -volatile bool second_tick; - -//volatile int32_t temp_adc; -//volatile int32_t psu_adc; - -// ***************************************************************************** - -#if defined(USE_WATCHDOG) - - void processWatchdog(void) - { - // random32 = UpdateCRC32(random32, IWDG->SR); - - if (watchdog_timer < watchdog_delay) - return; - - // the watchdog needs resetting - - watchdog_timer = 0; - - watchdog_Clear(); - } - - void enableWatchdog(void) - { // enable a watchdog - watchdog_timer = 0; - watchdog_delay = watchdog_Init(1000); // 1 second watchdog timeout - } - -#endif - -// ***************************************************************************** - -void sequenceLEDs(void) -{ - for (int i = 0; i < 2; i++) - { - USB_LED_ON; - PIOS_DELAY_WaitmS(80); - USB_LED_OFF; - - LINK_LED_ON; - PIOS_DELAY_WaitmS(80); - LINK_LED_OFF; - - RX_LED_ON; - PIOS_DELAY_WaitmS(80); - RX_LED_OFF; - - TX_LED_ON; - PIOS_DELAY_WaitmS(80); - TX_LED_OFF; - - #if defined(USE_WATCHDOG) - processWatchdog(); // process the watchdog - #endif - } -} - -// ***************************************************************************** -// timer interrupt - -void TIMER_INT_FUNC(void) -{ - inside_timer_int = TRUE; - - if (TIM_GetITStatus(TIMER_INT_TIMER, TIM_IT_Update) != RESET) - { - // Clear timer interrupt pending bit - TIM_ClearITPendingBit(TIMER_INT_TIMER, TIM_IT_Update); - -// random32 = UpdateCRC32(random32, PIOS_DELAY_GetuS() >> 8); -// random32 = UpdateCRC32(random32, PIOS_DELAY_GetuS()); - - uptime_ms++; - - #if defined(USE_WATCHDOG) - watchdog_timer++; - #endif - - // *********** - - if (!booting) - { - // *********** - - if (++second_tick_timer >= 1000) - { - second_tick_timer -= 1000; - second_tick = TRUE; - } - - // *********** - - // read the chip temperature -// temp_adc = PIOS_ADC_PinGet(0); - - // read the psu voltage -// psu_adc = PIOS_ADC_PinGet(1); - - // *********** - - uint8_t mode = saved_settings.mode; -// modeTxBlankCarrierTest, // blank carrier Tx mode (for calibrating the carrier frequency say) -// modeTxSpectrumTest // pseudo random Tx data mode (for checking the Tx carrier spectrum) - - rfm22_1ms_tick(); // rf module tick - - if (mode == MODE_NORMAL) - ph_1ms_tick(); // packet handler tick - - if (mode == MODE_STREAM_TX || mode == MODE_STREAM_RX) - stream_1ms_tick(); // continuous data stream tick - - if (mode == MODE_PPM_TX || mode == MODE_PPM_RX) - ppm_1ms_tick(); // ppm tick - - if (!API_Mode) - trans_1ms_tick(); // transparent communications tick - else -// api_1ms_tick(); // api communications tick - apiconfig_1ms_tick(); // api communications tick - - // *********** - } - } - - inside_timer_int = FALSE; -} - -void setup_TimerInt(uint16_t Hz) -{ // setup the timer interrupt - - // enable timer clock - switch ((uint32_t)TIMER_INT_TIMER) - { - case (uint32_t)TIM1: RCC_APB2PeriphClockCmd(RCC_APB2Periph_TIM1, ENABLE); break; - case (uint32_t)TIM2: RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2, ENABLE); break; - case (uint32_t)TIM3: RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM3, ENABLE); break; - case (uint32_t)TIM4: RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM4, ENABLE); break; - #ifdef STM32F10X_HD - case (uint32_t)TIM5: RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM5, ENABLE); break; - case (uint32_t)TIM6: RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM6, ENABLE); break; - case (uint32_t)TIM7: RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM7, ENABLE); break; - case (uint32_t)TIM8: RCC_APB2PeriphClockCmd(RCC_APB2Periph_TIM8, ENABLE); break; - #endif - } - - // enable timer interrupt - NVIC_InitTypeDef NVIC_InitStructure; - switch ((uint32_t)TIMER_INT_TIMER) - { -// case (uint32_t)TIM1: NVIC_InitStructure.NVIC_IRQChannel = TIM1_IRQn; break; - case (uint32_t)TIM2: NVIC_InitStructure.NVIC_IRQChannel = TIM2_IRQn; break; - case (uint32_t)TIM3: NVIC_InitStructure.NVIC_IRQChannel = TIM3_IRQn; break; - case (uint32_t)TIM4: NVIC_InitStructure.NVIC_IRQChannel = TIM4_IRQn; break; - #ifdef STM32F10X_HD - case (uint32_t)TIM5: NVIC_InitStructure.NVIC_IRQChannel = TIM5_IRQn; break; - case (uint32_t)TIM6: NVIC_InitStructure.NVIC_IRQChannel = TIM6_IRQn; break; - case (uint32_t)TIM7: NVIC_InitStructure.NVIC_IRQChannel = TIM7_IRQn; break; -// case (uint32_t)TIM8: NVIC_InitStructure.NVIC_IRQChannel = TIM8_IRQn; break; - #endif - } - NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = TIMER_INT_PRIORITY; - NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0; - NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; - NVIC_Init(&NVIC_InitStructure); - - // Time base configuration - TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure; - TIM_TimeBaseStructInit(&TIM_TimeBaseStructure); - TIM_TimeBaseStructure.TIM_Period = (1000000 / Hz) - 1; - TIM_TimeBaseStructure.TIM_Prescaler = (PIOS_MASTER_CLOCK / 1000000) - 1; // For 1 uS accuracy - TIM_TimeBaseStructure.TIM_ClockDivision = TIM_CKD_DIV1; - TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up; - TIM_TimeBaseInit(TIMER_INT_TIMER, &TIM_TimeBaseStructure); - - // Enable the CC2 Interrupt Request - TIM_ITConfig(TIMER_INT_TIMER, TIM_IT_Update, ENABLE); - - // Clear update pending flag - TIM_ClearFlag(TIMER_INT_TIMER, TIM_FLAG_Update); - - // Enable counter - TIM_Cmd(TIMER_INT_TIMER, ENABLE); -} - -// ***************************************************************************** -// read the CPU's flash and ram sizes - -void get_CPUDetails(void) -{ - // read the flash size - flash_size = (uint32_t)mem16(0x1FFFF7E0) * 1024; - - int j = 0; - - // read the CPU electronic signature (12-bytes) - serial_number_str[j] = 0; - for (int i = 0; i < 12; i++) - { - uint8_t ms_nibble = mem8(0x1ffff7e8 + i) >> 4; - uint8_t ls_nibble = mem8(0x1ffff7e8 + i) & 0x0f; - if (j > sizeof(serial_number_str) - 3) break; - serial_number_str[j++] = ((ms_nibble > 9) ? ('A' - 10) : '0') + ms_nibble; - serial_number_str[j++] = ((ls_nibble > 9) ? ('A' - 10) : '0') + ls_nibble; - serial_number_str[j] = 0; - } - - // create a 32-bit crc from the serial number hex string - serial_number_crc32 = updateCRC32Data(0xffffffff, serial_number_str, j); - serial_number_crc32 = updateCRC32(serial_number_crc32, j); - -// reset_addr = (uint32_t)&Reset_Handler; -} - -// ***************************************************************************** - -void init_RF_module(void) -{ - int i = -100; - - switch (saved_settings.frequency_band) - { - case FREQBAND_434MHz: - case FREQBAND_868MHz: - case FREQBAND_915MHz: - i = rfm22_init_normal(saved_settings.min_frequency_Hz, saved_settings.max_frequency_Hz, 50000); - break; - - default: - #if defined(PIOS_COM_DEBUG) - DEBUG_PRINTF("UNKNOWN BAND ERROR\r\n\r\n", i); - #endif - - for (int j = 0; j < 16; j++) - { - USB_LED_ON; - LINK_LED_OFF; - RX_LED_ON; - TX_LED_OFF; - - PIOS_DELAY_WaitmS(200); - - USB_LED_OFF; - LINK_LED_ON; - RX_LED_OFF; - TX_LED_ON; - - PIOS_DELAY_WaitmS(200); - - #if defined(USE_WATCHDOG) - processWatchdog(); - #endif - } - - PIOS_DELAY_WaitmS(1000); - - PIOS_SYS_Reset(); - - while (1); - break; - } - - if (i < 0) - { // RF module error .. flash the LED's - - #if defined(PIOS_COM_DEBUG) - DEBUG_PRINTF("RF ERROR res: %d\r\n\r\n", i); - #endif - - for (int j = 0; j < 16; j++) - { - USB_LED_ON; - LINK_LED_ON; - RX_LED_OFF; - TX_LED_OFF; - - PIOS_DELAY_WaitmS(200); - - USB_LED_OFF; - LINK_LED_OFF; - RX_LED_ON; - TX_LED_ON; - - PIOS_DELAY_WaitmS(200); - - #if defined(USE_WATCHDOG) - processWatchdog(); - #endif - } - - PIOS_DELAY_WaitmS(1000); - - PIOS_SYS_Reset(); - - while (1); - } - - rfm22_setFreqCalibration(saved_settings.rf_xtal_cap); - rfm22_setNominalCarrierFrequency(saved_settings.frequency_Hz); - rfm22_setDatarate(saved_settings.max_rf_bandwidth, TRUE); - rfm22_setTxPower(saved_settings.max_tx_power); -} - -// ***************************************************************************** -// find out what caused our reset and act on it - -void processReset(void) -{ - if (RCC_GetFlagStatus(RCC_FLAG_IWDGRST) != RESET) - { // Independant Watchdog Reset - - #if defined(PIOS_COM_DEBUG) - DEBUG_PRINTF("\r\nINDEPENDANT WATCHDOG CAUSED A RESET\r\n"); - #endif - - // all led's ON - USB_LED_ON; - LINK_LED_ON; - RX_LED_ON; - TX_LED_ON; - - PIOS_DELAY_WaitmS(500); // delay a bit - - // all led's OFF - USB_LED_OFF; - LINK_LED_OFF; - RX_LED_OFF; - TX_LED_OFF; - - } -/* - if (RCC_GetFlagStatus(RCC_FLAG_WWDGRST) != RESET) - { // Window Watchdog Reset - - DEBUG_PRINTF("\r\nWINDOW WATCHDOG CAUSED A REBOOT\r\n"); - - // all led's ON - USB_LED_ON; - LINK_LED_ON; - RX_LED_ON; - TX_LED_ON; - - PIOS_DELAY_WaitmS(500); // delay a bit - - // all led's OFF - USB_LED_OFF; - LINK_LED_OFF; - RX_LED_OFF; - TX_LED_OFF; - } -*/ - if (RCC_GetFlagStatus(RCC_FLAG_PORRST) != RESET) - { // Power-On Reset - #if defined(PIOS_COM_DEBUG) - DEBUG_PRINTF("\r\nPOWER-ON-RESET\r\n"); - #endif - } - - if (RCC_GetFlagStatus(RCC_FLAG_SFTRST) != RESET) - { // Software Reset - #if defined(PIOS_COM_DEBUG) - DEBUG_PRINTF("\r\nSOFTWARE RESET\r\n"); - #endif - } - - if (RCC_GetFlagStatus(RCC_FLAG_LPWRRST) != RESET) - { // Low-Power Reset - #if defined(PIOS_COM_DEBUG) - DEBUG_PRINTF("\r\nLOW POWER RESET\r\n"); - #endif - } - - if (RCC_GetFlagStatus(RCC_FLAG_PINRST) != RESET) - { // Pin Reset - #if defined(PIOS_COM_DEBUG) - DEBUG_PRINTF("\r\nPIN RESET\r\n"); - #endif - } - - // Clear reset flags - RCC_ClearFlag(); -} - -// ***************************************************************************** -// Main function - -int main() -{ - // ************* - // init various variables - - booting = TRUE; - - inside_timer_int = FALSE; - - uptime_ms = 0; - - flash_size = 0; - - serial_number_str[0] = 0; - serial_number_crc32 = 0; - - reset_addr = 0; - -// temp_adc = -1; -// psu_adc = -1; - -// API_Mode = FALSE; - API_Mode = TRUE; // TEST ONLY - - second_tick_timer = 0; - second_tick = FALSE; - - saved_settings.frequency_band = FREQBAND_UNKNOWN; - - // ************* - - PIOS_Board_Init(); - - CRC_init(); - - // read the CPU details - get_CPUDetails(); - - // setup the GPIO input pins - GPIO_IN_Init(); - - // ************* - // set various GPIO pin states - - // uart serial RTS line high - SERIAL_RTS_ENABLE; - SERIAL_RTS_SET; - - // RF module chip-select line high - RF_CS_ENABLE; - RF_CS_HIGH; - - // PPM OUT low - PPM_OUT_ENABLE; - PPM_OUT_LOW; - - // pin high - SPARE1_ENABLE; - SPARE1_HIGH; - - // pin high - SPARE2_ENABLE; - SPARE2_HIGH; - - // pin high - SPARE3_ENABLE; - SPARE3_HIGH; - - // pin high - SPARE4_ENABLE; - SPARE4_HIGH; - - // pin high - SPARE5_ENABLE; - SPARE5_HIGH; - - // ************* - - random32 ^= serial_number_crc32; // try to randomise the random number -// random32 ^= serial_number_crc32 ^ CRC_IDR; // try to randomise the random number - - trans_init(); // initialise the transparent communications module - -// api_init(); // initialise the API communications module - apiconfig_init(); // initialise the API communications module - - setup_TimerInt(1000); // setup a 1kHz timer interrupt - - #if defined(USE_WATCHDOG) - enableWatchdog(); // enable the watchdog - #endif - - // ************* - // do a simple LED flash test sequence so the user knows all the led's are working and that we have booted - - PIOS_DELAY_WaitmS(100); - - // turn all the leds off - USB_LED_OFF; - LINK_LED_OFF; - RX_LED_OFF; - TX_LED_OFF; - - PIOS_DELAY_WaitmS(200); - - sequenceLEDs(); - - // turn all the leds off - USB_LED_OFF; - LINK_LED_OFF; - RX_LED_OFF; - TX_LED_OFF; - - // ************* - - #if defined(PIOS_COM_DEBUG) - DEBUG_PRINTF("\r\n"); - DEBUG_PRINTF("PipXtreme v%u.%u rebooted\r\n", VERSION_MAJOR, VERSION_MINOR); - DEBUG_PRINTF("\r\n"); - DEBUG_PRINTF("CPU flash size: %u\r\n", flash_size); - DEBUG_PRINTF("CPU serial number: %s %08X\r\n", serial_number_str, serial_number_crc32); -// DEBUG_PRINTF("Reset address: %08X\r\n", reset_addr); - #endif - - // ************* - // initialise the saved settings module - - saved_settings_init(); - - if (saved_settings.mode == 0xff || - saved_settings.mode == MODE_TX_BLANK_CARRIER_TEST || - saved_settings.mode == MODE_TX_SPECTRUM_TEST || - saved_settings.mode == MODE_SCAN_SPECTRUM) - saved_settings.mode = MODE_NORMAL; // go back to NORMAL mode - - if (saved_settings.rts_time == 0xff || saved_settings.rts_time > 100) - saved_settings.rts_time = 10; // default to 10ms - - #if !defined(PIOS_COM_DEBUG) - if (saved_settings.serial_baudrate != 0xffffffff) - PIOS_COM_ChangeBaud(PIOS_COM_SERIAL, saved_settings.serial_baudrate); - #endif - - // ************* - // read the API mode pin - - if (!GPIO_IN(API_MODE_PIN)) - API_Mode = TRUE; - - #if defined(PIOS_COM_DEBUG) - if (!API_Mode) - DEBUG_PRINTF("TRANSPARENT mode\r\n"); - else - DEBUG_PRINTF("API mode\r\n"); - #endif - - // ************* - // read the 434/868/915 jumper options - - if (!GPIO_IN(_868MHz_PIN) && !GPIO_IN(_915MHz_PIN)) saved_settings.frequency_band = FREQBAND_434MHz; // 434MHz band - else - if (!GPIO_IN(_868MHz_PIN) && GPIO_IN(_915MHz_PIN)) saved_settings.frequency_band = FREQBAND_868MHz; // 868MHz band - else - if ( GPIO_IN(_868MHz_PIN) && !GPIO_IN(_915MHz_PIN)) saved_settings.frequency_band = FREQBAND_915MHz; // 915MHz band - - // set some defaults if they are not set - switch (saved_settings.frequency_band) - { - case FREQBAND_434MHz: - - if (saved_settings.min_frequency_Hz == 0xffffffff) - { - saved_settings.frequency_Hz = 434000000; - saved_settings.min_frequency_Hz = saved_settings.frequency_Hz - 2000000; - saved_settings.max_frequency_Hz = saved_settings.frequency_Hz + 2000000; - } - if (saved_settings.max_rf_bandwidth == 0xffffffff) - { - // saved_settings.max_rf_bandwidth = 500; - // saved_settings.max_rf_bandwidth = 1000; - // saved_settings.max_rf_bandwidth = 2000; - // saved_settings.max_rf_bandwidth = 4000; - // saved_settings.max_rf_bandwidth = 8000; - // saved_settings.max_rf_bandwidth = 9600; - // saved_settings.max_rf_bandwidth = 16000; - // saved_settings.max_rf_bandwidth = 19200; - // saved_settings.max_rf_bandwidth = 24000; - // saved_settings.max_rf_bandwidth = 32000; - // saved_settings.max_rf_bandwidth = 64000; - saved_settings.max_rf_bandwidth = 128000; - // saved_settings.max_rf_bandwidth = 192000; - } - if (saved_settings.max_tx_power == 0xff) - { - saved_settings.max_tx_power = RFM22_tx_pwr_txpow_0; // +1dBm ... 1.25mW - // saved_settings.max_tx_power = RFM22_tx_pwr_txpow_1; // +2dBm ... 1.6mW - // saved_settings.max_tx_power = RFM22_tx_pwr_txpow_2; // +5dBm ... 3.16mW - // saved_settings.max_tx_power = RFM22_tx_pwr_txpow_3; // +8dBm ... 6.3mW - // saved_settings.max_tx_power = RFM22_tx_pwr_txpow_4; // +11dBm .. 12.6mW - // saved_settings.max_tx_power = RFM22_tx_pwr_txpow_5; // +14dBm .. 25mW - // saved_settings.max_tx_power = RFM22_tx_pwr_txpow_6; // +17dBm .. 50mW - // saved_settings.max_tx_power = RFM22_tx_pwr_txpow_7; // +20dBm .. 100mW - } - break; - - case FREQBAND_868MHz: - if (saved_settings.min_frequency_Hz == 0xffffffff) - { - saved_settings.frequency_Hz = 868000000; - saved_settings.min_frequency_Hz = saved_settings.frequency_Hz - 10000000; - saved_settings.max_frequency_Hz = saved_settings.frequency_Hz + 10000000; - } - if (saved_settings.max_rf_bandwidth == 0xffffffff) - saved_settings.max_rf_bandwidth = 128000; - if (saved_settings.max_tx_power == 0xff) - saved_settings.max_tx_power = RFM22_tx_pwr_txpow_0; // +1dBm ... 1.25mW - break; - - case FREQBAND_915MHz: - if (saved_settings.min_frequency_Hz == 0xffffffff) - { - saved_settings.frequency_Hz = 915000000; - saved_settings.min_frequency_Hz = saved_settings.frequency_Hz - 13000000; - saved_settings.max_frequency_Hz = saved_settings.frequency_Hz + 13000000; - } - if (saved_settings.max_rf_bandwidth == 0xffffffff) - saved_settings.max_rf_bandwidth = 128000; - if (saved_settings.max_tx_power == 0xff) - saved_settings.max_tx_power = RFM22_tx_pwr_txpow_0; // +1dBm ... 1.25mW - break; - - default: - break; - } - - #if defined(PIOS_COM_DEBUG) - switch (saved_settings.frequency_band) - { - case FREQBAND_UNKNOWN: DEBUG_PRINTF("UNKNOWN band\r\n"); break; - case FREQBAND_434MHz: DEBUG_PRINTF("434MHz band\r\n"); break; - case FREQBAND_868MHz: DEBUG_PRINTF("868MHz band\r\n"); break; - case FREQBAND_915MHz: DEBUG_PRINTF("915MHz band\r\n"); break; - } - #endif - - // ************* - - processReset(); // Determine what caused the reset/reboot - - init_RF_module(); // initialise the RF module - - // ************* - - #if defined(PIOS_COM_DEBUG) - DEBUG_PRINTF("\r\n"); - DEBUG_PRINTF("RF datarate: %dbps\r\n", ph_getDatarate()); - DEBUG_PRINTF("RF frequency: %dHz\r\n", rfm22_getNominalCarrierFrequency()); - DEBUG_PRINTF("RF TX power: %d\r\n", ph_getTxPower()); - - DEBUG_PRINTF("\r\nUnit mode: "); - switch (saved_settings.mode) - { - case MODE_NORMAL: DEBUG_PRINTF("NORMAL\r\n"); break; - case MODE_STREAM_TX: DEBUG_PRINTF("STREAM-TX\r\n"); break; - case MODE_STREAM_RX: DEBUG_PRINTF("STREAM-RX\r\n"); break; - case MODE_PPM_TX: DEBUG_PRINTF("PPM-TX\r\n"); break; - case MODE_PPM_RX: DEBUG_PRINTF("PPM-RX\r\n"); break; - case MODE_SCAN_SPECTRUM: DEBUG_PRINTF("SCAN-SPECTRUM\r\n"); break; - case MODE_TX_BLANK_CARRIER_TEST: DEBUG_PRINTF("TX-BLANK-CARRIER\r\n"); break; - case MODE_TX_SPECTRUM_TEST: DEBUG_PRINTF("TX_SPECTRUM\r\n"); break; - default: DEBUG_PRINTF("UNKNOWN [%u]\r\n", saved_settings.mode); break; - } - #endif - - switch (saved_settings.mode) - { - case MODE_NORMAL: - ph_init(serial_number_crc32); // initialise the packet handler - break; - - case MODE_STREAM_TX: - case MODE_STREAM_RX: - stream_init(serial_number_crc32); // initialise the continuous packet stream module - break; - - case MODE_PPM_TX: - case MODE_PPM_RX: - ppm_init(serial_number_crc32); // initialise the ppm module - break; - - case MODE_SCAN_SPECTRUM: - case MODE_TX_BLANK_CARRIER_TEST: - case MODE_TX_SPECTRUM_TEST: - break; - } - - // ************* - // Main executive loop - - saved_settings_save(); - - booting = FALSE; - - for (;;) - { - random32 = updateCRC32(random32, PIOS_DELAY_GetuS() >> 8); - random32 = updateCRC32(random32, PIOS_DELAY_GetuS()); - - if (second_tick) - { - second_tick = FALSE; - - // ************************* - // display the up-time .. HH:MM:SS - -// #if defined(PIOS_COM_DEBUG) -// uint32_t _uptime_ms = uptime_ms; -// uint32_t _uptime_sec = _uptime_ms / 1000; -// DEBUG_PRINTF("Uptime: %02d:%02d:%02d.%03d\r\n", _uptime_sec / 3600, (_uptime_sec / 60) % 60, _uptime_sec % 60, _uptime_ms % 1000); -// #endif - - // ************************* - // process the Temperature - -// if (temp_adc >= 0) -// { -// int32_t degress_C = temp_adc; -// -// #if defined(PIOS_COM_DEBUG) -// DEBUG_PRINTF("TEMP: %d %d\r\n", temp_adc, degress_C); -// #endif -// } - - // ************************* - // process the PSU voltage level - -// if (psu_adc >= 0) -// { -// int32_t psu_mV = psu_adc * ADC_PSU_mV_SCALE; -// -// #if defined(PIOS_COM_DEBUG) -// DEBUG_PRINTF("PSU: %d, %dmV\r\n", psu_adc, psu_mV); -// #endif -// } - - // ************************* - } - - rfm22_process(); // rf hardware layer processing - - uint8_t mode = saved_settings.mode; -// modeTxBlankCarrierTest, // blank carrier Tx mode (for calibrating the carrier frequency say) -// modeTxSpectrumTest // pseudo random Tx data mode (for checking the Tx carrier spectrum) - - if (mode == MODE_NORMAL) - ph_process(); // packet handler processing - - if (mode == MODE_STREAM_TX || mode == MODE_STREAM_RX) - stream_process(); // continuous data stream processing - - if (mode == MODE_PPM_TX || mode == MODE_PPM_RX) - ppm_process(); // ppm processing - - if (!API_Mode) - trans_process(); // tranparent local communication processing (serial port and usb port) - else -// api_process(); // API local communication processing (serial port and usb port) - apiconfig_process(); // API local communication processing (serial port and usb port) - - - - - - - - - - - - - - - - - - - - - // ****************** - // TEST ONLY ... get/put data over the radio link .. speed testing .. comment out trans_process() and api_process() if testing with this -/* - int connection_index = 0; - - if (ph_connected(connection_index)) - { // we have a connection to a remote modem - - uint8_t buffer[128]; - - uint16_t num = ph_getData_used(connection_index); // number of bytes waiting for us to get - if (num > 0) - { // their is data in the received buffer - fetch it - if (num > sizeof(buffer)) num = sizeof(buffer); - num = ph_getData(connection_index, buffer, num); // fetch the received data - } - - // keep the tx buffer topped up - num = ph_putData_free(connection_index); - if (num > 0) - { // their is space available in the transmit buffer - top it up - if (num > sizeof(buffer)) num = sizeof(buffer); - for (int16_t i = 0; i < num; i++) buffer[i] = i; - num = ph_putData(connection_index, buffer, num); - } - } -*/ - // ****************** - - - - - - - - - - - - - - - - - #if defined(USE_WATCHDOG) - processWatchdog(); // process the watchdog - #endif - } - - // ************* - // we should never arrive here - - // disable all interrupts - PIOS_IRQ_Disable(); - - // turn off all leds - USB_LED_OFF; - LINK_LED_OFF; - RX_LED_OFF; - TX_LED_OFF; - - PIOS_SYS_Reset(); - - while (1); - - return 0; -} - -// ***************************************************************************** diff --git a/flight/PipXtreme/packet_handler.c b/flight/PipXtreme/packet_handler.c deleted file mode 100644 index 787a732b7..000000000 --- a/flight/PipXtreme/packet_handler.c +++ /dev/null @@ -1,1724 +0,0 @@ -/****************************************************************************** - * - * @file packet_handler.c - * @author The OpenPilot Team, http://www.openpilot.org Copyright (C) 2010. - * @brief Modem packet handling 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 - */ - - -// ******** - -// We use 128-bit AES CBC encryption if encryption is enabled - - -// encrypted packet format -// 16-byte CBC .. 1st byte must not be zero -// 4-byte source id -// 4-byte destination id -// 1-byte packet type -// 1-byte tx sequence value -// 1-byte rx sequence value -// 1-byte data size -// 4-byte crc of entire packet not including CBC bytes - - -// unencrypted packet format -// 1-byte null byte .. set to zero to indicate packet is not encrypted -// 4-byte source id -// 4-byte destination id -// 1-byte packet type -// 1-byte tx sequence value -// 1-byte rx sequence value -// 1-byte data size -// 4-byte crc of entire packet not including the null byte - -// ******** - -#include // memmove - -#include "main.h" -#include "rfm22b.h" -#include "fifo_buffer.h" -#include "aes.h" -#include "crc.h" -#include "saved_settings.h" -#include "packet_handler.h" - -#if defined(PIOS_COM_DEBUG) -// #define PACKET_DEBUG -#endif - -// ***************************************************************************** - -#define PH_FIFO_BUFFER_SIZE 2048 // FIFO buffer size - -// ***************************************************************************** - -#define AES_BLOCK_SIZE 16 // AES encryption does it in 16-byte blocks ONLY - -// default aes 128-bit encryption key -const uint8_t default_aes_key[AES_BLOCK_SIZE] = {0x65, 0x3b, 0x71, 0x89, 0x4a, 0xf4, 0xc8, 0xcb, 0x18, 0xd4, 0x9b, 0x4d, 0x4a, 0xbe, 0xc8, 0x37}; - -// ***************************************************************************** - -#define RETRY_RECONNECT_COUNT 60 // if transmission retries this many times then reset the link to the remote modem - -#define PACKET_TYPE_DATA_COMP_BIT 0x80 // data compressed bit. if set then the data in the packet is compressed -#define PACKET_TYPE_MASK 0x7f // packet type mask - -enum { - PACKET_TYPE_NONE = 0, - - PACKET_TYPE_CONNECT, // for requesting a connection - PACKET_TYPE_CONNECT_ACK, // ack - - PACKET_TYPE_DISCONNECT, // to tell the other modem they cannot connect to us - - PACKET_TYPE_DATA, // data packet (packet contains user data) - PACKET_TYPE_DATA_ACK, // ack - - PACKET_TYPE_READY, // tells the other modem we are ready to accept more data - PACKET_TYPE_READY_ACK, // ack - - PACKET_TYPE_NOTREADY, // tells the other modem we're not ready to accept more data - we can also send user data in this packet type - PACKET_TYPE_NOTREADY_ACK, // ack - - PACKET_TYPE_DATARATE, // for changing the RF data rate - PACKET_TYPE_DATARATE_ACK, // ack - - PACKET_TYPE_PING, // used to check link is still up - PACKET_TYPE_PONG, // ack - - PACKET_TYPE_ADJUST_TX_PWR, // used to ask the other modem to adjust it's tx power - PACKET_TYPE_ADJUST_TX_PWR_ACK // ack -}; - -#define BROADCAST_ADDR 0xffffffff - -//#pragma pack(push) -//#pragma pack(1) - -typedef struct -{ - uint32_t source_id; - uint32_t destination_id; - uint8_t type; - uint8_t tx_seq; - uint8_t rx_seq; - uint8_t data_size; - uint32_t crc; -} __attribute__((__packed__)) t_packet_header; - -// this structure must be a multiple of 'AES_BLOCK_SIZE' bytes in size and no more than 255 bytes in size -typedef struct -{ - uint8_t cbc[AES_BLOCK_SIZE]; // AES encryption Cipher-Block-Chaining key .. 1st byte must not be zero - to indicate the packet is encrypted - t_packet_header header; - uint8_t data[240 - sizeof(t_packet_header) - AES_BLOCK_SIZE]; -} __attribute__((__packed__)) t_encrypted_packet; - -// this structure must be no more than 255 bytes in size (255 = the maximum packet size) -typedef struct -{ - uint8_t null_byte; // this must be set to zero - to indicate the packet is unencrypted - t_packet_header header; - uint8_t data[255 - sizeof(t_packet_header) - 1]; -} __attribute__((__packed__)) t_unencrypted_packet; - -//#pragma pack(pop) - -// ***************************************************************************** -// link state for each remote connection - -enum { - LINK_DISCONNECTED = 0, - LINK_CONNECTING, - LINK_CONNECTED -}; - -typedef struct -{ - uint32_t serial_number; // their serial number - - uint8_t tx_buffer[PH_FIFO_BUFFER_SIZE] __attribute__ ((aligned(4))); - t_fifo_buffer tx_fifo_buffer; // holds the data to be transmitted to the other modem - - uint8_t rx_buffer[PH_FIFO_BUFFER_SIZE] __attribute__ ((aligned(4))); - t_fifo_buffer rx_fifo_buffer; // holds the data received from the other modem - - uint8_t link_state; // holds our current RF link state - - uint8_t tx_sequence; // incremented with each data packet transmitted, sent in every packet transmitted - uint8_t tx_sequence_data_size; // the size of data we sent in our last packet - - uint8_t rx_sequence; // incremented with each data packet received contain data, sent in every packet transmitted - - volatile uint16_t tx_packet_timer; // ms .. used for packet timing - - uint16_t tx_retry_time_slots; // add's some random packet transmission timing - to try to prevent transmission collisions - uint16_t tx_retry_time_slot_len; // ms .. " " " - uint16_t tx_retry_time; // ms .. " " " - uint16_t tx_retry_counter; // incremented on each transmission, reset back to '0' when we receive an ack to our transmission - - volatile uint16_t data_speed_timer; // used for calculating the transmit/receive data rate - volatile uint32_t tx_data_speed_count; // incremented with the number of data bits we send in our transmit packets - volatile uint32_t tx_data_speed; // holds the number of data bits we have sent each second - volatile uint32_t rx_data_speed_count; // incremented with the number of data bits we send in our transmit packets - volatile uint32_t rx_data_speed; // holds the number of data bits we have received each second - - uint16_t ping_time; // ping timer - uint16_t fast_ping_time; // ping timer - bool pinging; // TRUE if we are doing a ping test with the other modem - to check if it is still present - - bool rx_not_ready_mode; // TRUE if we have told the other modem we cannot receive data (due to buffer filling up). - // we set it back to FALSE when our received buffer starts to empty - - volatile int16_t ready_to_send_timer; // ms .. used to hold off packet transmission to wait a bit for data to mount up for transmission (improves data thru-put speed) - - volatile int32_t not_ready_timer; // ms .. >= 0 while we have been asked not to send anymore data to the other modem, -1 when we are allowed to send data - - bool send_encrypted; // TRUE if we are to AES encrypt in every packet we transmit - - int16_t rx_rssi_dBm; // the strength of the received packet - int32_t rx_afc_Hz; // the frequency offset of the received packet - -} t_connection; - -// ***************************************************************************** - -uint32_t our_serial_number = 0; // our serial number - -t_connection connection[PH_MAX_CONNECTIONS]; // holds each connection state - -uint8_t aes_key[AES_BLOCK_SIZE] __attribute__ ((aligned(4))); // holds the aes encryption key - the same for ALL connections -uint8_t dec_aes_key[AES_BLOCK_SIZE] __attribute__ ((aligned(4))); // holds the pre-calculated decryption key -uint8_t enc_cbc[AES_BLOCK_SIZE] __attribute__ ((aligned(4))); // holds the tx aes cbc bytes - -uint8_t ph_tx_buffer[256] __attribute__ ((aligned(4))); // holds the transmit packet - -uint8_t ph_rx_buffer[256] __attribute__ ((aligned(4))); // holds the received packet - -int16_t rx_rssi_dBm; -int32_t rx_afc_Hz; - -bool fast_ping; - -// ***************************************************************************** -// return TRUE if we are connected to the remote modem - -bool ph_connected(const int connection_index) -{ - if (connection_index < 0 || connection_index >= PH_MAX_CONNECTIONS) - return FALSE; - - t_connection *conn = &connection[connection_index]; - - return (conn->link_state == LINK_CONNECTED); -} - -// ***************************************************************************** -// public tx buffer functions - -uint16_t ph_putData_free(const int connection_index) -{ // return the free space size - if (connection_index < 0 || connection_index >= PH_MAX_CONNECTIONS) - return 0; - - return fifoBuf_getFree(&connection[connection_index].tx_fifo_buffer); -} - -uint16_t ph_putData(const int connection_index, const void *data, uint16_t len) -{ // add data to our tx buffer to be sent - if (connection_index < 0 || connection_index >= PH_MAX_CONNECTIONS) - return 0; - - return fifoBuf_putData(&connection[connection_index].tx_fifo_buffer, data, len); -} - -// ***************************************************************************** -// public rx buffer functions - -uint16_t ph_getData_used(const int connection_index) -{ // return the number of bytes available in the rx buffer - if (connection_index < 0 || connection_index >= PH_MAX_CONNECTIONS) - return 0; - - return fifoBuf_getUsed(&connection[connection_index].rx_fifo_buffer); -} - -uint16_t ph_getData(const int connection_index, void *data, uint16_t len) -{ // get data from our rx buffer - if (connection_index < 0 || connection_index >= PH_MAX_CONNECTIONS) - return 0; - - return fifoBuf_getData(&connection[connection_index].rx_fifo_buffer, data, len); -} - -// ***************************************************************************** -// start a connection to another modem - -int ph_startConnect(int connection_index, uint32_t sn) -{ - random32 = updateCRC32(random32, 0xff); - - if (connection_index < 0 || connection_index >= PH_MAX_CONNECTIONS) - return -1; - - t_connection *conn = &connection[connection_index]; - - conn->link_state = LINK_DISCONNECTED; - - LINK_LED_OFF; - - conn->serial_number = sn; - - conn->tx_sequence = 0; - conn->tx_sequence_data_size = 0; - conn->rx_sequence = 0; - -// fifoBuf_init(&conn->tx_fifo_buffer, conn->tx_buffer, PH_FIFO_BUFFER_SIZE); -// fifoBuf_init(&conn->rx_fifo_buffer, conn->rx_buffer, PH_FIFO_BUFFER_SIZE); - - conn->tx_packet_timer = 0; - - conn->tx_retry_time_slots = 5; - - uint32_t ms = 1280000ul / rfm22_getDatarate(); - if (ms < 10) ms = 10; - else - if (ms > 32000) ms = 32000; - conn->tx_retry_time_slot_len = ms; - - conn->tx_retry_time = conn->tx_retry_time_slot_len * 4 + (random32 % conn->tx_retry_time_slots) * conn->tx_retry_time_slot_len * 4; - - conn->tx_retry_counter = 0; - - conn->data_speed_timer = 0; - conn->tx_data_speed_count = 0; - conn->tx_data_speed = 0; - conn->rx_data_speed_count = 0; - conn->rx_data_speed = 0; - - conn->ping_time = 8000 + (random32 % 100) * 10; - conn->fast_ping_time = 600 + (random32 % 50) * 10; - conn->pinging = false; - - conn->rx_not_ready_mode = false; - - conn->ready_to_send_timer = -1; - - conn->not_ready_timer = -1; - -// conn->send_encrypted = true; -// conn->send_encrypted = false; - - conn->rx_rssi_dBm = -200; - conn->rx_afc_Hz = 0; - - if (sn != 0 && sn == our_serial_number) - return -2; // same as our own - - if (sn == BROADCAST_ADDR) - { - - return -3; - } - - if (conn->serial_number != 0) - conn->link_state = LINK_CONNECTING; - - return connection_index; -} - -// ***************************************************************************** -// return a byte for the tx packet transmission. -// -// return value < 0 if no more bytes available, otherwise return byte to be sent - -int16_t ph_TxDataByteCallback(void) -{ - return -1; -} - -// ************************************************************* -// we are being given a block of received bytes -// -// return TRUE to continue current packet receive, otherwise return FALSE to halt current packet reception - -bool ph_RxDataCallback(void *data, uint8_t len) -{ - return true; -} - -// ***************************************************************************** -// transmit a packet - -bool ph_sendPacket(int connection_index, bool encrypt, uint8_t packet_type, bool send_immediately) -{ - uint8_t key[AES_BLOCK_SIZE]; - - t_connection *conn = NULL; - - // *********** - - t_encrypted_packet *encrypted_packet = (t_encrypted_packet*)&ph_tx_buffer; // point to the tx buffer - t_unencrypted_packet *unencrypted_packet = (t_unencrypted_packet*)&ph_tx_buffer; // point to the tx buffer - - t_packet_header *header; - uint8_t *data; - uint16_t max_data_size; - - if (encrypt) - { - header = (t_packet_header *)&encrypted_packet->header; - data = (uint8_t *)&encrypted_packet->data; - max_data_size = sizeof(encrypted_packet->data); - } - else - { - header = (t_packet_header *)&unencrypted_packet->header; - data = (uint8_t *)&unencrypted_packet->data; - max_data_size = sizeof(unencrypted_packet->data); - } - - // *********** - - if (!rfm22_txReady()) - return false; - - if ((packet_type & PACKET_TYPE_MASK) == PACKET_TYPE_NONE) - return false; - - if (connection_index >= PH_MAX_CONNECTIONS) - return false; - - if (connection_index >= 0) - conn = (t_connection *)&connection[connection_index]; - else - return false; - - // ****************** - // stuff - - uint8_t pack_type = packet_type & PACKET_TYPE_MASK; - - bool data_packet = (pack_type == PACKET_TYPE_DATA || pack_type == PACKET_TYPE_NOTREADY); - - // ****************** - // calculate how many user data bytes we are going to add to the packet - - uint16_t data_size = 0; - - if (data_packet && conn) - { // we're adding user data to the packet - data_size = fifoBuf_getUsed(&connection[connection_index].tx_fifo_buffer); // the number of data bytes waiting to be sent - - if (data_size > max_data_size) - data_size = max_data_size; - - if (conn->tx_sequence_data_size > 0) - { // we are re-sending data the same data - if (data_size > conn->tx_sequence_data_size) - data_size = conn->tx_sequence_data_size; - } - } - - // ****************** - // calculate the total packet size (including null data bytes if we have to add null data byte in AES encrypted packets) - - uint32_t packet_size; - - if (encrypt) - { - packet_size = AES_BLOCK_SIZE + sizeof(t_packet_header) + data_size; - - // total packet size must be a multiple of 'AES_BLOCK_SIZE' bytes - aes encryption works on 16-byte blocks - packet_size = (packet_size + (AES_BLOCK_SIZE - 1)) & ~(AES_BLOCK_SIZE - 1); - } - else - { - packet_size = 1 + sizeof(t_packet_header) + data_size; - } - - // ****************** - // construct the packets entire header - - if (encrypt) - { - memmove(key, aes_key, sizeof(key)); // fetch the encryption key - aes_encrypt_cbc_128(enc_cbc, key, NULL); // help randomize the CBC bytes - - // ensure the 1st byte is not zero - to indicate this packet is encrypted - while (enc_cbc[0] == 0) - { - random32 = updateCRC32(random32, 0xff); - enc_cbc[0] ^= random32; - } - - memmove(encrypted_packet->cbc, enc_cbc, AES_BLOCK_SIZE); // copy the AES CBC bytes into the packet - } - else - unencrypted_packet->null_byte = 0; // packet is not encrypted - - header->source_id = our_serial_number; // our serial number -// header->destination_id = BROADCAST_ADDR; // broadcast packet - header->destination_id = conn->serial_number; // the other modems serial number - header->type = packet_type; // packet type - header->tx_seq = conn->tx_sequence; // our TX sequence number - header->rx_seq = conn->rx_sequence; // our RX sequence number - header->data_size = data_size; // the number of user data bytes in the packet - header->crc = 0; // the CRC of the header and user data bytes - - // ****************** - // add the user data to the packet - - if (data_packet) - { // we're adding user data to the packet - fifoBuf_getDataPeek(&connection[connection_index].tx_fifo_buffer, data, data_size); - - if (encrypt) - { // zero unused bytes - if (data_size < max_data_size) - memset(data + data_size, 0, max_data_size - data_size); - } - - conn->tx_sequence_data_size = data_size; // remember how much data we are sending in this packet - } - - // ****************** - // complete the packet header by adding the CRC - - if (encrypt) - header->crc = updateCRC32Data(0xffffffff, header, packet_size - AES_BLOCK_SIZE); - else - header->crc = updateCRC32Data(0xffffffff, header, packet_size - 1); - - // ****************** - // encrypt the packet - - if (encrypt) - { // encrypt the packet .. 'AES_BLOCK_SIZE' bytes at a time - uint8_t *p = (uint8_t *)encrypted_packet; - - // encrypt the cbc - memmove(key, aes_key, sizeof(key)); // fetch the encryption key - aes_encrypt_cbc_128(p, key, NULL); // encrypt block of data (the CBC bytes) - p += AES_BLOCK_SIZE; - - // encrypt the rest of the packet - for (uint16_t i = AES_BLOCK_SIZE; i < packet_size; i += AES_BLOCK_SIZE) - { - memmove(key, aes_key, sizeof(key)); // fetch the encryption key - aes_encrypt_cbc_128(p, key, enc_cbc); // encrypt block of data - p += AES_BLOCK_SIZE; - } - } - - // ****************** - // send the packet - - int32_t res = rfm22_sendData(&ph_tx_buffer, packet_size, send_immediately); - - // ****************** - - if (data_size > 0 && conn->tx_retry_counter == 0) - conn->tx_data_speed_count += data_size * 8; // + the number of data bits we just sent .. used for calculating the transmit data rate - - // ****************** - // debug stuff - -#if defined(PACKET_DEBUG) - - DEBUG_PRINTF("T-PACK "); - switch (pack_type) - { - case PACKET_TYPE_NONE: DEBUG_PRINTF("none"); break; - case PACKET_TYPE_CONNECT: DEBUG_PRINTF("connect"); break; - case PACKET_TYPE_CONNECT_ACK: DEBUG_PRINTF("connect_ack"); break; - case PACKET_TYPE_DISCONNECT: DEBUG_PRINTF("disconnect"); break; - case PACKET_TYPE_DATA: DEBUG_PRINTF("data"); break; - case PACKET_TYPE_DATA_ACK: DEBUG_PRINTF("data_ack"); break; - case PACKET_TYPE_READY: DEBUG_PRINTF("ready"); break; - case PACKET_TYPE_READY_ACK: DEBUG_PRINTF("ready_ack"); break; - case PACKET_TYPE_NOTREADY: DEBUG_PRINTF("notready"); break; - case PACKET_TYPE_NOTREADY_ACK: DEBUG_PRINTF("notready_ack"); break; - case PACKET_TYPE_DATARATE: DEBUG_PRINTF("datarate"); break; - case PACKET_TYPE_DATARATE_ACK: DEBUG_PRINTF("datarate_ack"); break; - case PACKET_TYPE_PING: DEBUG_PRINTF("ping"); break; - case PACKET_TYPE_PONG: DEBUG_PRINTF("pong"); break; - case PACKET_TYPE_ADJUST_TX_PWR: DEBUG_PRINTF("PACKET_TYPE_ADJUST_TX_PWR"); break; - case PACKET_TYPE_ADJUST_TX_PWR_ACK: DEBUG_PRINTF("PACKET_TYPE_ADJUST_TX_PWR_ACK"); break; - default: DEBUG_PRINTF("UNKNOWN [%d]", pack_type); break; - } - DEBUG_PRINTF(" tseq:%d rseq:%d", conn->tx_sequence, conn->rx_sequence); - DEBUG_PRINTF(" drate:%dbps", conn->tx_data_speed); - if (data_size > 0) DEBUG_PRINTF(" data_size:%d", data_size); - if (conn->tx_retry_counter > 0) DEBUG_PRINTF(" retry:%d", conn->tx_retry_counter); - DEBUG_PRINTF("\r\n"); -#endif - - // ****************** - - switch (pack_type) - { - case PACKET_TYPE_CONNECT: - case PACKET_TYPE_DISCONNECT: - case PACKET_TYPE_DATA: - case PACKET_TYPE_READY: - case PACKET_TYPE_NOTREADY: - case PACKET_TYPE_DATARATE: - case PACKET_TYPE_PING: - case PACKET_TYPE_ADJUST_TX_PWR: - if (conn->tx_retry_counter < 0xffff) - conn->tx_retry_counter++; - break; - - case PACKET_TYPE_CONNECT_ACK: - case PACKET_TYPE_DATA_ACK: - case PACKET_TYPE_READY_ACK: - case PACKET_TYPE_NOTREADY_ACK: - case PACKET_TYPE_DATARATE_ACK: - case PACKET_TYPE_PONG: - case PACKET_TYPE_ADJUST_TX_PWR_ACK: - break; - - case PACKET_TYPE_NONE: - break; - } - - return (res >= packet_size); -} - -// ***************************************************************************** - -void ph_processPacket2(bool was_encrypted, t_packet_header *header, uint8_t *data) -{ // process the received decrypted error-free packet - - USB_LED_TOGGLE; // TEST ONLY - - // *********** - - // fetch the data compressed bit - bool compressed_data = (header->type & PACKET_TYPE_DATA_COMP_BIT) != 0; - - // fetch the packet type - uint8_t packet_type = header->type & PACKET_TYPE_MASK; - - // fetch the number of data bytes in the packet - uint16_t data_size = header->data_size; - - // update the ramdon number - random32 = updateCRC32(random32, 0xff); - - // ********************* - // debug stuff -/* -#if defined(PACKET_DEBUG) - if (data_size > 0) - { - DEBUG_PRINTF("rx packet:"); - for (uint16_t i = 0; i < data_size; i++) - DEBUG_PRINTF(" %u", data[i]); - DEBUG_PRINTF("\r\n"); - } -#endif -*/ - // *********** - // debug stuff - -#if defined(PACKET_DEBUG) - DEBUG_PRINTF("R-PACK "); - switch (packet_type) - { - case PACKET_TYPE_NONE: DEBUG_PRINTF("none"); break; - case PACKET_TYPE_CONNECT: DEBUG_PRINTF("connect"); break; - case PACKET_TYPE_CONNECT_ACK: DEBUG_PRINTF("connect_ack"); break; - case PACKET_TYPE_DISCONNECT: DEBUG_PRINTF("disconnect"); break; - case PACKET_TYPE_DATA: DEBUG_PRINTF("data"); break; - case PACKET_TYPE_DATA_ACK: DEBUG_PRINTF("data_ack"); break; - case PACKET_TYPE_READY: DEBUG_PRINTF("ready"); break; - case PACKET_TYPE_READY_ACK: DEBUG_PRINTF("ready_ack"); break; - case PACKET_TYPE_NOTREADY: DEBUG_PRINTF("notready"); break; - case PACKET_TYPE_NOTREADY_ACK: DEBUG_PRINTF("notready_ack"); break; - case PACKET_TYPE_DATARATE: DEBUG_PRINTF("datarate"); break; - case PACKET_TYPE_DATARATE_ACK: DEBUG_PRINTF("datarate_ack"); break; - case PACKET_TYPE_PING: DEBUG_PRINTF("ping"); break; - case PACKET_TYPE_PONG: DEBUG_PRINTF("pong"); break; - case PACKET_TYPE_ADJUST_TX_PWR: DEBUG_PRINTF("PACKET_TYPE_ADJUST_TX_PWR"); break; - case PACKET_TYPE_ADJUST_TX_PWR_ACK: DEBUG_PRINTF("PACKET_TYPE_ADJUST_TX_PWR_ACK"); break; - default: DEBUG_PRINTF("UNKNOWN [%d]", packet_type); break; - } - DEBUG_PRINTF(" tseq-%d rseq-%d", header->tx_seq, header->rx_seq); -// DEBUG_PRINTF(" drate:%dbps", conn->rx_data_speed); - if (data_size > 0) DEBUG_PRINTF(" data_size:%d", data_size); - DEBUG_PRINTF(" %ddBm", rx_rssi_dBm); - DEBUG_PRINTF(" %dHz", rx_afc_Hz); - DEBUG_PRINTF("\r\n"); -#endif - - // ********************* - - if (header->source_id == our_serial_number) - return; // it's our own packet .. ignore it - - if (header->destination_id == BROADCAST_ADDR) - { // it's a broadcast packet - - - - // todo: - - - - - return; - } - - if (header->destination_id != our_serial_number) - return; // the packet is not meant for us - - // ********************* - // find out which remote connection this packet is from - - int connection_index = 0; - while (connection_index < PH_MAX_CONNECTIONS) - { - uint32_t sn = connection[connection_index].serial_number; - if (sn != 0) - { // connection used - if (header->source_id == sn) - break; // found it - } - connection_index++; - } - - if (connection_index >= PH_MAX_CONNECTIONS) - { // the packet is from an unknown source ID (unknown modem) - - if (packet_type != PACKET_TYPE_NONE) - { // send a disconnect packet back to them -// ph_sendPacket(-1, was_encrypted, PACKET_TYPE_DISCONNECT, true); - } - - return; - } - - t_connection *conn = &connection[connection_index]; - - // *********** - - conn->rx_rssi_dBm = rx_rssi_dBm; // remember the packets signal strength - conn->rx_afc_Hz = rx_afc_Hz; // remember the packets frequency offset - - // *********** - // decompress the data - - if (compressed_data && data_size > 0) - { - - - // todo: - - - } - - // *********** - - if (packet_type == PACKET_TYPE_NONE) - return; - - if (packet_type == PACKET_TYPE_DISCONNECT) - { - conn->link_state = LINK_DISCONNECTED; - LINK_LED_OFF; - return; - } - - if (packet_type == PACKET_TYPE_CONNECT) - { - LINK_LED_ON; - -// fifoBuf_init(&conn->tx_fifo_buffer, conn->tx_buffer, PH_FIFO_BUFFER_SIZE); -// fifoBuf_init(&conn->rx_fifo_buffer, conn->rx_buffer, PH_FIFO_BUFFER_SIZE); - - conn->tx_packet_timer = 0; - - conn->tx_retry_counter = 0; - conn->tx_retry_time = conn->tx_retry_time_slot_len + (random32 % conn->tx_retry_time_slots) * conn->tx_retry_time_slot_len; - - conn->rx_sequence = header->tx_seq; - conn->tx_sequence = 0; - conn->tx_sequence_data_size = 0; - - conn->data_speed_timer = 0; - conn->tx_data_speed_count = 0; - conn->tx_data_speed = 0; - conn->rx_data_speed_count = 0; - conn->rx_data_speed = 0; - - conn->ping_time = 8000 + (random32 % 100) * 10; - conn->fast_ping_time = 600 + (random32 % 50) * 10; - conn->pinging = false; - - conn->rx_not_ready_mode = false; - - conn->ready_to_send_timer = -1; - - conn->not_ready_timer = -1; - - conn->link_state = LINK_CONNECTED; - - // send an ack back - if (ph_sendPacket(connection_index, conn->send_encrypted, PACKET_TYPE_CONNECT_ACK, true)) - { - conn->tx_packet_timer = 0; - } - - return; - } - - if (packet_type == PACKET_TYPE_CONNECT_ACK) - { - LINK_LED_ON; - - if (conn->link_state != LINK_CONNECTING) - { // reset the link - ph_set_remote_serial_number(connection_index, conn->serial_number); - return; - } - - conn->tx_packet_timer = 0; - - conn->tx_retry_counter = 0; - conn->tx_retry_time = conn->tx_retry_time_slot_len + (random32 % conn->tx_retry_time_slots) * conn->tx_retry_time_slot_len; - - conn->rx_sequence = header->tx_seq; - conn->tx_sequence = 0; - conn->tx_sequence_data_size = 0; - - conn->data_speed_timer = 0; - conn->tx_data_speed_count = 0; - conn->tx_data_speed = 0; - conn->rx_data_speed_count = 0; - conn->rx_data_speed = 0; - - conn->ping_time = 8000 + (random32 % 100) * 10; - conn->fast_ping_time = 600 + (random32 % 50) * 10; - conn->pinging = false; - - conn->rx_not_ready_mode = false; - - conn->ready_to_send_timer = -1; - - conn->not_ready_timer = -1; - - conn->link_state = LINK_CONNECTED; - - return; - } - - - - - if (conn->link_state == LINK_CONNECTING) - { // we are trying to connect to them .. reply with a connect request packet - if (ph_sendPacket(connection_index, conn->send_encrypted, PACKET_TYPE_CONNECT, true)) - { - conn->tx_packet_timer = 0; - conn->tx_retry_time = conn->tx_retry_time_slot_len * 4 + (random32 % conn->tx_retry_time_slots) * conn->tx_retry_time_slot_len * 4; - } - return; - } - - if (conn->link_state != LINK_CONNECTED) - { // they have sent us a packet when we are not in a connected state - start a connection - ph_startConnect(connection_index, conn->serial_number); - return; - } - - - - - // check to make sure it's a wanted packet type - switch (packet_type) - { - case PACKET_TYPE_DATA: - case PACKET_TYPE_DATA_ACK: - case PACKET_TYPE_READY: - case PACKET_TYPE_READY_ACK: - case PACKET_TYPE_NOTREADY: - case PACKET_TYPE_NOTREADY_ACK: - case PACKET_TYPE_DATARATE: - case PACKET_TYPE_DATARATE_ACK: - case PACKET_TYPE_PING: - case PACKET_TYPE_PONG: - case PACKET_TYPE_ADJUST_TX_PWR: - case PACKET_TYPE_ADJUST_TX_PWR_ACK: - break; - default: - return; - } - - - - - - if ((conn->tx_sequence_data_size > 0) && (header->rx_seq == (uint8_t)(conn->tx_sequence + 1))) - { // they received our last data packet - - // remove the data we have sent and they have acked - fifoBuf_removeData(&conn->tx_fifo_buffer, conn->tx_sequence_data_size); - - conn->tx_sequence++; - conn->tx_retry_counter = 0; - conn->tx_sequence_data_size = 0; - conn->not_ready_timer = -1; // stop timer - } - - uint16_t size = fifoBuf_getUsed(&conn->tx_fifo_buffer); // the size of data waiting to be sent - - - - - if (packet_type == PACKET_TYPE_DATA || packet_type == PACKET_TYPE_DATA_ACK) - { - if (packet_type == PACKET_TYPE_DATA && header->tx_seq == conn->rx_sequence) - { // the packet number is what we expected - - if (data_size > 0) - { // save the data - - conn->rx_data_speed_count += data_size * 8; // + the number of data bits we just received - - uint16_t num = fifoBuf_getFree(&conn->rx_fifo_buffer); - if (num < data_size) - { // error .. we don't have enough space left in our fifo buffer to save the data .. discard it and tell them to hold off a sec -// conn->rx_not_ready_mode = true; - } - else - { // save the received data into our fifo buffer - fifoBuf_putData(&conn->rx_fifo_buffer, data, data_size); - conn->rx_sequence++; - conn->rx_not_ready_mode = false; - } - } - } - - if (size >= 200 || (conn->ready_to_send_timer >= 10 && size > 0) || (conn->tx_sequence_data_size > 0 && size > 0)) - { // send data - uint8_t pack_type = PACKET_TYPE_DATA; - if (conn->rx_not_ready_mode) - pack_type = PACKET_TYPE_NOTREADY; - - if (ph_sendPacket(connection_index, conn->send_encrypted, pack_type, true)) - { - conn->tx_packet_timer = 0; - conn->tx_retry_time = conn->tx_retry_time_slot_len + (random32 % conn->tx_retry_time_slots) * conn->tx_retry_time_slot_len; - return; - } - } - - if (packet_type == PACKET_TYPE_DATA) - { // send an ack back - uint8_t pack_type = PACKET_TYPE_DATA_ACK; - if (conn->rx_not_ready_mode) - pack_type = PACKET_TYPE_NOTREADY_ACK; - - if (ph_sendPacket(connection_index, conn->send_encrypted, pack_type, true)) - { - conn->tx_packet_timer = 0; - conn->tx_retry_time = conn->tx_retry_time_slot_len + (random32 % conn->tx_retry_time_slots) * conn->tx_retry_time_slot_len; - return; - } - } - - return; - } - - if (packet_type == PACKET_TYPE_READY) - { - conn->not_ready_timer = -1; // stop timer - - // send an ack back - if (ph_sendPacket(connection_index, conn->send_encrypted, PACKET_TYPE_READY_ACK, true)) - { - conn->tx_packet_timer = 0; - conn->tx_retry_time = conn->tx_retry_time_slot_len * 4 + (random32 % conn->tx_retry_time_slots) * conn->tx_retry_time_slot_len * 4; - return; - } - - return; - } - - if (packet_type == PACKET_TYPE_READY_ACK) - { - conn->rx_not_ready_mode = false; - return; - } - - if (packet_type == PACKET_TYPE_NOTREADY) - { -// conn->not_ready_timer = 0; // start timer - - if (header->tx_seq == conn->rx_sequence) - { // the packet number is what we expected - - if (data_size > 0) - { // save the data - - conn->rx_data_speed_count += data_size * 8; // + the number of data bits we just received - - uint16_t num = fifoBuf_getFree(&conn->rx_fifo_buffer); - if (num < data_size) - { // error .. we don't have enough space left in our fifo buffer to save the data .. discard it and tell them to hold off a sec -// conn->rx_not_ready_mode = true; - } - else - { // save the received data into our fifo buffer - fifoBuf_putData(&conn->rx_fifo_buffer, data, data_size); - conn->rx_sequence++; - conn->rx_not_ready_mode = false; - } - } - } - - // send an ack back - if (ph_sendPacket(connection_index, conn->send_encrypted, PACKET_TYPE_NOTREADY_ACK, true)) - { - conn->tx_packet_timer = 0; - conn->tx_retry_time = conn->tx_retry_time_slot_len * 4 + (random32 % conn->tx_retry_time_slots) * conn->tx_retry_time_slot_len * 4; - return; - } - - return; - } - - if (packet_type == PACKET_TYPE_NOTREADY_ACK) - { - return; - } - - if (packet_type == PACKET_TYPE_PING) - { // send a pong back - if (ph_sendPacket(connection_index, conn->send_encrypted, PACKET_TYPE_PONG, true)) - { - conn->tx_packet_timer = 0; - conn->tx_retry_time = conn->tx_retry_time_slot_len + (random32 % conn->tx_retry_time_slots) * conn->tx_retry_time_slot_len; - } - return; - } - - if (packet_type == PACKET_TYPE_PONG) - { - if (conn->pinging) - { - conn->pinging = false; - conn->tx_retry_counter = 0; - } - return; - } - - if (packet_type == PACKET_TYPE_DATARATE) - { - // send an ack back - if (ph_sendPacket(connection_index, conn->send_encrypted, PACKET_TYPE_DATARATE_ACK, true)) - { - conn->tx_packet_timer = 0; - conn->tx_retry_time = conn->tx_retry_time_slot_len + (random32 % conn->tx_retry_time_slots) * conn->tx_retry_time_slot_len; - } - return; - } - - if (packet_type == PACKET_TYPE_DATARATE_ACK) - { - return; - } - - if (packet_type == PACKET_TYPE_ADJUST_TX_PWR) - { - // send an ack back - if (ph_sendPacket(connection_index, conn->send_encrypted, PACKET_TYPE_ADJUST_TX_PWR_ACK, true)) - { - conn->tx_packet_timer = 0; - conn->tx_retry_time = conn->tx_retry_time_slot_len + (random32 % conn->tx_retry_time_slots) * conn->tx_retry_time_slot_len; - } - return; - } - - if (packet_type == PACKET_TYPE_ADJUST_TX_PWR_ACK) - { - return; - } - - // ********************* -} - -void ph_processRxPacket(void) -{ - uint32_t crc1, crc2; - uint8_t key[AES_BLOCK_SIZE]; - register uint8_t *p; - - // *********** - // fetch the received packet - - uint16_t packet_size = rfm22_receivedLength(); - if (packet_size == 0) - return; // nothing received - - if (packet_size > sizeof(ph_rx_buffer)) - { // packet too big .. discard it - rfm22_receivedDone(); - return; - } - - rx_rssi_dBm = rfm22_receivedRSSI(); // fetch the packets signal stength - rx_afc_Hz = rfm22_receivedAFCHz(); // fetch the packets frequency offset - - // copy the received packet into our own buffer - memmove(ph_rx_buffer, rfm22_receivedPointer(), packet_size); - - rfm22_receivedDone(); // the received packet has been saved - - // ********************* - // if the 1st byte in the packet is not zero, then the packet is encrypted - - bool encrypted = (ph_rx_buffer[0] != 0); - - // *********** - - t_encrypted_packet *encrypted_packet = (t_encrypted_packet *)&ph_rx_buffer; // point to the rx buffer - t_unencrypted_packet *unencrypted_packet = (t_unencrypted_packet *)&ph_rx_buffer; // point to the rx buffer - - t_packet_header *header; - uint8_t *data; - uint16_t min_packet_size; - uint16_t max_data_size; - - if (encrypted) - { - header = (t_packet_header *)&encrypted_packet->header; - data = (uint8_t *)&encrypted_packet->data; - min_packet_size = AES_BLOCK_SIZE + sizeof(t_packet_header); - max_data_size = sizeof(encrypted_packet->data); - } - else - { - header = (t_packet_header *)&unencrypted_packet->header; - data = (uint8_t *)&unencrypted_packet->data; - min_packet_size = 1 + sizeof(t_packet_header); - max_data_size = sizeof(unencrypted_packet->data); - } - - if (packet_size < min_packet_size) - { // packet too small .. discard it - return; - } - - random32 = updateCRC32(random32 ^ header->crc, 0xff); // help randomize the random number - - // ********************* - // help to randomize the tx aes cbc bytes by using the received packet - - p = (uint8_t *)&ph_rx_buffer; - for (uint16_t i = 0; i < packet_size; i += AES_BLOCK_SIZE) - { - for (int j = AES_BLOCK_SIZE - 1; j >= 0; j--) - enc_cbc[j] ^= *p++; - } - - // ********************* - // check the packet size - - if (encrypted) - { - if ((packet_size & (AES_BLOCK_SIZE - 1)) != 0) - return; // packet must be a multiple of 'AES_BLOCK_SIZE' bytes in length - for the aes decryption - } - - // ********************* - // decrypt the packet - - if (encrypted) - { - p = (uint8_t *)encrypted_packet; // point to the received packet - - // decrypt the cbc - memmove(key, (void *)dec_aes_key, sizeof(key)); // fetch the decryption key - aes_decrypt_cbc_128(p, key, NULL); // decrypt the cbc bytes - p += AES_BLOCK_SIZE; - - // decrypt the rest of the packet - for (uint16_t i = AES_BLOCK_SIZE; i < packet_size; i += AES_BLOCK_SIZE) - { - memmove(key, (void *)dec_aes_key, sizeof(key)); // fetch the decryption key - aes_decrypt_cbc_128(p, key, (void *)encrypted_packet->cbc); - p += AES_BLOCK_SIZE; - } - } - - // ********************* - -#if defined(PACKET_DEBUG) - DEBUG_PRINTF("rx packet: "); - DEBUG_PRINTF("%s", encrypted ? "encrypted " : "unencrypted"); - if (encrypted) - { - for (int i = 0; i < AES_BLOCK_SIZE; i++) - DEBUG_PRINTF("%02X", encrypted_packet->cbc[i]); - } - DEBUG_PRINTF(" %08X %08X %u %u %u %u %08X\r\n", - header->source_id, - header->destination_id, - header->type, - header->tx_seq, - header->rx_seq, - header->data_size, - header->crc); - - if (header->data_size > 0) - { - DEBUG_PRINTF("rx packet [%u]: ", header->data_size); - for (int i = 0; i < header->data_size; i++) - DEBUG_PRINTF("%02X", data[i]); - DEBUG_PRINTF("\r\n"); - } -#endif - - // ********************* - - uint32_t data_size = header->data_size; - - if (packet_size < (min_packet_size + data_size)) - return; // packet too small - -#if defined(PACKET_DEBUG) -// DEBUG_PRINTF("rx packet size: %d\r\n", packet_size); -#endif - - // ********************* - // check the packet is error free - - crc1 = header->crc; - header->crc = 0; - if (encrypted) - crc2 = updateCRC32Data(0xffffffff, header, packet_size - AES_BLOCK_SIZE); - else - crc2 = updateCRC32Data(0xffffffff, header, packet_size - 1); - if (crc1 != crc2) - { // corrupt packet - #if defined(PACKET_DEBUG) - if (encrypted) - DEBUG_PRINTF("ENC-R-PACK corrupt %08X %08X\r\n", crc1, crc2); - else - DEBUG_PRINTF("R-PACK corrupt %08X %08X\r\n", crc1, crc2); - #endif - return; - } - - // ********************* - // process the data - - ph_processPacket2(encrypted, header, data); - - // ********************* -} - -// ***************************************************************************** -// do all the link/packet handling stuff - request connection/disconnection, send data, acks etc - -void ph_processLinks(int connection_index) -{ - if (connection_index < 0 || connection_index >= PH_MAX_CONNECTIONS) - return; - - random32 = updateCRC32(random32, 0xff); - - t_connection *conn = &connection[connection_index]; - - bool canTx = (!rfm22_transmitting() && rfm22_channelIsClear());// TRUE is we can transmit - - bool timeToRetry = (rfm22_txReady() && conn->tx_packet_timer >= conn->tx_retry_time); - - bool tomanyRetries = (conn->tx_retry_counter >= RETRY_RECONNECT_COUNT); - - if (conn->tx_retry_counter > 3) - conn->rx_rssi_dBm = -200; - - switch (conn->link_state) - { - case LINK_DISCONNECTED: - if (!canTx) - { - conn->tx_packet_timer = 0; - break; - } - - if (!rfm22_txReady() || conn->tx_packet_timer < 60000) - break; - - if (our_serial_number != 0 && conn->serial_number != 0) - { // try to reconnect with the remote modem - ph_startConnect(connection_index, conn->serial_number); - break; - } - - break; - - case LINK_CONNECTING: - if (!canTx) - { - conn->tx_packet_timer = 0; - break; - } - - if (!timeToRetry) - break; - - if (ph_sendPacket(connection_index, conn->send_encrypted, PACKET_TYPE_CONNECT, false)) - { - conn->tx_packet_timer = 0; - conn->tx_retry_time = conn->tx_retry_time_slot_len * 4 + (random32 % conn->tx_retry_time_slots) * conn->tx_retry_time_slot_len * 4; - break; - } - - break; - - case LINK_CONNECTED: - if (!canTx) - { - conn->tx_packet_timer = 0; - break; - } - - if (!timeToRetry) - break; - - if (tomanyRetries) - { // reset the link if we have sent tomany retries - ph_startConnect(connection_index, conn->serial_number); - break; - } - - if (conn->pinging) - { // we are trying to ping them - if (ph_sendPacket(connection_index, conn->send_encrypted, PACKET_TYPE_PING, false)) - { - conn->tx_packet_timer = 0; - conn->tx_retry_time = conn->tx_retry_time_slot_len * 4 + (random32 % conn->tx_retry_time_slots) * conn->tx_retry_time_slot_len * 4; - } - break; - } - - uint16_t ping_time = conn->ping_time; - if (fast_ping) ping_time = conn->fast_ping_time; - if (conn->tx_packet_timer >= ping_time) - { // start pinging - if (ph_sendPacket(connection_index, conn->send_encrypted, PACKET_TYPE_PING, false)) - { - conn->ping_time = 8000 + (random32 % 100) * 10; - conn->fast_ping_time = 600 + (random32 % 50) * 10; - conn->tx_packet_timer = 0; - conn->tx_retry_time = conn->tx_retry_time_slot_len * 4 + (random32 % conn->tx_retry_time_slots) * conn->tx_retry_time_slot_len * 4; - conn->pinging = true; - } - break; - } - - // *********** - // exit rx not ready mode if we have space in our rx buffer for more data -/* - if (conn->rx_not_ready_mode) - { - uint16_t size = fifoBuf_getFree(&conn->rx_fifo_buffer); - if (size >= conn->rx_fifo_buffer.buf_size / 6) - { // leave 'rx not ready' mode - if (ph_sendPacket(connection_index, conn->send_encrypted, PACKET_TYPE_READY, false)) - { - conn->tx_packet_timer = 0; - conn->tx_retry_time = conn->tx_retry_time_slot_len + (random32 % conn->tx_retry_time_slots) * conn->tx_retry_time_slot_len; - break; - } - } - } -*/ - // *********** - // send data packets - -// if (conn->not_ready_timer < 0) - { - uint16_t size = fifoBuf_getUsed(&conn->tx_fifo_buffer); - - if (size == 0) - conn->ready_to_send_timer = -1; // no data to send - else - if (conn->ready_to_send_timer < 0) - conn->ready_to_send_timer = 0; // start timer - - if (size >= 200 || (conn->ready_to_send_timer >= saved_settings.rts_time && size > 0) || (conn->tx_sequence_data_size > 0 && size > 0)) - { // send data - - uint8_t pack_type = PACKET_TYPE_DATA; - if (conn->rx_not_ready_mode) - pack_type = PACKET_TYPE_NOTREADY; - - if (ph_sendPacket(connection_index, conn->send_encrypted, pack_type, false)) - { - conn->tx_packet_timer = 0; - conn->tx_retry_time = conn->tx_retry_time_slot_len + (random32 % conn->tx_retry_time_slots) * conn->tx_retry_time_slot_len; - } - break; - } - } - - // *********** - - break; - - default: // we should never end up here - maybe we should do a reboot? - conn->link_state = LINK_DISCONNECTED; -/* - // disable all interrupts - PIOS_IRQ_Disable(); - - // turn off all leds - USB_LED_OFF; - LINK_LED_OFF; - RX_LED_OFF; - TX_LED_OFF; - - PIOS_SYS_Reset(); - - while (1); -*/ - break; - } -} - -// ***************************************************************************** - -void ph_setFastPing(bool fast) -{ - fast_ping = fast; -} - -// ***************************************************************************** - -uint8_t ph_getCurrentLinkState(const int connection_index) -{ - if (connection_index < 0 || connection_index >= PH_MAX_CONNECTIONS) - return 0; - - return connection[connection_index].link_state; -} - -// ***************************************************************************** - -uint16_t ph_getRetries(const int connection_index) -{ - if (connection_index < 0 || connection_index >= PH_MAX_CONNECTIONS) - return 0; - - return connection[connection_index].tx_retry_counter; -} - -// ***************************************************************************** - -int16_t ph_getLastRSSI(const int connection_index) -{ - if (connection_index < 0 || connection_index >= PH_MAX_CONNECTIONS) - return 0; - - return connection[connection_index].rx_rssi_dBm; -} - -int32_t ph_getLastAFC(const int connection_index) -{ - if (connection_index < 0 || connection_index >= PH_MAX_CONNECTIONS) - return 0; - - return connection[connection_index].rx_afc_Hz; -} - -// ***************************************************************************** -// set/get the carrier frequency - -void ph_setNominalCarrierFrequency(uint32_t frequency_hz) -{ - rfm22_setNominalCarrierFrequency(frequency_hz); -} - -uint32_t ph_getNominalCarrierFrequency(void) -{ - return rfm22_getNominalCarrierFrequency(); -} - -// ***************************************************************************** -// set/get the RF datarate - -void ph_setDatarate(uint32_t datarate_bps) -{ - rfm22_setDatarate(datarate_bps, TRUE); - - uint32_t ms = 1280000ul / rfm22_getDatarate(); - if (ms < 10) ms = 10; - else - if (ms > 32000) ms = 32000; - - for (int i = 0; i < PH_MAX_CONNECTIONS; i++) - connection[i].tx_retry_time_slot_len = ms; -} - -uint32_t ph_getDatarate(void) -{ - return rfm22_getDatarate(); -} - -// ***************************************************************************** - -void ph_setTxPower(uint8_t tx_power) -{ - rfm22_setTxPower(tx_power); -} - -uint8_t ph_getTxPower(void) -{ - return rfm22_getTxPower(); -} - -// ***************************************************************************** -// set the AES encryption key - -void ph_set_AES128_key(const void *key) -{ - if (!key) - return; - - memmove(aes_key, key, sizeof(aes_key)); - - // create the AES decryption key - aes_decrypt_key_128_create(aes_key, (void *)&dec_aes_key); -} - -// ***************************************************************************** - -int ph_set_remote_serial_number(int connection_index, uint32_t sn) -{ - random32 = updateCRC32(random32, 0xff); - - if (ph_startConnect(connection_index, sn) >= 0) - { - t_connection *conn = &connection[connection_index]; - - // wipe any user data present in the buffers - fifoBuf_init(&conn->tx_fifo_buffer, conn->tx_buffer, PH_FIFO_BUFFER_SIZE); - fifoBuf_init(&conn->rx_fifo_buffer, conn->rx_buffer, PH_FIFO_BUFFER_SIZE); - - return connection_index; - } - - return -4; -} - -void ph_set_remote_encryption(int connection_index, bool enabled, const void *key) -{ - if (connection_index < 0 || connection_index >= PH_MAX_CONNECTIONS) - return; - - ph_set_AES128_key(key); - - connection[connection_index].send_encrypted = enabled; -} - -// ***************************************************************************** -// can be called from an interrupt if you wish. -// call this once every ms - -void ph_1ms_tick(void) -{ - if (booting) return; - - if (saved_settings.mode == MODE_NORMAL) - { - // help randomize the encryptor cbc bytes - register uint32_t *cbc = (uint32_t *)&enc_cbc; - for (int i = 0; i < sizeof(enc_cbc) / 4; i++) - { - random32 = updateCRC32(random32, 0xff); - *cbc++ ^= random32; - } - - for (int i = 0; i < PH_MAX_CONNECTIONS; i++) - { - t_connection *conn = &connection[i]; - - if (conn->tx_packet_timer < 0xffff) - conn->tx_packet_timer++; - - if (conn->link_state == LINK_CONNECTED) - { // we are connected - - if (conn->ready_to_send_timer >= 0 && conn->ready_to_send_timer < 0x7fff) - conn->ready_to_send_timer++; - - if (conn->not_ready_timer >= 0 && conn->not_ready_timer < 0x7fffffff) - conn->not_ready_timer++; - - if (conn->data_speed_timer < 0xffff) - { - if (++conn->data_speed_timer >= 1000) - { // 1 second gone by - conn->data_speed_timer = 0; - conn->tx_data_speed = (conn->tx_data_speed + conn->tx_data_speed_count) >> 1; - conn->tx_data_speed_count = 0; - conn->rx_data_speed = (conn->rx_data_speed + conn->rx_data_speed_count) >> 1; - conn->rx_data_speed_count = 0; - } - } - } - else - { // we are not connected - if (conn->data_speed_timer) conn->data_speed_timer = 0; - if (conn->tx_data_speed_count) conn->tx_data_speed_count = 0; - if (conn->tx_data_speed) conn->tx_data_speed = 0; - if (conn->rx_data_speed_count) conn->rx_data_speed_count = 0; - if (conn->rx_data_speed) conn->rx_data_speed = 0; - } - } - } -} - -// ***************************************************************************** -// call this as often as possible - not from an interrupt - -void ph_process(void) -{ - if (booting) return; - - if (saved_settings.mode == MODE_NORMAL) - { - ph_processRxPacket(); - - for (int i = 0; i < PH_MAX_CONNECTIONS; i++) - ph_processLinks(i); - } - else - { - - } -} - -// ***************************************************************************** - -void ph_disconnectAll(void) -{ - for (int i = 0; i < PH_MAX_CONNECTIONS; i++) - { - random32 = updateCRC32(random32, 0xff); - - t_connection *conn = &connection[i]; - - conn->serial_number = 0; - - conn->tx_sequence = 0; - conn->tx_sequence_data_size = 0; - - conn->rx_sequence = 0; - - fifoBuf_init(&conn->tx_fifo_buffer, conn->tx_buffer, PH_FIFO_BUFFER_SIZE); - fifoBuf_init(&conn->rx_fifo_buffer, conn->rx_buffer, PH_FIFO_BUFFER_SIZE); - - conn->link_state = LINK_DISCONNECTED; - - conn->tx_packet_timer = 0; - - conn->tx_retry_time_slots = 5; - conn->tx_retry_time_slot_len = 40; - conn->tx_retry_time = conn->tx_retry_time_slot_len * 4 + (random32 % conn->tx_retry_time_slots) * conn->tx_retry_time_slot_len * 4; - conn->tx_retry_counter = 0; - - conn->data_speed_timer = 0; - conn->tx_data_speed_count = 0; - conn->tx_data_speed = 0; - conn->rx_data_speed_count = 0; - conn->rx_data_speed = 0; - - conn->ping_time = 8000 + (random32 % 100) * 10; - conn->fast_ping_time = 600 + (random32 % 50) * 10; - conn->pinging = false; - - conn->rx_not_ready_mode = false; - - conn->ready_to_send_timer = -1; - - conn->not_ready_timer = -1; - - conn->send_encrypted = false; - - conn->rx_rssi_dBm = -200; - conn->rx_afc_Hz = 0; - } -} - -// ***************************************************************************** - -void ph_deinit(void) -{ - ph_disconnectAll(); -} - -void ph_init(uint32_t our_sn) -{ - our_serial_number = our_sn; // remember our own serial number - - fast_ping = false; - - ph_disconnectAll(); - - // set the AES encryption key using the default AES key - ph_set_AES128_key(default_aes_key); - - // try too randomise the tx AES CBC bytes - for (uint32_t j = 0, k = 0; j < 123 + (random32 & 1023); j++) - { - random32 = updateCRC32(random32, 0xff); - enc_cbc[k] ^= random32 >> 3; - if (++k >= sizeof(enc_cbc)) k = 0; - } - - // ****** - - rfm22_init_normal(saved_settings.min_frequency_Hz, saved_settings.max_frequency_Hz, rfm22_freqHopSize()); - - rfm22_TxDataByte_SetCallback(ph_TxDataByteCallback); - rfm22_RxData_SetCallback(ph_RxDataCallback); - - rfm22_setFreqCalibration(saved_settings.rf_xtal_cap); - ph_setNominalCarrierFrequency(saved_settings.frequency_Hz); - ph_setDatarate(saved_settings.max_rf_bandwidth); - ph_setTxPower(saved_settings.max_tx_power); - - ph_set_remote_encryption(0, saved_settings.aes_enable, (const void *)saved_settings.aes_key); - ph_set_remote_serial_number(0, saved_settings.destination_id); - - // ****** -} - -// ***************************************************************************** diff --git a/flight/PipXtreme/pios_board.c b/flight/PipXtreme/pios_board.c deleted file mode 100644 index a5536db2b..000000000 --- a/flight/PipXtreme/pios_board.c +++ /dev/null @@ -1,112 +0,0 @@ -/** - ****************************************************************************** - * - * @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 PipBee 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 - */ - -/* Pull in the board-specific static HW definitions. - * Including .c files is a bit ugly but this allows all of - * the HW definitions to be const and static to limit their - * scope. - * - * NOTE: THIS IS THE ONLY PLACE THAT SHOULD EVER INCLUDE THIS FILE - */ -#include "board_hw_defs.c" - -#include - -#define PIOS_COM_TELEM_USB_RX_BUF_LEN 192 -#define PIOS_COM_TELEM_USB_TX_BUF_LEN 192 - -static uint8_t pios_com_telem_usb_rx_buffer[PIOS_COM_TELEM_USB_RX_BUF_LEN]; -static uint8_t pios_com_telem_usb_tx_buffer[PIOS_COM_TELEM_USB_TX_BUF_LEN]; - -#define PIOS_COM_SERIAL_RX_BUF_LEN 192 -#define PIOS_COM_SERIAL_TX_BUF_LEN 192 - -static uint8_t pios_com_serial_rx_buffer[PIOS_COM_SERIAL_RX_BUF_LEN]; -static uint8_t pios_com_serial_tx_buffer[PIOS_COM_SERIAL_TX_BUF_LEN]; - -uint32_t pios_com_serial_id; -uint32_t pios_com_telem_usb_id; - -/** - * PIOS_Board_Init() - * initializes all the core subsystems on this specific hardware - * called from System/openpilot.c - */ -void PIOS_Board_Init(void) { - // Bring up System using CMSIS functions, enables the LEDs. - PIOS_SYS_Init(); - - // turn all the leds on - USB_LED_ON; - LINK_LED_ON; - RX_LED_ON; - TX_LED_ON; - - // Delay system - PIOS_DELAY_Init(); - - uint32_t pios_usart_serial_id; - if (PIOS_USART_Init(&pios_usart_serial_id, &pios_usart_serial_cfg)) { - PIOS_DEBUG_Assert(0); - } - if (PIOS_COM_Init(&pios_com_serial_id, &pios_usart_com_driver, pios_usart_serial_id, - pios_com_serial_rx_buffer, sizeof(pios_com_serial_rx_buffer), - pios_com_serial_tx_buffer, sizeof(pios_com_serial_tx_buffer))) { - PIOS_DEBUG_Assert(0); - } - -#if defined(PIOS_INCLUDE_USB) - /* Initialize board specific USB data */ - PIOS_USB_BOARD_DATA_Init(); - - if (PIOS_USB_DESC_HID_ONLY_Init()) { - PIOS_Assert(0); - } - - uint32_t pios_usb_id; - PIOS_USB_Init(&pios_usb_id, &pios_usb_main_cfg); - -#if defined(PIOS_INCLUDE_USB_HID) && defined(PIOS_INCLUDE_COM) - uint32_t pios_usb_hid_id; - if (PIOS_USB_HID_Init(&pios_usb_hid_id, &pios_usb_hid_cfg, pios_usb_id)) { - PIOS_Assert(0); - } - if (PIOS_COM_Init(&pios_com_telem_usb_id, &pios_usb_hid_com_driver, pios_usb_hid_id, - pios_com_telem_usb_rx_buffer, sizeof(pios_com_telem_usb_rx_buffer), - pios_com_telem_usb_tx_buffer, sizeof(pios_com_telem_usb_tx_buffer))) { - PIOS_Assert(0); - } -#endif /* PIOS_INCLUDE_USB_HID && PIOS_INCLUDE_COM */ - -#endif /* PIOS_INCLUDE_USB_HID */ - - // ADC system - // PIOS_ADC_Init(); - - // SPI link to master - if (PIOS_SPI_Init(&pios_spi_port_id, &pios_spi_port_cfg)) { - PIOS_DEBUG_Assert(0); - } -} diff --git a/flight/PipXtreme/ppm.c b/flight/PipXtreme/ppm.c deleted file mode 100644 index e67ea231d..000000000 --- a/flight/PipXtreme/ppm.c +++ /dev/null @@ -1,631 +0,0 @@ -/** - ****************************************************************************** - * - * @file ppm.c - * @author The OpenPilot Team, http://www.openpilot.org Copyright (C) 2010. - * @brief Sends or Receives the ppm values to/from the remote unit - * @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 // memmove - -#include "main.h" -#include "rfm22b.h" -#include "saved_settings.h" -#include "ppm.h" - -#if defined(PIOS_COM_DEBUG) - #define PPM_DEBUG -#endif - -// ************************************************************* - -#define PPM_OUT_FRAME_PERIOD_US 20000 // microseconds -#define PPM_OUT_HIGH_PULSE_US 480 // microseconds -#define PPM_OUT_MIN_CHANNEL_PULSE_US 850 // microseconds -#define PPM_OUT_MAX_CHANNEL_PULSE_US 2200 // microseconds - -#define PPM_IN_MIN_SYNC_PULSE_US 7000 // microseconds .. Pip's 6-chan TX goes down to 8.8ms -#define PPM_IN_MIN_CHANNEL_PULSE_US 750 // microseconds -#define PPM_IN_MAX_CHANNEL_PULSE_US 2400 // microseconds - -// ************************************************************* - -uint8_t ppm_mode; - -volatile bool ppm_initialising = true; - -volatile uint32_t ppm_In_PrevFrames = 0; -volatile uint32_t ppm_In_LastValidFrameTimer = 0; -volatile uint32_t ppm_In_Frames = 0; -volatile uint32_t ppm_In_ErrorFrames = 0; -volatile uint8_t ppm_In_NoisyChannelCounter = 0; -volatile int8_t ppm_In_ChannelsDetected = 0; -volatile int8_t ppm_In_ChannelPulseIndex = -1; -volatile int32_t ppm_In_PreviousValue = -1; -volatile uint32_t ppm_In_PulseWidth = 0; -volatile uint32_t ppm_In_ChannelPulseWidthNew[PIOS_PPM_MAX_CHANNELS]; -volatile uint32_t ppm_In_ChannelPulseWidth[PIOS_PPM_MAX_CHANNELS]; - -volatile uint16_t ppm_Out_ChannelPulseWidth[PIOS_PPM_MAX_CHANNELS]; -volatile uint32_t ppm_Out_SyncPulseWidth = PPM_OUT_FRAME_PERIOD_US; -volatile int8_t ppm_Out_ChannelPulseIndex = -1; -volatile uint8_t ppm_Out_ChannelsUsed = 0; - -// ************************************************************* - -// Initialise the PPM INPUT -void ppm_In_Init(void) -{ - TIM_ICInitTypeDef TIM_ICInitStructure; - - // disable the timer - TIM_Cmd(PIOS_PPM_TIM, DISABLE); - - ppm_In_PrevFrames = 0; - ppm_In_NoisyChannelCounter = 0; - ppm_In_LastValidFrameTimer = 0; - ppm_In_Frames = 0; - ppm_In_ErrorFrames = 0; - ppm_In_ChannelsDetected = 0; - ppm_In_ChannelPulseIndex = -1; - ppm_In_PreviousValue = -1; - ppm_In_PulseWidth = 0; - - for (int i = 0; i < PIOS_PPM_MAX_CHANNELS; i++) - { - ppm_In_ChannelPulseWidthNew[i] = 0; - ppm_In_ChannelPulseWidth[i] = 0; - } - - // Enable timer clock - PIOS_PPM_TIMER_EN_RCC_FUNC; - - // Enable timer interrupts - NVIC_InitTypeDef NVIC_InitStructure; - NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = PIOS_IRQ_PRIO_MID; - NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0; - NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; - NVIC_InitStructure.NVIC_IRQChannel = PIOS_PPM_TIM_IRQ; - NVIC_Init(&NVIC_InitStructure); - - // Init PPM IN pin - GPIO_InitTypeDef GPIO_InitStructure; - GPIO_StructInit(&GPIO_InitStructure); - GPIO_InitStructure.GPIO_Pin = PPM_IN_PIN; - GPIO_InitStructure.GPIO_Mode = PPM_IN_MODE; - GPIO_InitStructure.GPIO_Speed = GPIO_Speed_2MHz; - GPIO_Init(PPM_IN_PORT, &GPIO_InitStructure); - - // remap the pin to switch it to timer mode - if (PIOS_PPM_TIM == TIM2) - { -// GPIO_PinRemapConfig(GPIO_PartialRemap1_TIM2, ENABLE); - GPIO_PinRemapConfig(GPIO_PartialRemap2_TIM2, ENABLE); -// GPIO_PinRemapConfig(GPIO_FullRemap_TIM2, ENABLE); - } - - // Configure timer for input capture - TIM_ICInitStructure.TIM_ICPolarity = TIM_ICPolarity_Rising; - TIM_ICInitStructure.TIM_ICSelection = TIM_ICSelection_DirectTI; - TIM_ICInitStructure.TIM_ICPrescaler = TIM_ICPSC_DIV1; - TIM_ICInitStructure.TIM_ICFilter = 15; // 0 to 15 - TIM_ICInitStructure.TIM_Channel = PIOS_PPM_IN_TIM_CHANNEL; - TIM_ICInit(PIOS_PPM_TIM_PORT, &TIM_ICInitStructure); - - // Configure timer clocks - TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure; - TIM_TimeBaseStructInit(&TIM_TimeBaseStructure); - TIM_TimeBaseStructure.TIM_Period = 25000 - 1; // 25ms - can be anything you like now really - up to 65536us - TIM_TimeBaseStructure.TIM_Prescaler = (PIOS_MASTER_CLOCK / 1000000) - 1; - TIM_TimeBaseStructure.TIM_ClockDivision = TIM_CKD_DIV1; - TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up; - TIM_InternalClockConfig(PIOS_PPM_TIM_PORT); - TIM_TimeBaseInit(PIOS_PPM_TIM_PORT, &TIM_TimeBaseStructure); - - // Enable the Capture Compare and Update Interrupts - TIM_ITConfig(PIOS_PPM_TIM_PORT, PIOS_PPM_IN_TIM_CCR | TIM_IT_Update, ENABLE); - - // Clear TIMER Capture compare and update interrupt pending bits - TIM_ClearITPendingBit(PIOS_PPM_TIM_PORT, PIOS_PPM_IN_TIM_CCR | TIM_IT_Update); - - // Enable timer - TIM_Cmd(PIOS_PPM_TIM, ENABLE); - - // Setup local variable which stays in this scope - // Doing this here and using a local variable saves doing it in the ISR - TIM_ICInitStructure.TIM_ICSelection = TIM_ICSelection_DirectTI; - TIM_ICInitStructure.TIM_ICPrescaler = TIM_ICPSC_DIV1; - TIM_ICInitStructure.TIM_ICFilter = 0x0; - -#ifdef PPM_DEBUG - DEBUG_PRINTF("ppm_in: initialised\r\n"); -#endif -} - -// TIMER capture/compare/update interrupt -void PIOS_PPM_IN_CC_IRQ(void) -{ - uint16_t new_value = 0; - uint32_t period = (uint32_t)PIOS_PPM_TIM->ARR + 1; - - if (booting || ppm_initialising) - { // clear the interrupts - TIM_ClearITPendingBit(PIOS_PPM_TIM_PORT, PIOS_PPM_IN_TIM_CCR | TIM_IT_Update); - return; - } - - // determine the interrupt source(s) - bool update_int = TIM_GetITStatus(PIOS_PPM_TIM_PORT, TIM_IT_Update) == SET; // timer/counter overflow occured - bool capture_int = TIM_GetITStatus(PIOS_PPM_TIM_PORT, PIOS_PPM_IN_TIM_CCR) == SET; // PPM input capture - - if (capture_int) - new_value = PIOS_PPM_IN_TIM_GETCAP_FUNC(PIOS_PPM_TIM_PORT); - - // clear the interrupts - TIM_ClearITPendingBit(PIOS_PPM_TIM_PORT, PIOS_PPM_IN_TIM_CCR | TIM_IT_Update); - - // ******** - - uint32_t ticks = 0; - if (update_int) - { // timer/counter overflowed - - if (ppm_In_PreviousValue >= 0) - ticks = (period - ppm_In_PreviousValue) + new_value; - else - { - ticks = period; - if (capture_int) ticks += new_value; - } - ppm_In_PreviousValue = -1; - } - else - if (capture_int) - { - if (ppm_In_PreviousValue >= 0) - ticks = new_value - ppm_In_PreviousValue; - else - ticks += new_value; - } - - ppm_In_PulseWidth += ticks; - if (ppm_In_PulseWidth > 0x7fffffff) - ppm_In_PulseWidth = 0x7fffffff; // prevent overflows - - ppm_In_LastValidFrameTimer += ticks; - if (ppm_In_LastValidFrameTimer > 0x7fffffff) - ppm_In_LastValidFrameTimer = 0x7fffffff; // prevent overflows - - if (capture_int) - ppm_In_PreviousValue = new_value; - - // ******** - -#ifdef PPM_DEBUG -// DEBUG_PRINTF("ppm_in:"); -// if (update_int) DEBUG_PRINTF(" update"); -// if (capture_int) DEBUG_PRINTF(" capture"); -// DEBUG_PRINTF(" %u %u\r\n", ppm_In_LastValidFrameTimer, ppm_In_PulseWidth); -#endif - - if (ppm_In_LastValidFrameTimer >= 200000 && ppm_In_Frames > 0) - { // we haven't seen a valid PPM frame for at least 200ms - for (int i = 0; i < PIOS_PPM_MAX_CHANNELS; i++) - ppm_In_ChannelPulseWidth[i] = 0; - ppm_In_Frames = 0; - ppm_In_ErrorFrames = 0; - } - - if (ppm_In_ChannelPulseIndex < 0 || ppm_In_PulseWidth > PPM_IN_MAX_CHANNEL_PULSE_US) - { // we are looking for a SYNC pulse, or we are receiving one - - if (ppm_In_ChannelPulseIndex >= 0) - { // it's either the start of a sync pulse or a noisy channel .. assume it's the end of a PPM frame - - if (ppm_In_ChannelPulseIndex > 0) - { - if (ppm_In_Frames < 0xffffffff) - ppm_In_Frames++; // update frame counter - - #ifdef PPM_DEBUG -// DEBUG_PRINTF("ppm_in: %u %u\r\n", ppm_In_ChannelsDetected, ppm_In_ChannelPulseIndex); - #endif - - if (ppm_In_ChannelsDetected > 0 && - ppm_In_ChannelsDetected == ppm_In_ChannelPulseIndex && - ppm_In_NoisyChannelCounter <= 2) - { // detected same number of channels as in previous PPM frame .. save the new channel PWM values - #ifdef PPM_DEBUG -// DEBUG_PRINTF("ppm_in: %u channels detected\r\n", ppm_In_ChannelPulseIndex); - #endif - - for (int i = 0; i < PIOS_PPM_MAX_CHANNELS; i++) - ppm_In_ChannelPulseWidth[i] = ppm_In_ChannelPulseWidthNew[i]; - - ppm_In_LastValidFrameTimer = 0; // reset timer - } - else - { - if ((ppm_In_ChannelsDetected > 0 && ppm_In_ChannelsDetected != ppm_In_ChannelPulseIndex) || - ppm_In_NoisyChannelCounter >= 2) - { - if (ppm_In_ErrorFrames < 0xffffffff) - ppm_In_ErrorFrames++; - } - } - ppm_In_ChannelsDetected = ppm_In_ChannelPulseIndex; // the number of channels we found in this frame - } - - ppm_In_ChannelPulseIndex = -1; // back to looking for a SYNC pulse - } - - if (ppm_In_PulseWidth >= PPM_IN_MIN_SYNC_PULSE_US) - { // SYNC pulse found - ppm_In_NoisyChannelCounter = 0; // reset noisy channel detector - ppm_In_ChannelPulseIndex = 0; // start of PPM frame - } - } - else - if (capture_int) - { // CHANNEL pulse - - if (ppm_In_PulseWidth < PPM_IN_MIN_CHANNEL_PULSE_US) - { // bad/noisy channel pulse .. reset state to wait for next SYNC pulse - ppm_In_ChannelPulseIndex = -1; - - if (ppm_In_ErrorFrames < 0xffffffff) - ppm_In_ErrorFrames++; - } - else - { // pulse width is within the accepted tolerance range for a channel - if (ppm_In_ChannelPulseIndex < PIOS_PPM_MAX_CHANNELS) - { - if (ppm_In_ChannelPulseWidthNew[ppm_In_ChannelPulseIndex] > 0) - { - int32_t difference = (int32_t)ppm_In_PulseWidth - ppm_In_ChannelPulseWidthNew[ppm_In_ChannelPulseIndex]; - if (abs(difference) >= 600) - ppm_In_NoisyChannelCounter++; // possibly a noisy channel - or an RC switch was moved - } - - ppm_In_ChannelPulseWidthNew[ppm_In_ChannelPulseIndex] = ppm_In_PulseWidth; // save it - } - - if (ppm_In_ChannelPulseIndex < 127) - ppm_In_ChannelPulseIndex++; // next channel - } - } - - if (capture_int) - ppm_In_PulseWidth = 0; - - // ******** -} - -uint32_t ppm_In_NewFrame(void) -{ - if (booting || ppm_initialising) - return 0; - - if (ppm_In_Frames >= 2 && ppm_In_Frames != ppm_In_PrevFrames) - { // we have a new PPM frame - ppm_In_PrevFrames = ppm_In_Frames; - return ppm_In_PrevFrames; - } - - return 0; -} - -int32_t ppm_In_GetChannelPulseWidth(uint8_t channel) -{ - if (booting || ppm_initialising) - return -1; - - // Return error if channel not available - if (channel >= PIOS_PPM_MAX_CHANNELS || channel >= ppm_In_ChannelsDetected) - return -2; - - return ppm_In_ChannelPulseWidth[channel]; // return channel pulse width -} - -// ************************************************************* - -// Initialise the PPM INPUT -void ppm_Out_Init(void) -{ - // disable the timer - TIM_Cmd(PIOS_PPM_TIM, DISABLE); - - ppm_Out_SyncPulseWidth = PPM_OUT_FRAME_PERIOD_US; - ppm_Out_ChannelPulseIndex = -1; - ppm_Out_ChannelsUsed = 0; - for (int i = 0; i < PIOS_PPM_MAX_CHANNELS; i++) - ppm_Out_ChannelPulseWidth[i] = 1000; -// ppm_Out_ChannelPulseWidth[i] = 1000 + i * 100; // TEST ONLY - -// ppm_Out_ChannelsUsed = 5; // TEST ONLY - - // Enable timer clock - PIOS_PPM_TIMER_EN_RCC_FUNC; - - // Init PPM OUT pin - GPIO_InitTypeDef GPIO_InitStructure; - GPIO_StructInit(&GPIO_InitStructure); - GPIO_InitStructure.GPIO_Pin = PPM_OUT_PIN; - GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP; - GPIO_InitStructure.GPIO_Speed = GPIO_Speed_10MHz; - GPIO_Init(PPM_OUT_PORT, &GPIO_InitStructure); - - // remap the pin to switch it to timer mode -// GPIO_PinRemapConfig(GPIO_PartialRemap1_TIM2, ENABLE); -// GPIO_PinRemapConfig(GPIO_PartialRemap2_TIM2, ENABLE); - GPIO_PinRemapConfig(GPIO_FullRemap_TIM2, ENABLE); - - // Enable timer interrupt - NVIC_InitTypeDef NVIC_InitStructure; - NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = PIOS_IRQ_PRIO_MID; - NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0; - NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; - NVIC_InitStructure.NVIC_IRQChannel = PIOS_PPM_TIM_IRQ; - NVIC_Init(&NVIC_InitStructure); - - // Time base configuration - TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure; - TIM_TimeBaseStructInit(&TIM_TimeBaseStructure); - TIM_TimeBaseStructure.TIM_Period = ppm_Out_SyncPulseWidth - 1; - TIM_TimeBaseStructure.TIM_Prescaler = (PIOS_MASTER_CLOCK / 1000000) - 1; - TIM_TimeBaseStructure.TIM_ClockDivision = TIM_CKD_DIV1; - TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up; - TIM_InternalClockConfig(PIOS_PPM_TIM_PORT); - TIM_TimeBaseInit(PIOS_PPM_TIM_PORT, &TIM_TimeBaseStructure); - - // Set up for output compare function - TIM_OCInitTypeDef TIM_OCInitStructure; - TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM1; - TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable; - TIM_OCInitStructure.TIM_OutputNState = TIM_OutputNState_Disable; - TIM_OCInitStructure.TIM_Pulse = PPM_OUT_HIGH_PULSE_US; - TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_High; - TIM_OCInitStructure.TIM_OCNPolarity = TIM_OCPolarity_High; - TIM_OCInitStructure.TIM_OCIdleState = TIM_OCIdleState_Reset; - TIM_OCInitStructure.TIM_OCNIdleState = TIM_OCNIdleState_Reset; - TIM_OC3Init(PIOS_PPM_TIM, &TIM_OCInitStructure); - TIM_OC3PreloadConfig(PIOS_PPM_TIM, TIM_OCPreload_Enable); - - TIM_ARRPreloadConfig(PIOS_PPM_TIM, ENABLE); - - // TIMER Main Output Enable - TIM_CtrlPWMOutputs(PIOS_PPM_TIM, ENABLE); - - // TIM IT enable - TIM_ITConfig(PIOS_PPM_TIM, PIOS_PPM_OUT_TIM_CCR, ENABLE); - - // Clear TIMER Capture compare interrupt pending bit - TIM_ClearITPendingBit(PIOS_PPM_TIM_PORT, PIOS_PPM_IN_TIM_CCR); - - // Enable timer - TIM_Cmd(PIOS_PPM_TIM, ENABLE); - -#ifdef PPM_DEBUG - DEBUG_PRINTF("ppm_out: initialised\r\n"); -#endif -} - -// TIMER capture/compare interrupt -void PIOS_PPM_OUT_CC_IRQ(void) -{ - // clear the interrupt - TIM_ClearITPendingBit(PIOS_PPM_TIM_PORT, PIOS_PPM_OUT_TIM_CCR); - - if (booting || ppm_initialising) - return; - - // ************************* - // update the TIMER period (channel pulse width) - - if (ppm_Out_ChannelPulseIndex < 0) - { // SYNC PULSE - TIM_SetAutoreload(PIOS_PPM_TIM, ppm_Out_SyncPulseWidth - 1); // sync pulse length - ppm_Out_SyncPulseWidth = PPM_OUT_FRAME_PERIOD_US; // reset sync period - - if (ppm_Out_ChannelsUsed > 0) - ppm_Out_ChannelPulseIndex = 0; // onto channel-1 - } - else - { // CHANNEL PULSE - uint16_t pulse_width = ppm_Out_ChannelPulseWidth[ppm_Out_ChannelPulseIndex]; - if (pulse_width < PPM_OUT_MIN_CHANNEL_PULSE_US) pulse_width = PPM_OUT_MIN_CHANNEL_PULSE_US; - else - if (pulse_width > PPM_OUT_MAX_CHANNEL_PULSE_US) pulse_width = PPM_OUT_MAX_CHANNEL_PULSE_US; - - TIM_SetAutoreload(PIOS_PPM_TIM, pulse_width - 1); // channel pulse width - ppm_Out_SyncPulseWidth -= pulse_width; // maintain constant PPM frame period - - // TEST ONLY -// pulse_width += 4; -// if (pulse_width > 2000) pulse_width = 1000; -// ppm_Out_ChannelPulseWidth[ppm_Out_ChannelPulseIndex] = pulse_width; - - ppm_Out_ChannelPulseIndex++; - if (ppm_Out_ChannelPulseIndex >= ppm_Out_ChannelsUsed || ppm_Out_ChannelPulseIndex >= PIOS_PPM_MAX_CHANNELS) - ppm_Out_ChannelPulseIndex = -1; // back to SYNC pulse - } - - // ************************* -} - -// ************************************************************* -// TIMER capture/compare interrupt - -void PIOS_PPM_CC_IRQ_FUNC(void) -{ - if (ppm_mode == MODE_PPM_TX) - PIOS_PPM_IN_CC_IRQ(); - else - if (ppm_mode == MODE_PPM_RX) - PIOS_PPM_OUT_CC_IRQ(); - else - TIM_ClearITPendingBit(PIOS_PPM_TIM_PORT, PIOS_PPM_IN_TIM_CCR | TIM_IT_Update); // clear the interrupts -} - -// ************************************************************* -// can be called from an interrupt if you wish -// call this once every ms - -void ppm_1ms_tick(void) -{ - if (booting || ppm_initialising) - return; - - -} - -// ************************************************************* -// return a byte for the tx packet transmission. -// -// return value < 0 if no more bytes available, otherwise return byte to be sent - -int16_t ppm_TxDataByteCallback(void) -{ - return -1; -} - -// ************************************************************* -// we are being given a block of received bytes -// -// return TRUE to continue current packet receive, otherwise return FALSE to halt current packet reception - -bool ppm_RxDataCallback(void *data, uint8_t len) -{ - return true; -} - -// ************************************************************* -// call this from the main loop (not interrupt) as often as possible - -void ppm_process(void) -{ - if (booting || ppm_initialising) - return; - - if (ppm_mode == MODE_PPM_TX) - { - if (ppm_In_NewFrame() > 0) - { // we have a new PPM frame to send - - #ifdef PPM_DEBUG - DEBUG_PRINTF("ppm_in: %5u %5u ..", ppm_In_Frames, ppm_In_ErrorFrames); - #endif - - for (int i = 0; i < PIOS_PPM_MAX_CHANNELS && i < ppm_In_ChannelsDetected; i++) - { -// int32_t pwm = ppm_In_GetChannelPulseWidth(i); - - #ifdef PPM_DEBUG - DEBUG_PRINTF(" %4u", ppm_In_GetChannelPulseWidth(i)); - #endif - - // TODO: - } - - #ifdef PPM_DEBUG - DEBUG_PRINTF("\r\n"); - #endif - } - } - else - if (ppm_mode == MODE_PPM_RX) - { - // TODO: - } -} - -// ************************************************************* - -void ppm_deinit(void) -{ - ppm_initialising = true; - - ppm_mode = 0; - - // disable timer - TIM_Cmd(PIOS_PPM_TIM, DISABLE); - - // Disable timer clock - PIOS_PPM_TIMER_DIS_RCC_FUNC; - - // TIM IT disable - TIM_ITConfig(PIOS_PPM_TIM, PIOS_PPM_IN_TIM_CCR | PIOS_PPM_OUT_TIM_CCR, DISABLE); - - // TIMER Main Output Disable - TIM_CtrlPWMOutputs(PIOS_PPM_TIM, DISABLE); - - // un-remap the PPM pins - GPIO_PinRemapConfig(GPIO_FullRemap_TIM2, DISABLE); - - // Disable timer interrupt - NVIC_InitTypeDef NVIC_InitStructure; - NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = PIOS_IRQ_PRIO_MID; - NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0; - NVIC_InitStructure.NVIC_IRQChannelCmd = DISABLE; - NVIC_InitStructure.NVIC_IRQChannel = PIOS_PPM_TIM_IRQ; - NVIC_Init(&NVIC_InitStructure); - - ppm_initialising = false; -} - -void ppm_init(uint32_t our_sn) -{ - ppm_deinit(); - - ppm_initialising = true; - - ppm_mode = saved_settings.mode; - - #if defined(PPM_DEBUG) - DEBUG_PRINTF("\r\nPPM init\r\n"); - #endif - - if (ppm_mode == MODE_PPM_TX) - { - ppm_In_Init(); - rfm22_init_tx_stream(saved_settings.min_frequency_Hz, saved_settings.max_frequency_Hz); - } - else - if (ppm_mode == MODE_PPM_RX) - { - ppm_Out_Init(); - rfm22_init_rx_stream(saved_settings.min_frequency_Hz, saved_settings.max_frequency_Hz); - } - - rfm22_TxDataByte_SetCallback(ppm_TxDataByteCallback); - rfm22_RxData_SetCallback(ppm_RxDataCallback); - - rfm22_setFreqCalibration(saved_settings.rf_xtal_cap); - rfm22_setNominalCarrierFrequency(saved_settings.frequency_Hz); - rfm22_setDatarate(saved_settings.max_rf_bandwidth, FALSE); - rfm22_setTxPower(saved_settings.max_tx_power); - - if (ppm_mode == MODE_PPM_TX) - rfm22_setTxStream(); - - ppm_initialising = false; -} - -// ************************************************************* diff --git a/flight/PipXtreme/reserved/api_comms.c b/flight/PipXtreme/reserved/api_comms.c deleted file mode 100644 index 0f7d27708..000000000 --- a/flight/PipXtreme/reserved/api_comms.c +++ /dev/null @@ -1,500 +0,0 @@ -/** - ****************************************************************************** - * - * @file api_comms.h - * @author The OpenPilot Team, http://www.openpilot.org Copyright (C) 2010. - * @brief RF Module hardware layer - * @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 - */ - - - - -// see http://newwiki.openpilot.org/display/Doc/UAVTalk .. for UAVTalk protocol description -// -// This module scans for OP UAVTalk packets in the comm-port or RF data streams. -// It will discard any corrupt/invalid packets and only pass valid ones. - - - -#include - -#include "stm32f10x.h" -#include "gpio_in.h" -#include "api_comms.h" -#include "packet_handler.h" -#include "main.h" - -#if defined(PIOS_COM_DEBUG) - #define API_DEBUG -#endif - -// ***************************************************************************** -// modem configuration packets - -typedef struct -{ - uint32_t marker; - uint32_t serial_number; - uint8_t type; - uint8_t spare; - uint16_t data_size; - uint32_t header_crc; - uint32_t data_crc; -// uint8_t data[0]; -} __attribute__((__packed__)) t_pipx_config_header; - -typedef struct -{ - uint8_t mode; - uint8_t state; -} __attribute__((__packed__)) t_pipx_config_data_mode_state; - -typedef struct -{ - uint32_t serial_baudrate; // serial uart baudrate - - uint32_t destination_id; - - uint32_t min_frequency_Hz; - uint32_t max_frequency_Hz; - uint32_t frequency_Hz; - - uint32_t max_rf_bandwidth; - - uint8_t max_tx_power; - - uint8_t frequency_band; - - uint8_t rf_xtal_cap; - - bool aes_enable; - uint8_t aes_key[16]; - - uint16_t frequency_step_size; -} __attribute__((__packed__)) t_pipx_config_data_settings; - -typedef struct -{ - uint32_t start_frequency; - uint16_t frequency_step_size; - uint16_t magnitudes; -// int8_t magnitude[0]; -} __attribute__((__packed__)) t_pipx_config_data_spectrum; - -// ***************************************************************************** - -typedef struct -{ - uint8_t sync_byte; - uint8_t message_type; - uint16_t packet_size; // not including CRC byte - uint32_t object_id; -} __attribute__((__packed__)) t_uav_header1; - -typedef struct -{ - uint8_t sync_byte; - uint8_t message_type; - uint16_t packet_size; // not including CRC byte - uint32_t object_id; - uint16_t instance_id; -} __attribute__((__packed__)) t_uav_header2; - -#define SYNC_VAL 0x3C -#define TYPE_MASK 0xFC -#define TYPE_VER 0x20 -#define TYPE_OBJ (TYPE_VER | 0x00) -#define TYPE_OBJ_REQ (TYPE_VER | 0x01) -#define TYPE_OBJ_ACK (TYPE_VER | 0x02) -#define TYPE_ACK (TYPE_VER | 0x03) - -#define MIN_HEADER_LENGTH sizeof(t_uav_header1) -#define MAX_HEADER_LENGTH sizeof(t_uav_header2) -#define MAX_PAYLOAD_LENGTH 256 -#define CHECKSUM_LENGTH 1 - -#define MAX_PACKET_LENGTH (MAX_HEADER_LENGTH + MAX_PAYLOAD_LENGTH + CHECKSUM_LENGTH) - -// 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 -}; - -// ***************************************************************************** -// local variables - -uint32_t api_previous_com_port = 0; - -volatile uint16_t api_rx_timer = 0; -volatile uint16_t api_tx_timer = 0; - -uint8_t api_rx_buffer[MAX_PACKET_LENGTH] __attribute__ ((aligned(4))); -uint16_t api_rx_buffer_wr; - -uint8_t api_tx_buffer[MAX_PACKET_LENGTH] __attribute__ ((aligned(4))); -uint16_t api_tx_buffer_wr; - -// ***************************************************************************** -// 8-bit CRC updating - -uint8_t api_updateCRC_byte(uint8_t crc, uint8_t b) -{ - return crc_table[crc ^ b]; -} - -uint8_t api_updateCRC_buffer(uint8_t crc, const void *data, int32_t length) -{ - // use registers for speed - register uint8_t crc8 = crc; - register const uint8_t *p = (uint8_t *)data; - - for (register int32_t i = length; i > 0; i--) - crc8 = crc_table[crc8 ^ *p++]; - - return crc8; -} - -// returned value < 0 if no valid packet detected. -// otherwise returned value is the total size of the valid UAVTalk packet found in the buffer. -// -// any corrupt/invalid UAVTalk packets/data are deleted from the buffer and we scan for the next valid packet. -int16_t api_scanForUAVTalkPacket(void *buf, uint16_t *len) -{ - uint8_t *buffer = (uint8_t *)buf; - - t_uav_header1 *header1 = (t_uav_header1 *)buf; -// t_uav_header2 *header2 = (t_uav_header2 *)buf; - - register uint16_t num_bytes = *len; - - if (num_bytes < MIN_HEADER_LENGTH + CHECKSUM_LENGTH) - return -1; // not yet enough bytes for a complete packet - - while (TRUE) - { - // scan the buffer for the start of a UAVTalk packet - for (uint16_t i = 0; i < num_bytes; i++) - { - if (api_rx_buffer[i] != SYNC_VAL) - continue; // not the start of a packet - move on to the next byte in the buffer - - // possible start of packet found - we found a SYNC byte - - if (i > 0) - { // remove/delete leading bytes before the SYNC byte - num_bytes -= i; - if (num_bytes > 0) - memmove(buffer, buffer + i, num_bytes); - *len = num_bytes; - } - break; - } - - if (num_bytes < MIN_HEADER_LENGTH + CHECKSUM_LENGTH) - return -2; // not yet enough bytes for a complete packet - - if (header1->sync_byte != SYNC_VAL) - { // SYNC byte was not found - start of UAVTalk packet not found in any of the data in the buffer - *len = 0; // empty the entire buffer - return -3; - } - - if (header1->packet_size < MIN_HEADER_LENGTH || header1->packet_size > MAX_HEADER_LENGTH + MAX_PAYLOAD_LENGTH) - { // the packet size value is too small or too big - assume either a corrupt UAVTalk packet or we are at the start of a packet -// if (--num_bytes > 0) -// memmove(buffer, buffer + 1, num_bytes); // remove 1st byte -// *len = num_bytes; - buffer[0] ^= 0xaa; // corrupt the sync byte - we'll move the buffer bytes down further up in the code - continue; // continue scanning for a valid packet in the buffer - } - - if (num_bytes < header1->packet_size + CHECKSUM_LENGTH) - { // not yet enough bytes for a complete packet - return -4; - } - - // check the packet CRC - uint8_t crc1 = api_updateCRC_buffer(0, buffer, header1->packet_size); - uint8_t crc2 = buffer[header1->packet_size]; - if (crc1 != crc2) - { // faulty CRC -// if (--num_bytes > 0) -// memmove(buffer, buffer + 1, num_bytes); // remove 1st byte -// *len = num_bytes; - buffer[0] ^= 0xaa; // corrupt the sync byte - we'll move the buffer bytes down further up in the code - - #if defined(API_DEBUG) - DEBUG_PRINTF("UAVTalk packet corrupt %d\r\n", header1->packet_size + 1); - #endif - - continue; // continue scanning for a valid packet in the buffer - } - - #if defined(API_DEBUG) - DEBUG_PRINTF("UAVTalk packet found %d\r\n", header1->packet_size + 1); - #endif - - return (header1->packet_size + CHECKSUM_LENGTH); // return the size of the UAVTalk packet - } - - return -5; -} - -// ***************************************************************************** - -int16_t api_scanForConfigPacket(void *buf, uint16_t *len) -{ - return -1; -} - -// ***************************************************************************** -// can be called from an interrupt if you wish - -void api_1ms_tick(void) -{ // call this once every 1ms - - if (api_rx_timer < 0xffff) api_rx_timer++; - if (api_tx_timer < 0xffff) api_tx_timer++; -} - -// ***************************************************************************** -// call this as often as possible - not from an interrupt - -void api_process(void) -{ // copy data from comm-port RX buffer to RF packet handler TX buffer, and from RF packet handler RX buffer to comm-port TX buffer - - // ******************** - // decide which comm-port we are using (usart or usb) - - bool usb_comms = false; // TRUE if we are using the usb port for comms. - uint32_t comm_port = PIOS_COM_SERIAL; // default to using the usart comm-port - - #if defined(PIOS_INCLUDE_USB_HID) - if (PIOS_USB_HID_CheckAvailable(0)) - { // USB comms is up, use the USB comm-port instead of the USART comm-port - usb_comms = true; - comm_port = PIOS_COM_TELEM_USB; - } - #endif - - // ******************** - // check to see if the local communication port has changed (usart/usb) - - if (api_previous_com_port == 0 && api_previous_com_port != comm_port) - { // the local communications port has changed .. remove any data in the buffers - api_rx_buffer_wr = 0; - api_tx_buffer_wr = 0; - } - else - if (usb_comms) - { // we're using the USB for comms - keep the USART rx buffer empty - int32_t bytes = PIOS_COM_ReceiveBufferUsed(PIOS_COM_SERIAL); - while (bytes > 0) - { - PIOS_COM_ReceiveBuffer(PIOS_COM_SERIAL); - bytes--; - } - } - - api_previous_com_port = comm_port; // remember the current comm-port we are using - - // ******************** - - uint16_t connection_index = 0; // the RF connection we are using - - // ******************** - // send the data received from the local comm-port to the RF packet handler TX buffer - - while (TRUE) - { - int16_t packet_size; - - // free space size in the RF packet handler tx buffer - uint16_t ph_num = ph_putData_free(connection_index); - - // get the number of data bytes received down the comm-port - int32_t com_num = PIOS_COM_ReceiveBufferUsed(comm_port); - - // set the USART RTS handshaking line - if (!usb_comms && ph_connected(connection_index)) - { - if (ph_num < 32) - SERIAL_RTS_CLEAR; // lower the USART RTS line - we don't have space in the buffer for anymore bytes - else - SERIAL_RTS_SET; // release the USART RTS line - we have space in the buffer for now bytes - } - else - SERIAL_RTS_SET; // release the USART RTS line - - // limit number of bytes we will get to how much space we have in our RX buffer - if (com_num > sizeof(api_rx_buffer) - api_rx_buffer_wr) - com_num = sizeof(api_rx_buffer) - api_rx_buffer_wr; - - while (com_num > 0) - { // fetch a byte from the comm-port RX buffer and save it into our RX buffer - api_rx_buffer[api_rx_buffer_wr++] = PIOS_COM_ReceiveBuffer(comm_port); - com_num--; - } - -// packet_size = api_scanForConfigPacket(api_rx_buffer, &api_rx_buffer_wr); - - packet_size = api_scanForUAVTalkPacket(api_rx_buffer, &api_rx_buffer_wr); - if (packet_size < 0) - break; // no UAVTalk packet in our RX buffer - - api_rx_timer = 0; - - if (!ph_connected(connection_index)) - { // we don't have a link to a remote modem .. remove the UAVTalk packet from our RX buffer - if (api_rx_buffer_wr > packet_size) - { - api_rx_buffer_wr -= packet_size; - memmove(api_rx_buffer, api_rx_buffer + packet_size, api_rx_buffer_wr); - } - else - api_rx_buffer_wr = 0; - continue; - } - - if (ph_num < packet_size) - break; // not enough room in the RF packet handler TX buffer for the UAVTalk packet - - // copy the rx'ed UAVTalk packet into the RF packet handler TX buffer for sending over the RF link - ph_putData(connection_index, api_rx_buffer, packet_size); - - // remove the UAVTalk packet from our RX buffer - if (api_rx_buffer_wr > packet_size) - { - api_rx_buffer_wr -= packet_size; - memmove(api_rx_buffer, api_rx_buffer + packet_size, api_rx_buffer_wr); - } - else - api_rx_buffer_wr = 0; - } - - // ******************** - // send the data received via the RF link out the comm-port - - while (TRUE) - { - // get number of data bytes received via the RF link - uint16_t ph_num = ph_getData_used(connection_index); - - // limit to how much space we have in the temp TX buffer - if (ph_num > sizeof(api_tx_buffer) - api_tx_buffer_wr) - ph_num = sizeof(api_tx_buffer) - api_tx_buffer_wr; - - if (ph_num > 0) - { // fetch the data bytes received via the RF link and save into our temp buffer - ph_num = ph_getData(connection_index, api_tx_buffer + api_tx_buffer_wr, ph_num); - api_tx_buffer_wr += ph_num; - } - - int16_t packet_size = api_scanForUAVTalkPacket(api_tx_buffer, &api_tx_buffer_wr); - - if (packet_size <= 0) - break; // no UAV Talk packet found - - // we have a UAVTalk packet to send down the comm-port -/* - #if (defined(PIOS_COM_DEBUG) && (PIOS_COM_DEBUG == PIOS_COM_SERIAL)) - if (!usb_comms) - { // the serial-port is being used for debugging - don't send data down it - api_tx_buffer_wr = 0; - api_tx_timer = 0; - continue; - } - #endif -*/ - if (!usb_comms && !GPIO_IN(SERIAL_CTS_PIN)) - break; // we can't yet send data down the comm-port - - // send the data out the comm-port - int32_t res; -// if (usb_comms) -// res = PIOS_COM_SendBuffer(comm_port, api_tx_buffer, packet_size); -// else - res = PIOS_COM_SendBufferNonBlocking(comm_port, api_tx_buffer, packet_size); // this one doesn't work properly with USB :( - if (res < 0) - { // failed to send the data out the comm-port - #if defined(API_DEBUG) - DEBUG_PRINTF("PIOS_COM_SendBuffer %d %d\r\n", packet_size, res); - #endif - - if (api_tx_timer >= 5000) - { // seems we can't send our data for at least the last 5 seconds - delete it - if (api_tx_buffer_wr > packet_size) - { - api_tx_buffer_wr -= packet_size; - memmove(api_tx_buffer, api_tx_buffer + packet_size, api_tx_buffer_wr); - } - else - api_tx_buffer_wr = 0; - } - - break; - } - - // data was sent out the comm-port OK .. remove the sent data from our buffer - - if (api_tx_buffer_wr > packet_size) - { - api_tx_buffer_wr -= packet_size; - memmove(api_tx_buffer, api_tx_buffer + packet_size, api_tx_buffer_wr); - } - else - api_tx_buffer_wr = 0; - - api_tx_timer = 0; - } - - // ******************** -} - -// ***************************************************************************** - -void api_init(void) -{ - api_previous_com_port = 0; - - api_rx_buffer_wr = 0; - - api_tx_buffer_wr = 0; - - api_rx_timer = 0; - api_tx_timer = 0; -} - -// ***************************************************************************** diff --git a/flight/PipXtreme/rfm22b.c b/flight/PipXtreme/rfm22b.c deleted file mode 100644 index 57be9a493..000000000 --- a/flight/PipXtreme/rfm22b.c +++ /dev/null @@ -1,2491 +0,0 @@ -/** - ****************************************************************************** - * - * @file rfm22b.c - * @author The OpenPilot Team, http://www.openpilot.org Copyright (C) 2010. - * @brief RF Module hardware layer - * @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 - */ - -// ***************************************************************** -// RFM22B hardware layer -// -// This module uses the RFM22B's internal packet handling hardware to encapsulate our own packet data. -// -// The RFM22B internal hardware packet handler configuration is as follows .. -// -// 4-byte (32-bit) preamble .. alternating 0's & 1's -// 4-byte (32-bit) sync -// 1-byte packet length (number of data bytes to follow) -// 0 to 255 user data bytes -// -// Our own packet data will also contain it's own header and 32-bit CRC as a single 16-bit CRC is not sufficient for wireless comms. -// -// ***************************************************************** - -#include // memmove - -#include "stm32f10x.h" -#include "main.h" -#include "stopwatch.h" -#include "gpio_in.h" -#include "rfm22b.h" - -#if defined(PIOS_COM_DEBUG) -// #define RFM22_DEBUG -// #define RFM22_INT_TIMEOUT_DEBUG -#endif - -// ***************************************************************** -// forward delarations - -#if defined(RFM22_EXT_INT_USE) - void rfm22_processInt(void); -#endif - -// ************************************ -// this is too adjust the RF module so that it is on frequency - -#define OSC_LOAD_CAP 0x7F // cap = 12.5pf .. default - -#define OSC_LOAD_CAP_1 0x7D // board 1 -#define OSC_LOAD_CAP_2 0x7B // board 2 -#define OSC_LOAD_CAP_3 0x7E // board 3 -#define OSC_LOAD_CAP_4 0x7F // board 4 - -// ************************************ - -#define TX_TEST_MODE_TIMELIMIT_MS 30000 // TX test modes time limit (in ms) - -//#define TX_PREAMBLE_NIBBLES 8 // 7 to 511 (number of nibbles) -//#define RX_PREAMBLE_NIBBLES 5 // 5 to 31 (number of nibbles) -#define TX_PREAMBLE_NIBBLES 12 // 7 to 511 (number of nibbles) -#define RX_PREAMBLE_NIBBLES 6 // 5 to 31 (number of nibbles) - -#define FIFO_SIZE 64 // the size of the rf modules internal FIFO buffers - -#define TX_FIFO_HI_WATERMARK 62 // 0-63 -#define TX_FIFO_LO_WATERMARK 32 // 0-63 - -#define RX_FIFO_HI_WATERMARK 32 // 0-63 - -#define PREAMBLE_BYTE 0x55 // preamble byte (preceeds SYNC_BYTE's) - -#define SYNC_BYTE_1 0x2D // RF sync bytes (32-bit in all) -#define SYNC_BYTE_2 0xD4 // -#define SYNC_BYTE_3 0x4B // -#define SYNC_BYTE_4 0x59 // - -// ************************************ -// the default TX power level - -#define RFM22_DEFAULT_RF_POWER RFM22_tx_pwr_txpow_0 // +1dBm ... 1.25mW -//#define RFM22_DEFAULT_RF_POWER RFM22_tx_pwr_txpow_1 // +2dBm ... 1.6mW -//#define RFM22_DEFAULT_RF_POWER RFM22_tx_pwr_txpow_2 // +5dBm ... 3.16mW -//#define RFM22_DEFAULT_RF_POWER RFM22_tx_pwr_txpow_3 // +8dBm ... 6.3mW -//#define RFM22_DEFAULT_RF_POWER RFM22_tx_pwr_txpow_4 // +11dBm .. 12.6mW -//#define RFM22_DEFAULT_RF_POWER RFM22_tx_pwr_txpow_5 // +14dBm .. 25mW -//#define RFM22_DEFAULT_RF_POWER RFM22_tx_pwr_txpow_6 // +17dBm .. 50mW -//#define RFM22_DEFAULT_RF_POWER RFM22_tx_pwr_txpow_7 // +20dBm .. 100mW - -// ************************************ -// the default RF datarate - -//#define RFM22_DEFAULT_RF_DATARATE 500 // 500 bits per sec -//#define RFM22_DEFAULT_RF_DATARATE 1000 // 1k bits per sec -//#define RFM22_DEFAULT_RF_DATARATE 2000 // 2k bits per sec -//#define RFM22_DEFAULT_RF_DATARATE 4000 // 4k bits per sec -//#define RFM22_DEFAULT_RF_DATARATE 8000 // 8k bits per sec -//#define RFM22_DEFAULT_RF_DATARATE 9600 // 9.6k bits per sec -//#define RFM22_DEFAULT_RF_DATARATE 16000 // 16k bits per sec -//#define RFM22_DEFAULT_RF_DATARATE 19200 // 19k2 bits per sec -//#define RFM22_DEFAULT_RF_DATARATE 24000 // 24k bits per sec -//#define RFM22_DEFAULT_RF_DATARATE 32000 // 32k bits per sec -//#define RFM22_DEFAULT_RF_DATARATE 64000 // 64k bits per sec -#define RFM22_DEFAULT_RF_DATARATE 128000 // 128k bits per sec -//#define RFM22_DEFAULT_RF_DATARATE 192000 // 192k bits per sec -//#define RFM22_DEFAULT_RF_DATARATE 256000 // 256k bits per sec .. NOT YET WORKING - -// ************************************ - -#define RFM22_DEFAULT_SS_RF_DATARATE 125 // 128bps - -// ************************************ -// Normal data streaming -// GFSK modulation -// no manchester encoding -// data whitening -// FIFO mode -// 5-nibble rx preamble length detection -// 10-nibble tx preamble length -// AFC enabled - -#define LOOKUP_SIZE 14 - -// xtal 10 ppm, 434MHz -const uint32_t data_rate[LOOKUP_SIZE] = { 500, 1000, 2000, 4000, 8000, 9600, 16000, 19200, 24000, 32000, 64000, 128000, 192000, 256000}; -const uint8_t modulation_index[LOOKUP_SIZE] = { 16, 8, 4, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1}; -const uint32_t freq_deviation[LOOKUP_SIZE] = { 4000, 4000, 4000, 4000, 4000, 4800, 8000, 9600, 12000, 16000, 32000, 64000, 96000, 128000}; -const uint32_t rx_bandwidth[LOOKUP_SIZE] = { 17500, 17500, 17500, 17500, 17500, 19400, 32200, 38600, 51200, 64100, 137900, 269300, 420200, 518800}; -const int8_t est_rx_sens_dBm[LOOKUP_SIZE] = { -118, -118, -117, -116, -115, -115, -112, -112, -110, -109, -106, -103, -101, -100}; // estimated receiver sensitivity for BER = 1E-3 - -const uint8_t reg_1C[LOOKUP_SIZE] = { 0x37, 0x37, 0x37, 0x37, 0x3A, 0x3B, 0x26, 0x28, 0x2E, 0x16, 0x07, 0x83, 0x8A, 0x8C}; // rfm22_if_filter_bandwidth - -const uint8_t reg_1D[LOOKUP_SIZE] = { 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44}; // rfm22_afc_loop_gearshift_override -const uint8_t reg_1E[LOOKUP_SIZE] = { 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x02}; // rfm22_afc_timing_control - -const uint8_t reg_1F[LOOKUP_SIZE] = { 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03}; // rfm22_clk_recovery_gearshift_override -const uint8_t reg_20[LOOKUP_SIZE] = { 0xE8, 0xF4, 0xFA, 0x70, 0x3F, 0x34, 0x3F, 0x34, 0x2A, 0x3F, 0x3F, 0x5E, 0x3F, 0x2F}; // rfm22_clk_recovery_oversampling_ratio -const uint8_t reg_21[LOOKUP_SIZE] = { 0x60, 0x20, 0x00, 0x01, 0x02, 0x02, 0x02, 0x02, 0x03, 0x02, 0x02, 0x01, 0x02, 0x02}; // rfm22_clk_recovery_offset2 -const uint8_t reg_22[LOOKUP_SIZE] = { 0x20, 0x41, 0x83, 0x06, 0x0C, 0x75, 0x0C, 0x75, 0x12, 0x0C, 0x0C, 0x5D, 0x0C, 0xBB}; // rfm22_clk_recovery_offset1 -const uint8_t reg_23[LOOKUP_SIZE] = { 0xC5, 0x89, 0x12, 0x25, 0x4A, 0x25, 0x4A, 0x25, 0x6F, 0x4A, 0x4A, 0x86, 0x4A, 0x0D}; // rfm22_clk_recovery_offset0 -const uint8_t reg_24[LOOKUP_SIZE] = { 0x00, 0x00, 0x00, 0x02, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x05, 0x07, 0x07}; // rfm22_clk_recovery_timing_loop_gain1 -const uint8_t reg_25[LOOKUP_SIZE] = { 0x0A, 0x23, 0x85, 0x0E, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x74, 0xFF, 0xFF}; // rfm22_clk_recovery_timing_loop_gain0 - -const uint8_t reg_2A[LOOKUP_SIZE] = { 0x0E, 0x0E, 0x0E, 0x0E, 0x0E, 0x0D, 0x0D, 0x0E, 0x12, 0x17, 0x31, 0x50, 0x50, 0x50}; // rfm22_afc_limiter .. AFC_pull_in_range = ±AFCLimiter[7:0] x (hbsel+1) x 625 Hz - -const uint8_t reg_6E[LOOKUP_SIZE] = { 0x04, 0x08, 0x10, 0x20, 0x41, 0x4E, 0x83, 0x9D, 0xC4, 0x08, 0x10, 0x20, 0x31, 0x41}; // rfm22_tx_data_rate1 -const uint8_t reg_6F[LOOKUP_SIZE] = { 0x19, 0x31, 0x62, 0xC5, 0x89, 0xA5, 0x12, 0x49, 0x9C, 0x31, 0x62, 0xC5, 0x27, 0x89}; // rfm22_tx_data_rate0 - -const uint8_t reg_70[LOOKUP_SIZE] = { 0x2D, 0x2D, 0x2D, 0x2D, 0x2D, 0x2D, 0x2D, 0x2D, 0x2D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D}; // rfm22_modulation_mode_control1 -const uint8_t reg_71[LOOKUP_SIZE] = { 0x23, 0x23, 0x23, 0x23, 0x23, 0x23, 0x23, 0x23, 0x23, 0x23, 0x23, 0x23, 0x23, 0x23}; // rfm22_modulation_mode_control2 - -const uint8_t reg_72[LOOKUP_SIZE] = { 0x06, 0x06, 0x06, 0x06, 0x06, 0x08, 0x0D, 0x0F, 0x13, 0x1A, 0x33, 0x66, 0x9A, 0xCD}; // rfm22_frequency_deviation - -// ************************************ -// Scan Spectrum settings -// GFSK modulation -// no manchester encoding -// data whitening -// FIFO mode -// 5-nibble rx preamble length detection -// 10-nibble tx preamble length -// AFC disabled - -#define SS_LOOKUP_SIZE 2 - -// xtal 1 ppm, 434MHz -const uint32_t ss_rx_bandwidth[SS_LOOKUP_SIZE] = { 2600, 10600}; - -const uint8_t ss_reg_1C[SS_LOOKUP_SIZE] = { 0x51, 0x32}; // rfm22_if_filter_bandwidth -const uint8_t ss_reg_1D[SS_LOOKUP_SIZE] = { 0x00, 0x00}; // rfm22_afc_loop_gearshift_override - -const uint8_t ss_reg_20[SS_LOOKUP_SIZE] = { 0xE8, 0x38}; // rfm22_clk_recovery_oversampling_ratio -const uint8_t ss_reg_21[SS_LOOKUP_SIZE] = { 0x60, 0x02}; // rfm22_clk_recovery_offset2 -const uint8_t ss_reg_22[SS_LOOKUP_SIZE] = { 0x20, 0x4D}; // rfm22_clk_recovery_offset1 -const uint8_t ss_reg_23[SS_LOOKUP_SIZE] = { 0xC5, 0xD3}; // rfm22_clk_recovery_offset0 -const uint8_t ss_reg_24[SS_LOOKUP_SIZE] = { 0x00, 0x07}; // rfm22_clk_recovery_timing_loop_gain1 -const uint8_t ss_reg_25[SS_LOOKUP_SIZE] = { 0x0F, 0xFF}; // rfm22_clk_recovery_timing_loop_gain0 - -const uint8_t ss_reg_2A[SS_LOOKUP_SIZE] = { 0xFF, 0xFF}; // rfm22_afc_limiter .. AFC_pull_in_range = ±AFCLimiter[7:0] x (hbsel+1) x 625 Hz - -const uint8_t ss_reg_70[SS_LOOKUP_SIZE] = { 0x24, 0x2D}; // rfm22_modulation_mode_control1 -const uint8_t ss_reg_71[SS_LOOKUP_SIZE] = { 0x2B, 0x23}; // rfm22_modulation_mode_control2 - -// ************************************ - -volatile bool initialized = false; - -#if defined(RFM22_EXT_INT_USE) - volatile bool exec_using_spi; // set this if you want to access the SPI bus outside of the interrupt - volatile bool inside_ext_int; // this is set whenever we are inside the interrupt -#endif - -uint8_t device_type; // the RF chips device ID number -uint8_t device_version; // the RF chips revision number - -volatile uint8_t rf_mode; // holds our current RF mode - -uint32_t lower_carrier_frequency_limit_Hz; // the minimum RF frequency we can use -uint32_t upper_carrier_frequency_limit_Hz; // the maximum RF frequency we can use -uint32_t carrier_frequency_hz; // the current RF frequency we are on - -uint32_t carrier_datarate_bps; // the RF data rate we are using - -uint32_t rf_bandwidth_used; // the RF bandwidth currently used -uint32_t ss_rf_bandwidth_used; // the RF bandwidth currently used - -uint8_t hbsel; // holds the hbsel (1 or 2) -float frequency_step_size; // holds the minimum frequency step size - -uint8_t frequency_hop_channel; // current frequency hop channel - -uint8_t frequency_hop_step_size_reg; // - -uint8_t adc_config; // holds the adc config reg value - -volatile uint8_t device_status; // device status register -volatile uint8_t int_status1; // interrupt status register 1 -volatile uint8_t int_status2; // interrupt status register 2 -volatile uint8_t ezmac_status; // ezmac status register - -volatile int16_t afc_correction; // afc correction reading -volatile int32_t afc_correction_Hz; // afc correction reading (in Hz) - -volatile int16_t temperature_reg; // the temperature sensor reading - -#if defined(RFM22_DEBUG) - volatile uint8_t prev_device_status; // just for debugging - volatile uint8_t prev_int_status1; // " " - volatile uint8_t prev_int_status2; // " " - volatile uint8_t prev_ezmac_status; // " " - - bool debug_outputted; -#endif - -volatile uint8_t osc_load_cap; // xtal frequency calibration value - -volatile uint8_t rssi; // the current RSSI (register value) -volatile int16_t rssi_dBm; // dBm value - -uint8_t tx_power; // the transmit power to use for data transmissions -volatile uint8_t tx_pwr; // the tx power register read back - -volatile uint8_t rx_buffer_current; // the current receive buffer in use (double buffer) -volatile uint8_t rx_buffer[256] __attribute__ ((aligned(4))); // the receive buffer .. received packet data is saved here -volatile uint16_t rx_buffer_wr; // the receive buffer write index - -volatile uint8_t rx_packet_buf[256] __attribute__ ((aligned(4))); // the received packet -volatile uint16_t rx_packet_wr; // the receive packet write index -volatile int16_t rx_packet_start_rssi_dBm; // -volatile int32_t rx_packet_start_afc_Hz; // -volatile int16_t rx_packet_rssi_dBm; // the received packet signal strength -volatile int32_t rx_packet_afc_Hz; // the receive packet frequency offset - -volatile uint8_t *tx_data_addr; // the address of the data we send in the transmitted packets -volatile uint16_t tx_data_rd; // the tx data read index -volatile uint16_t tx_data_wr; // the tx data write index - -//volatile uint8_t tx_fifo[FIFO_SIZE]; // - -volatile uint8_t rx_fifo[FIFO_SIZE]; // -volatile uint8_t rx_fifo_wr; // - -int lookup_index; -int ss_lookup_index; - -volatile bool power_on_reset; // set if the RF module has reset itself - -volatile uint16_t rfm22_int_timer; // used to detect if the RF module stops responding. thus act accordingly if it does stop responding. -volatile uint16_t rfm22_int_time_outs; // counter -volatile uint16_t prev_rfm22_int_time_outs; // - -uint32_t clear_channel_count = (TX_PREAMBLE_NIBBLES + 4) * 2; // minimum clear channel time before allowing transmit - -uint16_t timeout_ms = 20000; // -uint16_t timeout_sync_ms = 3; // -uint16_t timeout_data_ms = 20; // - -t_rfm22_TxDataByteCallback tx_data_byte_callback_function = NULL; -t_rfm22_RxDataCallback rx_data_callback_function = NULL; - -// ************************************ -// SPI read/write - -void rfm22_startBurstWrite(uint8_t addr) -{ - // wait 1us .. so we don't toggle the CS line to quickly - PIOS_DELAY_WaituS(1); - - // chip select line LOW - PIOS_SPI_RC_PinSet(RFM22_PIOS_SPI, 0); - - PIOS_SPI_TransferByte(RFM22_PIOS_SPI, 0x80 | addr); -} - -inline void rfm22_burstWrite(uint8_t data) -{ - PIOS_SPI_TransferByte(RFM22_PIOS_SPI, data); -} - -void rfm22_endBurstWrite(void) -{ - // chip select line HIGH - PIOS_SPI_RC_PinSet(RFM22_PIOS_SPI, 1); -} - -void rfm22_write(uint8_t addr, uint8_t data) -{ - // wait 1us .. so we don't toggle the CS line to quickly - PIOS_DELAY_WaituS(1); - - // chip select line LOW - PIOS_SPI_RC_PinSet(RFM22_PIOS_SPI, 0); - - PIOS_SPI_TransferByte(RFM22_PIOS_SPI, 0x80 | addr); - PIOS_SPI_TransferByte(RFM22_PIOS_SPI, data); - - // chip select line HIGH - PIOS_SPI_RC_PinSet(RFM22_PIOS_SPI, 1); -} - -void rfm22_startBurstRead(uint8_t addr) -{ - // wait 1us .. so we don't toggle the CS line to quickly - PIOS_DELAY_WaituS(1); - - // chip select line LOW - PIOS_SPI_RC_PinSet(RFM22_PIOS_SPI, 0); - - PIOS_SPI_TransferByte(RFM22_PIOS_SPI, addr & 0x7f); -} - -inline uint8_t rfm22_burstRead(void) -{ - return PIOS_SPI_TransferByte(RFM22_PIOS_SPI, 0xff); -} - -void rfm22_endBurstRead(void) -{ - // chip select line HIGH - PIOS_SPI_RC_PinSet(RFM22_PIOS_SPI, 1); -} - -uint8_t rfm22_read(uint8_t addr) -{ - uint8_t rdata; - - // wait 1us .. so we don't toggle the CS line to quickly - PIOS_DELAY_WaituS(1); - - // chip select line LOW - PIOS_SPI_RC_PinSet(RFM22_PIOS_SPI, 0); - - PIOS_SPI_TransferByte(RFM22_PIOS_SPI, addr & 0x7f); - rdata = PIOS_SPI_TransferByte(RFM22_PIOS_SPI, 0xff); - - // chip select line HIGH - PIOS_SPI_RC_PinSet(RFM22_PIOS_SPI, 1); - - return rdata; -} - -// ************************************ -// external interrupt - -#if defined(RFM22_EXT_INT_USE) - - void RFM22_EXT_INT_FUNC(void) - { - inside_ext_int = TRUE; - - if (EXTI_GetITStatus(RFM22_EXT_INT_LINE) != RESET) - { - // Clear the EXTI line pending bit - EXTI_ClearITPendingBit(RFM22_EXT_INT_LINE); - -// USB_LED_TOGGLE; // TEST ONLY - - if (!booting && !exec_using_spi) - { -// while (!GPIO_IN(RF_INT_PIN) && !exec_using_spi) - { // stay here until the interrupt line returns HIGH - rfm22_processInt(); - } - } - } - - inside_ext_int = FALSE; - } - - void rfm22_disableExtInt(void) - { - // Configure the external interrupt - GPIO_EXTILineConfig(RFM22_EXT_INT_PORT_SOURCE, RFM22_EXT_INT_PIN_SOURCE); - EXTI_InitTypeDef EXTI_InitStructure; - EXTI_InitStructure.EXTI_Line = RFM22_EXT_INT_LINE; - EXTI_InitStructure.EXTI_Mode = EXTI_Mode_Interrupt; - EXTI_InitStructure.EXTI_Trigger = EXTI_Trigger_Falling; - EXTI_InitStructure.EXTI_LineCmd = DISABLE; - EXTI_Init(&EXTI_InitStructure); - - EXTI_ClearFlag(RFM22_EXT_INT_LINE); - } - - void rfm22_enableExtInt(void) - { - // Configure the external interrupt - GPIO_EXTILineConfig(RFM22_EXT_INT_PORT_SOURCE, RFM22_EXT_INT_PIN_SOURCE); - EXTI_InitTypeDef EXTI_InitStructure; - EXTI_InitStructure.EXTI_Line = RFM22_EXT_INT_LINE; - EXTI_InitStructure.EXTI_Mode = EXTI_Mode_Interrupt; - EXTI_InitStructure.EXTI_Trigger = EXTI_Trigger_Falling; - EXTI_InitStructure.EXTI_LineCmd = ENABLE; - EXTI_Init(&EXTI_InitStructure); - - EXTI_ClearFlag(RFM22_EXT_INT_LINE); - - // Enable and set the external interrupt - NVIC_InitTypeDef NVIC_InitStructure; - NVIC_InitStructure.NVIC_IRQChannel = RFM22_EXT_INT_IRQn; - NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = RFM22_EXT_INT_PRIORITY; - NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0; - NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; - NVIC_Init(&NVIC_InitStructure); - } - -#endif - -// ************************************ -// set/get the current tx power setting - -void rfm22_setTxPower(uint8_t tx_pwr) -{ - switch (tx_pwr) - { - case 0: tx_power = RFM22_tx_pwr_txpow_0; break; // +1dBm ... 1.25mW - case 1: tx_power = RFM22_tx_pwr_txpow_1; break; // +2dBm ... 1.6mW - case 2: tx_power = RFM22_tx_pwr_txpow_2; break; // +5dBm ... 3.16mW - case 3: tx_power = RFM22_tx_pwr_txpow_3; break; // +8dBm ... 6.3mW - case 4: tx_power = RFM22_tx_pwr_txpow_4; break; // +11dBm .. 12.6mW - case 5: tx_power = RFM22_tx_pwr_txpow_5; break; // +14dBm .. 25mW - case 6: tx_power = RFM22_tx_pwr_txpow_6; break; // +17dBm .. 50mW - case 7: tx_power = RFM22_tx_pwr_txpow_7; break; // +20dBm .. 100mW - default: break; - } -} - -uint8_t rfm22_getTxPower(void) -{ - return tx_power; -} - -// ************************************ - -uint32_t rfm22_minFrequency(void) -{ - return lower_carrier_frequency_limit_Hz; -} -uint32_t rfm22_maxFrequency(void) -{ - return upper_carrier_frequency_limit_Hz; -} - -void rfm22_setNominalCarrierFrequency(uint32_t frequency_hz) -{ - -#if defined(RFM22_EXT_INT_USE) - exec_using_spi = TRUE; -#endif - - // ******* - - if (frequency_hz < lower_carrier_frequency_limit_Hz) frequency_hz = lower_carrier_frequency_limit_Hz; - else - if (frequency_hz > upper_carrier_frequency_limit_Hz) frequency_hz = upper_carrier_frequency_limit_Hz; - - if (frequency_hz < 480000000) - hbsel = 1; - else - hbsel = 2; - uint8_t fb = (uint8_t)(frequency_hz / (10000000 * hbsel)); - - uint32_t fc = (uint32_t)(frequency_hz - (10000000 * hbsel * fb)); - - fc = (fc * 64u) / (10000ul * hbsel); - fb -= 24; - -// carrier_frequency_hz = frequency_hz; - carrier_frequency_hz = ((uint32_t)fb + 24 + ((float)fc / 64000)) * 10000000 * hbsel; - - if (hbsel > 1) - fb |= RFM22_fbs_hbsel; - - fb |= RFM22_fbs_sbse; // is this the RX LO polarity? - - frequency_step_size = 156.25f * hbsel; - - rfm22_write(RFM22_frequency_hopping_channel_select, frequency_hop_channel); // frequency hopping channel (0-255) - - rfm22_write(RFM22_frequency_offset1, 0); // no frequency offset - rfm22_write(RFM22_frequency_offset2, 0); // no frequency offset - - rfm22_write(RFM22_frequency_band_select, fb); // set the carrier frequency - rfm22_write(RFM22_nominal_carrier_frequency1, fc >> 8); // " " - rfm22_write(RFM22_nominal_carrier_frequency0, fc & 0xff); // " " - - // ******* - -#if defined(RFM22_DEBUG) - DEBUG_PRINTF("rf setFreq: %u\r\n", carrier_frequency_hz); -// DEBUG_PRINTF("rf setFreq frequency_step_size: %0.2f\r\n", frequency_step_size); -#endif - -#if defined(RFM22_EXT_INT_USE) - exec_using_spi = FALSE; -#endif -} - -uint32_t rfm22_getNominalCarrierFrequency(void) -{ - return carrier_frequency_hz; -} - -float rfm22_getFrequencyStepSize(void) -{ - return frequency_step_size; -} - -void rfm22_setFreqHopChannel(uint8_t channel) -{ // set the frequency hopping channel - frequency_hop_channel = channel; - rfm22_write(RFM22_frequency_hopping_channel_select, frequency_hop_channel); -} - -uint8_t rfm22_freqHopChannel(void) -{ // return the current frequency hopping channel - return frequency_hop_channel; -} - -uint32_t rfm22_freqHopSize(void) -{ // return the frequency hopping step size - return ((uint32_t)frequency_hop_step_size_reg * 10000); -} - -// ************************************ -// radio datarate about 19200 Baud -// radio frequency deviation 45kHz -// radio receiver bandwidth 67kHz. -// -// Carson's rule: -// The signal bandwidth is about 2(Delta-f + fm) .. -// -// Delta-f = frequency deviation -// fm = maximum frequency of the signal -// -// This gives 2(45 + 9.6) = 109.2kHz. - -void rfm22_setDatarate(uint32_t datarate_bps, bool data_whitening) -{ - -#if defined(RFM22_EXT_INT_USE) - exec_using_spi = TRUE; -#endif - // ******* - - lookup_index = 0; - while (lookup_index < (LOOKUP_SIZE - 1) && data_rate[lookup_index] < datarate_bps) - lookup_index++; - - carrier_datarate_bps = datarate_bps = data_rate[lookup_index]; - - rf_bandwidth_used = rx_bandwidth[lookup_index]; - - // ******************************** - -#if defined(RFM22_DEBUG) - uint32_t frequency_deviation = freq_deviation[lookup_index]; // Hz - uint32_t modulation_bandwidth = datarate_bps + (2 * frequency_deviation); -#endif - - - - - - - rfm22_write(0x1C, reg_1C[lookup_index]); // rfm22_if_filter_bandwidth - - rfm22_write(0x1D, reg_1D[lookup_index]); // rfm22_afc_loop_gearshift_override - rfm22_write(0x1E, reg_1E[lookup_index]); // RFM22_afc_timing_control - - rfm22_write(0x1F, reg_1F[lookup_index]); // RFM22_clk_recovery_gearshift_override - rfm22_write(0x20, reg_20[lookup_index]); // rfm22_clk_recovery_oversampling_ratio - rfm22_write(0x21, reg_21[lookup_index]); // rfm22_clk_recovery_offset2 - rfm22_write(0x22, reg_22[lookup_index]); // rfm22_clk_recovery_offset1 - rfm22_write(0x23, reg_23[lookup_index]); // rfm22_clk_recovery_offset0 - rfm22_write(0x24, reg_24[lookup_index]); // rfm22_clk_recovery_timing_loop_gain1 - rfm22_write(0x25, reg_25[lookup_index]); // rfm22_clk_recovery_timing_loop_gain0 - - rfm22_write(0x2A, reg_2A[lookup_index]); // rfm22_afc_limiter - - if (carrier_datarate_bps < 100000) - rfm22_write(0x58, 0x80); // rfm22_chargepump_current_trimming_override - else - rfm22_write(0x58, 0xC0); // rfm22_chargepump_current_trimming_override - - rfm22_write(0x6E, reg_6E[lookup_index]); // rfm22_tx_data_rate1 - rfm22_write(0x6F, reg_6F[lookup_index]); // rfm22_tx_data_rate0 - - // Enable data whitening -// uint8_t txdtrtscale_bit = rfm22_read(RFM22_modulation_mode_control1) & RFM22_mmc1_txdtrtscale; -// rfm22_write(RFM22_modulation_mode_control1, txdtrtscale_bit | RFM22_mmc1_enwhite); - - if (!data_whitening) - rfm22_write(0x70, reg_70[lookup_index] & ~RFM22_mmc1_enwhite); // rfm22_modulation_mode_control1 - else - rfm22_write(0x70, reg_70[lookup_index] | RFM22_mmc1_enwhite); // rfm22_modulation_mode_control1 - - rfm22_write(0x71, reg_71[lookup_index]); // rfm22_modulation_mode_control2 - - rfm22_write(0x72, reg_72[lookup_index]); // rfm22_frequency_deviation - - rfm22_write(RFM22_ook_counter_value1, 0x00); - rfm22_write(RFM22_ook_counter_value2, 0x00); - - // ******************************** - // calculate the TX register values -/* - uint16_t fd = frequency_deviation / 625; - - uint8_t mmc1 = RFM22_mmc1_enphpwdn | RFM22_mmc1_manppol; - uint16_t txdr; - if (datarate_bps < 30000) - { - txdr = (datarate_bps * 20972) / 10000; - mmc1 |= RFM22_mmc1_txdtrtscale; - } - else - txdr = (datarate_bps * 6553) / 100000; - - uint8_t mmc2 = RFM22_mmc2_dtmod_fifo | RFM22_mmc2_modtyp_gfsk; // FIFO mode, GFSK -// uint8_t mmc2 = RFM22_mmc2_dtmod_pn9 | RFM22_mmc2_modtyp_gfsk; // PN9 mode, GFSK .. TX TEST MODE - if (fd & 0x100) mmc2 |= RFM22_mmc2_fd; - - rfm22_write(RFM22_frequency_deviation, fd); // set the TX peak frequency deviation - - rfm22_write(RFM22_modulation_mode_control1, mmc1); - rfm22_write(RFM22_modulation_mode_control2, mmc2); - - rfm22_write(RFM22_tx_data_rate1, txdr >> 8); // set the TX data rate - rfm22_write(RFM22_tx_data_rate0, txdr); // " " -*/ - // ******************************** - // determine a clear channel time - - // initialise the stopwatch with a suitable resolution for the datarate - STOPWATCH_init(4000000ul / carrier_datarate_bps); // set resolution to the time for 1 nibble (4-bits) at rf datarate - - // ******************************** - // determine suitable time-out periods - - timeout_sync_ms = (8000ul * 16) / carrier_datarate_bps; // milliseconds - if (timeout_sync_ms < 3) - timeout_sync_ms = 3; // because out timer resolution is only 1ms - - timeout_data_ms = (8000ul * 100) / carrier_datarate_bps; // milliseconds - if (timeout_data_ms < 3) - timeout_data_ms = 3; // because out timer resolution is only 1ms - - // ******************************** - -#if defined(RFM22_DEBUG) - DEBUG_PRINTF("rf datarate_bps: %d\r\n", datarate_bps); - DEBUG_PRINTF("rf frequency_deviation: %d\r\n", frequency_deviation); - DEBUG_PRINTF("rf modulation_bandwidth: %u\r\n", modulation_bandwidth); - DEBUG_PRINTF("rf_rx_bandwidth[%u]: %u\r\n", lookup_index, rx_bandwidth[lookup_index]); - DEBUG_PRINTF("rf est rx sensitivity[%u]: %ddBm\r\n", lookup_index, est_rx_sens_dBm[lookup_index]); -#endif - - // ******* - -#if defined(RFM22_EXT_INT_USE) - exec_using_spi = FALSE; -#endif -} - -uint32_t rfm22_getDatarate(void) -{ - return carrier_datarate_bps; -} - -// ************************************ - -void rfm22_setSSBandwidth(uint32_t bandwidth_index) -{ - -#if defined(RFM22_EXT_INT_USE) - exec_using_spi = TRUE; -#endif - // ******* - - ss_lookup_index = bandwidth_index; - - ss_rf_bandwidth_used = ss_rx_bandwidth[lookup_index]; - - // ******************************** - - rfm22_write(0x1C, ss_reg_1C[ss_lookup_index]); // rfm22_if_filter_bandwidth - rfm22_write(0x1D, ss_reg_1D[ss_lookup_index]); // rfm22_afc_loop_gearshift_override - - rfm22_write(0x20, ss_reg_20[ss_lookup_index]); // rfm22_clk_recovery_oversampling_ratio - rfm22_write(0x21, ss_reg_21[ss_lookup_index]); // rfm22_clk_recovery_offset2 - rfm22_write(0x22, ss_reg_22[ss_lookup_index]); // rfm22_clk_recovery_offset1 - rfm22_write(0x23, ss_reg_23[ss_lookup_index]); // rfm22_clk_recovery_offset0 - rfm22_write(0x24, ss_reg_24[ss_lookup_index]); // rfm22_clk_recovery_timing_loop_gain1 - rfm22_write(0x25, ss_reg_25[ss_lookup_index]); // rfm22_clk_recovery_timing_loop_gain0 - - rfm22_write(0x2A, ss_reg_2A[ss_lookup_index]); // rfm22_afc_limiter - - rfm22_write(0x58, 0x80); // rfm22_chargepump_current_trimming_override - - rfm22_write(0x70, ss_reg_70[ss_lookup_index]); // rfm22_modulation_mode_control1 - rfm22_write(0x71, ss_reg_71[ss_lookup_index]); // rfm22_modulation_mode_control2 - - rfm22_write(RFM22_ook_counter_value1, 0x00); - rfm22_write(RFM22_ook_counter_value2, 0x00); - - // ******************************** - -#if defined(RFM22_DEBUG) - DEBUG_PRINTF("ss_rf_rx_bandwidth[%u]: %u\r\n", ss_lookup_index, ss_rx_bandwidth[ss_lookup_index]); -#endif - - // ******* - -#if defined(RFM22_EXT_INT_USE) - exec_using_spi = FALSE; -#endif -} - -// ************************************ - -void rfm22_setRxMode(uint8_t mode, bool multi_packet_mode) -{ -#if defined(RFM22_EXT_INT_USE) - exec_using_spi = TRUE; -#endif - - // disable interrupts - rfm22_write(RFM22_interrupt_enable1, 0x00); - rfm22_write(RFM22_interrupt_enable2, 0x00); - - // disable the receiver and transmitter -// rfm22_write(RFM22_op_and_func_ctrl1, RFM22_opfc1_xton); // READY mode - rfm22_write(RFM22_op_and_func_ctrl1, RFM22_opfc1_pllon); // TUNE mode - - RX_LED_OFF; - TX_LED_OFF; - -// rfm22_write(RFM22_rx_fifo_control, RX_FIFO_HI_WATERMARK); // RX FIFO Almost Full Threshold (0 - 63) - - if (rf_mode == TX_CARRIER_MODE || rf_mode == TX_PN_MODE) - { // FIFO mode, GFSK modulation - uint8_t fd_bit = rfm22_read(RFM22_modulation_mode_control2) & RFM22_mmc2_fd; - rfm22_write(RFM22_modulation_mode_control2, fd_bit | RFM22_mmc2_dtmod_fifo | RFM22_mmc2_modtyp_gfsk); - } - - rx_buffer_wr = 0; // empty the rx buffer - - rfm22_int_timer = 0; // reset the timer - - rf_mode = mode; - - if (mode != RX_SCAN_SPECTRUM) - { - STOPWATCH_reset(); // reset clear channel detect timer - - // enable RX interrupts - rfm22_write(RFM22_interrupt_enable1, RFM22_ie1_encrcerror | RFM22_ie1_enpkvalid | RFM22_ie1_enrxffafull | RFM22_ie1_enfferr); - rfm22_write(RFM22_interrupt_enable2, RFM22_ie2_enpreainval | RFM22_ie2_enpreaval | RFM22_ie2_enswdet); - } - - // read interrupt status - clear interrupts - rfm22_read(RFM22_interrupt_status1); - rfm22_read(RFM22_interrupt_status2); - - // clear FIFOs - if (!multi_packet_mode) - { - rfm22_write(RFM22_op_and_func_ctrl2, RFM22_opfc2_ffclrrx | RFM22_opfc2_ffclrtx); - rfm22_write(RFM22_op_and_func_ctrl2, 0x00); - } - else - { - rfm22_write(RFM22_op_and_func_ctrl2, RFM22_opfc2_rxmpk | RFM22_opfc2_ffclrrx | RFM22_opfc2_ffclrtx); - rfm22_write(RFM22_op_and_func_ctrl2, RFM22_opfc2_rxmpk); - } - - // enable the receiver -// rfm22_write(RFM22_op_and_func_ctrl1, RFM22_opfc1_xton | RFM22_opfc1_rxon); - rfm22_write(RFM22_op_and_func_ctrl1, RFM22_opfc1_pllon | RFM22_opfc1_rxon); - -#if defined(RFM22_EXT_INT_USE) - exec_using_spi = FALSE; -#endif - -#if defined(RFM22_DEBUG) - DEBUG_PRINTF(" RX Mode\r\n"); -#endif -} - -// ************************************ - -uint16_t rfm22_addHeader(uint8_t mode) -{ - uint16_t i = 0; - - if (mode == TX_STREAM_MODE) - { // add header - for (uint16_t j = (TX_PREAMBLE_NIBBLES + 1) / 2; j > 0; j--) - { - rfm22_burstWrite(PREAMBLE_BYTE); - i++; - } - rfm22_burstWrite(SYNC_BYTE_1); i++; - rfm22_burstWrite(SYNC_BYTE_2); i++; - } - - return i; -} - -// ************************************ - -void rfm22_setTxMode(uint8_t mode) -{ - if (mode != TX_DATA_MODE && mode != TX_STREAM_MODE && mode != TX_CARRIER_MODE && mode != TX_PN_MODE) - return; // invalid mode - -#if defined(RFM22_EXT_INT_USE) - exec_using_spi = TRUE; -#endif - - // ******************* - - // disable interrupts - rfm22_write(RFM22_interrupt_enable1, 0x00); - rfm22_write(RFM22_interrupt_enable2, 0x00); - -// rfm22_write(RFM22_op_and_func_ctrl1, RFM22_opfc1_xton); // READY mode - rfm22_write(RFM22_op_and_func_ctrl1, RFM22_opfc1_pllon); // TUNE mode - - RX_LED_OFF; - - // set the tx power -// rfm22_write(RFM22_tx_power, RFM22_tx_pwr_lna_sw | tx_power); -// rfm22_write(RFM22_tx_power, RFM22_tx_pwr_papeaken | RFM22_tx_pwr_papeaklvl_0 | RFM22_tx_pwr_lna_sw | tx_power); - rfm22_write(RFM22_tx_power, RFM22_tx_pwr_papeaken | RFM22_tx_pwr_papeaklvl_1 | RFM22_tx_pwr_papeaklvl_0 | RFM22_tx_pwr_lna_sw | tx_power); - - uint8_t fd_bit = rfm22_read(RFM22_modulation_mode_control2) & RFM22_mmc2_fd; - if (mode == TX_CARRIER_MODE) - { // blank carrier mode - for testing - rfm22_write(RFM22_modulation_mode_control2, fd_bit | RFM22_mmc2_dtmod_pn9 | RFM22_mmc2_modtyp_none); // FIFO mode, Blank carrier - } - else - if (mode == TX_PN_MODE) - { // psuedo random data carrier mode - for testing - rfm22_write(RFM22_modulation_mode_control2, fd_bit | RFM22_mmc2_dtmod_pn9 | RFM22_mmc2_modtyp_gfsk); // FIFO mode, PN9 carrier - } - else - { // data transmission - rfm22_write(RFM22_modulation_mode_control2, fd_bit | RFM22_mmc2_dtmod_fifo | RFM22_mmc2_modtyp_gfsk); // FIFO mode, GFSK modulation - } - -// rfm22_write(0x72, reg_72[lookup_index]); // rfm22_frequency_deviation - - // clear FIFOs - rfm22_write(RFM22_op_and_func_ctrl2, RFM22_opfc2_ffclrrx | RFM22_opfc2_ffclrtx); - rfm22_write(RFM22_op_and_func_ctrl2, 0x00); - - // ******************* - // add some data to the chips TX FIFO before enabling the transmitter - - { - uint16_t rd = 0; - uint16_t wr = tx_data_wr; - if (!tx_data_addr) wr = 0; - - if (mode == TX_DATA_MODE) - rfm22_write(RFM22_transmit_packet_length, wr); // set the total number of data bytes we are going to transmit - - uint16_t max_bytes = FIFO_SIZE - 1; - - uint16_t i = 0; - - rfm22_startBurstWrite(RFM22_fifo_access); - - if (mode == TX_STREAM_MODE) - { - if (rd >= wr) - { // no data to send - yet .. just send preamble pattern - while (true) - { - rfm22_burstWrite(PREAMBLE_BYTE); - if (++i >= max_bytes) break; - } - } - else - { // add the RF heaader - i += rfm22_addHeader(mode); - } - } - - // add some data - for (uint16_t j = wr - rd; j > 0; j--) - { -// int16_t b = -1; -// if (tx_data_byte_callback_function) -// b = tx_data_byte_callback_function(); - - rfm22_burstWrite(tx_data_addr[rd++]); - if (++i >= max_bytes) break; - } - - rfm22_endBurstWrite(); - - tx_data_rd = rd; - } - - // ******************* - - rfm22_int_timer = 0; // reset the timer - - rf_mode = mode; - - // enable TX interrupts -// rfm22_write(RFM22_interrupt_enable1, RFM22_ie1_enpksent | RFM22_ie1_entxffaem | RFM22_ie1_enfferr); - rfm22_write(RFM22_interrupt_enable1, RFM22_ie1_enpksent | RFM22_ie1_entxffaem); - - // read interrupt status - clear interrupts - rfm22_read(RFM22_interrupt_status1); - rfm22_read(RFM22_interrupt_status2); - - // enable the transmitter -// rfm22_write(RFM22_op_and_func_ctrl1, RFM22_opfc1_xton | RFM22_opfc1_txon); - rfm22_write(RFM22_op_and_func_ctrl1, RFM22_opfc1_pllon | RFM22_opfc1_txon); - - TX_LED_ON; - - // ******************* - // create new slightly random clear channel detector count value - - uint32_t ccc = (TX_PREAMBLE_NIBBLES + 8) + 4; // minimum clear channel time before allowing transmit - clear_channel_count = ccc + (random32 % (ccc * 2)); // plus a some randomness - - // ******************* - -#if defined(RFM22_EXT_INT_USE) - exec_using_spi = FALSE; -#endif - -#if defined(RFM22_DEBUG) - if (rf_mode == TX_DATA_MODE) DEBUG_PRINTF(" TX_Data_Mode\r\n"); - else - if (rf_mode == TX_STREAM_MODE) DEBUG_PRINTF(" TX_Stream_Mode\r\n"); - else - if (rf_mode == TX_CARRIER_MODE) DEBUG_PRINTF(" TX_Carrier_Mode\r\n"); - else - if (rf_mode == TX_PN_MODE) DEBUG_PRINTF(" TX_PN_Mode\r\n"); -#endif -} - -// ************************************ -// external interrupt line triggered (or polled) from the rf chip - -void rfm22_processRxInt(void) -{ - register uint8_t int_stat1 = int_status1; - register uint8_t int_stat2 = int_status2; - - if (int_stat2 & RFM22_is2_ipreaval) - { // Valid preamble detected - - if (rf_mode == RX_WAIT_PREAMBLE_MODE) - { - rfm22_int_timer = 0; // reset the timer - rf_mode = RX_WAIT_SYNC_MODE; - RX_LED_ON; - - #if defined(RFM22_DEBUG) && !defined(RFM22_EXT_INT_USE) - DEBUG_PRINTF(" pream_det"); - debug_outputted = true; - #endif - } - } -/* else - if (int_stat2 & RFM22_is2_ipreainval) - { // Invalid preamble detected - - if (rf_mode == RX_WAIT_SYNC_MODE) - { - #if defined(RFM22_DEBUG) && !defined(RFM22_EXT_INT_USE) - DEBUG_PRINTF(" invalid_preamble"); - debug_outputted = true; - #endif - - rfm22_setRxMode(RX_WAIT_PREAMBLE_MODE, false); - return; - } - else - { - } - } -*/ - if (int_stat2 & RFM22_is2_iswdet) - { // Sync word detected - - STOPWATCH_reset(); // reset timer - - if (rf_mode == RX_WAIT_PREAMBLE_MODE || rf_mode == RX_WAIT_SYNC_MODE) - { - rfm22_int_timer = 0; // reset the timer - rf_mode = RX_DATA_MODE; - RX_LED_ON; - - // read the 10-bit signed afc correction value - afc_correction = (uint16_t)rfm22_read(RFM22_afc_correction_read) << 8; // bits 9 to 2 - afc_correction |= (uint16_t)rfm22_read(RFM22_ook_counter_value1) & 0x00c0; // bits 1 & 0 - afc_correction >>= 6; - afc_correction_Hz = (int32_t)(frequency_step_size * afc_correction + 0.5f); // convert the afc value to Hz - - rx_packet_start_rssi_dBm = rssi_dBm; // remember the rssi for this packet - rx_packet_start_afc_Hz = afc_correction_Hz; // remember the afc value for this packet - - #if defined(RFM22_DEBUG) && !defined(RFM22_EXT_INT_USE) - DEBUG_PRINTF(" sync_det"); - DEBUG_PRINTF(" AFC_%d_%dHz", afc_correction, afc_correction_Hz); - debug_outputted = true; - #endif - } - } - - if (int_stat1 & RFM22_is1_irxffafull) - { // RX FIFO almost full, it needs emptying - - if (rf_mode == RX_DATA_MODE) - { // read data from the rf chips FIFO buffer - rfm22_int_timer = 0; // reset the timer - - register uint16_t len = rfm22_read(RFM22_received_packet_length); // read the total length of the packet data - - register uint16_t wr = rx_buffer_wr; - - if ((wr + RX_FIFO_HI_WATERMARK) > len) - { // some kind of error in the RF module - #if defined(RFM22_DEBUG) && !defined(RFM22_EXT_INT_USE) - DEBUG_PRINTF(" r_size_error1"); - debug_outputted = true; - #endif - - rfm22_setRxMode(RX_WAIT_PREAMBLE_MODE, false); - return; - } - - if (((wr + RX_FIFO_HI_WATERMARK) >= len) && !(int_stat1 & RFM22_is1_ipkvalid)) - { // some kind of error in the RF module - #if defined(RFM22_DEBUG) && !defined(RFM22_EXT_INT_USE) - DEBUG_PRINTF(" r_size_error2"); - debug_outputted = true; - #endif - - rfm22_setRxMode(RX_WAIT_PREAMBLE_MODE, false); - return; - } - - // fetch the rx'ed data from the rf chips RX FIFO - rfm22_startBurstRead(RFM22_fifo_access); - rx_fifo_wr = 0; - for (register uint8_t i = RX_FIFO_HI_WATERMARK; i > 0; i--) - rx_fifo[rx_fifo_wr++] = rfm22_burstRead(); // read a byte from the rf modules RX FIFO buffer - rfm22_endBurstRead(); - - uint16_t i = rx_fifo_wr; - if (wr + i > sizeof(rx_buffer)) i = sizeof(rx_buffer) - wr; - memcpy((void *)(rx_buffer + wr), (void *)rx_fifo, i); // save the new bytes into our rx buffer - wr += i; - - rx_buffer_wr = wr; - - if (rx_data_callback_function) - { // pass the new data onto whoever wanted it - if (!rx_data_callback_function((void *)rx_fifo, rx_fifo_wr)) - { - rfm22_setRxMode(RX_WAIT_PREAMBLE_MODE, false); - return; - } - } - - #if defined(RFM22_DEBUG) && !defined(RFM22_EXT_INT_USE) -// DEBUG_PRINTF(" r_data_%u/%u", rx_buffer_wr, len); -// debug_outputted = true; - #endif - } - else - { // just clear the RX FIFO - rfm22_startBurstRead(RFM22_fifo_access); - for (register uint16_t i = RX_FIFO_HI_WATERMARK; i > 0; i--) - rfm22_burstRead(); // read a byte from the rf modules RX FIFO buffer - rfm22_endBurstRead(); - } - } - - if (int_stat1 & RFM22_is1_icrerror) - { // CRC error .. discard the received data - - if (rf_mode == RX_DATA_MODE) - { - rfm22_int_timer = 0; // reset the timer - - #if defined(RFM22_DEBUG) && !defined(RFM22_EXT_INT_USE) - DEBUG_PRINTF(" CRC_ERR"); - debug_outputted = true; - #endif - - rfm22_setRxMode(RX_WAIT_PREAMBLE_MODE, false); // reset the receiver - return; - } - } - -// if (int_stat2 & RFM22_is2_irssi) -// { // RSSI level is >= the set threshold -// } - -// if (device_status & RFM22_ds_rxffem) -// { // RX FIFO empty -// } - -// if (device_status & RFM22_ds_headerr) -// { // Header check error -// } - - if (int_stat1 & RFM22_is1_ipkvalid) - { // Valid packet received - - if (rf_mode == RX_DATA_MODE) - { - rfm22_int_timer = 0; // reset the timer - - // disable the receiver -// rfm22_write(RFM22_op_and_func_ctrl1, RFM22_opfc1_xton); // READY mode - rfm22_write(RFM22_op_and_func_ctrl1, RFM22_opfc1_pllon); // TUNE mode - - register uint16_t len = rfm22_read(RFM22_received_packet_length); // read the total length of the packet data - - register uint16_t wr = rx_buffer_wr; - - if (wr < len) - { // their must still be data in the RX FIFO we need to get - - // fetch the rx'ed data from the rf chips RX FIFO - rfm22_startBurstRead(RFM22_fifo_access); - rx_fifo_wr = 0; - for (register uint8_t i = len - wr; i > 0; i--) - rx_fifo[rx_fifo_wr++] = rfm22_burstRead(); // read a byte from the rf modules RX FIFO buffer - rfm22_endBurstRead(); - - uint16_t i = rx_fifo_wr; - if (wr + i > sizeof(rx_buffer)) i = sizeof(rx_buffer) - wr; - memcpy((void *)(rx_buffer + wr), (void *)rx_fifo, i); // save the new bytes into our rx buffer - wr += i; - - rx_buffer_wr = wr; - - if (rx_data_callback_function) - { // pass the new data onto whoever wanted it - if (!rx_data_callback_function((void *)rx_fifo, rx_fifo_wr)) - { -// rfm22_setRxMode(RX_WAIT_PREAMBLE_MODE, false); -// return; - } - } - } - - rfm22_setRxMode(RX_WAIT_PREAMBLE_MODE, false); // reset the receiver - - if (wr != len) - { // we have a packet length error .. discard the packet - #if defined(RFM22_DEBUG) && !defined(RFM22_EXT_INT_USE) - DEBUG_PRINTF(" r_pack_len_error_%u_%u", len, wr); - debug_outputted = true; - #endif - - return; - } - - // we have a valid received packet - #if defined(RFM22_DEBUG) && !defined(RFM22_EXT_INT_USE) - DEBUG_PRINTF(" VALID_R_PACKET_%u", wr); - debug_outputted = true; - #endif - - if (rx_packet_wr == 0) - { // save the received packet for further processing - rx_packet_rssi_dBm = rx_packet_start_rssi_dBm; // remember the rssi for this packet - rx_packet_afc_Hz = rx_packet_start_afc_Hz; // remember the afc offset for this packet - memmove((void *)rx_packet_buf, (void *)rx_buffer, wr); // copy the packet data - rx_packet_wr = wr; // save the length of the data - } - else - { // the save buffer is still in use .. nothing we can do but to drop the packet - } - -// return; - } - else - { -// rfm22_setRxMode(RX_WAIT_PREAMBLE_MODE, false); // reset the receiver -// return; - } - } -} - -uint8_t rfm22_topUpRFTxFIFO(void) -{ - rfm22_int_timer = 0; // reset the timer - - uint16_t rd = tx_data_rd; - uint16_t wr = tx_data_wr; - - if (rf_mode == TX_DATA_MODE && (!tx_data_addr || rd >= wr)) - return 0; // no more data to send - - uint16_t max_bytes = FIFO_SIZE - TX_FIFO_LO_WATERMARK - 1; - - uint16_t i = 0; - - // top-up the rf chips TX FIFO buffer - rfm22_startBurstWrite(RFM22_fifo_access); - - // add some data - for (uint16_t j = wr - rd; j > 0; j--) - { -// int16_t b = -1; -// if (tx_data_byte_callback_function) -// b = tx_data_byte_callback_function(); - - rfm22_burstWrite(tx_data_addr[rd++]); - if (++i >= max_bytes) break; - } - tx_data_rd = rd; - - if (rf_mode == TX_STREAM_MODE && rd >= wr) - { // all data sent .. need to start sending RF header again - - tx_data_addr = NULL; - tx_data_rd = tx_data_wr = 0; - - while (i < max_bytes) - { - rfm22_burstWrite(PREAMBLE_BYTE); // preamble byte - i++; - } - - // todo: - - // add the RF heaader - // i += rfm22_addHeader(rf_mode); - } - - rfm22_endBurstWrite(); - - #if defined(RFM22_DEBUG) && !defined(RFM22_EXT_INT_USE) -// DEBUG_PRINTF(" added_%d_bytes", i); -// debug_outputted = true; - #endif - - return i; -} - -void rfm22_processTxInt(void) -{ - register uint8_t int_stat1 = int_status1; -// register uint8_t int_stat2 = int_status2; - - /* - if (int_stat1 & RFM22_is1_ifferr) - { // FIFO underflow/overflow error - rfm22_setRxMode(RX_WAIT_PREAMBLE_MODE, false); - tx_data_addr = NULL; - tx_data_rd = tx_data_wr = 0; - return; - } - */ - - if (int_stat1 & RFM22_is1_ixtffaem) - { // TX FIFO almost empty, it needs filling up - - #if defined(RFM22_DEBUG) && !defined(RFM22_EXT_INT_USE) -// DEBUG_PRINTF(" T_FIFO_AE"); -// debug_outputted = true; - #endif - -// uint8_t bytes_added = rfm22_topUpRFTxFIFO(); - rfm22_topUpRFTxFIFO(); - } - - if (int_stat1 & RFM22_is1_ipksent) - { // Packet has been sent - #if defined(RFM22_DEBUG) && !defined(RFM22_EXT_INT_USE) - DEBUG_PRINTF(" T_Sent"); - debug_outputted = true; - #endif - - if (rf_mode == TX_DATA_MODE) - { - rfm22_setRxMode(RX_WAIT_PREAMBLE_MODE, false); // back to receive mode - - tx_data_addr = NULL; - tx_data_rd = tx_data_wr = 0; - return; - } - else - if (rf_mode == TX_STREAM_MODE) - { - tx_data_addr = NULL; - tx_data_rd = tx_data_wr = 0; - - rfm22_setTxMode(TX_STREAM_MODE); - return; - } - } - -// if (int_stat1 & RFM22_is1_itxffafull) -// { // TX FIFO almost full, it needs to be transmitted -// } -} - -void rfm22_processInt(void) -{ // this is called from the external interrupt handler - - #if !defined(RFM22_EXT_INT_USE) - if (GPIO_IN(RF_INT_PIN)) - return; // the external int line is high (no signalled interrupt) - #endif - - if (!initialized || power_on_reset) - return; // we haven't yet been initialized - - #if defined(RFM22_DEBUG) - debug_outputted = false; - #endif - - // ******************************** - // read the RF modules current status registers - - // read device status register - device_status = rfm22_read(RFM22_device_status); - - // read ezmac status register - ezmac_status = rfm22_read(RFM22_ezmac_status); - - // read interrupt status registers - clears the interrupt line - int_status1 = rfm22_read(RFM22_interrupt_status1); - int_status2 = rfm22_read(RFM22_interrupt_status2); - - if (rf_mode != TX_DATA_MODE && rf_mode != TX_STREAM_MODE && rf_mode != TX_CARRIER_MODE && rf_mode != TX_PN_MODE) - { - rssi = rfm22_read(RFM22_rssi); // read rx signal strength .. 45 = -100dBm, 205 = -20dBm - rssi_dBm = ((int16_t)rssi / 2) - 122; // convert to dBm - - // calibrate the RSSI value (rf bandwidth appears to affect it) -// if (rf_bandwidth_used > 0) -// rssi_dBm -= 10000 / rf_bandwidth_used; - } - else - { - tx_pwr = rfm22_read(RFM22_tx_power); // read the tx power register - } - - if (int_status2 & RFM22_is2_ipor) - { // the RF module has gone and done a reset - we need to re-initialize the rf module - initialized = FALSE; - power_on_reset = TRUE; - return; - } - - // ******************************** - // debug stuff - - #if defined(RFM22_DEBUG) && !defined(RFM22_EXT_INT_USE) - if (prev_device_status != device_status || prev_int_status1 != int_status1 || prev_int_status2 != int_status2 || prev_ezmac_status != ezmac_status) - { - DEBUG_PRINTF("%02x %02x %02x %02x %dC", device_status, int_status1, int_status2, ezmac_status, temperature_reg); - - if ((device_status & RFM22_ds_cps_mask) == RFM22_ds_cps_rx) - DEBUG_PRINTF(" %ddBm", rssi_dBm); // rx mode - else - if ((device_status & RFM22_ds_cps_mask) == RFM22_ds_cps_tx) - DEBUG_PRINTF(" %s", (tx_pwr & RFM22_tx_pwr_papeakval) ? "ANT_MISMATCH" : "ant_ok"); // tx mode - - debug_outputted = true; - - prev_device_status = device_status; - prev_int_status1 = int_status1; - prev_int_status2 = int_status2; - prev_ezmac_status = ezmac_status; - } - #endif - - // ******************************** - // read the ADC - temperature sensor .. this can only be used in IDLE mode -/* - if (!(rfm22_read(RFM22_adc_config) & RFM22_ac_adcstartbusy)) - { // the ADC has completed it's conversion - - // read the ADC sample - temperature_reg = (int16_t)rfm22_read(RFM22_adc_value) * 0.5f - 64; - - // start a new ADC conversion - rfm22_write(RFM22_adc_config, adc_config | RFM22_ac_adcstartbusy); - - #if defined(RFM22_DEBUG) && !defined(RFM22_EXT_INT_USE) - DEBUG_PRINTF(", %dC", temperature_reg); - debug_outputted = true; - #endif - } -*/ - // ******************************** - - register uint16_t timer_ms = rfm22_int_timer; - - switch (rf_mode) - { - case RX_SCAN_SPECTRUM: - break; - - case RX_WAIT_PREAMBLE_MODE: - case RX_WAIT_SYNC_MODE: - case RX_DATA_MODE: - - if (device_status & (RFM22_ds_ffunfl | RFM22_ds_ffovfl)) - { // FIFO under/over flow error - - #if defined(RFM22_DEBUG) && !defined(RFM22_EXT_INT_USE) - DEBUG_PRINTF(" R_UNDER/OVERRUN"); - debug_outputted = true; - #endif - - rfm22_setRxMode(RX_WAIT_PREAMBLE_MODE, false); // reset the receiver - tx_data_rd = tx_data_wr = 0; // wipe TX buffer - break; - } - - if (rf_mode == RX_WAIT_SYNC_MODE && timer_ms >= timeout_sync_ms) - { - rfm22_int_time_outs++; - - #if defined(RFM22_DEBUG) && !defined(RFM22_EXT_INT_USE) - DEBUG_PRINTF(" R_SYNC_TIMEOUT"); - debug_outputted = true; - #endif - - rfm22_setRxMode(RX_WAIT_PREAMBLE_MODE, false); // reset the receiver - tx_data_rd = tx_data_wr = 0; // wipe TX buffer - break; - } - - if (rf_mode == RX_DATA_MODE && timer_ms >= timeout_data_ms) - { // missing interrupts - rfm22_int_time_outs++; - rfm22_setRxMode(RX_WAIT_PREAMBLE_MODE, false); // reset the receiver - tx_data_rd = tx_data_wr = 0; // wipe TX buffer - break; - } - - if ((device_status & RFM22_ds_cps_mask) != RFM22_ds_cps_rx) - { // the rf module is not in rx mode - if (timer_ms >= 100) - { - rfm22_int_time_outs++; - - #if defined(RFM22_DEBUG) && !defined(RFM22_EXT_INT_USE) - DEBUG_PRINTF(" R_TIMEOUT"); - debug_outputted = true; - #endif - - rfm22_setRxMode(RX_WAIT_PREAMBLE_MODE, false); // reset the receiver - tx_data_rd = tx_data_wr = 0; // wipe TX buffer - break; - } - } - - rfm22_processRxInt(); // process the interrupt - break; - - case TX_DATA_MODE: - - if (device_status & (RFM22_ds_ffunfl | RFM22_ds_ffovfl)) - { // FIFO under/over flow error - - #if defined(RFM22_DEBUG) && !defined(RFM22_EXT_INT_USE) - DEBUG_PRINTF(" T_UNDER/OVERRUN"); - debug_outputted = true; - #endif - - rfm22_setRxMode(RX_WAIT_PREAMBLE_MODE, false); // back to rx mode - tx_data_rd = tx_data_wr = 0; // wipe TX buffer - break; - } - - if (timer_ms >= timeout_data_ms) - { - rfm22_int_time_outs++; - rfm22_setRxMode(RX_WAIT_PREAMBLE_MODE, false); // back to rx mode - tx_data_rd = tx_data_wr = 0; // wipe TX buffer - break; - } - - if ((device_status & RFM22_ds_cps_mask) != RFM22_ds_cps_tx) - { // the rf module is not in tx mode - if (timer_ms >= 100) - { - rfm22_int_time_outs++; - - #if defined(RFM22_DEBUG) && !defined(RFM22_EXT_INT_USE) - DEBUG_PRINTF(" T_TIMEOUT"); - debug_outputted = true; - #endif - - rfm22_setRxMode(RX_WAIT_PREAMBLE_MODE, false); // back to rx mode - tx_data_rd = tx_data_wr = 0; // wipe TX buffer - break; - } - } - - rfm22_processTxInt(); // process the interrupt - break; - - case TX_STREAM_MODE: - - // todo: - rfm22_processTxInt(); // process the interrupt - - break; - - case TX_CARRIER_MODE: - case TX_PN_MODE: - -// if (timer_ms >= TX_TEST_MODE_TIMELIMIT_MS) // 'nn'ms limit -// { -// rfm22_setRxMode(RX_WAIT_PREAMBLE_MODE, false); // back to rx mode -// tx_data_rd = tx_data_wr = 0; // wipe TX buffer -// break; -// } - - break; - - default: // unknown mode - this should NEVER happen, maybe we should do a complete CPU reset here - rfm22_setRxMode(RX_WAIT_PREAMBLE_MODE, false); // to rx mode - tx_data_rd = tx_data_wr = 0; // wipe TX buffer - break; - } - - // ******************************** - - #if defined(RFM22_DEBUG) && !defined(RFM22_EXT_INT_USE) - if (debug_outputted) - { - switch (rf_mode) - { - case RX_SCAN_SPECTRUM: - DEBUG_PRINTF(" R_SCAN_SPECTRUM\r\n"); - break; - case RX_WAIT_PREAMBLE_MODE: - DEBUG_PRINTF(" R_WAIT_PREAMBLE\r\n"); - break; - case RX_WAIT_SYNC_MODE: - DEBUG_PRINTF(" R_WAIT_SYNC\r\n"); - break; - case RX_DATA_MODE: - DEBUG_PRINTF(" R_DATA\r\n"); - break; - case TX_DATA_MODE: - DEBUG_PRINTF(" T_DATA\r\n"); - break; - case TX_STREAM_MODE: - DEBUG_PRINTF(" T_STREAM\r\n"); - break; - case TX_CARRIER_MODE: - DEBUG_PRINTF(" T_CARRIER\r\n"); - break; - case TX_PN_MODE: - DEBUG_PRINTF(" T_PN\r\n"); - break; - default: - DEBUG_PRINTF(" UNKNOWN_MODE\r\n"); - break; - } - } - #endif - - // ******************************** -} - -// ************************************ - -int16_t rfm22_getRSSI(void) -{ - #if defined(RFM22_EXT_INT_USE) - exec_using_spi = TRUE; - #endif - - rssi = rfm22_read(RFM22_rssi); // read rx signal strength .. 45 = -100dBm, 205 = -20dBm - rssi_dBm = ((int16_t)rssi / 2) - 122; // convert to dBm - - #if defined(RFM22_EXT_INT_USE) - exec_using_spi = FALSE; - #endif - - return rssi_dBm; -} - -int16_t rfm22_receivedRSSI(void) -{ // return the packets signal strength - if (!initialized) - return -200; - else - return rx_packet_rssi_dBm; -} - -int32_t rfm22_receivedAFCHz(void) -{ // return the packets offset frequency - if (!initialized) - return 0; - else - return rx_packet_afc_Hz; -} - -uint16_t rfm22_receivedLength(void) -{ // return the size of the data received - if (!initialized) - return 0; - else - return rx_packet_wr; -} - -uint8_t * rfm22_receivedPointer(void) -{ // return the address of the data - return (uint8_t *)&rx_packet_buf; -} - -void rfm22_receivedDone(void) -{ // empty the rx packet buffer - rx_packet_wr = 0; -} - -// ************************************ - -int32_t rfm22_sendData(void *data, uint16_t length, bool send_immediately) -{ - if (!initialized) - return -1; // we are not yet initialized - - if (length == 0) - return -2; // no data to send - - if (!data || length > 255) - return -3; // no data or too much data to send - - if (tx_data_wr > 0) - return -4; // already have data to be sent - - if (rf_mode == TX_DATA_MODE || rf_mode == TX_STREAM_MODE || rf_mode == TX_CARRIER_MODE || rf_mode == TX_PN_MODE || rf_mode == RX_SCAN_SPECTRUM) - return -5; // we are currently transmitting or scanning the spectrum - - tx_data_addr = data; - tx_data_rd = 0; - tx_data_wr = length; - - #if defined(RFM22_DEBUG) - DEBUG_PRINTF("rf sendData(0x%08x %u)\r\n", (uint32_t)tx_data_addr, tx_data_wr); - #endif - - if (send_immediately || rfm22_channelIsClear()) // is the channel clear to transmit on? - rfm22_setTxMode(TX_DATA_MODE); // transmit NOW - - return tx_data_wr; -} - -// ************************************ - -void rfm22_setTxStream(void) // TEST ONLY -{ - if (!initialized) - return; - - tx_data_rd = tx_data_wr = 0; - - rfm22_setTxMode(TX_STREAM_MODE); -} - -// ************************************ - -void rfm22_setTxNormal(void) -{ - if (!initialized) - return; - -// if (rf_mode == TX_CARRIER_MODE || rf_mode == TX_PN_MODE) - if (rf_mode != RX_SCAN_SPECTRUM) - { - rfm22_setRxMode(RX_WAIT_PREAMBLE_MODE, false); - tx_data_rd = tx_data_wr = 0; - - rx_packet_wr = 0; - rx_packet_start_rssi_dBm = 0; - rx_packet_start_afc_Hz = 0; - rx_packet_rssi_dBm = 0; - rx_packet_afc_Hz = 0; - } -} - -// enable a blank tx carrier (for frequency alignment) -void rfm22_setTxCarrierMode(void) -{ - if (!initialized) - return; - - if (rf_mode != TX_CARRIER_MODE && rf_mode != RX_SCAN_SPECTRUM) - rfm22_setTxMode(TX_CARRIER_MODE); -} - -// enable a psuedo random data tx carrier (for spectrum inspection) -void rfm22_setTxPNMode(void) -{ - if (!initialized) - return; - - if (rf_mode != TX_PN_MODE && rf_mode != RX_SCAN_SPECTRUM) - rfm22_setTxMode(TX_PN_MODE); -} - -// ************************************ - -// return the current mode -int8_t rfm22_currentMode(void) -{ - return rf_mode; -} - -// return TRUE if we are transmitting -bool rfm22_transmitting(void) -{ - return (rf_mode == TX_DATA_MODE || rf_mode == TX_STREAM_MODE || rf_mode == TX_CARRIER_MODE || rf_mode == TX_PN_MODE); -} - -// return TRUE if the channel is clear to transmit on -bool rfm22_channelIsClear(void) -{ - if (!initialized) - return FALSE; // we haven't yet been initialized - - if (rf_mode != RX_WAIT_PREAMBLE_MODE && rf_mode != RX_WAIT_SYNC_MODE) - return FALSE; // we are receiving something or we are transmitting or we are scanning the spectrum - - return TRUE; -// return (STOPWATCH_get_count() > clear_channel_count); -} - -// return TRUE if the transmiter is ready for use -bool rfm22_txReady(void) -{ - if (!initialized) - return FALSE; // we haven't yet been initialized - - return (tx_data_rd == 0 && tx_data_wr == 0 && rf_mode != TX_DATA_MODE && rf_mode != TX_STREAM_MODE && rf_mode != TX_CARRIER_MODE && rf_mode != TX_PN_MODE && rf_mode != RX_SCAN_SPECTRUM); -} - -// ************************************ -// set/get the frequency calibration value - -void rfm22_setFreqCalibration(uint8_t value) -{ - osc_load_cap = value; - - if (!initialized || power_on_reset) - return; // we haven't yet been initialized - - uint8_t prev_rf_mode = rf_mode; - - if (rf_mode == TX_CARRIER_MODE || rf_mode == TX_PN_MODE) - { - rfm22_setRxMode(RX_WAIT_PREAMBLE_MODE, false); - tx_data_rd = tx_data_wr = 0; - } - - #if defined(RFM22_EXT_INT_USE) - exec_using_spi = TRUE; - #endif - - rfm22_write(RFM22_xtal_osc_load_cap, osc_load_cap); - - #if defined(RFM22_EXT_INT_USE) - exec_using_spi = FALSE; - #endif - - if (prev_rf_mode == TX_CARRIER_MODE || prev_rf_mode == TX_PN_MODE) - rfm22_setTxMode(prev_rf_mode); -} - -uint8_t rfm22_getFreqCalibration(void) -{ - return osc_load_cap; -} - -// ************************************ -// can be called from an interrupt if you wish - -void rfm22_1ms_tick(void) -{ // call this once every ms - if (booting) return; - if (!initialized) return; // we haven't yet been initialized - - if (rf_mode != RX_SCAN_SPECTRUM) - { - if (rfm22_int_timer < 0xffff) rfm22_int_timer++; - } -} - -// ***************************************************************************** -// call this as often as possible - not from an interrupt - -void rfm22_process(void) -{ - if (booting) return; - if (!initialized) return; // we haven't yet been initialized - - #if !defined(RFM22_EXT_INT_USE) - if (rf_mode != RX_SCAN_SPECTRUM) - rfm22_processInt(); // manually poll the interrupt line routine - #endif - - if (power_on_reset) - { // we need to re-initialize the RF module - it told us it's reset itself - if (rf_mode != RX_SCAN_SPECTRUM) - { // normal data mode - uint32_t current_freq = carrier_frequency_hz; // fetch current rf nominal frequency - rfm22_init_normal(lower_carrier_frequency_limit_Hz, upper_carrier_frequency_limit_Hz, rfm22_freqHopSize()); - rfm22_setNominalCarrierFrequency(current_freq); // restore the nominal carrier frequency - } - else - { // we are scanning the spectrum - rfm22_init_scan_spectrum(lower_carrier_frequency_limit_Hz, upper_carrier_frequency_limit_Hz); - } - return; - } - - switch (rf_mode) - { - case RX_SCAN_SPECTRUM: // we are scanning the spectrum - - // read device status register - device_status = rfm22_read(RFM22_device_status); - - // read ezmac status register - ezmac_status = rfm22_read(RFM22_ezmac_status); - - // read interrupt status registers - clears the interrupt line - int_status1 = rfm22_read(RFM22_interrupt_status1); - int_status2 = rfm22_read(RFM22_interrupt_status2); - - if (int_status2 & RFM22_is2_ipor) - { // the RF module has gone and done a reset - we need to re-initialize the rf module - initialized = FALSE; - power_on_reset = TRUE; - return; - } - - break; - - case RX_WAIT_PREAMBLE_MODE: - - if (rfm22_int_timer >= timeout_ms) - { // assume somethings locked up - rfm22_int_time_outs++; - rfm22_setRxMode(RX_WAIT_PREAMBLE_MODE, false); // reset the RF module to rx mode - tx_data_rd = tx_data_wr = 0; // wipe TX buffer - break; - } - - // go to transmit mode if we have data to send and the channel is clear to transmit on - if (tx_data_rd == 0 && tx_data_wr > 0 && rfm22_channelIsClear()) - { - rfm22_setTxMode(TX_DATA_MODE); // transmit packet NOW - break; - } - - break; - - case RX_WAIT_SYNC_MODE: - - if (rfm22_int_timer >= timeout_sync_ms) - { // assume somethings locked up - rfm22_int_time_outs++; - rfm22_setRxMode(RX_WAIT_PREAMBLE_MODE, false); // reset the RF module to rx mode - tx_data_rd = tx_data_wr = 0; // wipe TX buffer - break; - } - - // go to transmit mode if we have data to send and the channel is clear to transmit on - if (tx_data_rd == 0 && tx_data_wr > 0 && rfm22_channelIsClear()) - { - rfm22_setTxMode(TX_DATA_MODE); // transmit packet NOW - break; - } - - break; - - case RX_DATA_MODE: - case TX_DATA_MODE: - - if (rfm22_int_timer >= timeout_data_ms) - { // assume somethings locked up - rfm22_int_time_outs++; - rfm22_setRxMode(RX_WAIT_PREAMBLE_MODE, false); // reset the RF module to rx mode - tx_data_rd = tx_data_wr = 0; // wipe TX buffer - break; - } - - break; - - case TX_STREAM_MODE: - - // todo: - - break; - - case TX_CARRIER_MODE: - case TX_PN_MODE: - -// if (rfm22_int_timer >= TX_TEST_MODE_TIMELIMIT_MS) -// { -// rfm22_setRxMode(RX_WAIT_PREAMBLE_MODE, false); // back to rx mode -// tx_data_rd = tx_data_wr = 0; // wipe TX buffer -// break; -// } - - break; - - default: - // unknown mode - this should never happen, maybe we should do a complete CPU reset here? - rfm22_setRxMode(RX_WAIT_PREAMBLE_MODE, false); // to rx mode - tx_data_rd = tx_data_wr = 0; // wipe TX buffer - break; - } - - #if defined(RFM22_INT_TIMEOUT_DEBUG) - if (prev_rfm22_int_time_outs != rfm22_int_time_outs) - { - prev_rfm22_int_time_outs = rfm22_int_time_outs; - DEBUG_PRINTF("rf int timeouts %d\r\n", rfm22_int_time_outs); - } - #endif -} - -// ************************************ - -void rfm22_TxDataByte_SetCallback(t_rfm22_TxDataByteCallback new_function) -{ - tx_data_byte_callback_function = new_function; -} - -void rfm22_RxData_SetCallback(t_rfm22_RxDataCallback new_function) -{ - rx_data_callback_function = new_function; -} - -// ************************************ -// reset the RF module - -int rfm22_resetModule(uint8_t mode, uint32_t min_frequency_hz, uint32_t max_frequency_hz) -{ - initialized = false; - -#if defined(RFM22_EXT_INT_USE) - rfm22_disableExtInt(); -#endif - - power_on_reset = false; - - // **************** - -#if defined(RFM22_EXT_INT_USE) - exec_using_spi = TRUE; -#endif - - // **************** - // setup the SPI port - - // chip select line HIGH - PIOS_SPI_RC_PinSet(RFM22_PIOS_SPI, 1); - - // set SPI port SCLK frequency .. 4.5MHz - PIOS_SPI_SetClockSpeed(RFM22_PIOS_SPI, PIOS_SPI_PRESCALER_16); - // set SPI port SCLK frequency .. 2.25MHz -// PIOS_SPI_SetClockSpeed(RFM22_PIOS_SPI, PIOS_SPI_PRESCALER_32); - - // set SPI port SCLK frequency .. 285kHz .. purely for hardware fault finding -// PIOS_SPI_SetClockSpeed(RFM22_PIOS_SPI, PIOS_SPI_PRESCALER_256); - - // **************** - // software reset the RF chip .. following procedure according to Si4x3x Errata (rev. B) - - rfm22_write(RFM22_op_and_func_ctrl1, RFM22_opfc1_swres); // software reset the radio - - PIOS_DELAY_WaitmS(26); // wait 26ms - - for (int i = 50; i > 0; i--) - { - PIOS_DELAY_WaitmS(1); // wait 1ms - - // read the status registers - int_status1 = rfm22_read(RFM22_interrupt_status1); - int_status2 = rfm22_read(RFM22_interrupt_status2); - if (int_status2 & RFM22_is2_ichiprdy) break; - } - - // **************** - - // read status - clears interrupt - device_status = rfm22_read(RFM22_device_status); - int_status1 = rfm22_read(RFM22_interrupt_status1); - int_status2 = rfm22_read(RFM22_interrupt_status2); - ezmac_status = rfm22_read(RFM22_ezmac_status); - - // disable all interrupts - rfm22_write(RFM22_interrupt_enable1, 0x00); - rfm22_write(RFM22_interrupt_enable2, 0x00); - - // **************** - -#if defined(RFM22_EXT_INT_USE) - exec_using_spi = FALSE; -#endif - - // **************** - -#if defined(RFM22_EXT_INT_USE) - inside_ext_int = FALSE; -#endif - - rf_mode = mode; - - device_status = int_status1 = int_status2 = ezmac_status = 0; - - rssi = 0; - rssi_dBm = -200; - - tx_data_byte_callback_function = NULL; - rx_data_callback_function = NULL; - - rx_buffer_current = 0; - rx_buffer_wr = 0; - rx_packet_wr = 0; - rx_packet_rssi_dBm = -200; - rx_packet_afc_Hz = 0; - - tx_data_addr = NULL; - tx_data_rd = tx_data_wr = 0; - - lookup_index = 0; - ss_lookup_index = 0; - - rf_bandwidth_used = 0; - ss_rf_bandwidth_used = 0; - - rfm22_int_timer = 0; - rfm22_int_time_outs = 0; - prev_rfm22_int_time_outs = 0; - - hbsel = 0; - frequency_step_size = 0.0f; - - frequency_hop_channel = 0; - - afc_correction = 0; - afc_correction_Hz = 0; - - temperature_reg = 0; - - // set the TX power - tx_power = RFM22_DEFAULT_RF_POWER; - - tx_pwr = 0; - - // **************** - // read the RF chip ID bytes - - device_type = rfm22_read(RFM22_DEVICE_TYPE) & RFM22_DT_MASK; // read the device type - device_version = rfm22_read(RFM22_DEVICE_VERSION) & RFM22_DV_MASK; // read the device version - - #if defined(RFM22_DEBUG) - DEBUG_PRINTF("rf device type: %d\r\n", device_type); - DEBUG_PRINTF("rf device version: %d\r\n", device_version); - #endif - - if (device_type != 0x08) - { - #if defined(RFM22_DEBUG) - DEBUG_PRINTF("rf device type: INCORRECT - should be 0x08\r\n"); - #endif - return -1; // incorrect RF module type - } - -// if (device_version != RFM22_DEVICE_VERSION_V2) // V2 -// return -2; // incorrect RF module version -// if (device_version != RFM22_DEVICE_VERSION_A0) // A0 -// return -2; // incorrect RF module version - if (device_version != RFM22_DEVICE_VERSION_B1) // B1 - { - #if defined(RFM22_DEBUG) - DEBUG_PRINTF("rf device version: INCORRECT\r\n"); - #endif - return -2; // incorrect RF module version - } - - // **************** - // set the minimum and maximum carrier frequency allowed - - if (min_frequency_hz < RFM22_MIN_CARRIER_FREQUENCY_HZ) min_frequency_hz = RFM22_MIN_CARRIER_FREQUENCY_HZ; - else - if (min_frequency_hz > RFM22_MAX_CARRIER_FREQUENCY_HZ) min_frequency_hz = RFM22_MAX_CARRIER_FREQUENCY_HZ; - - if (max_frequency_hz < RFM22_MIN_CARRIER_FREQUENCY_HZ) max_frequency_hz = RFM22_MIN_CARRIER_FREQUENCY_HZ; - else - if (max_frequency_hz > RFM22_MAX_CARRIER_FREQUENCY_HZ) max_frequency_hz = RFM22_MAX_CARRIER_FREQUENCY_HZ; - - if (min_frequency_hz > max_frequency_hz) - { // swap them over - uint32_t tmp = min_frequency_hz; - min_frequency_hz = max_frequency_hz; - max_frequency_hz = tmp; - } - - lower_carrier_frequency_limit_Hz = min_frequency_hz; - upper_carrier_frequency_limit_Hz = max_frequency_hz; - - // **************** - // calibrate our RF module to be exactly on frequency .. different for every module - - osc_load_cap = OSC_LOAD_CAP; // default - rfm22_write(RFM22_xtal_osc_load_cap, osc_load_cap); - - // **************** - - // disable Low Duty Cycle Mode - rfm22_write(RFM22_op_and_func_ctrl2, 0x00); - - rfm22_write(RFM22_cpu_output_clk, RFM22_coc_1MHz); // 1MHz clock output - - rfm22_write(RFM22_op_and_func_ctrl1, RFM22_opfc1_xton); // READY mode -// rfm22_write(RFM22_op_and_func_ctrl1, RFM22_opfc1_pllon); // TUNE mode - - // choose the 3 GPIO pin functions - rfm22_write(RFM22_io_port_config, RFM22_io_port_default); // GPIO port use default value - rfm22_write(RFM22_gpio0_config, RFM22_gpio0_config_drv3 | RFM22_gpio0_config_txstate); // GPIO0 = TX State (to control RF Switch) - rfm22_write(RFM22_gpio1_config, RFM22_gpio1_config_drv3 | RFM22_gpio1_config_rxstate); // GPIO1 = RX State (to control RF Switch) - rfm22_write(RFM22_gpio2_config, RFM22_gpio2_config_drv3 | RFM22_gpio2_config_cca); // GPIO2 = Clear Channel Assessment - - // **************** - - return 0; // OK -} - -// ************************************ - -int rfm22_init_scan_spectrum(uint32_t min_frequency_hz, uint32_t max_frequency_hz) -{ - #if defined(RFM22_DEBUG) - DEBUG_PRINTF("\r\nRF init scan spectrum\r\n"); - #endif - - int res = rfm22_resetModule(RX_SCAN_SPECTRUM, min_frequency_hz, max_frequency_hz); - if (res < 0) - return res; - -// rfm22_setSSBandwidth(0); - rfm22_setSSBandwidth(1); - - // FIFO mode, GFSK modulation - uint8_t fd_bit = rfm22_read(RFM22_modulation_mode_control2) & RFM22_mmc2_fd; - rfm22_write(RFM22_modulation_mode_control2, RFM22_mmc2_trclk_clk_none | RFM22_mmc2_dtmod_fifo | fd_bit | RFM22_mmc2_modtyp_gfsk); - - rfm22_write(RFM22_cpu_output_clk, RFM22_coc_1MHz); // 1MHz clock output - - rfm22_write(RFM22_rssi_threshold_clear_chan_indicator, 0); - - rfm22_write(RFM22_preamble_detection_ctrl1, 31 << 3); // 31-nibbles rx preamble detection - - // avoid packet detection - rfm22_write(RFM22_data_access_control, RFM22_dac_enpacrx | RFM22_dac_encrc); - rfm22_write(RFM22_header_control1, 0x0f); - rfm22_write(RFM22_header_control2, 0x77); - - rfm22_write(RFM22_sync_word3, SYNC_BYTE_1); - rfm22_write(RFM22_sync_word2, SYNC_BYTE_2); - rfm22_write(RFM22_sync_word1, SYNC_BYTE_3 ^ 0xff); - rfm22_write(RFM22_sync_word0, SYNC_BYTE_4 ^ 0xff); - - // all the bits to be checked - rfm22_write(RFM22_header_enable3, 0xff); - rfm22_write(RFM22_header_enable2, 0xff); - rfm22_write(RFM22_header_enable1, 0xff); - rfm22_write(RFM22_header_enable0, 0xff); - -// rfm22_write(RFM22_frequency_hopping_step_size, 0); // set frequency hopping channel step size (multiples of 10kHz) - - rfm22_setNominalCarrierFrequency(min_frequency_hz); // set our nominal carrier frequency - - rfm22_write(RFM22_tx_power, RFM22_tx_pwr_lna_sw | 0); // set minimum tx power - - rfm22_write(RFM22_agc_override1, RFM22_agc_ovr1_sgi | RFM22_agc_ovr1_agcen); - -// rfm22_write(RFM22_vco_current_trimming, 0x7f); -// rfm22_write(RFM22_vco_calibration_override, 0x40); -// rfm22_write(RFM22_chargepump_current_trimming_override, 0x80); - -#if defined(RFM22_EXT_INT_USE) - // Enable RF module external interrupt - rfm22_enableExtInt(); -#endif - - rfm22_setRxMode(RX_SCAN_SPECTRUM, true); - - initialized = true; - - return 0; // OK -} - -// ************************************ - -int rfm22_init_tx_stream(uint32_t min_frequency_hz, uint32_t max_frequency_hz) -{ - #if defined(RFM22_DEBUG) - DEBUG_PRINTF("\r\nRF init TX stream\r\n"); - #endif - - int res = rfm22_resetModule(TX_STREAM_MODE, min_frequency_hz, max_frequency_hz); - if (res < 0) - return res; - - frequency_hop_step_size_reg = 0; - - // set the RF datarate - rfm22_setDatarate(RFM22_DEFAULT_RF_DATARATE, FALSE); - - // FIFO mode, GFSK modulation - uint8_t fd_bit = rfm22_read(RFM22_modulation_mode_control2) & RFM22_mmc2_fd; - rfm22_write(RFM22_modulation_mode_control2, RFM22_mmc2_trclk_clk_none | RFM22_mmc2_dtmod_fifo | fd_bit | RFM22_mmc2_modtyp_gfsk); - - // disable the internal Tx & Rx packet handlers (without CRC) - rfm22_write(RFM22_data_access_control, 0); - - rfm22_write(RFM22_preamble_length, TX_PREAMBLE_NIBBLES); // x-nibbles tx preamble - rfm22_write(RFM22_preamble_detection_ctrl1, RX_PREAMBLE_NIBBLES << 3); // x-nibbles rx preamble detection - - rfm22_write(RFM22_header_control1, RFM22_header_cntl1_bcen_none | RFM22_header_cntl1_hdch_none); // header control - we are not using the header - rfm22_write(RFM22_header_control2, RFM22_header_cntl2_fixpklen | RFM22_header_cntl2_hdlen_none | RFM22_header_cntl2_synclen_32 | ((TX_PREAMBLE_NIBBLES >> 8) & 0x01)); // no header bytes, synchronization word length 3, 2 used, packet length not included in header (fixed packet length). - - rfm22_write(RFM22_sync_word3, SYNC_BYTE_1); // sync word - rfm22_write(RFM22_sync_word2, SYNC_BYTE_2); // - -// rfm22_write(RFM22_modem_test, 0x01); - - rfm22_write(RFM22_agc_override1, RFM22_agc_ovr1_agcen); -// rfm22_write(RFM22_agc_override1, RFM22_agc_ovr1_sgi | RFM22_agc_ovr1_agcen); - - rfm22_write(RFM22_frequency_hopping_step_size, frequency_hop_step_size_reg); // set frequency hopping channel step size (multiples of 10kHz) - - rfm22_setNominalCarrierFrequency((min_frequency_hz + max_frequency_hz) / 2); // set our nominal carrier frequency - - rfm22_write(RFM22_tx_power, RFM22_tx_pwr_papeaken | RFM22_tx_pwr_papeaklvl_0 | RFM22_tx_pwr_lna_sw | tx_power); // set the tx power -// rfm22_write(RFM22_tx_power, RFM22_tx_pwr_lna_sw | tx_power); // set the tx power - -// rfm22_write(RFM22_vco_current_trimming, 0x7f); -// rfm22_write(RFM22_vco_calibration_override, 0x40); -// rfm22_write(RFM22_chargepump_current_trimming_override, 0x80); - - rfm22_write(RFM22_tx_fifo_control1, TX_FIFO_HI_WATERMARK); // TX FIFO Almost Full Threshold (0 - 63) - rfm22_write(RFM22_tx_fifo_control2, TX_FIFO_LO_WATERMARK); // TX FIFO Almost Empty Threshold (0 - 63) - - #if defined(RFM22_EXT_INT_USE) - // Enable RF module external interrupt - rfm22_enableExtInt(); - #endif - - initialized = true; - - return 0; // OK -} - -// ************************************ - -int rfm22_init_rx_stream(uint32_t min_frequency_hz, uint32_t max_frequency_hz) -{ - #if defined(RFM22_DEBUG) - DEBUG_PRINTF("\r\nRF init RX stream\r\n"); - #endif - - int res = rfm22_resetModule(RX_WAIT_PREAMBLE_MODE, min_frequency_hz, max_frequency_hz); - if (res < 0) - return res; - - frequency_hop_step_size_reg = 0; - - // set the RF datarate - rfm22_setDatarate(RFM22_DEFAULT_RF_DATARATE, FALSE); - - // FIFO mode, GFSK modulation - uint8_t fd_bit = rfm22_read(RFM22_modulation_mode_control2) & RFM22_mmc2_fd; - rfm22_write(RFM22_modulation_mode_control2, RFM22_mmc2_trclk_clk_none | RFM22_mmc2_dtmod_fifo | fd_bit | RFM22_mmc2_modtyp_gfsk); - - // disable the internal Tx & Rx packet handlers (without CRC) - rfm22_write(RFM22_data_access_control, 0); - - rfm22_write(RFM22_preamble_length, TX_PREAMBLE_NIBBLES); // x-nibbles tx preamble - rfm22_write(RFM22_preamble_detection_ctrl1, RX_PREAMBLE_NIBBLES << 3); // x-nibbles rx preamble detection - - rfm22_write(RFM22_header_control1, RFM22_header_cntl1_bcen_none | RFM22_header_cntl1_hdch_none); // header control - we are not using the header - rfm22_write(RFM22_header_control2, RFM22_header_cntl2_fixpklen | RFM22_header_cntl2_hdlen_none | RFM22_header_cntl2_synclen_32 | ((TX_PREAMBLE_NIBBLES >> 8) & 0x01)); // no header bytes, synchronization word length 3, 2 used, packet length not included in header (fixed packet length). - - rfm22_write(RFM22_sync_word3, SYNC_BYTE_1); // sync word - rfm22_write(RFM22_sync_word2, SYNC_BYTE_2); // - - // no header bits to be checked - rfm22_write(RFM22_header_enable3, 0x00); - rfm22_write(RFM22_header_enable2, 0x00); - rfm22_write(RFM22_header_enable1, 0x00); - rfm22_write(RFM22_header_enable0, 0x00); - -// rfm22_write(RFM22_modem_test, 0x01); - - rfm22_write(RFM22_agc_override1, RFM22_agc_ovr1_agcen); -// rfm22_write(RFM22_agc_override1, RFM22_agc_ovr1_sgi | RFM22_agc_ovr1_agcen); - - rfm22_write(RFM22_frequency_hopping_step_size, frequency_hop_step_size_reg); // set frequency hopping channel step size (multiples of 10kHz) - - rfm22_setNominalCarrierFrequency((min_frequency_hz + max_frequency_hz) / 2); // set our nominal carrier frequency - -// rfm22_write(RFM22_vco_current_trimming, 0x7f); -// rfm22_write(RFM22_vco_calibration_override, 0x40); -// rfm22_write(RFM22_chargepump_current_trimming_override, 0x80); - - rfm22_write(RFM22_rx_fifo_control, RX_FIFO_HI_WATERMARK); // RX FIFO Almost Full Threshold (0 - 63) - - #if defined(RFM22_EXT_INT_USE) - // Enable RF module external interrupt - rfm22_enableExtInt(); - #endif - - rfm22_setRxMode(RX_WAIT_PREAMBLE_MODE, false); - - initialized = true; - - return 0; // OK -} - -// ************************************ -// Initialise this hardware layer module and the rf module - -int rfm22_init_normal(uint32_t min_frequency_hz, uint32_t max_frequency_hz, uint32_t freq_hop_step_size) -{ - #if defined(RFM22_DEBUG) - DEBUG_PRINTF("\r\nRF init normal\r\n"); - #endif - - int res = rfm22_resetModule(RX_WAIT_PREAMBLE_MODE, min_frequency_hz, max_frequency_hz); - if (res < 0) - return res; - - // **************** - - freq_hop_step_size /= 10000; // in 10kHz increments - if (freq_hop_step_size > 255) freq_hop_step_size = 255; - - frequency_hop_step_size_reg = freq_hop_step_size; - - // **************** - - // set the RF datarate - rfm22_setDatarate(RFM22_DEFAULT_RF_DATARATE, TRUE); - - // FIFO mode, GFSK modulation - uint8_t fd_bit = rfm22_read(RFM22_modulation_mode_control2) & RFM22_mmc2_fd; - rfm22_write(RFM22_modulation_mode_control2, RFM22_mmc2_trclk_clk_none | RFM22_mmc2_dtmod_fifo | fd_bit | RFM22_mmc2_modtyp_gfsk); - - // setup to read the internal temperature sensor - adc_config = RFM22_ac_adcsel_temp_sensor | RFM22_ac_adcref_bg; // ADC used to sample the temperature sensor - rfm22_write(RFM22_adc_config, adc_config); // - rfm22_write(RFM22_adc_sensor_amp_offset, 0); // adc offset - rfm22_write(RFM22_temp_sensor_calib, RFM22_tsc_tsrange0 | RFM22_tsc_entsoffs); // temp sensor calibration .. –40C to +64C 0.5C resolution - rfm22_write(RFM22_temp_value_offset, 0); // temp sensor offset - rfm22_write(RFM22_adc_config, adc_config | RFM22_ac_adcstartbusy); // start an ADC conversion - - rfm22_write(RFM22_rssi_threshold_clear_chan_indicator, (-90 + 122) * 2); // set the RSSI threshold interrupt to about -90dBm - - // enable the internal Tx & Rx packet handlers (with CRC) -// rfm22_write(RFM22_data_access_control, RFM22_dac_enpacrx | RFM22_dac_enpactx | RFM22_dac_encrc | RFM22_dac_crc_crc16); - // enable the internal Tx & Rx packet handlers (without CRC) - rfm22_write(RFM22_data_access_control, RFM22_dac_enpacrx | RFM22_dac_enpactx); - - rfm22_write(RFM22_preamble_length, TX_PREAMBLE_NIBBLES); // x-nibbles tx preamble - rfm22_write(RFM22_preamble_detection_ctrl1, RX_PREAMBLE_NIBBLES << 3); // x-nibbles rx preamble detection - - rfm22_write(RFM22_header_control1, RFM22_header_cntl1_bcen_none | RFM22_header_cntl1_hdch_none); // header control - we are not using the header - rfm22_write(RFM22_header_control2, RFM22_header_cntl2_hdlen_none | RFM22_header_cntl2_synclen_3210 | ((TX_PREAMBLE_NIBBLES >> 8) & 0x01)); // no header bytes, synchronization word length 3, 2, 1 & 0 used, packet length included in header. - - rfm22_write(RFM22_sync_word3, SYNC_BYTE_1); // sync word - rfm22_write(RFM22_sync_word2, SYNC_BYTE_2); // - rfm22_write(RFM22_sync_word1, SYNC_BYTE_3); // - rfm22_write(RFM22_sync_word0, SYNC_BYTE_4); // -/* - rfm22_write(RFM22_transmit_header3, 'p'); // set tx header - rfm22_write(RFM22_transmit_header2, 'i'); // - rfm22_write(RFM22_transmit_header1, 'p'); // - rfm22_write(RFM22_transmit_header0, ' '); // - - rfm22_write(RFM22_check_header3, 'p'); // set expected rx header - rfm22_write(RFM22_check_header2, 'i'); // - rfm22_write(RFM22_check_header1, 'p'); // - rfm22_write(RFM22_check_header0, ' '); // - - // all the bits to be checked - rfm22_write(RFM22_header_enable3, 0xff); - rfm22_write(RFM22_header_enable2, 0xff); - rfm22_write(RFM22_header_enable1, 0xff); - rfm22_write(RFM22_header_enable0, 0xff); -*/ // no bits to be checked - rfm22_write(RFM22_header_enable3, 0x00); - rfm22_write(RFM22_header_enable2, 0x00); - rfm22_write(RFM22_header_enable1, 0x00); - rfm22_write(RFM22_header_enable0, 0x00); - -// rfm22_write(RFM22_modem_test, 0x01); - - rfm22_write(RFM22_agc_override1, RFM22_agc_ovr1_agcen); -// rfm22_write(RFM22_agc_override1, RFM22_agc_ovr1_sgi | RFM22_agc_ovr1_agcen); - - rfm22_write(RFM22_frequency_hopping_step_size, frequency_hop_step_size_reg); // set frequency hopping channel step size (multiples of 10kHz) - - rfm22_setNominalCarrierFrequency((min_frequency_hz + max_frequency_hz) / 2); // set our nominal carrier frequency - - rfm22_write(RFM22_tx_power, RFM22_tx_pwr_papeaken | RFM22_tx_pwr_papeaklvl_0 | RFM22_tx_pwr_lna_sw | tx_power); // set the tx power -// rfm22_write(RFM22_tx_power, RFM22_tx_pwr_lna_sw | tx_power); // set the tx power - -// rfm22_write(RFM22_vco_current_trimming, 0x7f); -// rfm22_write(RFM22_vco_calibration_override, 0x40); -// rfm22_write(RFM22_chargepump_current_trimming_override, 0x80); - - rfm22_write(RFM22_tx_fifo_control1, TX_FIFO_HI_WATERMARK); // TX FIFO Almost Full Threshold (0 - 63) - rfm22_write(RFM22_tx_fifo_control2, TX_FIFO_LO_WATERMARK); // TX FIFO Almost Empty Threshold (0 - 63) - - rfm22_write(RFM22_rx_fifo_control, RX_FIFO_HI_WATERMARK); // RX FIFO Almost Full Threshold (0 - 63) - -#if defined(RFM22_EXT_INT_USE) - // Enable RF module external interrupt - rfm22_enableExtInt(); -#endif - - rfm22_setRxMode(RX_WAIT_PREAMBLE_MODE, false); - - initialized = true; - - return 0; // ok -} - -// ************************************ diff --git a/flight/PipXtreme/saved_settings.c b/flight/PipXtreme/saved_settings.c deleted file mode 100644 index badef5673..000000000 --- a/flight/PipXtreme/saved_settings.c +++ /dev/null @@ -1,326 +0,0 @@ -/** - ****************************************************************************** - * - * @file saved_settings.c - * @author The OpenPilot Team, http://www.openpilot.org Copyright (C) 2010. - * @brief RF Module hardware layer - * @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 // memmove, memset - -#include "crc.h" -#include "gpio_in.h" -#include "saved_settings.h" -#include "main.h" - -#if defined(PIOS_COM_DEBUG) - #define SAVED_SETTINGS_DEBUG -#endif - -// ***************************************************************** - -// default aes 128-bit encryption key -const uint8_t saved_settings_default_aes_key[16] = {0x65, 0x3b, 0x71, 0x89, 0x4a, 0xf4, 0xc8, 0xcb, 0x18, 0xd4, 0x9b, 0x4d, 0x4a, 0xbe, 0xc8, 0x37}; - -// ***************************************************************** - -#define pages 1 // number of flash pages to use - -uint32_t eeprom_addr; // the address of the emulated EEPROM area in program flash area -uint16_t eeprom_page_size; // flash page size - -volatile t_saved_settings saved_settings __attribute__ ((aligned(4))); // a RAM copy of the settings stored in EEPROM -t_saved_settings tmp_settings __attribute__ ((aligned(4))); - -// ***************************************************************** -// Private functions - -bool saved_settings_page_empty(int page) -{ // return TRUE if the flash page is emtpy (erased), otherwise return FALSE - - if (page < 0 || page >= pages) - return FALSE; - - __IO uint32_t *addr = (__IO uint32_t *)(eeprom_addr + eeprom_page_size * page); - int32_t len = eeprom_page_size / 4; - - for (int32_t i = len; i > 0; i--) - if (*addr++ != 0xffffffff) - return FALSE; // the page is not erased - - return TRUE; -} - -bool saved_settings_settings_empty(uint32_t addr) -{ // return TRUE if the settings flash area is emtpy (erased), otherwise return FALSE - - __IO uint8_t *p = (__IO uint8_t *)addr; - - for (int32_t i = sizeof(t_saved_settings); i > 0; i--) - if (*p++ != 0xff) - return FALSE; // the flash area is not empty/erased - - return TRUE; -} - -// ***************************************************************** - -int32_t saved_settings_read(void) -{ // look for the last valid settings saved in EEPROM - - uint32_t flash_addr; - __IO uint8_t *p1; - uint8_t *p2; - - flash_addr = eeprom_addr; - - if (saved_settings_settings_empty(flash_addr)) - { - #if defined(SAVED_SETTINGS_DEBUG) - DEBUG_PRINTF("settings Read, no settings found at %08X\r\n", flash_addr); - #endif - - return -1; // no settings found at the specified addr - } - - // copy the data from program flash area into temp settings area - p1 = (__IO uint8_t *)flash_addr; - p2 = (uint8_t *)&tmp_settings; - for (int32_t i = 0; i < sizeof(t_saved_settings); i++) - *p2++ = *p1++; - - // calculate and check the CRC - uint32_t crc1 = tmp_settings.crc; - tmp_settings.crc = 0; - uint32_t crc2 = updateCRC32Data(0xffffffff, (void *)&tmp_settings, sizeof(t_saved_settings)); - if (crc2 != crc1) - { - #if defined(SAVED_SETTINGS_DEBUG) - DEBUG_PRINTF("settings Read crc error: %08X %08X\r\n", crc1, crc2); - #endif - - return -2; // error - } - - memmove((void *)&saved_settings, (void *)&tmp_settings, sizeof(t_saved_settings)); - - #if defined(SAVED_SETTINGS_DEBUG) - DEBUG_PRINTF("settings Read OK!\r\n"); - #endif - - return 0; // OK -} - -// ***************************************************************** -// Public functions - -int32_t saved_settings_save(void) -{ // save the settings into EEPROM - - FLASH_Status fs; - uint32_t flash_addr; - uint8_t *p1; - __IO uint8_t *p2; - uint32_t *p3; - bool do_save; - - // size of the settings aligned to 4 bytes -// uint16_t settings_size = (uint16_t)(sizeof(t_saved_settings) + 3) & 0xfffc; - - // address of settings in FLASH area - flash_addr = eeprom_addr; - - // ***************************************** - // calculate and add the CRC - - saved_settings.crc = 0; - saved_settings.crc = updateCRC32Data(0xffffffff, (void *)&saved_settings, sizeof(t_saved_settings)); - - // ***************************************** - // first check to see if we need to save the settings - - p1 = (uint8_t *)&saved_settings; - p2 = (__IO uint8_t *)flash_addr; - do_save = FALSE; - - for (int32_t i = 0; i < sizeof(t_saved_settings); i++) - { - if (*p1++ != *p2++) - { // we need to save the settings - do_save = TRUE; - break; - } - } - - if (!do_save) - { - #if defined(SAVED_SETTINGS_DEBUG) - DEBUG_PRINTF("settings already saved OK\r\n"); - #endif - - return 0; // settings already saved .. all OK - } - - // ***************************************** - - // Unlock the Flash Program Erase controller - FLASH_Unlock(); - - if (!saved_settings_page_empty(0)) - { // erase the page - #if defined(SAVED_SETTINGS_DEBUG) - DEBUG_PRINTF("settings erasing page .. "); - #endif - - fs = FLASH_ErasePage(eeprom_addr); - if (fs != FLASH_COMPLETE) - { // error - FLASH_Lock(); - - #if defined(SAVED_SETTINGS_DEBUG) - DEBUG_PRINTF("error %d\r\n", fs); - #endif - - return -1; - } - - #if defined(SAVED_SETTINGS_DEBUG) - DEBUG_PRINTF("OK\r\n"); - #endif - } - else - { - #if defined(SAVED_SETTINGS_DEBUG) - DEBUG_PRINTF("settings page already erased\r\n"); - #endif - } - - // ***************************************** - // save the settings into flash area (emulated EEPROM area) - - p1 = (uint8_t *)&saved_settings; - p3 = (uint32_t *)flash_addr; - - // write 4 bytes at a time into program flash area (emulated EEPROM area) - for (int32_t i = 0; i < sizeof(t_saved_settings); p3++) - { - uint32_t value = 0; - if (i < sizeof(t_saved_settings)) value |= (uint32_t)*p1++ << 0; else value |= 0x000000ff; i++; - if (i < sizeof(t_saved_settings)) value |= (uint32_t)*p1++ << 8; else value |= 0x0000ff00; i++; - if (i < sizeof(t_saved_settings)) value |= (uint32_t)*p1++ << 16; else value |= 0x00ff0000; i++; - if (i < sizeof(t_saved_settings)) value |= (uint32_t)*p1++ << 24; else value |= 0xff000000; i++; - - fs = FLASH_ProgramWord((uint32_t)p3, value); // write a 32-bit value - if (fs != FLASH_COMPLETE) - { - FLASH_Lock(); - - #if defined(SAVED_SETTINGS_DEBUG) - DEBUG_PRINTF("settings FLASH_ProgramWord error: %d\r\n", fs); - #endif - - return -2; // error - } - } - - // Lock the Flash Program Erase controller - FLASH_Lock(); - - // ***************************************** - // now error check it by reading it back (simple compare) - - p1 = (uint8_t *)&saved_settings; - p2 = (__IO uint8_t *)flash_addr; - - for (int32_t i = 0; i < sizeof(t_saved_settings); i++) - { - if (*p1++ != *p2++) - { - #if defined(SAVED_SETTINGS_DEBUG) - DEBUG_PRINTF("settings WriteSettings compare error\r\n"); - #endif - - return -3; // error - } - } - - // ***************************************** - - #if defined(SAVED_SETTINGS_DEBUG) - DEBUG_PRINTF("settings Save OK!\r\n"); - #endif - - return 0; // OK -} - -void saved_settings_init(void) -{ - // ********** - // determine emulated EEPROM details - - if (flash_size < 256000) - eeprom_page_size = 1024; // 1 kByte - else - eeprom_page_size = 2048; // 2 kByte - - // place emulated eeprom at end of program flash area - eeprom_addr = (0x08000000 + flash_size) - (eeprom_page_size * pages); - - #if defined(SAVED_SETTINGS_DEBUG) - DEBUG_PRINTF("\r\n"); - DEBUG_PRINTF("settings eeprom addr: %08x\r\n", eeprom_addr); - DEBUG_PRINTF("settings eeprom page size: %u\r\n", eeprom_page_size); - DEBUG_PRINTF("settings eeprom pages: %u\r\n", pages); - #endif - - // ********** - // default settings - - memset((void *)&saved_settings, 0xff, sizeof(t_saved_settings)); - - saved_settings.mode = MODE_NORMAL; - - saved_settings.destination_id = 0; - - saved_settings.frequency_band = FREQBAND_UNKNOWN; - - saved_settings.rf_xtal_cap = 0x7f; - - saved_settings.aes_enable = FALSE; - memmove((void *)&saved_settings.aes_key, saved_settings_default_aes_key, sizeof(saved_settings.aes_key)); - - saved_settings.serial_baudrate = 57600; - - saved_settings.rts_time = 10; // ms - -// saved_settings.crc = 0; -// saved_settings.crc = updateCRC32Data(0xffffffff, (void *)&saved_settings, sizeof(t_saved_settings)); - - // ********** - - // Lock the Flash Program Erase controller - FLASH_Lock(); - - saved_settings_read(); - - // ********** -} - -// ***************************************************************** diff --git a/flight/PipXtreme/stopwatch.c b/flight/PipXtreme/stopwatch.c deleted file mode 100644 index c1e983e91..000000000 --- a/flight/PipXtreme/stopwatch.c +++ /dev/null @@ -1,156 +0,0 @@ -/** - ****************************************************************************** - * - * @file stopwatch.c - * @author The OpenPilot Team, http://www.openpilot.org Copyright (C) 2010. - * @brief Stop watch function - * @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 "stopwatch.h" -#include "main.h" - -// ***************************************************************************** - -uint32_t resolution_us = 0; - -// ***************************************************************************** -// initialise the stopwatch - -void STOPWATCH_init(uint32_t resolution) -{ - resolution_us = resolution; - - if (resolution_us == 0) - return; - - // enable timer clock - switch ((uint32_t)STOPWATCH_TIMER) - { - case (uint32_t)TIM1: RCC_APB2PeriphClockCmd(RCC_APB2Periph_TIM1, ENABLE); break; - case (uint32_t)TIM2: RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2, ENABLE); break; - case (uint32_t)TIM3: RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM3, ENABLE); break; - case (uint32_t)TIM4: RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM4, ENABLE); break; - #ifdef STM32F10X_HD - case (uint32_t)TIM5: RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM5, ENABLE); break; - case (uint32_t)TIM6: RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM6, ENABLE); break; - case (uint32_t)TIM7: RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM7, ENABLE); break; - case (uint32_t)TIM8: RCC_APB2PeriphClockCmd(RCC_APB2Periph_TIM8, ENABLE); break; - #endif - } - - // time base configuration - TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure; - TIM_TimeBaseStructure.TIM_Period = 0xffff; // max period - TIM_TimeBaseStructure.TIM_Prescaler = ((PIOS_MASTER_CLOCK / 1000000) * resolution_us) - 1; // uS accuracy @ 72 MHz - TIM_TimeBaseStructure.TIM_ClockDivision = 0; - TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up; - TIM_TimeBaseInit(STOPWATCH_TIMER, &TIM_TimeBaseStructure); - - // enable interrupt request - TIM_ITConfig(STOPWATCH_TIMER, TIM_IT_Update, ENABLE); - - // start counter - TIM_Cmd(STOPWATCH_TIMER, ENABLE); -} - -// ***************************************************************************** -// timer interrupt -/* -#ifdef STM32F10X_MD - #if (STOPWATCH_TIMER == TIM1) - void TIM1_IRQHandler(void) - #if (STOPWATCH_TIMER == TIM2) - void TIM2_IRQHandler(void) - #elif (STOPWATCH_TIMER == TIM3) - void TIM3_IRQHandler(void) - #elif (STOPWATCH_TIMER == TIM4) - void TIM4_IRQHandler(void) - #endif -#endif -#ifdef STM32F10X_HD - #if (STOPWATCH_TIMER == TIM1) - void TIM1_IRQHandler(void) - #if (STOPWATCH_TIMER == TIM2) - void TIM2_IRQHandler(void) - #elif (STOPWATCH_TIMER == TIM3) - void TIM3_IRQHandler(void) - #elif (STOPWATCH_TIMER == TIM4) - void TIM4_IRQHandler(void) - #elif (STOPWATCH_TIMER == TIM5) - void TIM5_IRQHandler(void) - #elif (STOPWATCH_TIMER == TIM6) - void TIM6_IRQHandler(void) - #elif (STOPWATCH_TIMER == TIM7) - void TIM7_IRQHandler(void) - #elif (STOPWATCH_TIMER == TIM8) - void TIM8_IRQHandler(void) - #endif -#endif -{ - -} -*/ -// ***************************************************************************** -// resets the stopwatch - -void STOPWATCH_reset(void) -{ - if (resolution_us > 0) - { // reset the counter - STOPWATCH_TIMER->CNT = 1; // set to 1 instead of 0 to avoid new IRQ request - TIM_ClearITPendingBit(STOPWATCH_TIMER, TIM_IT_Update); - } -} - -// ***************************************************************************** -// returns the timer count since the last STOPWATCH_reset() call -// return 0xffffffff if counter overrun or not initialised - -uint32_t STOPWATCH_get_count(void) -{ - uint32_t value = STOPWATCH_TIMER->CNT; // get counter value ASAP - - if (resolution_us == 0) - return 0xffffffff; // not initialized - - if (TIM_GetITStatus(STOPWATCH_TIMER, TIM_IT_Update) != RESET) - return 0xffffffff; // timer overfloaw - - return value; // return the timer count -} - -// ***************************************************************************** -// returns number of us since the last STOPWATCH_reset() call -// return 0xffffffff if counter overrun or not initialised - -uint32_t STOPWATCH_get_us(void) -{ - uint32_t value = STOPWATCH_TIMER->CNT; // get counter value ASAP - - if (resolution_us == 0) - return 0xffffffff; // not initialized - - if (TIM_GetITStatus(STOPWATCH_TIMER, TIM_IT_Update) != RESET) - return 0xffffffff; // timer overfloaw - - return (value * resolution_us); // return number of micro seconds -} - -// ***************************************************************************** diff --git a/flight/PipXtreme/stream.c b/flight/PipXtreme/stream.c deleted file mode 100644 index 924333a24..000000000 --- a/flight/PipXtreme/stream.c +++ /dev/null @@ -1,122 +0,0 @@ -/** - ****************************************************************************** - * - * @file stream.c - * @author The OpenPilot Team, http://www.openpilot.org Copyright (C) 2010. - * @brief Sends or Receives a continuous packet stream to/from the remote unit - * @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 // memmove - -#include "main.h" -#include "rfm22b.h" -#include "fifo_buffer.h" -#include "aes.h" -#include "crc.h" -#include "saved_settings.h" -#include "stream.h" - -#if defined(PIOS_COM_DEBUG) - #define STREAM_DEBUG -#endif - -// ************************************************************* -// can be called from an interrupt if you wish -// call this once every ms - -void stream_1ms_tick(void) -{ - if (booting) return; - - if (saved_settings.mode == MODE_STREAM_TX) - { - } - else - if (saved_settings.mode == MODE_STREAM_RX) - { - } -} - -// ************************************************************* -// return a byte for the tx packet transmission. -// -// return value < 0 if no more bytes available, otherwise return byte to be sent - -int16_t stream_TxDataByteCallback(void) -{ - return -1; -} - -// ************************************************************* -// we are being given a block of received bytes -// -// return TRUE to continue current packet receive, otherwise return FALSE to halt current packet reception - -bool stream_RxDataCallback(void *data, uint8_t len) -{ - return true; -} - -// ************************************************************* -// call this from the main loop (not interrupt) as often as possible - -void stream_process(void) -{ - if (booting) return; - - if (saved_settings.mode == MODE_STREAM_TX) - { - } - else - if (saved_settings.mode == MODE_STREAM_RX) - { - } -} - -// ************************************************************* - -void stream_deinit(void) -{ -} - -void stream_init(uint32_t our_sn) -{ - #if defined(STREAM_DEBUG) - DEBUG_PRINTF("\r\nSTREAM init\r\n"); - #endif - - if (saved_settings.mode == MODE_STREAM_TX) - rfm22_init_tx_stream(saved_settings.min_frequency_Hz, saved_settings.max_frequency_Hz); - else - if (saved_settings.mode == MODE_STREAM_RX) - rfm22_init_rx_stream(saved_settings.min_frequency_Hz, saved_settings.max_frequency_Hz); - - rfm22_TxDataByte_SetCallback(stream_TxDataByteCallback); - rfm22_RxData_SetCallback(stream_RxDataCallback); - - rfm22_setFreqCalibration(saved_settings.rf_xtal_cap); - rfm22_setNominalCarrierFrequency(saved_settings.frequency_Hz); - rfm22_setDatarate(saved_settings.max_rf_bandwidth, FALSE); - rfm22_setTxPower(saved_settings.max_tx_power); - - rfm22_setTxStream(); // TEST ONLY -} - -// ************************************************************* diff --git a/flight/PipXtreme/transparent_comms.c b/flight/PipXtreme/transparent_comms.c deleted file mode 100644 index dc5e0384a..000000000 --- a/flight/PipXtreme/transparent_comms.c +++ /dev/null @@ -1,218 +0,0 @@ -/** - ****************************************************************************** - * - * @file transparent_comms.c - * @author The OpenPilot Team, http://www.openpilot.org Copyright (C) 2010. - * @brief Serial communication port handling 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 - */ - -#include - -#include "stm32f10x.h" -#include "gpio_in.h" -#include "transparent_comms.h" -#include "packet_handler.h" -#include "saved_settings.h" -#include "main.h" -#include "pios_usb.h" /* PIOS_USB_* */ - -#if defined(PIOS_COM_DEBUG) - #define TRANS_DEBUG -#endif - -// ***************************************************************************** -// local variables - -uint32_t trans_previous_com_port = 0; - -volatile uint16_t trans_rx_timer = 0; -volatile uint16_t trans_tx_timer = 0; - -uint8_t trans_temp_buffer1[128]; - -uint8_t trans_temp_buffer2[128]; -uint16_t trans_temp_buffer2_wr; - -// ***************************************************************************** -// can be called from an interrupt if you wish - -void trans_1ms_tick(void) -{ // call this once every 1ms - if (trans_rx_timer < 0xffff) trans_rx_timer++; - if (trans_tx_timer < 0xffff) trans_tx_timer++; -} - -// ***************************************************************************** -// call this as often as possible - not from an interrupt - -void trans_process(void) -{ // copy data from comm-port RX buffer to RF packet handler TX buffer, and from RF packet handler RX buffer to comm-port TX buffer - - // ******************** - // decide which comm-port we are using (usart or usb) - - bool usb_comms = false; // TRUE if we are using the usb port for comms. - uint32_t comm_port = PIOS_COM_SERIAL; // default to using the usart comm-port - - #if defined(PIOS_INCLUDE_USB) - if (PIOS_USB_CheckAvailable(0)) - { // USB comms is up, use the USB comm-port instead of the USART comm-port - usb_comms = true; - comm_port = PIOS_COM_TELEM_USB; - } - #endif - - // ******************** - // check to see if the local communication port has changed (usart/usb) - - if (trans_previous_com_port == 0 && trans_previous_com_port != comm_port) - { // the local communications port has changed .. remove any data in the buffers - trans_temp_buffer2_wr = 0; - } - else - if (usb_comms) - { // we're using the USB for comms - keep the USART rx buffer empty - uint8_t c; - while (PIOS_COM_ReceiveBuffer(PIOS_COM_SERIAL, &c, 1, 0) > 0); - } - - trans_previous_com_port = comm_port; // remember the current comm-port we are using - - // ******************** - - uint16_t connection_index = 0; // the RF connection we are using - - // ******************** - // send the data received down the comm-port to the RF packet handler TX buffer - - if (saved_settings.mode == MODE_NORMAL || saved_settings.mode == MODE_STREAM_TX) - { - // free space size in the RF packet handler tx buffer - uint16_t ph_num = ph_putData_free(connection_index); - - // set the USART RTS handshaking line - if (!usb_comms) - { - if (ph_num < 32 || !ph_connected(connection_index)) - SERIAL_RTS_CLEAR; // lower the USART RTS line - we don't have space in the buffer for anymore bytes - else - SERIAL_RTS_SET; // release the USART RTS line - we have space in the buffer for now bytes - } - else - SERIAL_RTS_SET; // release the USART RTS line - - // limit number of bytes we will get to the size of the temp buffer - if (ph_num > sizeof(trans_temp_buffer1)) - ph_num = sizeof(trans_temp_buffer1); - - // copy data received down the comm-port into our temp buffer - register uint16_t bytes_saved = 0; - bytes_saved = PIOS_COM_ReceiveBuffer(comm_port, trans_temp_buffer1, ph_num, 0); - - // put the received comm-port data bytes into the RF packet handler TX buffer - if (bytes_saved > 0) - { - trans_rx_timer = 0; - ph_putData(connection_index, trans_temp_buffer1, bytes_saved); - } - } - else - { // empty the comm-ports rx buffer - uint8_t c; - while (PIOS_COM_ReceiveBuffer(comm_port, &c, 1, 0) > 0); - } - - // ******************** - // send the data received via the RF link out the comm-port - - if (saved_settings.mode == MODE_NORMAL || saved_settings.mode == MODE_STREAM_RX) - { - if (trans_temp_buffer2_wr < sizeof(trans_temp_buffer2)) - { - // get number of data bytes received via the RF link - uint16_t ph_num = ph_getData_used(connection_index); - - // limit to how much space we have in the temp buffer - if (ph_num > sizeof(trans_temp_buffer2) - trans_temp_buffer2_wr) - ph_num = sizeof(trans_temp_buffer2) - trans_temp_buffer2_wr; - - if (ph_num > 0) - { // fetch the data bytes received via the RF link and save into our temp buffer - ph_num = ph_getData(connection_index, trans_temp_buffer2 + trans_temp_buffer2_wr, ph_num); - trans_temp_buffer2_wr += ph_num; - } - } - - #if (defined(PIOS_COM_DEBUG) && (PIOS_COM_DEBUG == PIOS_COM_SERIAL)) - if (!usb_comms) - { // the serial-port is being used for debugging - don't send data down it - trans_temp_buffer2_wr = 0; - trans_tx_timer = 0; - return; - } - #endif - - if (trans_temp_buffer2_wr > 0) - { // we have data in our temp buffer that needs sending out the comm-port - - if (usb_comms || (!usb_comms && GPIO_IN(SERIAL_CTS_PIN))) - { // we are OK to send the data out the comm-port - - // send the data out the comm-port - int32_t res = PIOS_COM_SendBufferNonBlocking(comm_port, trans_temp_buffer2, trans_temp_buffer2_wr); // this one doesn't work properly with USB :( - if (res >= 0) - { // data was sent out the comm-port OK .. remove the sent data from the temp buffer - trans_temp_buffer2_wr = 0; - trans_tx_timer = 0; - } - else - { // failed to send the data out the comm-port - #if defined(TRANS_DEBUG) - DEBUG_PRINTF("PIOS_COM_SendBuffer %d %d\r\n", trans_temp_buffer2_wr, res); - #endif - - if (trans_tx_timer >= 5000) - trans_temp_buffer2_wr = 0; // seems we can't send our data for at least the last 5 seconds - delete it - } - } - } - } - else - { // empty the buffer - trans_temp_buffer2_wr = 0; - trans_tx_timer = 0; - } - - // ******************** -} - -// ***************************************************************************** - -void trans_init(void) -{ - trans_previous_com_port = 0; - - trans_temp_buffer2_wr = 0; - - trans_rx_timer = 0; - trans_tx_timer = 0; -} - -// ***************************************************************************** diff --git a/flight/PipXtreme/watchdog.c b/flight/PipXtreme/watchdog.c deleted file mode 100644 index 044e3d3f3..000000000 --- a/flight/PipXtreme/watchdog.c +++ /dev/null @@ -1,71 +0,0 @@ -/** - ****************************************************************************** - * - * @file watchdog.c - * @author The OpenPilot Team, http://www.openpilot.org Copyright (C) 2010. - * @brief Modem packet handling 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 - */ - -#include "pios.h" -#include "stm32f10x_iwdg.h" -#include "stm32f10x_dbgmcu.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 - */ -uint16_t watchdog_Init(uint16_t delayMs) -{ - uint16_t delay = ((uint32_t)delayMs * 60) / 16; - if (delay > 0x0fff) - delay = 0x0fff; - - DBGMCU_Config(DBGMCU_IWDG_STOP, ENABLE); // make the watchdog stop counting in debug mode - IWDG_WriteAccessCmd(IWDG_WriteAccess_Enable); - IWDG_SetPrescaler(IWDG_Prescaler_16); - IWDG_SetReload(delay); - IWDG_ReloadCounter(); - IWDG_Enable(); - - return ((((uint32_t)delay * 16) / 60) * .75f); -} - -/** - * @brief Clear the watchdog timer - * - * This function must be called at the appropriate delay to prevent a reset event occuring - */ -void watchdog_Clear(void) -{ - IWDG_ReloadCounter(); -} diff --git a/flight/Project/Windows USB/OpenPilot-CDC.inf b/flight/Project/Windows USB/OpenPilot-CDC.inf new file mode 100644 index 000000000..7b799c8b0 --- /dev/null +++ b/flight/Project/Windows USB/OpenPilot-CDC.inf @@ -0,0 +1,35 @@ +[Version] +Signature="$Windows NT$" +Class=Ports +ClassGuid={4D36E978-E325-11CE-BFC1-08002BE10318} +Provider=%ProviderName% +DriverVer=10/15/2009,1.0.0.0 + +[MANUFACTURER] +%ProviderName%=DeviceList, NTx86, NTamd64 + +[DeviceList.NTx86] +%CopterControl%= DriverInstall,USB\VID_20A0&PID_415b&MI_00 +%PipXtreme%= DriverInstall,USB\VID_20A0&PID_415c&MI_00 + +[DeviceList.NTamd64] +%CopterControl%= DriverInstall,USB\VID_20A0&PID_415b&MI_00 +%PipXtreme%= DriverInstall,USB\VID_20A0&PID_415c&MI_00 + +[DriverInstall] +include=mdmcpq.inf +CopyFiles=FakeModemCopyFileSection +AddReg=LowerFilterAddReg,SerialPropPageAddReg + +[DriverInstall.Services] +include = mdmcpq.inf +AddService = usbser, 0x00000002, LowerFilter_Service_Inst + +; This adds the serial port property tab to the device properties dialog +[SerialPropPageAddReg] +HKR,,EnumPropPages32,,"MsPorts.dll,SerialPortPropPageProvider" + +[Strings] +ProviderName = "CDC Driver" +CopterControl = "OpenPilot CDC Driver" +PipXtreme = "OpenPilot CDC Driver" diff --git a/flight/RemoteSystemsTempFiles/.project b/flight/RemoteSystemsTempFiles/.project new file mode 100644 index 000000000..5447a64fa --- /dev/null +++ b/flight/RemoteSystemsTempFiles/.project @@ -0,0 +1,12 @@ + + + RemoteSystemsTempFiles + + + + + + + org.eclipse.rse.ui.remoteSystemsTempNature + + diff --git a/flight/SimPosix/Makefile b/flight/SimPosix/Makefile new file mode 100644 index 000000000..9c3a8cdcf --- /dev/null +++ b/flight/SimPosix/Makefile @@ -0,0 +1,511 @@ +##### +# Project: OpenPilot INS +# +# +# Makefile for OpenPilot INS project +# +# The OpenPilot Team, http://www.openpilot.org, Copyright (C) 2009. +# +# +# 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 +##### + +WHEREAMI := $(dir $(lastword $(MAKEFILE_LIST))) +TOP := $(realpath $(WHEREAMI)/../../) + +override TCHAIN_PREFIX := +override THUMB := +include $(TOP)/make/firmware-defs.mk +include $(TOP)/make/boards/$(BOARD_NAME)/board-info.mk + +# Target file name (without extension). +TARGET := fw_$(BOARD_NAME) + +# Directory for output files (lst, obj, dep, elf, sym, map, hex, bin etc.) +OUTDIR := $(TOP)/build/$(TARGET) + +# Set developer code and compile options +# Set to YES for debugging +DEBUG ?= NO + +# Set to YES when using Code Sourcery toolchain +CODE_SOURCERY ?= NO + +ifeq ($(CODE_SOURCERY), YES) +REMOVE_CMD = cs-rm +else +REMOVE_CMD = rm +endif + +FLASH_TOOL = OPENOCD + +# List of modules to include +MODULES = ManualControl Stabilization GPS +MODULES += CameraStab +MODULES += Telemetry +#MODULES += OveroSync +PYMODULES = +#FlightPlan + +# Paths +OPSYSTEM = ./System +OPSYSTEMINC = $(OPSYSTEM)/inc +OPUAVTALK = ../UAVTalk +OPUAVTALKINC = $(OPUAVTALK)/inc +OPUAVOBJ = ../UAVObjects +OPUAVOBJINC = $(OPUAVOBJ)/inc +PIOS = ../PiOS.posix +PIOSINC = $(PIOS)/inc +OPMODULEDIR = ../Modules +FLIGHTLIB = ../Libraries +FLIGHTLIBINC = ../Libraries/inc +PIOSPOSIX = $(PIOS)/posix +PIOSCOMMON = $(PIOS)/posix +PIOSBOARDS = $(PIOS)/Boards +PIOSCOMMONLIB = $(PIOSCOMMON)/Libraries +#APPLIBDIR = $(PIOSSTM32F4XX)/Libraries +OPUAVOBJ = ../UAVObjects +OPUAVOBJINC = $(OPUAVOBJ)/inc +BOOT = +BOOTINC = +PYMITE = $(FLIGHTLIB)/PyMite +PYMITELIB = $(PYMITE)/lib +PYMITEPLAT = $(PYMITE)/platform/openpilot +PYMITETOOLS = $(PYMITE)/tools +PYMITEVM = $(PYMITE)/vm +PYMITEINC = $(PYMITEVM) +PYMITEINC += $(PYMITEPLAT) +PYMITEINC += $(OUTDIR) +FLIGHTPLANLIB = $(OPMODULEDIR)/FlightPlan/lib +FLIGHTPLANS = $(OPMODULEDIR)/FlightPlan/flightplans +HWDEFSINC = ../board_hw_defs/$(BOARD_NAME) +UAVOBJSYNTHDIR = $(OUTDIR)/../uavobject-synthetics/flight + +SRC = +# optional component libraries +include $(PIOSCOMMONLIB)/FreeRTOS/library.mk +#include $(PIOSCOMMONLIB)/dosfs/library.mk +#include $(PIOSCOMMONLIB)/msheap/library.mk + + +# List C source files here. (C dependencies are automatically generated.) +# use file-extension c for "c-only"-files + +## PyMite files and modules +SRC += $(OUTDIR)/pmlib_img.c +SRC += $(OUTDIR)/pmlib_nat.c +SRC += $(OUTDIR)/pmlibusr_img.c +SRC += $(OUTDIR)/pmlibusr_nat.c +PYSRC += $(wildcard ${PYMITEVM}/*.c) +PYSRC += $(wildcard ${PYMITEPLAT}/*.c) +PYSRC += ${foreach MOD, ${PYMODULES}, ${wildcard ${OPMODULEDIR}/${MOD}/*.c}} +SRC += $(PYSRC) + +## MODULES +SRC += ${foreach MOD, ${MODULES}, ${wildcard ${OPMODULEDIR}/${MOD}/*.c}} +SRC += ${OUTDIR}/InitMods.c +## OPENPILOT CORE: +SRC += ${OPMODULEDIR}/System/systemmod.c +SRC += $(OPSYSTEM)/simposix.c +SRC += $(OPSYSTEM)/pios_board.c +SRC += $(OPSYSTEM)/alarms.c +SRC += $(OPUAVTALK)/uavtalk.c +SRC += $(OPUAVOBJ)/uavobjectmanager.c +SRC += $(OPUAVOBJ)/eventdispatcher.c +SRC += $(UAVOBJSYNTHDIR)/uavobjectsinit.c + +SRC += $(FLIGHTLIB)/CoordinateConversions.c +SRC += $(FLIGHTLIB)/fifo_buffer.c +SRC += $(FLIGHTLIB)/WorldMagModel.c +SRC += $(FLIGHTLIB)/insgps13state.c +SRC += $(FLIGHTLIB)/taskmonitor.c + +## PIOS Hardware (STM32F4xx) +include $(PIOS)/posix/library.mk + +## PIOS Hardware (Common) +#SRC += $(PIOSCOMMON)/pios_mpu6000.c +#SRC += $(PIOSCOMMON)/pios_bma180.c +#SRC += $(PIOSCOMMON)/pios_l3gd20.c +#SRC += $(PIOSCOMMON)/pios_hmc5883.c +#SRC += $(PIOSCOMMON)/pios_ms5611.c +#SRC += $(PIOSCOMMON)/pios_crc.c +#SRC += $(PIOSCOMMON)/pios_com.c +#SRC += $(PIOSCOMMON)/pios_rcvr.c +#SRC += $(PIOSCOMMON)/pios_flash_jedec.c +#SRC += $(PIOSCOMMON)/pios_flashfs_objlist.c +#SRC += $(PIOSCOMMON)/printf-stdarg.c +#SRC += $(PIOSCOMMON)/pios_usb_desc_hid_cdc.c +#SRC += $(PIOSCOMMON)/pios_usb_desc_hid_only.c + +include ./UAVObjects.inc +SRC += $(UAVOBJSRC) + +# 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 Assembler source files here. +# Make them always end in a capital .S. Files ending in a lowercase .s +# will not be considered source files but generated files (assembler +# output from the compiler), and will be deleted upon "make clean"! +# Even though the DOS/Win* filesystem matches both .s and .S the same, +# it will preserve the spelling of the filenames, and gcc itself does +# care about how the name is spelled on its command-line. + + +# List Assembler source files here which must be assembled in ARM-Mode.. +ASRCARM = + +# List any extra directories to look for include files here. +# Each directory must be seperated by a space. +EXTRAINCDIRS += $(PIOS) +EXTRAINCDIRS += $(PIOSINC) +EXTRAINCDIRS += $(OPSYSTEMINC) +EXTRAINCDIRS += $(OPUAVTALK) +EXTRAINCDIRS += $(OPUAVTALKINC) +EXTRAINCDIRS += $(OPUAVOBJ) +EXTRAINCDIRS += $(OPUAVOBJINC) +EXTRAINCDIRS += $(UAVOBJSYNTHDIR) +EXTRAINCDIRS += $(FLIGHTLIBINC) +#EXTRAINCDIRS += $(PIOSSTM32F4XX) +EXTRAINCDIRS += $(PIOSCOMMON) +EXTRAINCDIRS += $(PIOSBOARDS) +#EXTRAINCDIRS += $(STMSPDINCDIR) +EXTRAINCDIRS += $(CMSISDIR) +EXTRAINCDIRS += $(OPUAVSYNTHDIR) +EXTRAINCDIRS += $(BOOTINC) +EXTRAINCDIRS += $(PYMITEINC) +EXTRAINCDIRS += $(HWDEFSINC) + +# Generate intermediate code +gencode: ${OUTDIR}/pmlib_img.c ${OUTDIR}/pmlib_nat.c ${OUTDIR}/pmlibusr_img.c ${OUTDIR}/pmlibusr_nat.c ${OUTDIR}/pmfeatures.h + +$(PYSRC): gencode + +PYTHON = python + +# 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) + @echo $(MSG_PYMITEINIT) $(call toprel, $@) + @$(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) + @$(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 +EXTRAINCDIRS += ${foreach MOD, ${MODULES} ${PYMODULES}, $(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 = $(PIOSSTM32F4XX) + +# 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) +CFLAGS += -O0 +CFLAGS += -DGENERAL_COV +CFLAGS += -finstrument-functions -ffixed-r10 +else +CFLAGS += -Os +endif + + + +# common architecture-specific flags from the device-specific library makefile +CFLAGS += $(ARCHFLAGS) + +CFLAGS += $(UAVOBJDEFINE) +CFLAGS += -DDIAGNOSTICS +CFLAGS += -DDIAG_TASKS + +# This is not the best place for these. Really should abstract out +# to the board file or something +#CFLAGS += -DSTM32F4XX +CFLAGS += -DMEM_SIZE=1024000000 + +# 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. +CDEFS += -DHSE_VALUE=$(OSCILLATOR_FREQ) +CDEFS += -DSYSCLK_FREQ=$(SYSCLK_FREQ) +CDEFS += -DUSE_STDPERIPH_DRIVER +CDEFS += -DUSE_$(BOARD) + +# Place project-specific -D and/or -U options for +# Assembler with preprocessor here. +#ADEFS = -DUSE_IRQ_ASM_WRAPPER +ADEFS = -D__ASSEMBLY__ + +# 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++) + +CFLAGS += -g$(DEBUGF) + +CFLAGS += -ffast-math + +#CFLAGS += -mcpu=$(MCU) +CFLAGS += $(CDEFS) +CFLAGS += $(patsubst %,-I%,$(EXTRAINCDIRS)) -I. + +#CFLAGS += -mapcs-frame +CFLAGS += -fomit-frame-pointer +ifeq ($(CODE_SOURCERY), YES) +CFLAGS += -fpromote-loop-indices +endif + +CFLAGS += -Wall +#CFLAGS += -Werror +CFLAGS += -Wa,-adhlns=$(addprefix $(OUTDIR)/, $(notdir $(addsuffix .lst, $(basename $<)))) +# 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 = $(ARCHFLAGS) -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 = -nostartfiles -Wl,-Map=$(OUTDIR)/$(TARGET).map,--cref,--gc-sections +LDFLAGS = -Wl,-Map=$(OUTDIR)/$(TARGET).map,--cref,--gc-sections +LDFLAGS += $(patsubst %,-L%,$(EXTRA_LIBDIRS)) +LDFLAGS += -lc +LDFLAGS += $(patsubst %,-l%,$(EXTRA_LIBS)) +LDFLAGS += $(MATH_LIB) +LDFLAGS += -lc -lgcc -lpthread -lrt + +#Linker scripts +LDFLAGS += $(addprefix -T,$(LINKER_SCRIPTS_APP)) + + +# Define programs and commands. +REMOVE = $(REMOVE_CMD) -f +PYHON = python + +# 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))) + +# Default target. +all: gccversion build + +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 + + +# Link: create ELF output file from object files. +$(eval $(call LINK_TEMPLATE, $(OUTDIR)/$(TARGET).elf, $(ALLOBJ))) + +# Assemble: create object files from assembler source files. +$(foreach src, $(ASRC), $(eval $(call ASSEMBLE_TEMPLATE, $(src)))) + +# Assemble: create object files from assembler source files. ARM-only +$(foreach src, $(ASRCARM), $(eval $(call ASSEMBLE_ARM_TEMPLATE, $(src)))) + +# Compile: create object files from C source files. +$(foreach src, $(SRC), $(eval $(call COMPILE_C_TEMPLATE, $(src)))) + +# Compile: create object files from C source files. ARM-only +$(foreach src, $(SRCARM), $(eval $(call COMPILE_C_ARM_TEMPLATE, $(src)))) + +# Compile: create object files from C++ source files. +$(foreach src, $(CPPSRC), $(eval $(call COMPILE_CPP_TEMPLATE, $(src)))) + +# Compile: create object files from C++ source files. ARM-only +$(foreach src, $(CPPSRCARM), $(eval $(call COMPILE_CPP_ARM_TEMPLATE, $(src)))) + +# Compile: create assembler files from C source files. ARM/Thumb +$(eval $(call PARTIAL_COMPILE_TEMPLATE, SRC)) + +# Compile: create assembler files from C source files. ARM only +$(eval $(call PARTIAL_COMPILE_ARM_TEMPLATE, SRCARM)) + +$(OUTDIR)/$(TARGET).bin.o: $(OUTDIR)/$(TARGET).bin + +$(eval $(call OPFW_TEMPLATE,$(OUTDIR)/$(TARGET).bin,$(BOARD_TYPE),$(BOARD_REVISION))) + +# Add jtag targets (program and wipe) +$(eval $(call JTAG_TEMPLATE,$(OUTDIR)/$(TARGET).bin,$(FW_BANK_BASE),$(FW_BANK_SIZE),$(OPENOCD_JTAG_CONFIG),$(OPENOCD_CONFIG))) + +.PHONY: elf lss sym hex bin bino opfw +elf: $(OUTDIR)/$(TARGET).elf +lss: $(OUTDIR)/$(TARGET).lss +sym: $(OUTDIR)/$(TARGET).sym +hex: $(OUTDIR)/$(TARGET).hex +bin: $(OUTDIR)/$(TARGET).bin +bino: $(OUTDIR)/$(TARGET).bin.o +opfw: $(OUTDIR)/$(TARGET).opfw + +# Display sizes of sections. +$(eval $(call SIZE_TEMPLATE, $(OUTDIR)/$(TARGET).elf)) + +# Generate Doxygen documents +docs: + doxygen $(DOXYGENDIR)/doxygen.cfg + +# Install: install binary file with prefix/suffix into install directory +install: $(OUTDIR)/$(TARGET).opfw +ifneq ($(INSTALL_DIR),) + @echo $(MSG_INSTALLING) $(call toprel, $<) + $(V1) mkdir -p $(INSTALL_DIR) + $(V1) $(INSTALL) $< $(INSTALL_DIR)/$(INSTALL_PFX)$(TARGET)$(INSTALL_SFX).opfw +else + $(error INSTALL_DIR must be specified for $@) +endif + +# Target: clean project. +clean: clean_list + +clean_list : + @echo $(MSG_CLEANING) + $(V1) $(REMOVE) $(OUTDIR)/$(TARGET).map + $(V1) $(REMOVE) $(OUTDIR)/$(TARGET).elf + $(V1) $(REMOVE) $(OUTDIR)/$(TARGET).hex + $(V1) $(REMOVE) $(OUTDIR)/$(TARGET).bin + $(V1) $(REMOVE) $(OUTDIR)/$(TARGET).sym + $(V1) $(REMOVE) $(OUTDIR)/$(TARGET).lss + $(V1) $(REMOVE) $(OUTDIR)/$(TARGET).bin.o + $(V1) $(REMOVE) $(ALLOBJ) + $(V1) $(REMOVE) $(LSTFILES) + $(V1) $(REMOVE) $(DEPFILES) + $(V1) $(REMOVE) $(SRC:.c=.s) + $(V1) $(REMOVE) $(SRCARM:.c=.s) + $(V1) $(REMOVE) $(CPPSRC:.cpp=.s) + $(V1) $(REMOVE) $(CPPSRCARM:.cpp=.s) + +# Create output files directory +# all known MS Windows OS define the ComSpec environment variable +ifdef ComSpec +$(shell md $(subst /,\\,$(OUTDIR)) 2>NUL) +else +$(shell mkdir -p $(OUTDIR) 2>/dev/null) +endif + +# Include the dependency files. +ifdef ComSpec +-include $(shell md $(subst /,\\,$(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 + +#create compile-time module auto-initialisation +MODNAMES = ${notdir $(subst /revolution,,$(MODULES))} + +# 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 + @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 + +# Listing of phony targets. +.PHONY : all build clean clean_list install diff --git a/flight/SimPosix/System/alarms.c b/flight/SimPosix/System/alarms.c new file mode 100644 index 000000000..6ccd5fb62 --- /dev/null +++ b/flight/SimPosix/System/alarms.c @@ -0,0 +1,210 @@ +/** + ****************************************************************************** + * @addtogroup OpenPilotSystem OpenPilot System + * @{ + * @addtogroup OpenPilotLibraries OpenPilot System Libraries + * @brief OpenPilot System libraries are available to all OP modules. + * @{ + * @file alarms.c + * @author The OpenPilot Team, http://www.openpilot.org Copyright (C) 2010. + * @brief Library for setting and clearing system alarms + * @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 "openpilot.h" +#include "alarms.h" + +// Private constants + +// Private types + +// Private variables +static xSemaphoreHandle lock; + +// Private functions +static int32_t hasSeverity(SystemAlarmsAlarmOptions severity); + +/** + * Initialize the alarms library + */ +int32_t AlarmsInitialize(void) +{ + SystemAlarmsInitialize(); + lock = xSemaphoreCreateRecursiveMutex(); + return 0; +} + +/** + * Set an alarm + * @param alarm The system alarm to be modified + * @param severity The alarm severity + * @return 0 if success, -1 if an error + */ +int32_t AlarmsSet(SystemAlarmsAlarmElem alarm, SystemAlarmsAlarmOptions severity) +{ + SystemAlarmsData alarms; + + // Check that this is a valid alarm + if (alarm >= SYSTEMALARMS_ALARM_NUMELEM) + { + return -1; + } + + // Lock + xSemaphoreTakeRecursive(lock, portMAX_DELAY); + + // Read alarm and update its severity only if it was changed + SystemAlarmsGet(&alarms); + if ( alarms.Alarm[alarm] != severity ) + { + alarms.Alarm[alarm] = severity; + SystemAlarmsSet(&alarms); + } + + // Release lock + xSemaphoreGiveRecursive(lock); + return 0; + +} + +/** + * Get an alarm + * @param alarm The system alarm to be read + * @return Alarm severity + */ +SystemAlarmsAlarmOptions AlarmsGet(SystemAlarmsAlarmElem alarm) +{ + SystemAlarmsData alarms; + + // Check that this is a valid alarm + if (alarm >= SYSTEMALARMS_ALARM_NUMELEM) + { + return 0; + } + + // Read alarm + SystemAlarmsGet(&alarms); + return alarms.Alarm[alarm]; +} + +/** + * Set an alarm to it's default value + * @param alarm The system alarm to be modified + * @return 0 if success, -1 if an error + */ +int32_t AlarmsDefault(SystemAlarmsAlarmElem alarm) +{ + return AlarmsSet(alarm, SYSTEMALARMS_ALARM_DEFAULT); +} + +/** + * Default all alarms + */ +void AlarmsDefaultAll() +{ + uint32_t n; + for (n = 0; n < SYSTEMALARMS_ALARM_NUMELEM; ++n) + { + AlarmsDefault(n); + } +} + +/** + * Clear an alarm + * @param alarm The system alarm to be modified + * @return 0 if success, -1 if an error + */ +int32_t AlarmsClear(SystemAlarmsAlarmElem alarm) +{ + return AlarmsSet(alarm, SYSTEMALARMS_ALARM_OK); +} + +/** + * Clear all alarms + */ +void AlarmsClearAll() +{ + uint32_t n; + for (n = 0; n < SYSTEMALARMS_ALARM_NUMELEM; ++n) + { + AlarmsClear(n); + } +} + +/** + * Check if there are any alarms with the given or higher severity + * @return 0 if no alarms are found, 1 if at least one alarm is found + */ +int32_t AlarmsHasWarnings() +{ + return hasSeverity(SYSTEMALARMS_ALARM_WARNING); +} + +/** + * Check if there are any alarms with error or higher severity + * @return 0 if no alarms are found, 1 if at least one alarm is found + */ +int32_t AlarmsHasErrors() +{ + return hasSeverity(SYSTEMALARMS_ALARM_ERROR); +}; + +/** + * Check if there are any alarms with critical or higher severity + * @return 0 if no alarms are found, 1 if at least one alarm is found + */ +int32_t AlarmsHasCritical() +{ + return hasSeverity(SYSTEMALARMS_ALARM_CRITICAL); +}; + +/** + * Check if there are any alarms with the given or higher severity + * @return 0 if no alarms are found, 1 if at least one alarm is found + */ +static int32_t hasSeverity(SystemAlarmsAlarmOptions severity) +{ + SystemAlarmsData alarms; + uint32_t n; + + // Lock + xSemaphoreTakeRecursive(lock, portMAX_DELAY); + + // Read alarms + SystemAlarmsGet(&alarms); + + // Go through alarms and check if any are of the given severity or higher + for (n = 0; n < SYSTEMALARMS_ALARM_NUMELEM; ++n) + { + if ( alarms.Alarm[n] >= severity) + { + xSemaphoreGiveRecursive(lock); + return 1; + } + } + + // If this point is reached then no alarms found + xSemaphoreGiveRecursive(lock); + return 0; +} +/** + * @} + * @} + */ + diff --git a/flight/SimPosix/System/inc/FreeRTOSConfig.h b/flight/SimPosix/System/inc/FreeRTOSConfig.h new file mode 100644 index 000000000..72d6e288a --- /dev/null +++ b/flight/SimPosix/System/inc/FreeRTOSConfig.h @@ -0,0 +1,103 @@ + +#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. + *----------------------------------------------------------*/ + +/** + * @addtogroup PIOS PIOS + * @{ + * @addtogroup FreeRTOS FreeRTOS + * @{ + */ + +/* Notes: We use 5 task priorities */ + +#define configCPU_CLOCK_HZ (SYSCLK_FREQ) // really the NVIC clock ... +#define configTICK_RATE_HZ ((portTickType )1000) +#define configMAX_PRIORITIES ((unsigned portBASE_TYPE)5) +#define configMINIMAL_STACK_SIZE ((unsigned short)512) +#define configTOTAL_HEAP_SIZE ((size_t)(180 * 1024)) // this is minimum, not total +#define configMAX_TASK_NAME_LEN (16) + +#define configUSE_PREEMPTION 1 +#define configUSE_IDLE_HOOK 1 +#define configUSE_TICK_HOOK 0 +#define configUSE_TRACE_FACILITY 0 +#define configUSE_16_BIT_TICKS 0 +#define configIDLE_SHOULD_YIELD 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 + +#define configUSE_TIMERS 1 +#define configTIMER_TASK_PRIORITY (configMAX_PRIORITIES - 1) /* run timers at max priority */ +#define configTIMER_QUEUE_LENGTH 10 +#define configTIMER_TASK_STACK_DEPTH configMINIMAL_STACK_SIZE + +/* 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 1 +#define INCLUDE_vTaskSuspend 1 +#define INCLUDE_vTaskDelayUntil 1 +#define INCLUDE_vTaskDelay 1 +#define INCLUDE_xTaskGetSchedulerState 1 +#define INCLUDE_xTaskGetCurrentTaskHandle 1 +#define INCLUDE_uxTaskGetStackHighWaterMark 1 + +/* 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 + +/* Enable run time stats collection */ +#define configGENERATE_RUN_TIME_STATS 1 +#define INCLUDE_uxTaskGetRunTime 1 + +/* + * Once we move to CMSIS2 we can at least use: + * + * CoreDebug->DEMCR |= CoreDebug_DEMCR_TRCENA_Msk; + * + * (still nothing for the DWT registers, surprisingly) + */ +#define portCONFIGURE_TIMER_FOR_RUN_TIME_STATS() \ + do { \ + (*(unsigned long *)0xe000edfc) |= (1<<24); /* DEMCR |= DEMCR_TRCENA */ \ + (*(unsigned long *)0xe0001000) |= 1; /* DWT_CTRL |= DWT_CYCCNT_ENA */ \ + } while(0) +#define portGET_RUN_TIME_COUNTER_VALUE() (*(unsigned long *)0xe0001004) /* DWT_CYCCNT */ + + +/** + * @} + */ + +#endif /* FREERTOS_CONFIG_H */ diff --git a/flight/SimPosix/System/inc/alarms.h b/flight/SimPosix/System/inc/alarms.h new file mode 100644 index 000000000..0f0faeb8f --- /dev/null +++ b/flight/SimPosix/System/inc/alarms.h @@ -0,0 +1,50 @@ +/** + ****************************************************************************** + * @addtogroup OpenPilotSystem OpenPilot System + * @{ + * @addtogroup OpenPilotLibraries OpenPilot System Libraries + * @{ + * @file alarms.h + * @author The OpenPilot Team, http://www.openpilot.org Copyright (C) 2010. + * @brief Include file of the alarm library + * @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 ALARMS_H +#define ALARMS_H + +#include "systemalarms.h" +#define SYSTEMALARMS_ALARM_DEFAULT SYSTEMALARMS_ALARM_UNINITIALISED + +int32_t AlarmsInitialize(void); +int32_t AlarmsSet(SystemAlarmsAlarmElem alarm, SystemAlarmsAlarmOptions severity); +SystemAlarmsAlarmOptions AlarmsGet(SystemAlarmsAlarmElem alarm); +int32_t AlarmsDefault(SystemAlarmsAlarmElem alarm); +void AlarmsDefaultAll(); +int32_t AlarmsClear(SystemAlarmsAlarmElem alarm); +void AlarmsClearAll(); +int32_t AlarmsHasWarnings(); +int32_t AlarmsHasErrors(); +int32_t AlarmsHasCritical(); + +#endif // ALARMS_H + +/** + * @} + * @} + */ diff --git a/flight/SimPosix/System/inc/dcc_stdio.h b/flight/SimPosix/System/inc/dcc_stdio.h new file mode 100644 index 000000000..dbfd39342 --- /dev/null +++ b/flight/SimPosix/System/inc/dcc_stdio.h @@ -0,0 +1,36 @@ +/*************************************************************************** + * Copyright (C) 2008 by Dominic Rath * + * Dominic.Rath@gmx.de * + * Copyright (C) 2008 by Spencer Oliver * + * spen@spen-soft.co.uk * + * * + * 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 DCC_STDIO_H +#define DCC_STDIO_H + +void dbg_trace_point(unsigned long number); + +void dbg_write_u32(const unsigned long *val, long len); +void dbg_write_u16(const unsigned short *val, long len); +void dbg_write_u8(const unsigned char *val, long len); + +void dbg_write_str(const char *msg); +void dbg_write_char(char msg); +void dbg_write_hex32(const unsigned long val); + +#endif /* DCC_STDIO_H */ diff --git a/flight/SimPosix/System/inc/op_config.h b/flight/SimPosix/System/inc/op_config.h new file mode 100644 index 000000000..0fe9e2bdc --- /dev/null +++ b/flight/SimPosix/System/inc/op_config.h @@ -0,0 +1,39 @@ +/** + ****************************************************************************** + * @addtogroup OpenPilotSystem OpenPilot System + * @{ + * @addtogroup OpenPilotCore OpenPilot Core + * @{ + * + * @file op_config.h + * @author The OpenPilot Team, http://www.openpilot.org Copyright (C) 2010. + * @brief OpenPilot configuration header. + * Compile time config for OpenPilot Application + * @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 OP_CONFIG_H +#define OP_CONFIG_H + +#endif /* OP_CONFIG_H */ +/** + * @} + * @} + */ diff --git a/flight/SimPosix/System/inc/openpilot.h b/flight/SimPosix/System/inc/openpilot.h new file mode 100644 index 000000000..0bbdf971b --- /dev/null +++ b/flight/SimPosix/System/inc/openpilot.h @@ -0,0 +1,53 @@ +/** + ****************************************************************************** + * @addtogroup OpenPilotSystem OpenPilot System + * @{ + * @addtogroup OpenPilotCore OpenPilot Core + * @{ + * @file openpilot.h + * @author The OpenPilot Team, http://www.openpilot.org Copyright (C) 2010. + * @brief Main OpenPilot 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 OPENPILOT_H +#define OPENPILOT_H + + +/* PIOS Includes */ +#include + +/* OpenPilot Libraries */ +#include "op_config.h" +#include "utlist.h" +#include "uavobjectmanager.h" +#include "eventdispatcher.h" +#include "alarms.h" +#include "taskmonitor.h" +#include "uavtalk.h" + +/* Global Functions */ +void OpenPilotInit(void); + +#endif /* OPENPILOT_H */ +/** + * @} + * @} + */ diff --git a/flight/SimPosix/System/inc/pios_config.h b/flight/SimPosix/System/inc/pios_config.h new file mode 100644 index 000000000..d4add3666 --- /dev/null +++ b/flight/SimPosix/System/inc/pios_config.h @@ -0,0 +1,120 @@ +/** + ****************************************************************************** + * @addtogroup OpenPilotSystem OpenPilot System + * @{ + * @addtogroup OpenPilotCore OpenPilot Core + * @{ + * + * @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. + * In particular, pios_config.h is where you define which PiOS libraries + * and features are included in the firmware. + * @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_H +#define PIOS_CONFIG_H + +/* Major features */ +#define PIOS_INCLUDE_FREERTOS +#define PIOS_INCLUDE_BL_HELPER + +/* Enable/Disable PiOS Modules */ +//#define PIOS_INCLUDE_ADC +#define PIOS_INCLUDE_DELAY +//#define PIOS_INCLUDE_I2C +#define PIOS_INCLUDE_IRQ +#define PIOS_INCLUDE_LED +#define PIOS_INCLUDE_SDCARD +//#define PIOS_INCLUDE_IAP +#define PIOS_INCLUDE_SERVO +#define PIOS_INCLUDE_SPI +#define PIOS_INCLUDE_SYS +#define PIOS_INCLUDE_USART +//#define PIOS_INCLUDE_USB +#define PIOS_INCLUDE_USB_HID +//#define PIOS_INCLUDE_GPIO +#define PIOS_INCLUDE_EXTI +#define PIOS_INCLUDE_RTC +#define PIOS_INCLUDE_WDG +#define PIOS_INCLUDE_UDP + +/* Select the sensors to include */ +//#define PIOS_INCLUDE_BMA180 +//#define PIOS_INCLUDE_HMC5883 +//#define PIOS_INCLUDE_MPU6000 +//#define PIOS_MPU6000_ACCEL +//#define PIOS_INCLUDE_L3GD20 +//#define PIOS_INCLUDE_MS5611 +//#define PIOS_INCLUDE_HCSR04 +#define PIOS_FLASH_ON_ACCEL /* true for second revo */ +#define FLASH_FREERTOS +/* Com systems to include */ +#define PIOS_INCLUDE_COM +#define PIOS_INCLUDE_COM_TELEM +#define PIOS_INCLUDE_COM_AUX +#define PIOS_INCLUDE_COM_AUXSBUS +#define PIOS_INCLUDE_COM_FLEXI + +#define PIOS_INCLUDE_GPS +#define PIOS_OVERO_SPI +/* Supported receiver interfaces */ +#define PIOS_INCLUDE_RCVR +#define PIOS_INCLUDE_DSM +//#define PIOS_INCLUDE_SBUS +#define PIOS_INCLUDE_PPM +#define PIOS_INCLUDE_PWM +//#define PIOS_INCLUDE_GCSRCVR + +#define PIOS_INCLUDE_SETTINGS +#define PIOS_INCLUDE_FLASH +/* A really shitty setting saving implementation */ +//#define PIOS_INCLUDE_FLASH_SECTOR_SETTINGS + +/* Other Interfaces */ +//#define PIOS_INCLUDE_I2C_ESC + +/* Flags that alter behaviors - mostly to lower resources for CC */ +#define PIOS_INCLUDE_INITCALL /* Include init call structures */ +#define PIOS_TELEM_PRIORITY_QUEUE /* Enable a priority queue in telemetry */ +#define PIOS_QUATERNION_STABILIZATION /* Stabilization options */ +//#define PIOS_GPS_SETS_HOMELOCATION /* GPS options */ + +/* Alarm Thresholds */ +#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 + +// This actually needs calibrating +#define IDLE_COUNTS_PER_SEC_AT_NO_LOAD (8379692) + +#define REVOLUTION +#define SIMPOSIX + +#endif /* PIOS_CONFIG_H */ +/** + * @} + * @} + */ diff --git a/flight/SimPosix/System/pios_board.c b/flight/SimPosix/System/pios_board.c new file mode 100644 index 000000000..45b078120 --- /dev/null +++ b/flight/SimPosix/System/pios_board.c @@ -0,0 +1,187 @@ +/** + ****************************************************************************** + * @addtogroup Revolution Revolution configuration files + * @{ + * @brief Configures the revolution board + * @{ + * + * @file pios_board.c + * @author The OpenPilot Team, http://www.openpilot.org Copyright (C) 2011. + * @brief Defines board specific static initializers for hardware for the Revolution 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 + +#include +#include +#include "hwsettings.h" +#include "manualcontrolsettings.h" + +#include "board_hw_defs.c" + +/** + * Sensor configurations + */ + +/* One slot per selectable receiver group. + * eg. PWM, PPM, GCS, SPEKTRUM1, SPEKTRUM2, SBUS + * NOTE: No slot in this map for NONE. + */ +uint32_t pios_rcvr_group_map[MANUALCONTROLSETTINGS_CHANNELGROUPS_NONE]; + +#define PIOS_COM_TELEM_RF_RX_BUF_LEN 512 +#define PIOS_COM_TELEM_RF_TX_BUF_LEN 512 + +#define PIOS_COM_GPS_RX_BUF_LEN 32 + +#define PIOS_COM_TELEM_USB_RX_BUF_LEN 65 +#define PIOS_COM_TELEM_USB_TX_BUF_LEN 65 + +#define PIOS_COM_BRIDGE_RX_BUF_LEN 65 +#define PIOS_COM_BRIDGE_TX_BUF_LEN 12 + +#define PIOS_COM_AUX_RX_BUF_LEN 512 +#define PIOS_COM_AUX_TX_BUF_LEN 512 + +uint32_t pios_com_aux_id = 0; +uint32_t pios_com_gps_id = 0; +uint32_t pios_com_telem_usb_id = 0; +uint32_t pios_com_telem_rf_id = 0; +uint32_t pios_com_bridge_id = 0; + +/* + * Setup a com port based on the passed cfg, driver and buffer sizes. tx size of -1 make the port rx only + */ +static void PIOS_Board_configure_com(const struct pios_udp_cfg *usart_port_cfg, size_t rx_buf_len, size_t tx_buf_len, + const struct pios_com_driver *com_driver, uint32_t *pios_com_id) +{ + uint32_t pios_usart_id; + if (PIOS_UDP_Init(&pios_usart_id, usart_port_cfg)) { + PIOS_Assert(0); + } + + uint8_t * rx_buffer = (uint8_t *) pvPortMalloc(rx_buf_len); + PIOS_Assert(rx_buffer); + if(tx_buf_len!= -1){ // this is the case for rx/tx ports + uint8_t * tx_buffer = (uint8_t *) pvPortMalloc(tx_buf_len); + PIOS_Assert(tx_buffer); + + if (PIOS_COM_Init(pios_com_id, com_driver, pios_usart_id, + rx_buffer, rx_buf_len, + tx_buffer, tx_buf_len)) { + PIOS_Assert(0); + } + } + else{ //rx only port + if (PIOS_COM_Init(pios_com_id, com_driver, pios_usart_id, + rx_buffer, rx_buf_len, + NULL, 0)) { + PIOS_Assert(0); + } + } +} + +/** + * PIOS_Board_Init() + * initializes all the core subsystems on this specific hardware + * called from System/openpilot.c + */ +void PIOS_Board_Init(void) { + + /* Delay system */ + PIOS_DELAY_Init(); + + /* Initialize UAVObject libraries */ + EventDispatcherInitialize(); + UAVObjInitialize(); + + HwSettingsInitialize(); + + UAVObjectsInitializeAll(); + + /* Initialize the alarms library */ + AlarmsInitialize(); + + /* Initialize the task monitor library */ + TaskMonitorInitialize(); + + /* Configure IO ports */ + + /* Configure Telemetry port */ + uint8_t hwsettings_rv_telemetryport; + HwSettingsRV_TelemetryPortGet(&hwsettings_rv_telemetryport); + + switch (hwsettings_rv_telemetryport){ + case HWSETTINGS_RV_TELEMETRYPORT_DISABLED: + break; + case HWSETTINGS_RV_TELEMETRYPORT_TELEMETRY: + PIOS_Board_configure_com(&pios_udp_telem_cfg, PIOS_COM_TELEM_RF_RX_BUF_LEN, PIOS_COM_TELEM_RF_TX_BUF_LEN, &pios_udp_com_driver, &pios_com_telem_rf_id); + break; + case HWSETTINGS_RV_TELEMETRYPORT_COMAUX: + PIOS_Board_configure_com(&pios_udp_telem_cfg, PIOS_COM_AUX_RX_BUF_LEN, PIOS_COM_AUX_TX_BUF_LEN, &pios_udp_com_driver, &pios_com_aux_id); + break; + + } /* hwsettings_rv_telemetryport */ + + /* Configure GPS port */ + uint8_t hwsettings_rv_gpsport; + HwSettingsRV_GPSPortGet(&hwsettings_rv_gpsport); + switch (hwsettings_rv_gpsport){ + case HWSETTINGS_RV_GPSPORT_DISABLED: + break; + + case HWSETTINGS_RV_GPSPORT_TELEMETRY: + PIOS_Board_configure_com(&pios_udp_gps_cfg, PIOS_COM_TELEM_RF_RX_BUF_LEN, PIOS_COM_TELEM_RF_TX_BUF_LEN, &pios_udp_com_driver, &pios_com_telem_rf_id); + break; + + case HWSETTINGS_RV_GPSPORT_GPS: + PIOS_Board_configure_com(&pios_udp_gps_cfg, PIOS_COM_GPS_RX_BUF_LEN, -1, &pios_udp_com_driver, &pios_com_gps_id); + break; + + case HWSETTINGS_RV_GPSPORT_COMAUX: + PIOS_Board_configure_com(&pios_udp_gps_cfg, PIOS_COM_AUX_RX_BUF_LEN, PIOS_COM_AUX_TX_BUF_LEN, &pios_udp_com_driver, &pios_com_aux_id); + break; + + }/* hwsettings_rv_gpsport */ + + /* Configure AUXPort */ + uint8_t hwsettings_rv_auxport; + HwSettingsRV_AuxPortGet(&hwsettings_rv_auxport); + + switch (hwsettings_rv_auxport) { + case HWSETTINGS_RV_AUXPORT_DISABLED: + break; + + case HWSETTINGS_RV_AUXPORT_TELEMETRY: + PIOS_Board_configure_com(&pios_udp_aux_cfg, PIOS_COM_TELEM_RF_RX_BUF_LEN, PIOS_COM_TELEM_RF_TX_BUF_LEN, &pios_udp_com_driver, &pios_com_telem_rf_id); + break; + + case HWSETTINGS_RV_AUXPORT_COMAUX: + PIOS_Board_configure_com(&pios_udp_aux_cfg, PIOS_COM_AUX_RX_BUF_LEN, PIOS_COM_AUX_TX_BUF_LEN, &pios_udp_com_driver, &pios_com_aux_id); + break; + break; + } /* hwsettings_rv_auxport */ +} + +/** + * @} + * @} + */ + diff --git a/flight/SimPosix/System/simposix.c b/flight/SimPosix/System/simposix.c new file mode 100644 index 000000000..1863b81c7 --- /dev/null +++ b/flight/SimPosix/System/simposix.c @@ -0,0 +1,142 @@ +/** + ****************************************************************************** + * @addtogroup OpenPilotSystem OpenPilot System + * @brief These files are the core system files of OpenPilot. + * They are the ground layer just above PiOS. In practice, OpenPilot actually starts + * in the main() function of openpilot.c + * @{ + * @addtogroup OpenPilotCore OpenPilot Core + * @brief This is where the OP firmware starts. Those files also define the compile-time + * options of the firmware. + * @{ + * @file openpilot.c + * @author The OpenPilot Team, http://www.openpilot.org Copyright (C) 2010. + * @brief Sets up and runs main OpenPilot tasks. + * @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 + */ + + +/* OpenPilot Includes */ +#include "openpilot.h" +#include "uavobjectsinit.h" +#include "systemmod.h" + +/* Task Priorities */ +#define PRIORITY_TASK_HOOKS (tskIDLE_PRIORITY + 3) + +/* Global Variables */ + +/* Local Variables */ +#define INCLUDE_TEST_TASKS 0 +#if INCLUDE_TEST_TASKS +static uint8_t sdcard_available; +#endif +FILEINFO File; +char Buffer[1024]; +uint32_t Cache; + +/* Function Prototypes */ +#if INCLUDE_TEST_TASKS +static void TaskTick(void *pvParameters); +static void TaskTesting(void *pvParameters); +static void TaskHIDTest(void *pvParameters); +static void TaskServos(void *pvParameters); +static void TaskSDCard(void *pvParameters); +#endif +int32_t CONSOLE_Parse(uint8_t port, char c); +void OP_ADC_NotifyChange(uint32_t pin, uint32_t pin_value); + +/* Prototype of PIOS_Board_Init() function */ +extern void PIOS_Board_Init(void); +extern void Stack_Change(void); +static void Stack_Change_Weak () __attribute__ ((weakref ("Stack_Change"))); + +/* Local Variables */ +#define INIT_TASK_PRIORITY (tskIDLE_PRIORITY + configMAX_PRIORITIES - 1) // max priority +#define INIT_TASK_STACK (1024 / 4) // XXX this seems excessive +static xTaskHandle initTaskHandle; + +/* Function Prototypes */ +static void initTask(void *parameters); + +/* Prototype of generated InitModules() function */ +extern void InitModules(void); + +/** +* OpenPilot Main function: +* +* Initialize PiOS
+* Create the "System" task (SystemModInitializein Modules/System/systemmod.c)
+* Start FreeRTOS Scheduler (vTaskStartScheduler)
+* If something goes wrong, blink LED1 and LED2 every 100ms +* +*/ +int main() +{ + int result; + + /* NOTE: Do NOT modify the following start-up sequence */ + /* Any new initialization functions should be added in OpenPilotInit() */ + + /* Brings up System using CMSIS functions, enables the LEDs. */ + PIOS_SYS_Init(); + + /* For Revolution we use a FreeRTOS task to bring up the system so we can */ + /* always rely on FreeRTOS primitive */ + result = xTaskCreate(initTask, (const signed char *)"init", + INIT_TASK_STACK, NULL, INIT_TASK_PRIORITY, + &initTaskHandle); + PIOS_Assert(result == pdPASS); + + /* Start the FreeRTOS scheduler */ + vTaskStartScheduler(); + + /* If all is well we will never reach here as the scheduler will now be running. */ + /* Do some PIOS_LED_HEARTBEAT to user that something bad just happened */ + PIOS_LED_Off(PIOS_LED_HEARTBEAT); \ + for(;;) { \ + PIOS_LED_Toggle(PIOS_LED_HEARTBEAT); \ + PIOS_DELAY_WaitmS(100); \ + }; + + return 0; +} +/** + * Initialisation task. + * + * Runs board and module initialisation, then terminates. + */ +void +initTask(void *parameters) +{ + /* board driver init */ + PIOS_Board_Init(); + + /* Initialize modules */ + MODULE_INITIALISE_ALL; + + /* terminate this task */ + vTaskDelete(NULL); +} + +/** + * @} + * @} + */ + diff --git a/flight/SimPosix/UAVObjects.inc b/flight/SimPosix/UAVObjects.inc new file mode 100644 index 000000000..d91eb9c17 --- /dev/null +++ b/flight/SimPosix/UAVObjects.inc @@ -0,0 +1,83 @@ +##### +# Project: OpenPilot +# +# Makefile for OpenPilot UAVObject code +# +# The OpenPilot Team, http://www.openpilot.org, Copyright (C) 2011. +# +# 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 +##### + +# These are the UAVObjects supposed to be build as part of the OpenPilot target +# (all architectures) + +UAVOBJSRCFILENAMES = +UAVOBJSRCFILENAMES += accessorydesired +UAVOBJSRCFILENAMES += actuatorcommand +UAVOBJSRCFILENAMES += actuatordesired +UAVOBJSRCFILENAMES += actuatorsettings +UAVOBJSRCFILENAMES += altholdsmoothed +UAVOBJSRCFILENAMES += attitudesettings +UAVOBJSRCFILENAMES += attitudeactual +UAVOBJSRCFILENAMES += gyros +UAVOBJSRCFILENAMES += gyrosbias +UAVOBJSRCFILENAMES += accels +UAVOBJSRCFILENAMES += magnetometer +UAVOBJSRCFILENAMES += baroaltitude +UAVOBJSRCFILENAMES += flightbatterysettings +UAVOBJSRCFILENAMES += firmwareiapobj +UAVOBJSRCFILENAMES += flightbatterystate +UAVOBJSRCFILENAMES += flightplancontrol +UAVOBJSRCFILENAMES += flightplansettings +UAVOBJSRCFILENAMES += flightplanstatus +UAVOBJSRCFILENAMES += flighttelemetrystats +UAVOBJSRCFILENAMES += gcstelemetrystats +UAVOBJSRCFILENAMES += gpsposition +UAVOBJSRCFILENAMES += gpssatellites +UAVOBJSRCFILENAMES += gpstime +UAVOBJSRCFILENAMES += guidancesettings +UAVOBJSRCFILENAMES += homelocation +UAVOBJSRCFILENAMES += i2cstats +UAVOBJSRCFILENAMES += manualcontrolcommand +UAVOBJSRCFILENAMES += manualcontrolsettings +UAVOBJSRCFILENAMES += mixersettings +UAVOBJSRCFILENAMES += mixerstatus +UAVOBJSRCFILENAMES += nedaccel +UAVOBJSRCFILENAMES += objectpersistence +UAVOBJSRCFILENAMES += overosyncstats +UAVOBJSRCFILENAMES += positionactual +UAVOBJSRCFILENAMES += positiondesired +UAVOBJSRCFILENAMES += ratedesired +UAVOBJSRCFILENAMES += revocalibration +UAVOBJSRCFILENAMES += sonaraltitude +UAVOBJSRCFILENAMES += stabilizationdesired +UAVOBJSRCFILENAMES += stabilizationsettings +UAVOBJSRCFILENAMES += systemalarms +UAVOBJSRCFILENAMES += systemsettings +UAVOBJSRCFILENAMES += systemstats +UAVOBJSRCFILENAMES += taskinfo +UAVOBJSRCFILENAMES += velocityactual +UAVOBJSRCFILENAMES += velocitydesired +UAVOBJSRCFILENAMES += watchdogstatus +UAVOBJSRCFILENAMES += flightstatus +UAVOBJSRCFILENAMES += hwsettings +UAVOBJSRCFILENAMES += receiveractivity +UAVOBJSRCFILENAMES += cameradesired +UAVOBJSRCFILENAMES += camerastabsettings +UAVOBJSRCFILENAMES += altitudeholdsettings +UAVOBJSRCFILENAMES += altitudeholddesired + +UAVOBJSRC = $(foreach UAVOBJSRCFILE,$(UAVOBJSRCFILENAMES),$(UAVOBJSYNTHDIR)/$(UAVOBJSRCFILE).c ) +UAVOBJDEFINE = $(foreach UAVOBJSRCFILE,$(UAVOBJSRCFILENAMES),-DUAVOBJ_INIT_$(UAVOBJSRCFILE) ) diff --git a/flight/UAVObjects/uavobjectsinittemplate.c b/flight/UAVObjects/uavobjectsinittemplate.c index 97a1525a4..75a104d18 100644 --- a/flight/UAVObjects/uavobjectsinittemplate.c +++ b/flight/UAVObjects/uavobjectsinittemplate.c @@ -36,7 +36,5 @@ $(OBJINC) */ void UAVObjectsInitializeAll() { -return; -// This function is no longer used anyway $(OBJINIT) } diff --git a/flight/UAVTalk/inc/uavtalk.h b/flight/UAVTalk/inc/uavtalk.h index 3b7f2a2f9..a45fdb0db 100644 --- a/flight/UAVTalk/inc/uavtalk.h +++ b/flight/UAVTalk/inc/uavtalk.h @@ -45,13 +45,18 @@ typedef struct { typedef void* UAVTalkConnection; +typedef enum {UAVTALK_STATE_ERROR=0, UAVTALK_STATE_SYNC, UAVTALK_STATE_TYPE, UAVTALK_STATE_SIZE, UAVTALK_STATE_OBJID, UAVTALK_STATE_INSTID, UAVTALK_STATE_DATA, UAVTALK_STATE_CS, UAVTALK_STATE_COMPLETE} UAVTalkRxState; + // Public functions UAVTalkConnection UAVTalkInitialize(UAVTalkOutputStream outputStream); int32_t UAVTalkSetOutputStream(UAVTalkConnection connection, UAVTalkOutputStream outputStream); UAVTalkOutputStream UAVTalkGetOutputStream(UAVTalkConnection connection); int32_t UAVTalkSendObject(UAVTalkConnection connection, UAVObjHandle obj, uint16_t instId, uint8_t acked, int32_t timeoutMs); int32_t UAVTalkSendObjectRequest(UAVTalkConnection connection, UAVObjHandle obj, uint16_t instId, int32_t timeoutMs); -int32_t UAVTalkProcessInputStream(UAVTalkConnection connection, uint8_t rxbyte); +int32_t UAVTalkSendAck(UAVTalkConnection connectionHandle, UAVObjHandle obj, uint16_t instId); +int32_t UAVTalkSendNack(UAVTalkConnection connectionHandle, uint32_t objId); +UAVTalkRxState UAVTalkProcessInputStream(UAVTalkConnection connection, uint8_t rxbyte); +UAVTalkRxState UAVTalkProcessInputStreamQuiet(UAVTalkConnection connection, uint8_t rxbyte); void UAVTalkGetStats(UAVTalkConnection connection, UAVTalkStats *stats); void UAVTalkResetStats(UAVTalkConnection connection); diff --git a/flight/UAVTalk/inc/uavtalk_priv.h b/flight/UAVTalk/inc/uavtalk_priv.h index 77863a6a8..992bf91af 100644 --- a/flight/UAVTalk/inc/uavtalk_priv.h +++ b/flight/UAVTalk/inc/uavtalk_priv.h @@ -55,8 +55,6 @@ typedef uint8_t uavtalk_checksum; #define UAVTALK_MIN_PACKET_LENGTH UAVTALK_MAX_HEADER_LENGTH + UAVTALK_CHECKSUM_LENGTH #define UAVTALK_MAX_PACKET_LENGTH UAVTALK_MIN_PACKET_LENGTH + UAVTALK_MAX_PAYLOAD_LENGTH -typedef enum {UAVTALK_STATE_SYNC, UAVTALK_STATE_TYPE, UAVTALK_STATE_SIZE, UAVTALK_STATE_OBJID, UAVTALK_STATE_INSTID, UAVTALK_STATE_DATA, UAVTALK_STATE_CS} UAVTalkRxState; - typedef struct { UAVObjHandle obj; uint8_t type; diff --git a/flight/UAVTalk/uavtalk.c b/flight/UAVTalk/uavtalk.c index 844ed5e38..bf0d7e100 100644 --- a/flight/UAVTalk/uavtalk.c +++ b/flight/UAVTalk/uavtalk.c @@ -252,16 +252,18 @@ static int32_t objectTransaction(UAVTalkConnectionData *connection, UAVObjHandle * Process an byte from the telemetry stream. * \param[in] connection UAVTalkConnection to be used * \param[in] rxbyte Received byte - * \return 0 Success - * \return -1 Failure + * \return UAVTalkRxState */ -int32_t UAVTalkProcessInputStream(UAVTalkConnection connectionHandle, uint8_t rxbyte) +UAVTalkRxState UAVTalkProcessInputStreamQuiet(UAVTalkConnection connectionHandle, uint8_t rxbyte) { UAVTalkConnectionData *connection; CHECKCONHANDLE(connectionHandle,connection,return -1); UAVTalkInputProcessor *iproc = &connection->iproc; ++connection->stats.rxBytes; + + if (iproc->state == UAVTALK_STATE_ERROR || iproc->state == UAVTALK_STATE_COMPLETE) + iproc->state = UAVTALK_STATE_SYNC; if (iproc->rxPacketLength < 0xffff) iproc->rxPacketLength++; // update packet byte count @@ -288,7 +290,7 @@ int32_t UAVTalkProcessInputStream(UAVTalkConnection connectionHandle, uint8_t rx if ((rxbyte & UAVTALK_TYPE_MASK) != UAVTALK_TYPE_VER) { - iproc->state = UAVTALK_STATE_SYNC; + iproc->state = UAVTALK_STATE_ERROR; break; } @@ -316,7 +318,7 @@ int32_t UAVTalkProcessInputStream(UAVTalkConnection connectionHandle, uint8_t rx if (iproc->packet_size < UAVTALK_MIN_HEADER_LENGTH || iproc->packet_size > UAVTALK_MAX_HEADER_LENGTH + UAVTALK_MAX_PAYLOAD_LENGTH) { // incorrect packet size - iproc->state = UAVTALK_STATE_SYNC; + iproc->state = UAVTALK_STATE_ERROR; break; } @@ -335,17 +337,8 @@ int32_t UAVTalkProcessInputStream(UAVTalkConnection connectionHandle, uint8_t rx if (iproc->rxCount < 4) break; - // Search for object, if not found reset state machine - // except if we got a OBJ_REQ for an object which does not - // exist, in which case we'll send a NACK - + // Search for object. iproc->obj = UAVObjGetByID(iproc->objId); - if (iproc->obj == 0 && iproc->type != UAVTALK_TYPE_OBJ_REQ) - { - connection->stats.rxErrors++; - iproc->state = UAVTALK_STATE_SYNC; - break; - } // Determine data length if (iproc->type == UAVTALK_TYPE_OBJ_REQ || iproc->type == UAVTALK_TYPE_ACK || iproc->type == UAVTALK_TYPE_NACK) @@ -355,15 +348,24 @@ int32_t UAVTalkProcessInputStream(UAVTalkConnection connectionHandle, uint8_t rx } else { - iproc->length = UAVObjGetNumBytes(iproc->obj); - iproc->instanceLength = (UAVObjIsSingleInstance(iproc->obj) ? 0 : 2); + if (iproc->obj) + { + iproc->length = UAVObjGetNumBytes(iproc->obj); + iproc->instanceLength = (UAVObjIsSingleInstance(iproc->obj) ? 0 : 2); + } + else + { + // We don't know if it's a multi-instance object, so just assume it's 0. + iproc->instanceLength = 0; + iproc->length = iproc->packet_size - iproc->rxPacketLength; + } } // Check length and determine next state if (iproc->length >= UAVTALK_MAX_PAYLOAD_LENGTH) { connection->stats.rxErrors++; - iproc->state = UAVTALK_STATE_SYNC; + iproc->state = UAVTALK_STATE_ERROR; break; } @@ -371,34 +373,30 @@ int32_t UAVTalkProcessInputStream(UAVTalkConnection connectionHandle, uint8_t rx if ((iproc->rxPacketLength + iproc->instanceLength + iproc->length) != iproc->packet_size) { // packet error - mismatched packet size connection->stats.rxErrors++; - iproc->state = UAVTALK_STATE_SYNC; + iproc->state = UAVTALK_STATE_ERROR; break; } iproc->instId = 0; - if (iproc->obj == 0) + if (iproc->type == UAVTALK_TYPE_NACK) { // If this is a NACK, we skip to Checksum iproc->state = UAVTALK_STATE_CS; - iproc->rxCount = 0; - } // Check if this is a single instance object (i.e. if the instance ID field is coming next) - else if (UAVObjIsSingleInstance(iproc->obj)) + else if ((iproc->obj != 0) && !UAVObjIsSingleInstance(iproc->obj)) + { + iproc->state = UAVTALK_STATE_INSTID; + } + else { // If there is a payload get it, otherwise receive checksum if (iproc->length > 0) iproc->state = UAVTALK_STATE_DATA; else iproc->state = UAVTALK_STATE_CS; - - iproc->rxCount = 0; - } - else - { - iproc->state = UAVTALK_STATE_INSTID; - iproc->rxCount = 0; } + iproc->rxCount = 0; break; @@ -441,33 +439,84 @@ int32_t UAVTalkProcessInputStream(UAVTalkConnection connectionHandle, uint8_t rx if (rxbyte != iproc->cs) { // packet error - faulty CRC connection->stats.rxErrors++; - iproc->state = UAVTALK_STATE_SYNC; + iproc->state = UAVTALK_STATE_ERROR; break; } if (iproc->rxPacketLength != (iproc->packet_size + 1)) { // packet error - mismatched packet size connection->stats.rxErrors++; - iproc->state = UAVTALK_STATE_SYNC; + iproc->state = UAVTALK_STATE_ERROR; break; } - - xSemaphoreTakeRecursive(connection->lock, portMAX_DELAY); - receiveObject(connection, iproc->type, iproc->objId, iproc->instId, connection->rxBuffer, iproc->length); + connection->stats.rxObjectBytes += iproc->length; connection->stats.rxObjects++; - xSemaphoreGiveRecursive(connection->lock); - - iproc->state = UAVTALK_STATE_SYNC; + + iproc->state = UAVTALK_STATE_COMPLETE; break; default: connection->stats.rxErrors++; - iproc->state = UAVTALK_STATE_SYNC; + iproc->state = UAVTALK_STATE_ERROR; } // Done - return 0; + return iproc->state; +} + +/** + * Process an byte from the telemetry stream. + * \param[in] connection UAVTalkConnection to be used + * \param[in] rxbyte Received byte + * \return UAVTalkRxState + */ +UAVTalkRxState UAVTalkProcessInputStream(UAVTalkConnection connectionHandle, uint8_t rxbyte) +{ + UAVTalkRxState state = UAVTalkProcessInputStreamQuiet(connectionHandle, rxbyte); + + if (state == UAVTALK_STATE_COMPLETE) + { + UAVTalkConnectionData *connection; + CHECKCONHANDLE(connectionHandle,connection,return -1); + UAVTalkInputProcessor *iproc = &connection->iproc; + + xSemaphoreTakeRecursive(connection->lock, portMAX_DELAY); + receiveObject(connection, iproc->type, iproc->objId, iproc->instId, connection->rxBuffer, iproc->length); + xSemaphoreGiveRecursive(connection->lock); + } + + return state; +} + +/** + * Send a ACK through the telemetry link. + * \param[in] connectionHandle UAVTalkConnection to be used + * \param[in] objId Object ID to send a NACK for + * \return 0 Success + * \return -1 Failure + */ +int32_t UAVTalkSendAck(UAVTalkConnection connectionHandle, UAVObjHandle obj, uint16_t instId) +{ + UAVTalkConnectionData *connection; + CHECKCONHANDLE(connectionHandle,connection,return -1); + + return sendObject(connection, obj, instId, UAVTALK_TYPE_ACK); +} + +/** + * Send a NACK through the telemetry link. + * \param[in] connectionHandle UAVTalkConnection to be used + * \param[in] objId Object ID to send a NACK for + * \return 0 Success + * \return -1 Failure + */ +int32_t UAVTalkSendNack(UAVTalkConnection connectionHandle, uint32_t objId) +{ + UAVTalkConnectionData *connection; + CHECKCONHANDLE(connectionHandle,connection,return -1); + + return sendNack(connection, objId); } /** @@ -494,7 +543,7 @@ static int32_t receiveObject(UAVTalkConnectionData *connection, uint8_t type, ui switch (type) { case UAVTALK_TYPE_OBJ: // All instances, not allowed for OBJ messages - if (instId != UAVOBJ_ALL_INSTANCES) + if (obj && (instId != UAVOBJ_ALL_INSTANCES)) { // Unpack object, if the instance does not exist it will be created! UAVObjUnpack(obj, instId, data); @@ -508,7 +557,7 @@ static int32_t receiveObject(UAVTalkConnectionData *connection, uint8_t type, ui break; case UAVTALK_TYPE_OBJ_ACK: // All instances, not allowed for OBJ_ACK messages - if (instId != UAVOBJ_ALL_INSTANCES) + if (obj && (instId != UAVOBJ_ALL_INSTANCES)) { // Unpack object, if the instance does not exist it will be created! if ( UAVObjUnpack(obj, instId, data) == 0 ) @@ -538,7 +587,7 @@ static int32_t receiveObject(UAVTalkConnectionData *connection, uint8_t type, ui break; case UAVTALK_TYPE_ACK: // All instances, not allowed for ACK messages - if (instId != UAVOBJ_ALL_INSTANCES) + if (obj && (instId != UAVOBJ_ALL_INSTANCES)) { // Check if an ack is pending updateAck(connection, obj, instId); diff --git a/flight/board_hw_defs/coptercontrol/board_hw_defs.c b/flight/board_hw_defs/coptercontrol/board_hw_defs.c index cb1ce745e..328fd44ce 100644 --- a/flight/board_hw_defs/coptercontrol/board_hw_defs.c +++ b/flight/board_hw_defs/coptercontrol/board_hw_defs.c @@ -27,6 +27,10 @@ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #include +#include + +#define BOARD_REVISION_CC 1 +#define BOARD_REVISION_CC3D 2 #if defined(PIOS_INCLUDE_LED) @@ -59,6 +63,7 @@ static const struct pios_led pios_leds_cc3d[] = { .GPIO_Speed = GPIO_Speed_50MHz, }, }, + .remap = GPIO_Remap_SWJ_JTAGDisable, }, }; @@ -67,6 +72,15 @@ static const struct pios_led_cfg pios_led_cfg_cc3d = { .num_leds = NELEMENTS(pios_leds_cc3d), }; +const struct pios_led_cfg * PIOS_BOARD_HW_DEFS_GetLedCfg (uint32_t board_revision) +{ + switch (board_revision) { + case BOARD_REVISION_CC: return &pios_led_cfg_cc; + case BOARD_REVISION_CC3D: return &pios_led_cfg_cc3d; + default: return NULL; + } +} + #endif /* PIOS_INCLUDE_LED */ #if defined(PIOS_INCLUDE_SPI) @@ -1263,20 +1277,21 @@ static const struct pios_usb_cfg pios_usb_main_cfg_cc3d = { #include const struct pios_usb_hid_cfg pios_usb_hid_cfg = { - .data_if = 0, + .data_if = 2, .data_rx_ep = 1, .data_tx_ep = 1, }; + #endif /* PIOS_INCLUDE_USB_HID */ #if defined(PIOS_INCLUDE_USB_CDC) #include const struct pios_usb_cdc_cfg pios_usb_cdc_cfg = { - .ctrl_if = 1, + .ctrl_if = 0, .ctrl_tx_ep = 2, - .data_if = 2, + .data_if = 1, .data_rx_ep = 3, .data_tx_ep = 3, }; diff --git a/flight/board_hw_defs/pipxtreme/board_hw_defs.c b/flight/board_hw_defs/pipxtreme/board_hw_defs.c index 8dc17d5ba..bf2e713f6 100644 --- a/flight/board_hw_defs/pipxtreme/board_hw_defs.c +++ b/flight/board_hw_defs/pipxtreme/board_hw_defs.c @@ -1,5 +1,58 @@ #include +#if defined(PIOS_INCLUDE_LED) + +#include +static const struct pios_led pios_leds[] = { + [PIOS_LED_USB] = { + .pin = { + .gpio = GPIOA, + .init = { + .GPIO_Pin = GPIO_Pin_3, + .GPIO_Mode = GPIO_Mode_Out_PP, + .GPIO_Speed = GPIO_Speed_50MHz, + }, + }, + }, + [PIOS_LED_LINK] = { + .pin = { + .gpio = GPIOB, + .init = { + .GPIO_Pin = GPIO_Pin_5, + .GPIO_Mode = GPIO_Mode_Out_PP, + .GPIO_Speed = GPIO_Speed_50MHz, + }, + }, + }, + [PIOS_LED_RX] = { + .pin = { + .gpio = GPIOB, + .init = { + .GPIO_Pin = GPIO_Pin_6, + .GPIO_Mode = GPIO_Mode_Out_PP, + .GPIO_Speed = GPIO_Speed_50MHz, + }, + }, + }, + [PIOS_LED_TX] = { + .pin = { + .gpio = GPIOB, + .init = { + .GPIO_Pin = GPIO_Pin_7, + .GPIO_Mode = GPIO_Mode_Out_PP, + .GPIO_Speed = GPIO_Speed_50MHz, + }, + }, + }, +}; + +static const struct pios_led_cfg pios_led_cfg = { + .leds = pios_leds, + .num_leds = NELEMENTS(pios_leds), +}; + +#endif /* PIOS_INCLUDE_LED */ + #if defined(PIOS_INCLUDE_SPI) #include @@ -74,9 +127,9 @@ static const struct pios_spi_cfg pios_spi_port_cfg = }, }, }, - + .slave_count = 1, .ssel = - { + {{ .gpio = GPIOA, .init = { @@ -84,7 +137,7 @@ static const struct pios_spi_cfg pios_spi_port_cfg = .GPIO_Speed = GPIO_Speed_10MHz, .GPIO_Mode = GPIO_Mode_Out_PP, }, - }, + }}, .sclk = { .gpio = GPIOA, @@ -181,6 +234,86 @@ void PIOS_ADC_handler() { #endif /* PIOS_INCLUDE_ADC */ +#if defined(PIOS_INCLUDE_TIM) + +#include "pios_tim_priv.h" + +static const TIM_TimeBaseInitTypeDef tim_1_2_3_4_time_base = { + .TIM_Prescaler = (PIOS_MASTER_CLOCK / 1000000) - 1, + .TIM_ClockDivision = TIM_CKD_DIV1, + .TIM_CounterMode = TIM_CounterMode_Up, + .TIM_Period = ((1000000 / PIOS_SERVO_UPDATE_HZ) - 1), + .TIM_RepetitionCounter = 0x0000, +}; + +static const struct pios_tim_clock_cfg tim_1_cfg = { + .timer = TIM1, + .time_base_init = &tim_1_2_3_4_time_base, + .irq = { + .init = { + .NVIC_IRQChannel = TIM1_CC_IRQn, + .NVIC_IRQChannelPreemptionPriority = PIOS_IRQ_PRIO_MID, + .NVIC_IRQChannelSubPriority = 0, + .NVIC_IRQChannelCmd = ENABLE, + }, + }, +}; + +static const struct pios_tim_clock_cfg tim_2_cfg = { + .timer = TIM2, + .time_base_init = &tim_1_2_3_4_time_base, + .irq = { + .init = { + .NVIC_IRQChannel = TIM2_IRQn, + .NVIC_IRQChannelPreemptionPriority = PIOS_IRQ_PRIO_MID, + .NVIC_IRQChannelSubPriority = 0, + .NVIC_IRQChannelCmd = ENABLE, + }, + }, +}; + +static const struct pios_tim_clock_cfg tim_3_cfg = { + .timer = TIM3, + .time_base_init = &tim_1_2_3_4_time_base, + .irq = { + .init = { + .NVIC_IRQChannel = TIM3_IRQn, + .NVIC_IRQChannelPreemptionPriority = PIOS_IRQ_PRIO_MID, + .NVIC_IRQChannelSubPriority = 0, + .NVIC_IRQChannelCmd = ENABLE, + }, + }, +}; + +static const struct pios_tim_clock_cfg tim_4_cfg = { + .timer = TIM4, + .time_base_init = &tim_1_2_3_4_time_base, + .irq = { + .init = { + .NVIC_IRQChannel = TIM4_IRQn, + .NVIC_IRQChannelPreemptionPriority = PIOS_IRQ_PRIO_MID, + .NVIC_IRQChannelSubPriority = 0, + .NVIC_IRQChannelCmd = ENABLE, + }, + }, +}; + +static const struct pios_tim_channel pios_tim_ppm_flexi_port = { + .timer = TIM2, + .timer_chan = TIM_Channel_4, + .pin = { + .gpio = GPIOB, + .init = { + .GPIO_Pin = GPIO_Pin_11, + .GPIO_Mode = GPIO_Mode_IPD, + .GPIO_Speed = GPIO_Speed_2MHz, + }, + }, + .remap = GPIO_PartialRemap2_TIM2, +}; + +#endif /* PIOS_INCLUDE_TIM */ + #if defined(PIOS_INCLUDE_USART) #include @@ -232,6 +365,42 @@ static const struct pios_usart_cfg pios_usart_serial_cfg = }, }; +static const struct pios_usart_cfg pios_usart_telem_flexi_cfg = { + .regs = USART3, + .init = { + .USART_BaudRate = 57600, + .USART_WordLength = USART_WordLength_8b, + .USART_Parity = USART_Parity_No, + .USART_StopBits = USART_StopBits_1, + .USART_HardwareFlowControl = USART_HardwareFlowControl_None, + .USART_Mode = USART_Mode_Rx | USART_Mode_Tx, + }, + .irq = { + .init = { + .NVIC_IRQChannel = USART3_IRQn, + .NVIC_IRQChannelPreemptionPriority = PIOS_IRQ_PRIO_MID, + .NVIC_IRQChannelSubPriority = 0, + .NVIC_IRQChannelCmd = ENABLE, + }, + }, + .rx = { + .gpio = GPIOB, + .init = { + .GPIO_Pin = GPIO_Pin_11, + .GPIO_Speed = GPIO_Speed_2MHz, + .GPIO_Mode = GPIO_Mode_IPU, + }, + }, + .tx = { + .gpio = GPIOB, + .init = { + .GPIO_Pin = GPIO_Pin_10, + .GPIO_Speed = GPIO_Speed_2MHz, + .GPIO_Mode = GPIO_Mode_AF_PP, + }, + }, +}; + #endif /* PIOS_INCLUDE_USART */ #if defined(PIOS_INCLUDE_COM) @@ -240,34 +409,136 @@ static const struct pios_usart_cfg pios_usart_serial_cfg = #endif /* PIOS_INCLUDE_COM */ -// *********************************************************************************** +#if defined(PIOS_INCLUDE_RTC) +/* + * Realtime Clock (RTC) + */ +#include + +void PIOS_RTC_IRQ_Handler (void); +void RTC_IRQHandler() __attribute__ ((alias ("PIOS_RTC_IRQ_Handler"))); +static const struct pios_rtc_cfg pios_rtc_main_cfg = { + .clksrc = RCC_RTCCLKSource_HSE_Div128, + .prescaler = 100, + .irq = { + .init = { + .NVIC_IRQChannel = RTC_IRQn, + .NVIC_IRQChannelPreemptionPriority = PIOS_IRQ_PRIO_MID, + .NVIC_IRQChannelSubPriority = 0, + .NVIC_IRQChannelCmd = ENABLE, + }, + }, +}; + +void PIOS_RTC_IRQ_Handler (void) +{ + PIOS_RTC_irq_handler (); +} + +#endif + +/* + * PPM Inputs + */ +#if defined(PIOS_INCLUDE_PPM) +#include + +const struct pios_ppm_cfg pios_ppm_cfg = { + .tim_ic_init = { + .TIM_ICPolarity = TIM_ICPolarity_Rising, + .TIM_ICSelection = TIM_ICSelection_DirectTI, + .TIM_ICPrescaler = TIM_ICPSC_DIV1, + .TIM_ICFilter = 0x0, + }, + .channels = &pios_tim_ppm_flexi_port, + .num_channels = 1, +}; + +#endif /* PIOS_INCLUDE_PPM */ + +#if defined(PIOS_INCLUDE_RCVR) +#include "pios_rcvr_priv.h" + +#endif /* PIOS_INCLUDE_RCVR */ #if defined(PIOS_INCLUDE_USB) #include "pios_usb_priv.h" static const struct pios_usb_cfg pios_usb_main_cfg = { - .irq = { - .init = { - .NVIC_IRQChannel = USB_LP_CAN1_RX0_IRQn, - .NVIC_IRQChannelPreemptionPriority = PIOS_IRQ_PRIO_LOW, - .NVIC_IRQChannelSubPriority = 0, - .NVIC_IRQChannelCmd = ENABLE, - }, - }, + .irq = { + .init = { + .NVIC_IRQChannel = USB_LP_CAN1_RX0_IRQn, + .NVIC_IRQChannelPreemptionPriority = PIOS_IRQ_PRIO_LOW, + .NVIC_IRQChannelSubPriority = 0, + .NVIC_IRQChannelCmd = ENABLE, + }, + }, + .vsense = { + .gpio = GPIOA, + .init = { + .GPIO_Pin = GPIO_Pin_8, + .GPIO_Speed = GPIO_Speed_10MHz, + .GPIO_Mode = GPIO_Mode_AF_OD, + }, + } }; #include "pios_usb_board_data_priv.h" +#include "pios_usb_desc_hid_cdc_priv.h" #include "pios_usb_desc_hid_only_priv.h" #endif /* PIOS_INCLUDE_USB */ +#if defined(PIOS_INCLUDE_COM_MSG) + +#include + +#endif /* PIOS_INCLUDE_COM_MSG */ + #if defined(PIOS_INCLUDE_USB_HID) #include const struct pios_usb_hid_cfg pios_usb_hid_cfg = { - .data_if = 0, + .data_if = 2, .data_rx_ep = 1, .data_tx_ep = 1, }; +#endif /* PIOS_INCLUDE_USB_HID */ -#endif /* PIOS_INCLUDE_USB_HID */ +#if defined(PIOS_INCLUDE_USB_CDC) +#include + +const struct pios_usb_cdc_cfg pios_usb_cdc_cfg = { + .ctrl_if = 0, + .ctrl_tx_ep = 2, + + .data_if = 1, + .data_rx_ep = 3, + .data_tx_ep = 3, +}; +#endif /* PIOS_INCLUDE_USB_CDC */ + +#if defined(PIOS_INCLUDE_FLASH_EEPROM) +#include + +const struct pios_eeprom_cfg pios_eeprom_cfg = { + .base_address = PIOS_FLASH_EEPROM_ADDR, + .max_size = PIOS_FLASH_EEPROM_LEN, +}; +#endif /* PIOS_INCLUDE_FLASH_EEPROM */ + +#if defined(PIOS_INCLUDE_RFM22B) +#include + +#endif /* PIOS_INCLUDE_RFM22B */ + +#if defined(PIOS_INCLUDE_PACKET_HANDLER) +#include + +// Initialize the packet handler +PacketHandlerConfig pios_ph_cfg = { + .winSize = PIOS_PH_WIN_SIZE, + .maxConnections = PIOS_PH_MAX_CONNECTIONS, +}; + +#endif /* PIOS_INCLUDE_PACKET_HANDLER */ diff --git a/flight/board_hw_defs/simposix/board_hw_defs.c b/flight/board_hw_defs/simposix/board_hw_defs.c new file mode 100644 index 000000000..28740cdb9 --- /dev/null +++ b/flight/board_hw_defs/simposix/board_hw_defs.c @@ -0,0 +1,73 @@ +/** + ****************************************************************************** + * @addtogroup OpenPilotSystem OpenPilot System + * @{ + * @addtogroup OpenPilotCore OpenPilot Core + * @{ + * + * @file board_hw_defs.c + * @author The OpenPilot Team, http://www.openpilot.org Copyright (C) 2012. + * @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 + +#ifdef PIOS_INCLUDE_UDP + +#include + +#ifdef PIOS_INCLUDE_COM_TELEM +/* + * Telemetry on main USART + */ +const struct pios_udp_cfg pios_udp_telem_cfg = { + .ip = "0.0.0.0", + .port = 9000, +}; +#endif /* PIOS_COM_TELEM */ + +#ifdef PIOS_INCLUDE_GPS +/* + * GPS USART + */ +const struct pios_udp_cfg pios_udp_gps_cfg = { + .ip = "0.0.0.0", + .port = 9001, +}; + +#endif /* PIOS_INCLUDE_GPS */ + +#ifdef PIOS_INCLUDE_COM_AUX +/* + * AUX USART (UART label on rev2) + */ +const struct pios_udp_cfg pios_udp_aux_cfg = { + .ip = "0.0.0.0", + .port = 9002, +}; +#endif /* PIOS_COM_AUX */ + +#endif /* PIOS_UDP */ + +#if defined(PIOS_INCLUDE_COM) + +#include + +#endif /* PIOS_INCLUDE_COM */ + diff --git a/ground/openpilotgcs/src/plugins/config/config.pro b/ground/openpilotgcs/src/plugins/config/config.pro index 9bc94bcd0..8e49cb54d 100644 --- a/ground/openpilotgcs/src/plugins/config/config.pro +++ b/ground/openpilotgcs/src/plugins/config/config.pro @@ -20,6 +20,7 @@ HEADERS += configplugin.h \ config_pro_hw_widget.h \ config_cc_hw_widget.h \ configccattitudewidget.h \ + configpipxtremewidget.h \ cfg_vehicletypes/configccpmwidget.h \ configstabilizationwidget.h \ assertions.h \ @@ -50,6 +51,7 @@ SOURCES += configplugin.cpp \ config_cc_hw_widget.cpp \ configccattitudewidget.cpp \ configstabilizationwidget.cpp \ + configpipxtremewidget.cpp \ twostep.cpp \ legacy-calibration.cpp \ gyro-calibration.cpp \ @@ -80,5 +82,6 @@ FORMS += airframe.ui \ camerastabilization.ui \ outputchannelform.ui \ revosensors.ui \ - txpid.ui + txpid.ui \ + pipxtreme.ui RESOURCES += configgadget.qrc diff --git a/ground/openpilotgcs/src/plugins/config/configgadgetwidget.cpp b/ground/openpilotgcs/src/plugins/config/configgadgetwidget.cpp index b7b5d76d7..600b9be6f 100644 --- a/ground/openpilotgcs/src/plugins/config/configgadgetwidget.cpp +++ b/ground/openpilotgcs/src/plugins/config/configgadgetwidget.cpp @@ -36,6 +36,7 @@ #include "configtxpidwidget.h" #include "config_pro_hw_widget.h" #include "config_cc_hw_widget.h" +#include "configpipxtremewidget.h" #include "configrevowidget.h" #include "defaultattitudewidget.h" #include "defaulthwsettingswidget.h" @@ -89,8 +90,8 @@ ConfigGadgetWidget::ConfigGadgetWidget(QWidget *parent) : QWidget(parent) qwd = new ConfigTxPIDWidget(this); ftw->insertTab(ConfigGadgetWidget::txpid, qwd, QIcon(":/configgadget/images/txpid.png"), QString("TxPID")); -// qwd = new ConfigPipXtremeWidget(this); -// ftw->insertTab(5, qwd, QIcon(":/configgadget/images/PipXtreme.png"), QString("PipXtreme")); + qwd = new ConfigPipXtremeWidget(this); + ftw->insertTab(ConfigGadgetWidget::pipxtreme, qwd, QIcon(":/configgadget/images/PipXtreme.png"), QString("PipXtreme")); // ********************* // Listen to autopilot connection events diff --git a/ground/openpilotgcs/src/plugins/config/configgadgetwidget.h b/ground/openpilotgcs/src/plugins/config/configgadgetwidget.h index c53fe6b87..1d0e8675a 100644 --- a/ground/openpilotgcs/src/plugins/config/configgadgetwidget.h +++ b/ground/openpilotgcs/src/plugins/config/configgadgetwidget.h @@ -50,7 +50,7 @@ class ConfigGadgetWidget: public QWidget public: ConfigGadgetWidget(QWidget *parent = 0); ~ConfigGadgetWidget(); - enum widgetTabs {hardware=0, aircraft, input, output, sensors, stabilization, camerastabilization, txpid}; + enum widgetTabs {hardware=0, aircraft, input, output, sensors, stabilization, camerastabilization, txpid, pipxtreme}; public slots: void onAutopilotConnect(); diff --git a/ground/openpilotgcs/src/plugins/config/configpipxtremewidget.cpp b/ground/openpilotgcs/src/plugins/config/configpipxtremewidget.cpp new file mode 100644 index 000000000..f4d20fc5d --- /dev/null +++ b/ground/openpilotgcs/src/plugins/config/configpipxtremewidget.cpp @@ -0,0 +1,306 @@ +/** +****************************************************************************** +* +* @file configtxpidswidget.cpp +* @author The OpenPilot Team, http://www.openpilot.org Copyright (C) 2012. +* @addtogroup GCSPlugins GCS Plugins +* @{ +* @addtogroup ConfigPlugin Config Plugin +* @{ +* @brief The Configuration Gadget used to configure the PipXtreme +*****************************************************************************/ +/* + * 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 "configpipxtremewidget.h" + +#include +#include + +ConfigPipXtremeWidget::ConfigPipXtremeWidget(QWidget *parent) : ConfigTaskWidget(parent) +{ + m_pipx = new Ui_PipXtremeWidget(); + m_pipx->setupUi(this); + + // Connect to the PipXStatus object updates + ExtensionSystem::PluginManager *pm = ExtensionSystem::PluginManager::instance(); + UAVObjectManager *objManager = pm->getObject(); + pipxStatusObj = dynamic_cast(objManager->getObject("PipXStatus")); + if (pipxStatusObj != NULL ) { + connect(pipxStatusObj, SIGNAL(objectUpdated(UAVObject*)), this, SLOT(updateStatus(UAVObject*))); + } else { + qDebug() << "Error: Object is unknown (PipXStatus)."; + } + + // Connect to the PipXSettings object updates + pipxSettingsObj = dynamic_cast(objManager->getObject("PipXSettings")); + if (pipxSettingsObj != NULL ) { + connect(pipxSettingsObj, SIGNAL(objectUpdated(UAVObject*)), this, SLOT(updateSettings(UAVObject*))); + } else { + qDebug() << "Error: Object is unknown (PipXSettings)."; + } + + addApplySaveButtons(m_pipx->Apply, m_pipx->Save); + + addUAVObjectToWidgetRelation("PipXSettings", "TelemetryConfig", m_pipx->TelemPortConfig); + addUAVObjectToWidgetRelation("PipXSettings", "TelemetrySpeed", m_pipx->TelemPortSpeed); + addUAVObjectToWidgetRelation("PipXSettings", "FlexiConfig", m_pipx->FlexiPortConfig); + addUAVObjectToWidgetRelation("PipXSettings", "FlexiSpeed", m_pipx->FlexiPortSpeed); + addUAVObjectToWidgetRelation("PipXSettings", "VCPConfig", m_pipx->VCPConfig); + addUAVObjectToWidgetRelation("PipXSettings", "VCPSpeed", m_pipx->VCPSpeed); + addUAVObjectToWidgetRelation("PipXSettings", "RFSpeed", m_pipx->MaxRFDatarate); + addUAVObjectToWidgetRelation("PipXSettings", "MaxRFPower", m_pipx->MaxRFTxPower); + addUAVObjectToWidgetRelation("PipXSettings", "SendTimeout", m_pipx->SendTimeout); + addUAVObjectToWidgetRelation("PipXSettings", "MinPacketSize", m_pipx->MinPacketSize); + addUAVObjectToWidgetRelation("PipXSettings", "FrequencyCalibration", m_pipx->FrequencyCalibration); + addUAVObjectToWidgetRelation("PipXSettings", "Frequency", m_pipx->Frequency); + + addUAVObjectToWidgetRelation("PipXStatus", "MinFrequency", m_pipx->MinFrequency); + addUAVObjectToWidgetRelation("PipXStatus", "MaxFrequency", m_pipx->MaxFrequency); + addUAVObjectToWidgetRelation("PipXStatus", "FrequencyStepSize", m_pipx->FrequencyStepSize); + addUAVObjectToWidgetRelation("PipXStatus", "AFC", m_pipx->RxAFC); + addUAVObjectToWidgetRelation("PipXStatus", "Retries", m_pipx->Retries); + addUAVObjectToWidgetRelation("PipXStatus", "Errors", m_pipx->Errors); + addUAVObjectToWidgetRelation("PipXStatus", "UAVTalkErrors", m_pipx->UAVTalkErrors); + addUAVObjectToWidgetRelation("PipXStatus", "Resets", m_pipx->Resets); + addUAVObjectToWidgetRelation("PipXStatus", "RXRate", m_pipx->RXRate); + addUAVObjectToWidgetRelation("PipXStatus", "TXRate", m_pipx->TXRate); + + // Connect to the pair ID radio buttons. + connect(m_pipx->PairSelect1, SIGNAL(toggled(bool)), this, SLOT(pair1Toggled(bool))); + connect(m_pipx->PairSelect2, SIGNAL(toggled(bool)), this, SLOT(pair2Toggled(bool))); + connect(m_pipx->PairSelect3, SIGNAL(toggled(bool)), this, SLOT(pair3Toggled(bool))); + connect(m_pipx->PairSelect4, SIGNAL(toggled(bool)), this, SLOT(pair4Toggled(bool))); + + // Create the timer that is used to timeout the connection to the PipX. + timeOut = new QTimer(this); + connect(timeOut, SIGNAL(timeout()),this,SLOT(disconnected())); + + // Request and update of the setting object. + settingsUpdated = false; + pipxSettingsObj->requestUpdate(); +} + +ConfigPipXtremeWidget::~ConfigPipXtremeWidget() +{ + // Do nothing +} + +void ConfigPipXtremeWidget::refreshValues() +{ +} + +void ConfigPipXtremeWidget::applySettings() +{ + PipXSettings *pipxSettings = PipXSettings::GetInstance(getObjectManager()); + PipXSettings::DataFields pipxSettingsData = pipxSettings->getData(); + + // Get the pair ID. + quint32 pairID = 0; + bool okay; + if (m_pipx->PairSelect1->isChecked()) + pairID = m_pipx->PairID1->text().toUInt(&okay, 16); + else if (m_pipx->PairSelect2->isChecked()) + pairID = m_pipx->PairID2->text().toUInt(&okay, 16); + else if (m_pipx->PairSelect3->isChecked()) + pairID = m_pipx->PairID3->text().toUInt(&okay, 16); + else if (m_pipx->PairSelect4->isChecked()) + pairID = m_pipx->PairID4->text().toUInt(&okay, 16); + pipxSettingsData.PairID = pairID; + pipxSettings->setData(pipxSettingsData); +} + +void ConfigPipXtremeWidget::saveSettings() +{ + //applySettings(); + UAVObject *obj = PipXSettings::GetInstance(getObjectManager()); + saveObjectToSD(obj); +} + +/*! + \brief Called by updates to @PipXStatus + */ +void ConfigPipXtremeWidget::updateStatus(UAVObject *object) +{ + + // Restart the disconnection timer. + timeOut->start(10000); + + // Request and update of the setting object if we haven't received it yet. + if (!settingsUpdated) + pipxSettingsObj->requestUpdate(); + + // Get the current pairID + PipXSettings *pipxSettings = PipXSettings::GetInstance(getObjectManager()); + quint32 pairID = 0; + if (pipxSettings) + pipxSettings->getPairID(); + + // Update the detected devices. + UAVObjectField* pairIdField = object->getField("PairIDs"); + if (pairIdField) { + quint32 pairid1 = pairIdField->getValue(0).toUInt(); + m_pipx->PairID1->setText(QString::number(pairid1, 16).toUpper()); + m_pipx->PairID1->setEnabled(false); + m_pipx->PairSelect1->setChecked(pairID && (pairID == pairid1)); + m_pipx->PairSelect1->setEnabled(pairid1); + quint32 pairid2 = pairIdField->getValue(1).toUInt(); + m_pipx->PairID2->setText(QString::number(pairIdField->getValue(1).toUInt(), 16).toUpper()); + m_pipx->PairID2->setEnabled(false); + m_pipx->PairSelect2->setChecked(pairID && (pairID == pairid2)); + m_pipx->PairSelect2->setEnabled(pairid2); + quint32 pairid3 = pairIdField->getValue(2).toUInt(); + m_pipx->PairID3->setText(QString::number(pairIdField->getValue(2).toUInt(), 16).toUpper()); + m_pipx->PairID3->setEnabled(false); + m_pipx->PairSelect3->setChecked(pairID && (pairID == pairid3)); + m_pipx->PairSelect3->setEnabled(pairid3); + quint32 pairid4 = pairIdField->getValue(3).toUInt(); + m_pipx->PairID4->setText(QString::number(pairIdField->getValue(3).toUInt(), 16).toUpper()); + m_pipx->PairID4->setEnabled(false); + m_pipx->PairSelect4->setChecked(pairID && (pairID == pairid4)); + m_pipx->PairSelect4->setEnabled(pairid4); + } else { + qDebug() << "PipXtremeGadgetWidget: Count not read PairID field."; + } + UAVObjectField* pairRssiField = object->getField("PairSignalStrengths"); + if (pairRssiField) { + m_pipx->PairSignalStrength1->setValue(pairRssiField->getValue(0).toInt()); + m_pipx->PairSignalStrength2->setValue(pairRssiField->getValue(1).toInt()); + m_pipx->PairSignalStrength3->setValue(pairRssiField->getValue(2).toInt()); + m_pipx->PairSignalStrength4->setValue(pairRssiField->getValue(3).toInt()); + } else { + qDebug() << "PipXtremeGadgetWidget: Count not read PairID field."; + } + + // Update the Description field + UAVObjectField* descField = object->getField("Description"); + if (descField) { + /* + * This looks like a binary with a description at the end + * 4 bytes: header: "OpFw" + * 4 bytes: git commit hash (short version of SHA1) + * 4 bytes: Unix timestamp of last git commit + * 2 bytes: target platform. Should follow same rule as BOARD_TYPE and BOARD_REVISION in board define files. + * 26 bytes: commit tag if it is there, otherwise "Unreleased". Zero-padded + * ---- 40 bytes limit --- + * 20 bytes: SHA1 sum of the firmware. + * 40 bytes: free for now. + */ + char buf[PipXStatus::DESCRIPTION_NUMELEM]; + for (unsigned int i = 0; i < 26; ++i) + buf[i] = descField->getValue(i + 14).toChar().toAscii(); + buf[26] = '\0'; + QString descstr(buf); + quint32 gitDate = descField->getValue(11).toChar().toAscii() & 0xFF; + for (int i = 1; i < 4; i++) { + gitDate = gitDate << 8; + gitDate += descField->getValue(11-i).toChar().toAscii() & 0xFF; + } + QString date = QDateTime::fromTime_t(gitDate).toUTC().toString("yyyy-MM-dd HH:mm"); + m_pipx->FirmwareVersion->setText(descstr + " " + date); + } else { + qDebug() << "PipXtremeGadgetWidget: Count not read Description field."; + } + + // Update the serial number field + UAVObjectField* serialField = object->getField("CPUSerial"); + if (serialField) { + char buf[PipXStatus::CPUSERIAL_NUMELEM * 2 + 1]; + for (unsigned int i = 0; i < PipXStatus::CPUSERIAL_NUMELEM; ++i) + { + unsigned char val = serialField->getValue(i).toUInt() >> 4; + buf[i * 2] = ((val < 10) ? '0' : '7') + val; + val = serialField->getValue(i).toUInt() & 0xf; + buf[i * 2 + 1] = ((val < 10) ? '0' : '7') + val; + } + buf[PipXStatus::CPUSERIAL_NUMELEM * 2] = '\0'; + m_pipx->SerialNumber->setText(buf); + } else { + qDebug() << "PipXtremeGadgetWidget: Count not read Description field."; + } + + // Update the DeviceID field + UAVObjectField* idField = object->getField("DeviceID"); + if (idField) { + m_pipx->DeviceID->setText(QString::number(idField->getValue().toUInt(), 16).toUpper()); + } else { + qDebug() << "PipXtremeGadgetWidget: Count not read DeviceID field."; + } + + // Update the link state + UAVObjectField* linkField = object->getField("LinkState"); + if (linkField) { + m_pipx->LinkState->setText(linkField->getValue().toString()); + } else { + qDebug() << "PipXtremeGadgetWidget: Count not read link state field."; + } +} + +/*! + \brief Called by updates to @PipXSettings + */ +void ConfigPipXtremeWidget::updateSettings(UAVObject *object) +{ + settingsUpdated = true; + enableControls(true); +} + +void ConfigPipXtremeWidget::disconnected() +{ + settingsUpdated = false; + enableControls(false); +} + +void ConfigPipXtremeWidget::pairIDToggled(bool checked, quint8 idx) +{ + if(checked) + { + PipXStatus *pipxStatus = PipXStatus::GetInstance(getObjectManager()); + PipXSettings *pipxSettings = PipXSettings::GetInstance(getObjectManager()); + + if (pipxStatus && pipxSettings) + { + quint32 pairID = pipxStatus->getPairIDs(idx); + if (pairID) + pipxSettings->setPairID(pairID); + } + } +} + +void ConfigPipXtremeWidget::pair1Toggled(bool checked) +{ + pairIDToggled(checked, 0); +} + +void ConfigPipXtremeWidget::pair2Toggled(bool checked) +{ + pairIDToggled(checked, 1); +} + +void ConfigPipXtremeWidget::pair3Toggled(bool checked) +{ + pairIDToggled(checked, 2); +} + +void ConfigPipXtremeWidget::pair4Toggled(bool checked) +{ + pairIDToggled(checked, 3); +} + +/** + @} + @} +*/ diff --git a/ground/openpilotgcs/src/plugins/config/configpipxtremewidget.h b/ground/openpilotgcs/src/plugins/config/configpipxtremewidget.h new file mode 100644 index 000000000..34c1f1673 --- /dev/null +++ b/ground/openpilotgcs/src/plugins/config/configpipxtremewidget.h @@ -0,0 +1,71 @@ +/** +****************************************************************************** +* +* @file configpipxtremewidget.h +* @author The OpenPilot Team, http://www.openpilot.org Copyright (C) 2012. +* @addtogroup GCSPlugins GCS Plugins +* @{ +* @addtogroup ConfigPlugin Config Plugin +* @{ +* @brief The Configuration Gadget used to configure PipXtreme +*****************************************************************************/ +/* + * 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 CONFIGPIPXTREMEWIDGET_H +#define CONFIGPIPXTREMEWIDGET_H + +#include "ui_pipxtreme.h" +#include "configtaskwidget.h" + +class ConfigPipXtremeWidget : public ConfigTaskWidget +{ + Q_OBJECT + +public: + ConfigPipXtremeWidget(QWidget *parent = 0); + ~ConfigPipXtremeWidget(); + +public slots: + void updateStatus(UAVObject *object1); + void updateSettings(UAVObject *object1); + +private: + Ui_PipXtremeWidget *m_pipx; + + // The PipXtreme status UAVObject + UAVDataObject* pipxStatusObj; + + // The PipXtreme ssettins UAVObject + UAVDataObject* pipxSettingsObj; + + bool settingsUpdated; + + // A timer that timesout the connction to the PipX. + QTimer *timeOut; + +private slots: + void refreshValues(); + void applySettings(); + void saveSettings(); + void disconnected(); + void pairIDToggled(bool checked, quint8 idx); + void pair1Toggled(bool checked); + void pair2Toggled(bool checked); + void pair3Toggled(bool checked); + void pair4Toggled(bool checked); +}; + +#endif // CONFIGTXPIDWIDGET_H diff --git a/ground/openpilotgcs/src/plugins/config/pipxtreme.ui b/ground/openpilotgcs/src/plugins/config/pipxtreme.ui new file mode 100644 index 000000000..06662e450 --- /dev/null +++ b/ground/openpilotgcs/src/plugins/config/pipxtreme.ui @@ -0,0 +1,1310 @@ + + + PipXtremeWidget + + + + 0 + 0 + 840 + 724 + + + + Form + + + + + + QFrame::StyledPanel + + + QFrame::Raised + + + + + + QFrame::StyledPanel + + + QFrame::Raised + + + + + + + 75 + true + + + + Pairing + + + + + + + + + + + + + + + + -127 + + + 0 + + + -127 + + + true + + + %v dBm + + + + + + + + + + + + + + + + + -127 + + + 0 + + + 0 + + + true + + + %v dBm + + + + + + + + + + + + + + + + + -127 + + + 0 + + + 0 + + + true + + + %v dBm + + + + + + + + + + + + + + + + + -127 + + + 0 + + + 0 + + + true + + + %v dBm + + + + + + + + + + + 75 + true + + + + Status + + + + + + Firmware Version + + + Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter + + + + + + + + 75 + true + + + + QLineEdit { + border: none; + border-radius: 1px; + padding: 0 8px; + background: rgba(0, 0, 0, 16); +/* background: transparent; */ +/* selection-background-color: darkgray;*/ +} + + + false + + + true + + + + + + + Serial Number + + + Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter + + + + + + + + 0 + 0 + + + + + 16777215 + 16777215 + + + + + 75 + false + true + + + + false + + + The modems serial number + + + QLineEdit { + border: none; + border-radius: 1px; + padding: 0 8px; + background: rgba(0, 0, 0, 16); +/* background: transparent; */ +/* selection-background-color: darkgray;*/ +} + + + true + + + Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter + + + true + + + + + + + Min Frequency + + + Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter + + + + + + + + 0 + 0 + + + + + 16777215 + 16777215 + + + + + 75 + true + + + + The modems minimum allowed frequency + + + QLineEdit { + border: none; + border-radius: 1px; + padding: 0 8px; + background: rgba(0, 0, 0, 16); +/* background: transparent; */ +/* selection-background-color: darkgray;*/ +} + + + Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter + + + true + + + + + + + Max Frequency + + + Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter + + + + + + + + 0 + 0 + + + + + 16777215 + 16777215 + + + + + 75 + true + + + + The modems maximum allowed frequency + + + QLineEdit { + border: none; + border-radius: 1px; + padding: 0 8px; + background: rgba(0, 0, 0, 16); +/* background: transparent; */ +/* selection-background-color: darkgray;*/ +} + + + Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter + + + true + + + + + + + Frequency Step Size + + + Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter + + + + + + + + 0 + 0 + + + + + 16777215 + 16777215 + + + + + 75 + true + + + + The modems minimum frequency step size + + + QLineEdit { + border: none; + border-radius: 1px; + padding: 0 8px; + background: rgba(0, 0, 0, 16); +/* background: transparent; */ +/* selection-background-color: darkgray;*/ +} + + + Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter + + + true + + + + + + + Link State + + + Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter + + + + + + + + 0 + 0 + + + + + 16777215 + 16777215 + + + + + 75 + true + + + + The modems current state + + + QLineEdit { + border: none; + border-radius: 1px; + padding: 0 8px; + background: rgba(0, 0, 0, 16); +/* background: transparent; */ +/* selection-background-color: darkgray;*/ +} + + + Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter + + + true + + + + + + + Rx AFC + + + Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter + + + + + + + + 75 + true + + + + QLineEdit { + border: none; + border-radius: 1px; + padding: 0 8px; + background: rgba(0, 0, 0, 16); +/* background: transparent; */ +/* selection-background-color: darkgray;*/ +} + + + true + + + + + + + Retries + + + Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter + + + + + + + + 75 + true + + + + QLineEdit { + border: none; + border-radius: 1px; + padding: 0 8px; + background: rgba(0, 0, 0, 16); +/* background: transparent; */ +/* selection-background-color: darkgray;*/ +} + + + false + + + true + + + + + + + + 75 + true + + + + QLineEdit { + border: none; + border-radius: 1px; + padding: 0 8px; + background: rgba(0, 0, 0, 16); +/* background: transparent; */ +/* selection-background-color: darkgray;*/ +} + + + false + + + true + + + + + + + Errors + + + Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter + + + + + + + UAVTalk Errors + + + Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter + + + + + + + + 75 + true + + + + QLineEdit { + border: none; + border-radius: 1px; + padding: 0 8px; + background: rgba(0, 0, 0, 16); +/* background: transparent; */ +/* selection-background-color: darkgray;*/ +} + + + false + + + true + + + + + + + Resets + + + Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter + + + + + + + + 75 + true + + + + QLineEdit { + border: none; + border-radius: 1px; + padding: 0 8px; + background: rgba(0, 0, 0, 16); +/* background: transparent; */ +/* selection-background-color: darkgray;*/ +} + + + false + + + true + + + + + + + TX Rate (B/s) + + + Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter + + + + + + + + 75 + true + + + + QLineEdit { + border: none; + border-radius: 1px; + padding: 0 8px; + background: rgba(0, 0, 0, 16); +/* background: transparent; */ +/* selection-background-color: darkgray;*/ +} + + + false + + + true + + + + + + + RX Rate (B/s) + + + Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter + + + + + + + + 75 + true + + + + QLineEdit { + border: none; + border-radius: 1px; + padding: 0 8px; + background: rgba(0, 0, 0, 16); +/* background: transparent; */ +/* selection-background-color: darkgray;*/ +} + + + false + + + true + + + + + + + + 75 + true + + + + QLineEdit { + border: none; + border-radius: 1px; + padding: 0 8px; + background: rgba(0, 0, 0, 16); +/* background: transparent; */ +/* selection-background-color: darkgray;*/ +} + + + false + + + true + + + + + + + Device ID + + + Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter + + + + + + + + + + + + + + 75 + true + + + + Configuration + + + + + + Telemetry Port Configuration + + + Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter + + + + + + + + 16777215 + 16777215 + + + + Set the telemetry port configuration + + + + + + + Telemetry Port Speed + + + Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter + + + + + + + + 16777215 + 16777215 + + + + Set the telemetry port speed + + + + + + + Flexi Port Configuration + + + Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter + + + + + + + + 16777215 + 16777215 + + + + Set the flexi port configuration + + + + + + + Flexi Port Speed + + + Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter + + + + + + + + 16777215 + 16777215 + + + + Set the flexi port speed + + + + + + + VCP Configuration + + + Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter + + + + + + + + 16777215 + 16777215 + + + + Set the virtual serial port configuration + + + + + + + VCP Speed + + + Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter + + + + + + + + 16777215 + 16777215 + + + + Set the virtual serial port speed + + + + + + + Max RF Datarate (bits/s) + + + Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter + + + + + + + + 16777215 + 16777215 + + + + Set the maximum RF datarate/channel bandwidth the modem will use + + + + + + + Max RF Tx Power(mW) + + + Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter + + + + + + + + 16777215 + 16777215 + + + + Set the maximum TX output power the modem will use + + + Qt::LeftToRight + + + 0 + + + + + + + Send Timeout (ms) + + + Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter + + + + + + + + 0 + 0 + + + + + 16777215 + 16777215 + + + + Calibrate the modems RF carrier frequency + + + true + + + 255 + + + + + + + Min Packet Size + + + Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter + + + + + + + + 0 + 0 + + + + + 16777215 + 16777215 + + + + Calibrate the modems RF carrier frequency + + + true + + + 255 + + + + + + + Frequency Calibration + + + Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter + + + + + + + + 0 + 0 + + + + + 16777215 + 16777215 + + + + Calibrate the modems RF carrier frequency + + + true + + + 255 + + + + + + + Frequency (Hz) + + + Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter + + + + + + + + 0 + 0 + + + + + 16777215 + 16777215 + + + + Set the modems RF carrier frequency + + + Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter + + + true + + + 0 + + + 1000000000 + + + 100000 + + + + + + + AES Encription + + + + + + + Courier New + 9 + + + + The AES encryption key - has to be the same key on the remote modem. + + + + + + 32 + + + true + + + Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter + + + + + + + + 0 + 0 + + + + Radomise the AES encryption key + + + Rand + + + + + + + + 75 + true + + + + Enable/Disable AES encryption + + + Qt::RightToLeft + + + Enable + + + + + + + + + + Qt::Vertical + + + + 20 + 40 + + + + + + + + Scan whole band to see where their is interference and/or used channels + + + Scan Spectrum + + + + + + + + + + + + + + + + + 0 + 0 + 0 + + + + + + + 0 + 0 + 0 + + + + + true + + + + + + + + + + + + + + + + + + + + QFrame::StyledPanel + + + QFrame::Raised + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + Send settings to the board but do not save to the non-volatile memory + + + Apply + + + + + + + Send settings to the board and save to the non-volatile memory + + + Save + + + false + + + + + + + + + + + + diff --git a/ground/openpilotgcs/src/plugins/coreplugin/OpenPilotGCS.xml b/ground/openpilotgcs/src/plugins/coreplugin/OpenPilotGCS.xml index 05ce6a7ea..64c653f23 100644 --- a/ground/openpilotgcs/src/plugins/coreplugin/OpenPilotGCS.xml +++ b/ground/openpilotgcs/src/plugins/coreplugin/OpenPilotGCS.xml @@ -1734,6 +1734,7 @@ 60 4294901760 + None x Accels 0 @@ -1742,6 +1743,7 @@ 4283782655 + None y Accels 0 @@ -1750,6 +1752,7 @@ 4283804160 + None z Accels 0 @@ -1774,6 +1777,7 @@ 20 4294901760 + None Channel-4 ActuatorCommand 0 @@ -1782,6 +1786,7 @@ 4294901760 + None Channel-5 ActuatorCommand 0 @@ -1790,6 +1795,7 @@ 4289374847 + None Channel-6 ActuatorCommand 0 @@ -1798,6 +1804,7 @@ 4289374847 + None Channel-7 ActuatorCommand 0 @@ -1822,6 +1829,7 @@ 60 4283760895 + None Roll AttitudeActual 0 @@ -1830,6 +1838,7 @@ 4278233600 + None Yaw AttitudeActual 0 @@ -1838,6 +1847,7 @@ 4294901760 + None Pitch AttitudeActual 0 @@ -1862,6 +1872,7 @@ 60 4278190080 + None Pressure BaroAltitude 0 @@ -1886,6 +1897,7 @@ 40 4278190207 + None Channel-1 ManualControlCommand 0 @@ -1894,6 +1906,7 @@ 4294901760 + None Channel-4 ManualControlCommand 0 @@ -1902,6 +1915,7 @@ 4294901760 + None Channel-5 ManualControlCommand 0 @@ -1910,6 +1924,7 @@ 4294901760 + None Channel-6 ManualControlCommand 0 @@ -1918,6 +1933,7 @@ 4294901760 + None Channel-7 ManualControlCommand 0 @@ -1926,6 +1942,7 @@ 4283825920 + None Channel-2 ManualControlCommand 0 @@ -1934,6 +1951,7 @@ 4294923520 + None Channel-3 ManualControlCommand 0 @@ -1942,6 +1960,7 @@ 4294967040 + None Channel-0 ManualControlCommand 0 @@ -1966,6 +1985,7 @@ 60 4294901760 + None x Accels 0 @@ -1974,6 +1994,7 @@ 4283782655 + None y Accels 0 @@ -1982,6 +2003,7 @@ 4283804160 + None z Accels 0 @@ -2006,6 +2028,7 @@ 60 4283804160 + None z Gyros 0 @@ -2014,6 +2037,7 @@ 4283782655 + None y Gyros 0 @@ -2022,6 +2046,7 @@ 4294901760 + None x Gyros 0 @@ -2046,6 +2071,7 @@ 60 4294901760 + None X Magnetometer 0 @@ -2054,6 +2080,7 @@ 4283782655 + None Y Magnetometer 0 @@ -2062,6 +2089,7 @@ 4283804160 + None Z Magnetometer 0 @@ -2086,6 +2114,7 @@ 240 4294945280 + None StackRemaining-System TaskInfo 0 @@ -2094,6 +2123,7 @@ 4294945280 + None StackRemaining-Actuator TaskInfo 0 @@ -2102,6 +2132,7 @@ 4294945280 + None StackRemaining-Guidance TaskInfo 0 @@ -2110,6 +2141,7 @@ 4294945280 + None StackRemaining-Watchdog TaskInfo 0 @@ -2118,6 +2150,7 @@ 4294945280 + None StackRemaining-TelemetryTx TaskInfo 0 @@ -2126,6 +2159,7 @@ 4294945280 + None StackRemaining-TelemetryTxPri TaskInfo 0 @@ -2134,6 +2168,7 @@ 4294945280 + None StackRemaining-TelemetryRx TaskInfo 0 @@ -2142,6 +2177,7 @@ 4294945280 + None StackRemaining-GPS TaskInfo 0 @@ -2150,6 +2186,7 @@ 4294945280 + None StackRemaining-ManualControl TaskInfo 0 @@ -2158,6 +2195,7 @@ 4294945280 + None StackRemaining-Altitude TaskInfo 0 @@ -2166,6 +2204,7 @@ 4294945280 + None StackRemaining-AHRSComms TaskInfo 0 @@ -2174,6 +2213,7 @@ 4294945280 + None StackRemaining-Stabilization TaskInfo 0 @@ -2198,6 +2238,7 @@ 20 4289374847 + None TxFailures GCSTelemetryStats 0 @@ -2206,6 +2247,7 @@ 4283782655 + None RxFailures GCSTelemetryStats 0 @@ -2214,6 +2256,7 @@ 4294901760 + None TxRetries GCSTelemetryStats 0 @@ -2238,6 +2281,7 @@ 240 4294945407 + None FlightTime SystemStats 0 diff --git a/ground/openpilotgcs/src/plugins/pipxtreme/images/view-refresh.svg b/ground/openpilotgcs/src/plugins/pipxtreme/images/view-refresh.svg deleted file mode 100644 index 3d0cc562d..000000000 --- a/ground/openpilotgcs/src/plugins/pipxtreme/images/view-refresh.svg +++ /dev/null @@ -1,230 +0,0 @@ - - - - - - - - image/svg+xml - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/ground/openpilotgcs/src/plugins/pipxtreme/pipxtreme.pluginspec b/ground/openpilotgcs/src/plugins/pipxtreme/pipxtreme.pluginspec deleted file mode 100644 index f67f414af..000000000 --- a/ground/openpilotgcs/src/plugins/pipxtreme/pipxtreme.pluginspec +++ /dev/null @@ -1,13 +0,0 @@ - - The OpenPilot Project - (C) 2011 Cathy Moss A.K.A. Pip - The GNU Public License (GPL) Version 3 - A plugin to configure the PipXtreme OP modem via USB HID or Serial Port - http://www.openpilot.org - - - - - - - diff --git a/ground/openpilotgcs/src/plugins/pipxtreme/pipxtreme.pro b/ground/openpilotgcs/src/plugins/pipxtreme/pipxtreme.pro deleted file mode 100644 index cd3d2f230..000000000 --- a/ground/openpilotgcs/src/plugins/pipxtreme/pipxtreme.pro +++ /dev/null @@ -1,38 +0,0 @@ -TEMPLATE = lib -TARGET = PipXtreme - -QT += svg -QT += opengl - -include(../../openpilotgcsplugin.pri) -include(../../plugins/coreplugin/coreplugin.pri) -include(../../plugins/uavobjects/uavobjects.pri) -include(../../plugins/uavtalk/uavtalk.pri) -include(../../plugins/rawhid/rawhid.pri) - -INCLUDEPATH += ../../libs/qextserialport/src - -HEADERS += pipxtremegadget.h \ - pipxtremegadgetconfiguration.h \ - pipxtremegadgetfactory.h \ - pipxtremegadgetoptionspage.h \ - pipxtremegadgetwidget.h \ - pipxtremeplugin.h \ - widgetbar.h - -SOURCES += pipxtremegadget.cpp \ - pipxtremegadgetconfiguration.cpp \ - pipxtremegadgetfactory.cpp \ - pipxtremegadgetoptionspage.cpp \ - pipxtremegadgetwidget.cpp \ - pipxtremeplugin.cpp \ - widgetbar.cpp - -OTHER_FILES += pipxtreme.pluginspec - -FORMS += \ - pipxtreme.ui \ - pipxtremegadgetoptionspage.ui - -RESOURCES += \ - pipxtreme.qrc diff --git a/ground/openpilotgcs/src/plugins/pipxtreme/pipxtreme.qrc b/ground/openpilotgcs/src/plugins/pipxtreme/pipxtreme.qrc deleted file mode 100644 index d397a930b..000000000 --- a/ground/openpilotgcs/src/plugins/pipxtreme/pipxtreme.qrc +++ /dev/null @@ -1,5 +0,0 @@ - - - images/view-refresh.svg - - diff --git a/ground/openpilotgcs/src/plugins/pipxtreme/pipxtreme.ui b/ground/openpilotgcs/src/plugins/pipxtreme/pipxtreme.ui deleted file mode 100644 index d5547494d..000000000 --- a/ground/openpilotgcs/src/plugins/pipxtreme/pipxtreme.ui +++ /dev/null @@ -1,1026 +0,0 @@ - - - PipXtremeWidget - - - - 0 - 0 - 571 - 527 - - - - Form - - - - - - - - - 100 - 0 - - - - The PC port serial baud rate - - - - - - - - 200 - 0 - - - - Set the PC port the modem is connected too - - - - - - - true - - - true - - - Connect to the modem (when normal telemetry is not used) - - - Connect - - - - - - - Refresh the list of serial and USB ports available - - - ... - - - - - - - Qt::Horizontal - - - - 40 - 20 - - - - - - - - Qt::Horizontal - - - - 40 - 20 - - - - - - - - Serial Baudrate - - - Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter - - - - - - - - - Qt::Horizontal - - - - - - - - - Serial Number (hex) - - - Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter - - - - - - - - 0 - 0 - - - - - 16777215 - 16777215 - - - - - 75 - false - true - - - - false - - - The modems serial number - - - QLineEdit { - border: none; - border-radius: 1px; - padding: 0 8px; - background: rgba(0, 0, 0, 16); -/* background: transparent; */ -/* selection-background-color: darkgray;*/ -} - - - true - - - Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter - - - true - - - - - - - Frequency Band - - - Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter - - - - - - - - 0 - 0 - - - - - 16777215 - 16777215 - - - - - 75 - true - - - - The modems frequency band - - - QLineEdit { - border: none; - border-radius: 1px; - padding: 0 8px; - background: rgba(0, 0, 0, 16); -/* background: transparent; */ -/* selection-background-color: darkgray;*/ -} - - - Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter - - - true - - - - - - - Min Frequency - - - Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter - - - - - - - - 0 - 0 - - - - - 16777215 - 16777215 - - - - - 75 - true - - - - The modems minimum allowed frequency - - - QLineEdit { - border: none; - border-radius: 1px; - padding: 0 8px; - background: rgba(0, 0, 0, 16); -/* background: transparent; */ -/* selection-background-color: darkgray;*/ -} - - - Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter - - - true - - - - - - - Max Frequency - - - Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter - - - - - - - - 0 - 0 - - - - - 16777215 - 16777215 - - - - - 75 - true - - - - The modems maximum allowed frequency - - - QLineEdit { - border: none; - border-radius: 1px; - padding: 0 8px; - background: rgba(0, 0, 0, 16); -/* background: transparent; */ -/* selection-background-color: darkgray;*/ -} - - - Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter - - - true - - - - - - - Frequency Step Size - - - Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter - - - - - - - - 0 - 0 - - - - - 16777215 - 16777215 - - - - - 75 - true - - - - The modems minimum frequency step size - - - QLineEdit { - border: none; - border-radius: 1px; - padding: 0 8px; - background: rgba(0, 0, 0, 16); -/* background: transparent; */ -/* selection-background-color: darkgray;*/ -} - - - Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter - - - true - - - - - - - Link State - - - Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter - - - - - - - - 0 - 0 - - - - - 16777215 - 16777215 - - - - - 75 - true - - - - The modems current state - - - QLineEdit { - border: none; - border-radius: 1px; - padding: 0 8px; - background: rgba(0, 0, 0, 16); -/* background: transparent; */ -/* selection-background-color: darkgray;*/ -} - - - Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter - - - true - - - - - - - RSSI - - - Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter - - - - - - - - 0 - 0 - - - - - 1 - 1 - - - - false - - - false - - - background-color: rgb(112, 112, 112); - - - - - - - Rx AFC - - - Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter - - - - - - - - 75 - true - - - - QLineEdit { - border: none; - border-radius: 1px; - padding: 0 8px; - background: rgba(0, 0, 0, 16); -/* background: transparent; */ -/* selection-background-color: darkgray;*/ -} - - - true - - - - - - - Firmware Version - - - Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter - - - - - - - - 75 - true - - - - QLineEdit { - border: none; - border-radius: 1px; - padding: 0 8px; - background: rgba(0, 0, 0, 16); -/* background: transparent; */ -/* selection-background-color: darkgray;*/ -} - - - false - - - true - - - - - - - - 0 - 0 - - - - - 16777215 - 16777215 - - - - Calibrate the modems RF carrier frequency - - - true - - - 255 - - - - - - - Frequency Calibration - - - Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter - - - - - - - - 0 - 0 - - - - - 16777215 - 16777215 - - - - Set the modems RF carrier frequency - - - Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter - - - true - - - 8 - - - 0.000000000000000 - - - 1000.000000000000000 - - - 0.000001000000000 - - - - - - - Frequency (MHz) - - - Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter - - - - - - - - 16777215 - 16777215 - - - - Set the maximum RF datarate/channel bandwidth the modem will use - - - - - - - Max RF Datarate (bits/s) - - - Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter - - - - - - - - 16777215 - 16777215 - - - - Set the maximum TX output power the modem will use - - - Qt::LeftToRight - - - 0 - - - - - - - Max RF Tx Power - - - Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter - - - - - - - - 16777215 - 16777215 - - - - Set the modems serial port speed - - - - - - - Serial Port Speed - - - Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter - - - - - - - Mode - - - Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter - - - - - - - true - - - - 16777215 - 16777215 - - - - Set the modems operating mode - - - - - - - - 0 - 0 - - - - - 16777215 - 16777215 - - - - Serial number of the remote modem you want to pair with - - - - - - 8 - - - Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter - - - - - - - Paired Serial Number (hex) - - - Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter - - - - - - - Retries - - - Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter - - - - - - - - 75 - true - - - - QLineEdit { - border: none; - border-radius: 1px; - padding: 0 8px; - background: rgba(0, 0, 0, 16); -/* background: transparent; */ -/* selection-background-color: darkgray;*/ -} - - - false - - - true - - - - - - - RTS time (ms) - - - Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter - - - - - - - Ready-To-Send time is the maximum time the modem waits for more data before sending it. This is to try and make the RF link a little more efficient by creating larger packets. - - - 100 - - - - - - - - - - - AES Encryption Key - - - Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter - - - - - - - - Courier New - 9 - - - - The AES encryption key - has to be the same key on the remote modem. - - - - - - 32 - - - true - - - Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter - - - - - - - - 0 - 0 - - - - Radomise the AES encryption key - - - Rand - - - - - - - Enable/Disable AES encryption - - - Qt::RightToLeft - - - AES Enable - - - - - - - - - Qt::Horizontal - - - - - - - - - true - - - Restore the settings from a file - - - Import - - - - - - - true - - - Save the settings into a file - - - Export - - - - - - - Qt::Horizontal - - - - 40 - 20 - - - - - - - - Click to save your new settings into PipX flash - - - - - - Save to flash - - - - - - - - - Qt::Horizontal - - - - - - - TextLabel - - - - - - - - - Scan whole band to see where their is interference and/or used channels - - - Scan Spectrum - - - - - - - Qt::Horizontal - - - - 40 - 20 - - - - - - - - - - - - - - 0 - 0 - 0 - - - - - - - 0 - 0 - 0 - - - - - true - - - - - - - - - - WidgetBar - QWidget -
widgetbar.h
-
-
- - -
diff --git a/ground/openpilotgcs/src/plugins/pipxtreme/pipxtremegadget.cpp b/ground/openpilotgcs/src/plugins/pipxtreme/pipxtremegadget.cpp deleted file mode 100644 index d38e36b67..000000000 --- a/ground/openpilotgcs/src/plugins/pipxtreme/pipxtremegadget.cpp +++ /dev/null @@ -1,48 +0,0 @@ -/** - ****************************************************************************** - * - * @file pipxtremegadget.cpp - * @author The OpenPilot Team, http://www.openpilot.org Copyright (C) 2010. - * @addtogroup GCSPlugins GCS Plugins - * @{ - * @{ - *****************************************************************************/ -/* - * 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 "pipxtremegadget.h" -#include "pipxtremegadgetwidget.h" -#include "pipxtremegadgetconfiguration.h" - -PipXtremeGadget::PipXtremeGadget(QString classId, PipXtremeGadgetWidget *widget, QWidget *parent) : - IUAVGadget(classId, parent), - m_widget(widget) -{ -} - -PipXtremeGadget::~PipXtremeGadget() -{ - delete m_widget; - m_widget = NULL; -} - -// Loads a configuration. -void PipXtremeGadget::loadConfiguration(IUAVGadgetConfiguration* config) -{ - Q_UNUSED(config); -/* PipXtremeGadgetConfiguration *m = qobject_cast< PipXtremeGadgetConfiguration*>(config); - */ -} - diff --git a/ground/openpilotgcs/src/plugins/pipxtreme/pipxtremegadget.h b/ground/openpilotgcs/src/plugins/pipxtreme/pipxtremegadget.h deleted file mode 100644 index 547cb81a4..000000000 --- a/ground/openpilotgcs/src/plugins/pipxtreme/pipxtremegadget.h +++ /dev/null @@ -1,55 +0,0 @@ -/** - ****************************************************************************** - * - * @file pipxtremegadget.h - * @author The OpenPilot Team, http://www.openpilot.org Copyright (C) 2010. - * @addtogroup GCSPlugins GCS Plugins - * @{ - * @{ - * @brief The YModem protocol serial uploader plugin - *****************************************************************************/ -/* - * 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 PIPXTREMEGADGET_H -#define PIPXTREMEGADGET_H - -#include -#include "pipxtremegadgetwidget.h" - -class IUAVGadget; -class QWidget; -class QString; -class PipXtremeGadgetWidget; - -using namespace Core; - -class PipXtremeGadget : public Core::IUAVGadget -{ - Q_OBJECT -public: - PipXtremeGadget(QString classId, PipXtremeGadgetWidget *widget, QWidget *parent = 0); - ~PipXtremeGadget(); - - QWidget *widget() { return m_widget; } - void loadConfiguration(IUAVGadgetConfiguration* config); - -private: - PipXtremeGadgetWidget *m_widget; -}; - -#endif - diff --git a/ground/openpilotgcs/src/plugins/pipxtreme/pipxtremegadgetconfiguration.cpp b/ground/openpilotgcs/src/plugins/pipxtreme/pipxtremegadgetconfiguration.cpp deleted file mode 100644 index c59d49ea6..000000000 --- a/ground/openpilotgcs/src/plugins/pipxtreme/pipxtremegadgetconfiguration.cpp +++ /dev/null @@ -1,66 +0,0 @@ -/** - ****************************************************************************** - * - * @file pipxtremegadgetconfiguration.cpp - * @author The OpenPilot Team, http://www.openpilot.org Copyright (C) 2010. - * @addtogroup GCSPlugins GCS Plugins - * @{ - * @{ - *****************************************************************************/ -/* - * 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 "pipxtremegadgetconfiguration.h" -#include - -/** - * Loads a saved configuration or defaults if non exist. - * - */ -PipXtremeGadgetConfiguration::PipXtremeGadgetConfiguration(QString classId, QSettings* qSettings, QObject *parent) : - IUAVGadgetConfiguration(classId, parent) -{ - //if a saved configuration exists load it - if (qSettings != 0) - { - } -} - -PipXtremeGadgetConfiguration::~PipXtremeGadgetConfiguration() -{ -} - -/** - * Clones a configuration. - * - */ -IUAVGadgetConfiguration *PipXtremeGadgetConfiguration::clone() -{ - PipXtremeGadgetConfiguration *m = new PipXtremeGadgetConfiguration(this->classId()); - return m; -} - -/** - * Saves a configuration. - * - */ -void PipXtremeGadgetConfiguration::saveConfig(QSettings *qSettings) const -{ - if (qSettings) - { - - } -} diff --git a/ground/openpilotgcs/src/plugins/pipxtreme/pipxtremegadgetconfiguration.h b/ground/openpilotgcs/src/plugins/pipxtreme/pipxtremegadgetconfiguration.h deleted file mode 100644 index e65a5368c..000000000 --- a/ground/openpilotgcs/src/plugins/pipxtreme/pipxtremegadgetconfiguration.h +++ /dev/null @@ -1,48 +0,0 @@ -/** - ****************************************************************************** - * - * @file pipxtremegadgetconfiguration.h - * @author The OpenPilot Team, http://www.openpilot.org Copyright (C) 2010. - * @addtogroup GCSPlugins GCS Plugins - * @{ - * @{ - * @brief The YModem protocol serial uploader plugin - *****************************************************************************/ -/* - * 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 PIPXTREMEGADGETCONFIGURATION_H -#define PIPXTREMEGADGETCONFIGURATION_H - -#include -#include - -using namespace Core; - -class PipXtremeGadgetConfiguration : public IUAVGadgetConfiguration -{ -Q_OBJECT -public: - explicit PipXtremeGadgetConfiguration(QString classId, QSettings* qSettings = 0, QObject *parent = 0); - ~PipXtremeGadgetConfiguration(); - - void saveConfig(QSettings *settings) const; - IUAVGadgetConfiguration *clone(); - -private: -}; - -#endif diff --git a/ground/openpilotgcs/src/plugins/pipxtreme/pipxtremegadgetfactory.cpp b/ground/openpilotgcs/src/plugins/pipxtreme/pipxtremegadgetfactory.cpp deleted file mode 100644 index 4574913d5..000000000 --- a/ground/openpilotgcs/src/plugins/pipxtreme/pipxtremegadgetfactory.cpp +++ /dev/null @@ -1,51 +0,0 @@ -/** - ****************************************************************************** - * - * @file pipxtremegadgetfactory.cpp - * @author The OpenPilot Team, http://www.openpilot.org Copyright (C) 2010. - * @addtogroup GCSPlugins GCS Plugins - * @{ - * @{ - *****************************************************************************/ -/* - * 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 "pipxtremegadgetfactory.h" -#include "pipxtremegadgetwidget.h" -#include "pipxtremegadget.h" -#include "pipxtremegadgetconfiguration.h" -#include "pipxtremegadgetoptionspage.h" -#include - -PipXtremeGadgetFactory::PipXtremeGadgetFactory(QObject *parent) : - IUAVGadgetFactory(QString("PipXtreme"), tr("PipXtreme"), parent) -{ -} - -PipXtremeGadgetFactory::~PipXtremeGadgetFactory() -{ -} - -Core::IUAVGadget* PipXtremeGadgetFactory::createGadget(QWidget *parent) -{ - PipXtremeGadgetWidget *gadgetWidget = new PipXtremeGadgetWidget(parent); - return new PipXtremeGadget(QString("PipXtreme"), gadgetWidget, parent); -} - -IUAVGadgetConfiguration * PipXtremeGadgetFactory::createConfiguration(QSettings *qSettings) -{ - return new PipXtremeGadgetConfiguration(QString("PipXtreme"), qSettings); -} diff --git a/ground/openpilotgcs/src/plugins/pipxtreme/pipxtremegadgetfactory.h b/ground/openpilotgcs/src/plugins/pipxtreme/pipxtremegadgetfactory.h deleted file mode 100644 index 8bd48f46b..000000000 --- a/ground/openpilotgcs/src/plugins/pipxtreme/pipxtremegadgetfactory.h +++ /dev/null @@ -1,50 +0,0 @@ -/** - ****************************************************************************** - * - * @file pipxtremegadgetfactory.h - * @author The OpenPilot Team, http://www.openpilot.org Copyright (C) 2010. - * @addtogroup GCSPlugins GCS Plugins - * @{ - * @{ - *****************************************************************************/ -/* - * 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 PIPXTREMEGADGETFACTORY_H -#define PIPXTREMEGADGETFACTORY_H - -#include - -namespace Core { - class IUAVGadget; - class IUAVGadgetFactory; -} - -using namespace Core; - -class PipXtremeGadgetFactory : public Core::IUAVGadgetFactory -{ - Q_OBJECT - -public: - PipXtremeGadgetFactory(QObject *parent = 0); - ~PipXtremeGadgetFactory(); - - Core::IUAVGadget * createGadget(QWidget *parent); - IUAVGadgetConfiguration * createConfiguration(QSettings *qSettings); -}; - -#endif diff --git a/ground/openpilotgcs/src/plugins/pipxtreme/pipxtremegadgetoptionspage.cpp b/ground/openpilotgcs/src/plugins/pipxtreme/pipxtremegadgetoptionspage.cpp deleted file mode 100644 index 2fd8057af..000000000 --- a/ground/openpilotgcs/src/plugins/pipxtreme/pipxtremegadgetoptionspage.cpp +++ /dev/null @@ -1,72 +0,0 @@ -/** - ****************************************************************************** - * - * @file pipxtremegadgetoptionspage.cpp - * @author The OpenPilot Team, http://www.openpilot.org Copyright (C) 2010. - * @addtogroup GCSPlugins GCS Plugins - * @{ - * @{ - *****************************************************************************/ -/* - * 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 "pipxtremegadgetoptionspage.h" -#include "pipxtremegadgetconfiguration.h" -#include "ui_pipxtremegadgetoptionspage.h" - -PipXtremeGadgetOptionsPage::PipXtremeGadgetOptionsPage(PipXtremeGadgetConfiguration *config, QObject *parent) : - IOptionsPage(parent), - options_page(NULL), - m_config(config) -{ -} - -//creates options page widget -QWidget *PipXtremeGadgetOptionsPage::createPage(QWidget *parent) -{ -// QWidget *widget = new QWidget; -// return widget; - - options_page = new Ui::PipXtremeGadgetOptionsPage(); - QWidget *optionsPageWidget = new QWidget; - options_page->setupUi(optionsPageWidget); - - - - - return optionsPageWidget; -} -/** - * Called when the user presses apply or OK. - * - * Saves the current values - * - */ -void PipXtremeGadgetOptionsPage::apply() -{ - -} - -void PipXtremeGadgetOptionsPage::finish() -{ - if (options_page) - { - delete options_page; - options_page = NULL; - } -} - - diff --git a/ground/openpilotgcs/src/plugins/pipxtreme/pipxtremegadgetoptionspage.h b/ground/openpilotgcs/src/plugins/pipxtreme/pipxtremegadgetoptionspage.h deleted file mode 100644 index 97aa0006e..000000000 --- a/ground/openpilotgcs/src/plugins/pipxtreme/pipxtremegadgetoptionspage.h +++ /dev/null @@ -1,62 +0,0 @@ -/** - ****************************************************************************** - * - * @file pipxtremegadgetoptionspage.h - * @author The OpenPilot Team, http://www.openpilot.org Copyright (C) 2010. - * @addtogroup GCSPlugins GCS Plugins - * @{ - * @{ - *****************************************************************************/ -/* - * 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 PIPXTREMEGADGETOPTIONSPAGE_H -#define PIPXTREMEGADGETOPTIONSPAGE_H - -#include -#include "coreplugin/dialogs/ioptionspage.h" -#include "QString" -#include -#include - -namespace Core { - class IUAVGadgetConfiguration; -} - -class PipXtremeGadgetConfiguration; - -namespace Ui { - class PipXtremeGadgetOptionsPage; -} - -using namespace Core; - -class PipXtremeGadgetOptionsPage : public IOptionsPage -{ -Q_OBJECT -public: - explicit PipXtremeGadgetOptionsPage(PipXtremeGadgetConfiguration *config, QObject *parent = 0); - - QWidget *createPage(QWidget *parent); - void apply(); - void finish(); - -private: - Ui::PipXtremeGadgetOptionsPage *options_page; - PipXtremeGadgetConfiguration *m_config; -}; - -#endif diff --git a/ground/openpilotgcs/src/plugins/pipxtreme/pipxtremegadgetoptionspage.ui b/ground/openpilotgcs/src/plugins/pipxtreme/pipxtremegadgetoptionspage.ui deleted file mode 100644 index 3436b9567..000000000 --- a/ground/openpilotgcs/src/plugins/pipxtreme/pipxtremegadgetoptionspage.ui +++ /dev/null @@ -1,51 +0,0 @@ - - - PipXtremeGadgetOptionsPage - - - - 0 - 0 - 587 - 359 - - - - - 0 - 0 - - - - Form - - - - 0 - - - - - - - - - 10 - - - - No options to set - - - Qt::AlignCenter - - - - - - - - - - - diff --git a/ground/openpilotgcs/src/plugins/pipxtreme/pipxtremegadgetwidget.cpp b/ground/openpilotgcs/src/plugins/pipxtreme/pipxtremegadgetwidget.cpp deleted file mode 100644 index 6dc2d1047..000000000 --- a/ground/openpilotgcs/src/plugins/pipxtreme/pipxtremegadgetwidget.cpp +++ /dev/null @@ -1,1431 +0,0 @@ -/** - ****************************************************************************** - * - * @file pipxtremegadgetwidget.cpp - * @author The OpenPilot Team, http://www.openpilot.org Copyright (C) 2010. - * @addtogroup GCSPlugins GCS Plugins - * @{ - * @{ - *****************************************************************************/ -/* - * 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 -#include -#include -#include -#include -#include -#include - -#include "pipxtremegadgetwidget.h" - -#define NO_PORT 0 -#define SERIAL_PORT 1 -#define USB_PORT 2 - -// *************************************************************************************** -// config packet details - -#define MAX_RETRIES 7 -#define RETRY_TIME 500 // ms - -#define PIPX_HEADER_MARKER 0x76b38a52 - -enum { - PIPX_PACKET_TYPE_REQ_DETAILS = 0, - PIPX_PACKET_TYPE_DETAILS, - PIPX_PACKET_TYPE_REQ_SETTINGS, - PIPX_PACKET_TYPE_SETTINGS, - PIPX_PACKET_TYPE_REQ_STATE, - PIPX_PACKET_TYPE_STATE, - PIPX_PACKET_TYPE_SPECTRUM -}; - -enum { - FREQBAND_UNKNOWN = 0, - FREQBAND_434MHz, - FREQBAND_868MHz, - FREQBAND_915MHz -}; - -enum { - LINK_DISCONNECTED = 0, - LINK_CONNECTING, - LINK_CONNECTED -}; - -// *************************************************************************************** - -enum { - MODE_NORMAL = 0, // normal 2-way packet mode - MODE_STREAM_TX, // 1-way continuous tx packet mode - MODE_STREAM_RX, // 1-way continuous rx packet mode - MODE_PPM_TX, // PPM tx mode - MODE_PPM_RX, // PPM rx mode - MODE_SCAN_SPECTRUM, // scan the receiver over the whole band - MODE_TX_BLANK_CARRIER_TEST, // blank carrier Tx mode (for calibrating the carrier frequency say) - MODE_TX_SPECTRUM_TEST // pseudo random Tx data mode (for checking the Tx carrier spectrum) -}; - -// *************************************************************************************** - -#define Poly32 0x04c11db7 // 32-bit polynomial .. this should produce the same as the STM32 hardware CRC - -uint32_t CRC_Table32[] = { - 0x00000000, 0x04c11db7, 0x09823b6e, 0x0d4326d9, 0x130476dc, 0x17c56b6b, 0x1a864db2, 0x1e475005, - 0x2608edb8, 0x22c9f00f, 0x2f8ad6d6, 0x2b4bcb61, 0x350c9b64, 0x31cd86d3, 0x3c8ea00a, 0x384fbdbd, - 0x4c11db70, 0x48d0c6c7, 0x4593e01e, 0x4152fda9, 0x5f15adac, 0x5bd4b01b, 0x569796c2, 0x52568b75, - 0x6a1936c8, 0x6ed82b7f, 0x639b0da6, 0x675a1011, 0x791d4014, 0x7ddc5da3, 0x709f7b7a, 0x745e66cd, - 0x9823b6e0, 0x9ce2ab57, 0x91a18d8e, 0x95609039, 0x8b27c03c, 0x8fe6dd8b, 0x82a5fb52, 0x8664e6e5, - 0xbe2b5b58, 0xbaea46ef, 0xb7a96036, 0xb3687d81, 0xad2f2d84, 0xa9ee3033, 0xa4ad16ea, 0xa06c0b5d, - 0xd4326d90, 0xd0f37027, 0xddb056fe, 0xd9714b49, 0xc7361b4c, 0xc3f706fb, 0xceb42022, 0xca753d95, - 0xf23a8028, 0xf6fb9d9f, 0xfbb8bb46, 0xff79a6f1, 0xe13ef6f4, 0xe5ffeb43, 0xe8bccd9a, 0xec7dd02d, - 0x34867077, 0x30476dc0, 0x3d044b19, 0x39c556ae, 0x278206ab, 0x23431b1c, 0x2e003dc5, 0x2ac12072, - 0x128e9dcf, 0x164f8078, 0x1b0ca6a1, 0x1fcdbb16, 0x018aeb13, 0x054bf6a4, 0x0808d07d, 0x0cc9cdca, - 0x7897ab07, 0x7c56b6b0, 0x71159069, 0x75d48dde, 0x6b93dddb, 0x6f52c06c, 0x6211e6b5, 0x66d0fb02, - 0x5e9f46bf, 0x5a5e5b08, 0x571d7dd1, 0x53dc6066, 0x4d9b3063, 0x495a2dd4, 0x44190b0d, 0x40d816ba, - 0xaca5c697, 0xa864db20, 0xa527fdf9, 0xa1e6e04e, 0xbfa1b04b, 0xbb60adfc, 0xb6238b25, 0xb2e29692, - 0x8aad2b2f, 0x8e6c3698, 0x832f1041, 0x87ee0df6, 0x99a95df3, 0x9d684044, 0x902b669d, 0x94ea7b2a, - 0xe0b41de7, 0xe4750050, 0xe9362689, 0xedf73b3e, 0xf3b06b3b, 0xf771768c, 0xfa325055, 0xfef34de2, - 0xc6bcf05f, 0xc27dede8, 0xcf3ecb31, 0xcbffd686, 0xd5b88683, 0xd1799b34, 0xdc3abded, 0xd8fba05a, - 0x690ce0ee, 0x6dcdfd59, 0x608edb80, 0x644fc637, 0x7a089632, 0x7ec98b85, 0x738aad5c, 0x774bb0eb, - 0x4f040d56, 0x4bc510e1, 0x46863638, 0x42472b8f, 0x5c007b8a, 0x58c1663d, 0x558240e4, 0x51435d53, - 0x251d3b9e, 0x21dc2629, 0x2c9f00f0, 0x285e1d47, 0x36194d42, 0x32d850f5, 0x3f9b762c, 0x3b5a6b9b, - 0x0315d626, 0x07d4cb91, 0x0a97ed48, 0x0e56f0ff, 0x1011a0fa, 0x14d0bd4d, 0x19939b94, 0x1d528623, - 0xf12f560e, 0xf5ee4bb9, 0xf8ad6d60, 0xfc6c70d7, 0xe22b20d2, 0xe6ea3d65, 0xeba91bbc, 0xef68060b, - 0xd727bbb6, 0xd3e6a601, 0xdea580d8, 0xda649d6f, 0xc423cd6a, 0xc0e2d0dd, 0xcda1f604, 0xc960ebb3, - 0xbd3e8d7e, 0xb9ff90c9, 0xb4bcb610, 0xb07daba7, 0xae3afba2, 0xaafbe615, 0xa7b8c0cc, 0xa379dd7b, - 0x9b3660c6, 0x9ff77d71, 0x92b45ba8, 0x9675461f, 0x8832161a, 0x8cf30bad, 0x81b02d74, 0x857130c3, - 0x5d8a9099, 0x594b8d2e, 0x5408abf7, 0x50c9b640, 0x4e8ee645, 0x4a4ffbf2, 0x470cdd2b, 0x43cdc09c, - 0x7b827d21, 0x7f436096, 0x7200464f, 0x76c15bf8, 0x68860bfd, 0x6c47164a, 0x61043093, 0x65c52d24, - 0x119b4be9, 0x155a565e, 0x18197087, 0x1cd86d30, 0x029f3d35, 0x065e2082, 0x0b1d065b, 0x0fdc1bec, - 0x3793a651, 0x3352bbe6, 0x3e119d3f, 0x3ad08088, 0x2497d08d, 0x2056cd3a, 0x2d15ebe3, 0x29d4f654, - 0xc5a92679, 0xc1683bce, 0xcc2b1d17, 0xc8ea00a0, 0xd6ad50a5, 0xd26c4d12, 0xdf2f6bcb, 0xdbee767c, - 0xe3a1cbc1, 0xe760d676, 0xea23f0af, 0xeee2ed18, 0xf0a5bd1d, 0xf464a0aa, 0xf9278673, 0xfde69bc4, - 0x89b8fd09, 0x8d79e0be, 0x803ac667, 0x84fbdbd0, 0x9abc8bd5, 0x9e7d9662, 0x933eb0bb, 0x97ffad0c, - 0xafb010b1, 0xab710d06, 0xa6322bdf, 0xa2f33668, 0xbcb4666d, 0xb8757bda, 0xb5365d03, 0xb1f740b4 -}; - -// *************************************************************************************** - -// constructor -PipXtremeGadgetWidget::PipXtremeGadgetWidget(QWidget *parent) : - QWidget(parent), - m_widget(NULL), - m_ioDevice(NULL), - m_stage(PIPX_IDLE) -{ - m_widget = new Ui_PipXtremeWidget(); - m_widget->setupUi(this); - - #if QT_VERSION >= 0x040700 - qsrand(QDateTime::currentDateTime().toMSecsSinceEpoch()); - #else - qsrand(QDateTime::currentDateTime().toTime_t()); - #endif - - device_input_buffer.size = 8192; - device_input_buffer.used = 0; - device_input_buffer.buffer = new quint8 [device_input_buffer.size]; - - memset(&pipx_config_details, 0, sizeof(pipx_config_details)); - memset(&pipx_config_settings, 0, sizeof(pipx_config_settings)); - - m_widget->comboBox_SerialBaudrate->clear(); - m_widget->comboBox_SerialBaudrate->addItem("1200", 1200); - m_widget->comboBox_SerialBaudrate->addItem("2400", 2400); - m_widget->comboBox_SerialBaudrate->addItem("4800", 4800); - m_widget->comboBox_SerialBaudrate->addItem("9600", 9600); - m_widget->comboBox_SerialBaudrate->addItem("19200", 19200); - m_widget->comboBox_SerialBaudrate->addItem("38400", 38400); - m_widget->comboBox_SerialBaudrate->addItem("57600", 57600); - m_widget->comboBox_SerialBaudrate->addItem("115200", 115200); - #if (defined Q_OS_WIN) - m_widget->comboBox_SerialBaudrate->addItem("230400", 230400); - m_widget->comboBox_SerialBaudrate->addItem("460800", 460800); - m_widget->comboBox_SerialBaudrate->addItem("921600", 921600); - #endif - m_widget->comboBox_SerialBaudrate->setCurrentIndex(m_widget->comboBox_SerialBaudrate->findText("57600")); - - m_widget->comboBox_Mode->clear(); - m_widget->comboBox_Mode->addItem("Normal", MODE_NORMAL); - m_widget->comboBox_Mode->addItem("Continuous Stream Tx", MODE_STREAM_TX); - m_widget->comboBox_Mode->addItem("Continuous Stream Rx", MODE_STREAM_RX); - m_widget->comboBox_Mode->addItem("PPM Tx", MODE_PPM_TX); - m_widget->comboBox_Mode->addItem("PPM Rx", MODE_PPM_RX); - m_widget->comboBox_Mode->addItem("Scan Spectrum", MODE_SCAN_SPECTRUM); - m_widget->comboBox_Mode->addItem("Test Tx Blank Carrier Frequency", MODE_TX_BLANK_CARRIER_TEST); - m_widget->comboBox_Mode->addItem("Test Tx Spectrum", MODE_TX_SPECTRUM_TEST); - - m_widget->comboBox_SerialPortSpeed->clear(); - for (int i = 0; i < m_widget->comboBox_SerialBaudrate->count(); i++) - m_widget->comboBox_SerialPortSpeed->addItem(m_widget->comboBox_SerialBaudrate->itemText(i), m_widget->comboBox_SerialBaudrate->itemData(i)); - m_widget->comboBox_SerialPortSpeed->setCurrentIndex(m_widget->comboBox_SerialPortSpeed->findText("57600")); - - m_widget->comboBox_MaxRFBandwidth->clear(); - m_widget->comboBox_MaxRFBandwidth->addItem("500", 500); - m_widget->comboBox_MaxRFBandwidth->addItem("1000", 1000); - m_widget->comboBox_MaxRFBandwidth->addItem("2000", 2000); - m_widget->comboBox_MaxRFBandwidth->addItem("4000", 4000); - m_widget->comboBox_MaxRFBandwidth->addItem("8000", 8000); - m_widget->comboBox_MaxRFBandwidth->addItem("9600", 9600); - m_widget->comboBox_MaxRFBandwidth->addItem("16000", 16000); - m_widget->comboBox_MaxRFBandwidth->addItem("19200", 19200); - m_widget->comboBox_MaxRFBandwidth->addItem("24000", 24000); - m_widget->comboBox_MaxRFBandwidth->addItem("32000", 32000); - m_widget->comboBox_MaxRFBandwidth->addItem("64000", 64000); - m_widget->comboBox_MaxRFBandwidth->addItem("128000", 128000); - m_widget->comboBox_MaxRFBandwidth->addItem("192000", 192000); - m_widget->comboBox_MaxRFBandwidth->addItem("256000", 256000); - m_widget->comboBox_MaxRFBandwidth->setCurrentIndex(m_widget->comboBox_MaxRFBandwidth->findText("128000")); - - m_widget->comboBox_MaxRFTxPower->clear(); - m_widget->comboBox_MaxRFTxPower->addItem("1.25mW", 0); - m_widget->comboBox_MaxRFTxPower->addItem("1.6mW", 1); - m_widget->comboBox_MaxRFTxPower->addItem("3.16mW", 2); - m_widget->comboBox_MaxRFTxPower->addItem("6.3mW", 3); - m_widget->comboBox_MaxRFTxPower->addItem("12.6mW", 4); - m_widget->comboBox_MaxRFTxPower->addItem("25mW", 5); - m_widget->comboBox_MaxRFTxPower->addItem("50mW", 6); - m_widget->comboBox_MaxRFTxPower->addItem("100mW", 7); - m_widget->comboBox_MaxRFTxPower->setCurrentIndex(m_widget->comboBox_MaxRFTxPower->findText("12.6mW")); - - m_widget->doubleSpinBox_Frequency->setSingleStep(0.00015625); - - m_widget->widgetRSSI->setMinimum(-120); - m_widget->widgetRSSI->setMaximum(0); - m_widget->widgetRSSI->setValue(m_widget->widgetRSSI->minimum()); - - m_widget->label_RSSI->setText("RSSI"); - - m_widget->graphicsView_Spectrum->setScene(new QGraphicsScene(this)); - m_widget->graphicsView_Spectrum->setViewport(new QGLWidget(QGLFormat(QGL::SampleBuffers))); -// m_widget->graphicsView_Spectrum->setViewport(new QWidget); - m_widget->graphicsView_Spectrum->setCacheMode(QGraphicsView::CacheBackground); - m_widget->graphicsView_Spectrum->setRenderHints(QPainter::Antialiasing | QPainter::TextAntialiasing | QPainter::SmoothPixmapTransform | QPainter::HighQualityAntialiasing); - QGraphicsScene *spec_scene = m_widget->graphicsView_Spectrum->scene(); - if (spec_scene) - { - spec_scene->setBackgroundBrush(QColor(80, 80, 80)); - spec_scene->clear(); - -// spec_scene->addItem(m_background); -// spec_scene->addItem(m_joystickEnd); -// spec_scene->setSceneRect(m_background->boundingRect()); - } - - m_widget->pushButton_Save->setEnabled(false); - m_widget->pushButton_ScanSpectrum->setEnabled(false); - m_widget->pushButton_Import->setEnabled(false); - m_widget->pushButton_Export->setEnabled(false); - - QIcon rbi; - rbi.addFile(QString(":pipxtreme/images/view-refresh.svg")); - m_widget->refreshPorts->setIcon(rbi); - - // Listen to telemetry connection events - ExtensionSystem::PluginManager *pluginManager = ExtensionSystem::PluginManager::instance(); - if (pluginManager) - { - TelemetryManager *telemetryManager = pluginManager->getObject(); - if (telemetryManager) - { - connect(telemetryManager, SIGNAL(myStart()), this, SLOT(onTelemetryStart())); - connect(telemetryManager, SIGNAL(myStop()), this, SLOT(onTelemetryStop())); - connect(telemetryManager, SIGNAL(connected()), this, SLOT(onTelemetryConnect())); - connect(telemetryManager, SIGNAL(disconnected()), this, SLOT(onTelemetryDisconnect())); - } - } - - getPorts(); - - connect(m_widget->connectButton, SIGNAL(clicked()), this, SLOT(connectDisconnect())); - connect(m_widget->refreshPorts, SIGNAL(clicked()), this, SLOT(getPorts())); - connect(m_widget->pushButton_AESKeyRandom, SIGNAL(clicked()), this, SLOT(randomiseAESKey())); - connect(m_widget->pushButton_ScanSpectrum, SIGNAL(clicked()), this, SLOT(scanSpectrum())); - connect(m_widget->pushButton_Save, SIGNAL(clicked()), this, SLOT(saveToFlash())); - connect(m_widget->lineEdit_AESKey, SIGNAL(textChanged(const QString &)), this, SLOT(textChangedAESKey(const QString &))); - connect(m_widget->pushButton_Import, SIGNAL(clicked()), this, SLOT(importSettings())); - connect(m_widget->pushButton_Export, SIGNAL(clicked()), this, SLOT(exportSettings())); -} - -// destructor .. this never gets called :( -PipXtremeGadgetWidget::~PipXtremeGadgetWidget() -{ - disconnectPort(false); - - device_input_buffer.mutex.lock(); - if (device_input_buffer.buffer) - { - delete [] device_input_buffer.buffer; - device_input_buffer.buffer = NULL; - device_input_buffer.size = 0; - device_input_buffer.used = 0; - } - device_input_buffer.mutex.unlock(); -} - -// *************************************************************************************** - -void PipXtremeGadgetWidget::resizeEvent(QResizeEvent *event) -{ - if (m_widget) - { - if (m_widget->graphicsView_Spectrum) - { - QGraphicsScene *spec_scene = m_widget->graphicsView_Spectrum->scene(); - if (spec_scene) - { -// spec_scene->setSceneRect(QRect(QPoint(0, 0), event->size())); -// spec_scene->setBackgroundBrush(Qt::black); - } - } - } - -// PipXtremeGadgetWidget::resizeEvent(event); -} - -// *************************************************************************************** - -void PipXtremeGadgetWidget::onComboBoxPorts_currentIndexChanged(int index) -{ - if (index < 0) - { - m_widget->comboBox_SerialBaudrate->setEnabled(false); - return; - } - - int type = m_widget->comboBox_Ports->itemData(index).toInt(); - - m_widget->comboBox_SerialBaudrate->setEnabled(type == SERIAL_PORT); -} - -// *************************************************************************************** - -uint32_t PipXtremeGadgetWidget::updateCRC32(uint32_t crc, uint8_t b) -{ - return (crc << 8) ^ CRC_Table32[(crc >> 24) ^ b]; -} - -uint32_t PipXtremeGadgetWidget::updateCRC32Data(uint32_t crc, void *data, int len) -{ - register uint8_t *p = (uint8_t *)data; - register uint32_t _crc = crc; - for (int i = len; i > 0; i--) - _crc = (_crc << 8) ^ CRC_Table32[(_crc >> 24) ^ *p++]; - return _crc; -} - -// Generate the CRC table -void PipXtremeGadgetWidget::makeCRC_Table32() -{ - for (int i = 0; i < 256; i++) - { - uint32_t crc = i; - for (int j = 8; j > 0; j--) - crc = (crc & 1) ? (crc << 1) ^ Poly32 : crc << 1; - CRC_Table32[i] = crc; - } -} - -// *************************************************************************************** - -QString PipXtremeGadgetWidget::getSerialPortDevice(const QString &friendName) -{ - QList ports = QextSerialEnumerator::getPorts(); - - foreach (QextPortInfo port, ports) - { - #ifdef Q_OS_WIN - if (port.friendName == friendName) - return port.portName; - #else - if (port.friendName == friendName) - return port.physName; - #endif - } - - return ""; -} - -bool sortSerialPorts(const QextPortInfo &s1, const QextPortInfo &s2) -{ - return (s1.portName < s2.portName); -} - -void PipXtremeGadgetWidget::getPorts() -{ - disconnect(m_widget->comboBox_Ports, 0, 0, 0); - - m_widget->comboBox_Ports->clear(); - - // ******************************** - // Populate the telemetry combo box with serial ports - - QList serial_ports = QextSerialEnumerator::getPorts(); - - qSort(serial_ports.begin(), serial_ports.end(), sortSerialPorts); - - QStringList list; - - foreach (QextPortInfo port, serial_ports) - list.append(port.friendName); - - for (int i = 0; i < list.count(); i++) - m_widget->comboBox_Ports->addItem("com: " + list.at(i), SERIAL_PORT); - - // ******************************** - // Populate the telemetry combo box with usb ports - - pjrc_rawhid *rawHidHandle = new pjrc_rawhid(); - if (rawHidHandle) - { - int opened = rawHidHandle->open(10, 0x20A0, 0x415C, 0xFF9C, 0x0001); - if (opened > 0) - { - QList usb_ports; - - for (int i = 0; i < opened; i++) - usb_ports.append(rawHidHandle->getserial(i)); - - qSort(usb_ports.begin(), usb_ports.end()); - - for (int i = 0; i < usb_ports.count(); i++) - m_widget->comboBox_Ports->addItem("usb: " + usb_ports.at(i), USB_PORT); - } - - delete rawHidHandle; - } - - // ******************************** - - connect(m_widget->comboBox_Ports, SIGNAL(currentIndexChanged(int)), this, SLOT(onComboBoxPorts_currentIndexChanged(int))); - - onComboBoxPorts_currentIndexChanged(m_widget->comboBox_Ports->currentIndex()); - - // ******************************** -} - -// *************************************************************************************** - -void PipXtremeGadgetWidget::onTelemetryStart() -{ - setEnabled(false); - -// m_widget->connectButton->setEnabled(false); -// m_widget->comboBox_Ports->setEnabled(false); -// m_widget->refreshPorts->setEnabled(false); -// m_widget->comboBox_SerialBaudrate->setEnabled(false); -} - -void PipXtremeGadgetWidget::onTelemetryStop() -{ - setEnabled(true); - -// m_widget->connectButton->setEnabled(true); -// m_widget->comboBox_Ports->setEnabled(true); -// m_widget->refreshPorts->setEnabled(true); -// m_widget->comboBox_SerialBaudrate->setEnabled(true); -} - -// *************************************************************************************** - -void PipXtremeGadgetWidget::onTelemetryConnect() -{ -} - -void PipXtremeGadgetWidget::onTelemetryDisconnect() -{ -} - -// *************************************************************************************** - -void PipXtremeGadgetWidget::disableTelemetry() -{ // Suspend telemetry & polling - - Core::ConnectionManager *cm = Core::ICore::instance()->connectionManager(); - if (!cm) return; - - cm->disconnectDevice(); - cm->suspendPolling(); -} - -void PipXtremeGadgetWidget::enableTelemetry() -{ // Restart the polling thread - - Core::ConnectionManager *cm = Core::ICore::instance()->connectionManager(); - if (!cm) return; - - cm->resumePolling(); -} - -// *************************************************************************************** - -void PipXtremeGadgetWidget::randomiseAESKey() -{ - #if QT_VERSION >= 0x040700 - uint32_t crc = ((uint32_t)qrand() << 16) ^ qrand() ^ QDateTime::currentDateTime().toMSecsSinceEpoch(); // only available with Qt 4.7.1 and later - #else - uint32_t crc = ((uint32_t)qrand() << 16) ^ qrand() ^ QDateTime::currentDateTime().toTime_t(); - #endif - - QString key = ""; - for (int i = 0; i < 4; i++) - { - for (int i = 0; i < (27 + (qrand() & 0x7f)); i++) - crc = updateCRC32(crc, qrand()); - - key += QString::number(crc, 16).rightJustified(8, '0'); - } - - m_widget->lineEdit_AESKey->setText(key); -} - -void PipXtremeGadgetWidget::scanSpectrum() -{ -} - -void PipXtremeGadgetWidget::saveToFlash() -{ - QMutexLocker locker_dev(&device_mutex); - QMutexLocker locker_inbuf(&device_input_buffer.mutex); - - if (!m_ioDevice) return; - if (!m_ioDevice->isOpen()) return; - - if (pipx_config_details.serial_number == 0) return; // we first need some details before sending new setings - - QString s; - bool ok; - - t_pipx_config_settings settings; - - settings.mode = m_widget->comboBox_Mode->itemData(m_widget->comboBox_Mode->currentIndex()).toUInt(); - - s = m_widget->lineEdit_PairedSerialNumber->text().trimmed().toLower(); - s.replace(' ', ""); // remove all spaces - if (s.startsWith("0x")) - { - s.remove(0, 2); - s = s.trimmed(); - } - settings.destination_id = s.toUInt(&ok, 16); - if (s.isEmpty() || !ok) - { - error("Check your \"Paired Serial Number\" entry!", 0); - return; - } - - settings.rf_xtal_cap = m_widget->spinBox_FrequencyCalibration->value(); - - s = m_widget->doubleSpinBox_Frequency->text().trimmed(); - s.replace(' ', ""); // remove all spaces - settings.frequency_Hz = (uint32_t)(s.toDouble(&ok) * 1e6); - if (ok) // round it to the 'frequency step size' - settings.frequency_Hz = (uint32_t)(((double)settings.frequency_Hz + pipx_config_details.frequency_step_size / 2) / pipx_config_details.frequency_step_size) * pipx_config_details.frequency_step_size; - if (s.isEmpty() || !ok || settings.frequency_Hz < pipx_config_details.min_frequency_Hz || settings.frequency_Hz > pipx_config_details.max_frequency_Hz) - { - error("Check your \"Frequency\" entry!", 0); - return; - } - - settings.max_rf_bandwidth = m_widget->comboBox_MaxRFBandwidth->itemData(m_widget->comboBox_MaxRFBandwidth->currentIndex()).toInt(); - settings.max_tx_power = m_widget->comboBox_MaxRFTxPower->itemData(m_widget->comboBox_MaxRFTxPower->currentIndex()).toInt(); - settings.serial_baudrate = m_widget->comboBox_SerialPortSpeed->itemData(m_widget->comboBox_SerialPortSpeed->currentIndex()).toInt(); - settings.aes_enable = m_widget->checkBox_AESEnable->isChecked(); - settings.rts_time = m_widget->spinBox_RTSTime->value(); - - memset(settings.aes_key, 0, sizeof(settings.aes_key)); - s = m_widget->lineEdit_AESKey->text().trimmed(); - s.replace(' ', ""); // remove all spaces - while (s.length() < 32) s = '0' + s; - if (settings.aes_enable && s.length() != 32) - { - error("Check your \"AES Key\" entry! .. it must be 32 hex characters long", 0); - return; - } - for (int i = 0; i < (int)sizeof(settings.aes_key); i++) - { - QString s2 = s.left(2); - s.remove(0, 2); - s = s.trimmed(); - settings.aes_key[i] = s2.toUInt(&ok, 16); - if (!ok) - { - error("Check your \"AES Key\" entry! .. it must contain only hex characters (0-9, a-f)", 0); - return; - } - } - - // send the new settings to the modem - sendSettings(pipx_config_details.serial_number, &settings); - - // retrieve them back - m_stage_retries = 0; - m_stage = PIPX_REQ_SETTINGS; -} - -void PipXtremeGadgetWidget::textChangedAESKey(const QString &text) -{ - QString s = text; - s.replace(' ', ""); - m_widget->label_AESkey->setText("AES Encryption Key (" + QString::number(s.length()) + ")"); -} - -// *************************************************************************************** -// send various packets - -void PipXtremeGadgetWidget::sendRequestDetails(uint32_t serial_number) -{ - // ***************** - // create the packet - - t_pipx_config_header header; - header.marker = PIPX_HEADER_MARKER; - header.serial_number = serial_number; - header.type = PIPX_PACKET_TYPE_REQ_DETAILS; - header.spare = 0; - header.data_size = 0; - header.data_crc = 0xffffffff; - header.header_crc = 0; - header.header_crc = updateCRC32Data(0xffffffff, &header, sizeof(t_pipx_config_header)); - - // ***************** - // send the packet - -// QMutexLocker locker_dev(&device_mutex); - if (!m_ioDevice) return; - if (!m_ioDevice->isOpen()) return; - qint64 bytes_written = m_ioDevice->write((const char*)&header, sizeof(t_pipx_config_header)); - - Q_UNUSED(bytes_written) - - // ***************** -} - -void PipXtremeGadgetWidget::sendRequestSettings(uint32_t serial_number) -{ - if (serial_number == 0) - return; - - // ***************** - // create the packet - - t_pipx_config_header header; - header.marker = PIPX_HEADER_MARKER; - header.serial_number = serial_number; - header.type = PIPX_PACKET_TYPE_REQ_SETTINGS; - header.spare = 0; - header.data_size = 0; - header.data_crc = 0xffffffff; - header.header_crc = 0; - header.header_crc = updateCRC32Data(0xffffffff, &header, sizeof(t_pipx_config_header)); - - // ***************** - // send the packet - -// QMutexLocker locker_dev(&device_mutex); - if (!m_ioDevice) return; - if (!m_ioDevice->isOpen()) return; - qint64 bytes_written = m_ioDevice->write((const char*)&header, sizeof(t_pipx_config_header)); - -// qDebug() << "PipX m_ioDevice->write: " << QString::number(bytes_written) << endl; - - Q_UNUSED(bytes_written) - -// error("Bytes written", bytes_written); // TEST ONLY - - // ***************** -} - -void PipXtremeGadgetWidget::sendRequestState(uint32_t serial_number) -{ - if (serial_number == 0) - return; - - // ***************** - // create the packet - - t_pipx_config_header header; - header.marker = PIPX_HEADER_MARKER; - header.serial_number = serial_number; - header.type = PIPX_PACKET_TYPE_REQ_STATE; - header.spare = 0; - header.data_size = 0; - header.data_crc = 0xffffffff; - header.header_crc = 0; - header.header_crc = updateCRC32Data(0xffffffff, &header, sizeof(t_pipx_config_header)); - - // ***************** - // send the packet - -// QMutexLocker locker_dev(&device_mutex); - if (!m_ioDevice) return; - if (!m_ioDevice->isOpen()) return; - qint64 bytes_written = m_ioDevice->write((const char*)&header, sizeof(t_pipx_config_header)); - -// qDebug() << "PipX m_ioDevice->write: " << QString::number(bytes_written) << endl; - - Q_UNUSED(bytes_written) - -// error("Bytes written", bytes_written); // TEST ONLY - - // ***************** -} - -void PipXtremeGadgetWidget::sendSettings(uint32_t serial_number, t_pipx_config_settings *settings) -{ - if (serial_number == 0) - return; - - if (!settings) - return; - - uint8_t buffer[sizeof(t_pipx_config_header) + sizeof(t_pipx_config_settings)]; - - t_pipx_config_header *header = (t_pipx_config_header *)buffer; - uint8_t *data = (uint8_t *) header + sizeof(t_pipx_config_header); - - // ***************** - // create the packet - - memcpy(data, settings, sizeof(t_pipx_config_settings)); - - header->marker = PIPX_HEADER_MARKER; - header->serial_number = serial_number; - header->type = PIPX_PACKET_TYPE_SETTINGS; - header->spare = 0; - header->data_size = sizeof(t_pipx_config_settings); - header->data_crc = updateCRC32Data(0xffffffff, data, header->data_size); - header->header_crc = 0; - header->header_crc = updateCRC32Data(0xffffffff, header, sizeof(t_pipx_config_header)); - - // ***************** - // send the packet - -// QMutexLocker locker_dev(&device_mutex); - if (!m_ioDevice) return; - if (!m_ioDevice->isOpen()) return; - qint64 bytes_written = m_ioDevice->write((const char*)buffer, sizeof(t_pipx_config_header) + header->data_size); - -// error("Bytes written", bytes_written); // TEST ONLY - - Q_UNUSED(bytes_written) - - // ***************** -} - -// *************************************************************************************** -// process rx stream data - -void PipXtremeGadgetWidget::processRxStream() -{ - QMutexLocker locker_dev(&device_mutex); - QMutexLocker locker_inbuf(&device_input_buffer.mutex); - - if (!m_ioDevice) return; - if (!m_ioDevice->isOpen()) return; - - QTimer::singleShot(100, this, SLOT(processRxStream())); - - qint64 bytes_available = m_ioDevice->bytesAvailable(); - if (bytes_available <= 0) return; - - // ensure we have buffer space for the new data - if (!device_input_buffer.buffer) - { // allocate a buffer for the data - device_input_buffer.size = bytes_available * 2; - device_input_buffer.used = 0; - device_input_buffer.buffer = new quint8 [device_input_buffer.size]; - if (!device_input_buffer.buffer) return; - } - else - { - if ((device_input_buffer.used + (bytes_available * 2)) > device_input_buffer.size) - { // need to increase the buffer size - - // create a new larger buffer - int new_size = device_input_buffer.used + bytes_available * 2; - quint8 *new_buf = new quint8 [new_size]; - if (!new_buf) return; - - // copy the data from the old buffer into the new buffer - memmove(new_buf, device_input_buffer.buffer, device_input_buffer.used); - - // delete the old buffer - delete [] device_input_buffer.buffer; - - // keep the new buffer - device_input_buffer.buffer = new_buf; - device_input_buffer.size = new_size; - } - } - - // add the new data into the buffer - qint64 bytes_read = m_ioDevice->read((char *)(device_input_buffer.buffer + device_input_buffer.used), device_input_buffer.size - device_input_buffer.used); - if (bytes_read <= 0) return; - device_input_buffer.used += bytes_read; - - processRxBuffer(); -} - -void PipXtremeGadgetWidget::processRxBuffer() -{ // scan the buffer for a valid packet - - if (!device_input_buffer.buffer || device_input_buffer.used < (int)sizeof(t_pipx_config_header)) - return; // no data as yet or not yet enough data - - while (device_input_buffer.used >= (int)sizeof(t_pipx_config_header)) - { - uint32_t crc1, crc2; - - t_pipx_config_header *header = (t_pipx_config_header *)device_input_buffer.buffer; - uint8_t *data = (uint8_t *)header + sizeof(t_pipx_config_header); - - // check packet marker - if (header->marker != PIPX_HEADER_MARKER) - { // marker not yet found - // remove a byte - int i = 1; - if (i < device_input_buffer.used) - memmove(device_input_buffer.buffer, device_input_buffer.buffer + i, device_input_buffer.used - i); - device_input_buffer.used -= i; - continue; - } - - // check the header CRC - crc1 = header->header_crc; - header->header_crc = 0; - crc2 = updateCRC32Data(0xffffffff, header, sizeof(t_pipx_config_header)); - header->header_crc = crc1; - if (crc2 != crc1) - { // faulty header - int i = 1; - if (i < device_input_buffer.used) - memmove(device_input_buffer.buffer, device_input_buffer.buffer + i, device_input_buffer.used - i); - device_input_buffer.used -= i; - continue; - } - - // valid error free header found! - - int total_packet_size = sizeof(t_pipx_config_header) + header->data_size; - - if (device_input_buffer.used < total_packet_size) - { // not yet got a full packet - break; - } - - if (header->data_size > 0) - { - // check the data crc - crc1 = header->data_crc; - crc2 = updateCRC32Data(0xffffffff, data, header->data_size); - if (crc2 != crc1) - { // faulty data - int i = 1; - if (i < device_input_buffer.used) - memmove(device_input_buffer.buffer, device_input_buffer.buffer + i, device_input_buffer.used - i); - device_input_buffer.used -= i; - continue; - } - } - - processRxPacket(device_input_buffer.buffer, total_packet_size); - - // remove the packet from the buffer - if (total_packet_size < device_input_buffer.used) - memmove(device_input_buffer.buffer, device_input_buffer.buffer + total_packet_size, device_input_buffer.used - total_packet_size); - device_input_buffer.used -= total_packet_size; - } -} - -void PipXtremeGadgetWidget::processRxPacket(quint8 *packet, int packet_size) -{ - if (!packet || packet_size <= 0) - return; - - t_pipx_config_header *header = (t_pipx_config_header *)packet; - uint8_t *data = (uint8_t *)header + sizeof(t_pipx_config_header); - - switch (header->type) - { - case PIPX_PACKET_TYPE_REQ_DETAILS: - break; - - case PIPX_PACKET_TYPE_DETAILS: - if (m_stage == PIPX_REQ_DETAILS) - { - m_stage_retries = 0; - m_stage = PIPX_REQ_SETTINGS; - - if (packet_size < (int)sizeof(t_pipx_config_header) + (int)sizeof(t_pipx_config_details)) - break; // packet size is too small - error - - memcpy(&pipx_config_details, data, sizeof(t_pipx_config_details)); - - if (pipx_config_details.major_version < 0 || (pipx_config_details.major_version <= 0 && pipx_config_details.minor_version < 6)) - { - QMessageBox msgBox; - msgBox.setIcon(QMessageBox::Critical); - msgBox.setText("You need to update your PipX modem firmware to V0.5 or later"); - msgBox.exec(); - disconnectPort(true); - return; - } - - m_widget->lineEdit_FirmwareVersion->setText(QString::number(pipx_config_details.major_version) + "." + QString::number(pipx_config_details.minor_version)); - - m_widget->lineEdit_SerialNumber->setText(QString::number(pipx_config_details.serial_number, 16).toUpper()); - - if (pipx_config_details.frequency_band == FREQBAND_434MHz) - m_widget->lineEdit_FrequencyBand->setText("434MHz"); - else - if (pipx_config_details.frequency_band == FREQBAND_868MHz) - m_widget->lineEdit_FrequencyBand->setText("868MHz"); - else - if (pipx_config_details.frequency_band == FREQBAND_915MHz) - m_widget->lineEdit_FrequencyBand->setText("915MHz"); - else - m_widget->lineEdit_FrequencyBand->setText("UNKNOWN [" + QString::number(pipx_config_details.frequency_band) + "]"); - - m_widget->lineEdit_MinFrequency->setText(QString::number((double)pipx_config_details.min_frequency_Hz / 1e6, 'f', 6) + "MHz"); - m_widget->lineEdit_MaxFrequency->setText(QString::number((double)pipx_config_details.max_frequency_Hz / 1e6, 'f', 6) + "MHz"); - - m_widget->doubleSpinBox_Frequency->setMinimum((double)pipx_config_details.min_frequency_Hz / 1e6); - m_widget->doubleSpinBox_Frequency->setMaximum((double)pipx_config_details.max_frequency_Hz / 1e6); - m_widget->doubleSpinBox_Frequency->setSingleStep(((double)pipx_config_details.frequency_step_size * 4) / 1e6); - - m_widget->lineEdit_FrequencyStepSize->setText(QString::number(pipx_config_details.frequency_step_size, 'f', 2) + "Hz"); - - m_widget->pushButton_Save->setEnabled(true); - m_widget->pushButton_ScanSpectrum->setEnabled(true); - m_widget->pushButton_Import->setEnabled(true); - m_widget->pushButton_Export->setEnabled(true); - } - break; - - case PIPX_PACKET_TYPE_REQ_SETTINGS: - break; - - case PIPX_PACKET_TYPE_SETTINGS: - if (m_stage == PIPX_REQ_SETTINGS && pipx_config_details.serial_number != 0) - { - if (packet_size < (int)sizeof(t_pipx_config_header) + (int)sizeof(t_pipx_config_settings)) - break; // packet size is too small - error - - m_stage_retries = 0; - m_stage = PIPX_REQ_STATE; - - memcpy(&pipx_config_settings, data, sizeof(t_pipx_config_settings)); - - m_widget->comboBox_Mode->setCurrentIndex(m_widget->comboBox_Mode->findData(pipx_config_settings.mode)); - m_widget->lineEdit_PairedSerialNumber->setText(QString::number(pipx_config_settings.destination_id, 16).toUpper()); - m_widget->spinBox_FrequencyCalibration->setValue(pipx_config_settings.rf_xtal_cap); - m_widget->doubleSpinBox_Frequency->setValue((double)pipx_config_settings.frequency_Hz / 1e6); - m_widget->comboBox_MaxRFBandwidth->setCurrentIndex(m_widget->comboBox_MaxRFBandwidth->findData(pipx_config_settings.max_rf_bandwidth)); - m_widget->comboBox_MaxRFTxPower->setCurrentIndex(m_widget->comboBox_MaxRFTxPower->findData(pipx_config_settings.max_tx_power)); - m_widget->comboBox_SerialPortSpeed->setCurrentIndex(m_widget->comboBox_SerialPortSpeed->findData(pipx_config_settings.serial_baudrate)); - m_widget->spinBox_RTSTime->setValue(pipx_config_settings.rts_time); - - QString key = ""; - for (int i = 0; i < (int)sizeof(pipx_config_settings.aes_key); i++) - key += QString::number(pipx_config_settings.aes_key[i], 16).rightJustified(2, '0'); - m_widget->lineEdit_AESKey->setText(key); - m_widget->checkBox_AESEnable->setChecked(pipx_config_settings.aes_enable); - } - - break; - - case PIPX_PACKET_TYPE_REQ_STATE: - break; - - case PIPX_PACKET_TYPE_STATE: - if (m_stage == PIPX_REQ_STATE && pipx_config_details.serial_number != 0) - { - if (packet_size < (int)sizeof(t_pipx_config_header) + (int)sizeof(t_pipx_config_state)) - break; // packet size is too small - error - - m_stage_retries = 0; -// m_stage = PIPX_REQ_STATE; - - memcpy(&pipx_config_state, data, sizeof(t_pipx_config_state)); - - switch (pipx_config_state.link_state) - { - case LINK_DISCONNECTED: - m_widget->lineEdit_LinkState->setText("Disconnected"); - break; - case LINK_CONNECTING: - m_widget->lineEdit_LinkState->setText("Connecting"); - break; - case LINK_CONNECTED: - m_widget->lineEdit_LinkState->setText("Connected"); - break; - default: - m_widget->lineEdit_LinkState->setText("Unknown [" + QString::number(pipx_config_state.link_state) + "]"); - break; - } - if (pipx_config_state.rssi < m_widget->widgetRSSI->minimum()) - m_widget->widgetRSSI->setValue(m_widget->widgetRSSI->minimum()); - else - if (pipx_config_state.rssi > m_widget->widgetRSSI->maximum()) - m_widget->widgetRSSI->setValue(m_widget->widgetRSSI->maximum()); - else - m_widget->widgetRSSI->setValue(pipx_config_state.rssi); - m_widget->label_RSSI->setText("RSSI " + QString::number(pipx_config_state.rssi) + "dBm"); - m_widget->lineEdit_RxAFC->setText(QString::number(pipx_config_state.afc) + "Hz"); - m_widget->lineEdit_Retries->setText(QString::number(pipx_config_state.retries)); - } - - break; - - case PIPX_PACKET_TYPE_SPECTRUM: // a packet with scanned spectrum data - if (pipx_config_details.serial_number != 0) - { - if (packet_size < (int)sizeof(t_pipx_config_header) + (int)sizeof(t_pipx_config_spectrum)) - break; // packet size is too small - error - - memcpy(&pipx_config_spectrum, data, sizeof(t_pipx_config_spectrum)); - int8_t *spec_data = (int8_t *)(data + sizeof(t_pipx_config_spectrum)); - - if (pipx_config_spectrum.magnitudes > 0) - { - m_widget->label_19->setText(QString::number(pipx_config_spectrum.start_frequency) + " " + QString::number(pipx_config_spectrum.frequency_step_size) + " " + QString::number(pipx_config_spectrum.magnitudes)); -/* - QGraphicsScene *spec_scene = m_widget->graphicsView_Spectrum->scene(); - if (spec_scene) - { - if (pipx_config_spectrum.start_frequency - pipx_config_details.min_frequency_Hz <= 0) - spec_scene->clear(); - - int w = 500; - int h = 500; - - float xscale = (float)w / (pipx_config_details.max_frequency_Hz - pipx_config_details.min_frequency_Hz); - float yscale = h / 128.0f; - - float xs = xscale * (pipx_config_spectrum.start_frequency - pipx_config_details.min_frequency_Hz); - - for (int i = 0; i < pipx_config_spectrum.magnitudes; i++) - { - int x = -(w / 2) + xs + (xscale * i * pipx_config_spectrum.frequency_step_size); - int rssi = (int)spec_data[i] + 128; - int y = yscale * rssi; - spec_scene->addLine(x, -h / 2, x, (-h / 2) - y, QPen(Qt::green, 1, Qt::SolidLine, Qt::SquareCap)); - } - } -*/ - } - } - - break; - - default: - break; - } -} - - -// *************************************************************************************** - -void PipXtremeGadgetWidget::processStream() -{ - QMutexLocker locker_dev(&device_mutex); - QMutexLocker locker_inbuf(&device_input_buffer.mutex); - - if (!m_ioDevice) return; - if (!m_ioDevice->isOpen()) return; - - switch (m_stage) - { - case PIPX_IDLE: - QTimer::singleShot(RETRY_TIME, this, SLOT(processStream())); - break; - - case PIPX_REQ_DETAILS: - if (++m_stage_retries > MAX_RETRIES) - { - disconnectPort(true, false); - break; - } - sendRequestDetails(0); - QTimer::singleShot(RETRY_TIME, this, SLOT(processStream())); - break; - - case PIPX_REQ_SETTINGS: - if (++m_stage_retries > MAX_RETRIES) - { - disconnectPort(true, false); - break; - } - sendRequestSettings(pipx_config_details.serial_number); - QTimer::singleShot(RETRY_TIME, this, SLOT(processStream())); - break; - - case PIPX_REQ_STATE: - if (++m_stage_retries > MAX_RETRIES) - { - disconnectPort(true, false); - break; - } - sendRequestState(pipx_config_details.serial_number); - QTimer::singleShot(RETRY_TIME, this, SLOT(processStream())); - break; - - default: - m_stage_retries = 0; - m_stage = PIPX_IDLE; - QTimer::singleShot(RETRY_TIME, this, SLOT(processStream())); - break; - } -} - -// *************************************************************************************** - -void PipXtremeGadgetWidget::disconnectPort(bool enable_telemetry, bool lock_stuff) -{ // disconnect the comms port - - if (lock_stuff) - { - QMutexLocker locker_dev(&device_mutex); - QMutexLocker locker_inbuf(&device_input_buffer.mutex); - } - - m_stage_retries = 0; - m_stage = PIPX_IDLE; - - device_input_buffer.used = 0; - - memset(&pipx_config_details, 0, sizeof(pipx_config_details)); - memset(&pipx_config_settings, 0, sizeof(pipx_config_settings)); - - if (m_ioDevice) - { - m_ioDevice->close(); - disconnect(m_ioDevice, 0, 0, 0); - delete m_ioDevice; - m_ioDevice = NULL; - } - - m_widget->connectButton->setText("Connect"); - m_widget->comboBox_SerialBaudrate->setEnabled(true); - m_widget->comboBox_Ports->setEnabled(true); - m_widget->refreshPorts->setEnabled(true); - m_widget->pushButton_ScanSpectrum->setEnabled(false); - m_widget->pushButton_Save->setEnabled(false); - m_widget->pushButton_Import->setEnabled(false); - m_widget->pushButton_Export->setEnabled(false); - - m_widget->lineEdit_FirmwareVersion->setText(""); - m_widget->lineEdit_SerialNumber->setText(""); - m_widget->lineEdit_FrequencyBand->setText(""); - m_widget->lineEdit_MinFrequency->setText(""); - m_widget->lineEdit_MaxFrequency->setText(""); - m_widget->lineEdit_FrequencyStepSize->setText(""); - m_widget->lineEdit_LinkState->setText(""); - m_widget->widgetRSSI->setValue(m_widget->widgetRSSI->minimum()); - m_widget->label_RSSI->setText("RSSI"); - m_widget->lineEdit_RxAFC->setText(""); - m_widget->lineEdit_Retries->setText(""); - m_widget->lineEdit_PairedSerialNumber->setText(""); - m_widget->spinBox_FrequencyCalibration->setValue(0); - m_widget->doubleSpinBox_Frequency->setValue(0); - m_widget->lineEdit_AESKey->setText(""); - m_widget->checkBox_AESEnable->setChecked(false); - - if (enable_telemetry) - enableTelemetry(); -} - -void PipXtremeGadgetWidget::connectPort() -{ // connect the comms port - - disconnectPort(true); - - QMutexLocker locker_dev(&device_mutex); - - int device_idx = m_widget->comboBox_Ports->currentIndex(); - if (device_idx < 0) - return; - - QString device_str = m_widget->comboBox_Ports->currentText().trimmed(); - if (device_str.isEmpty()) - return; - - int type = NO_PORT; - if (device_str.toLower().startsWith("com: ")) - { - type = SERIAL_PORT; - device_str.remove(0, 5); - device_str = device_str.trimmed(); - } - else - if (device_str.toLower().startsWith("usb: ")) - { - type = USB_PORT; - device_str.remove(0, 5); - device_str = device_str.trimmed(); - } - -// type = m_widget->comboBox_Ports->itemData(device_idx).toInt(); - -// qDebug() << QString::number(type) << ": " << device_str; - - // Suspend GCS telemety & polling - disableTelemetry(); - - switch (type) - { - case SERIAL_PORT: // serial port - { - QString str = getSerialPortDevice(device_str); - if (str.isEmpty()) - break; - - int br_idx = m_widget->comboBox_SerialBaudrate->currentIndex(); - if (br_idx < 0) - break; - - int baudrate = m_widget->comboBox_SerialBaudrate->itemData(br_idx).toInt(); - - BaudRateType bdt = BAUD57600; - switch (baudrate) - { - case 1200: bdt = BAUD1200; break; - case 2400: bdt = BAUD2400; break; - case 4800: bdt = BAUD4800; break; - case 9600: bdt = BAUD9600; break; - case 19200: bdt = BAUD19200; break; - case 38400: bdt = BAUD38400; break; - case 57600: bdt = BAUD57600; break; - case 115200: bdt = BAUD115200; break; - case 128000: bdt = BAUD128000; break; - case 256000: bdt = BAUD256000; break; - #if (defined Q_OS_WIN) - case 230400: bdt = BAUD230400; break; - case 460800: bdt = BAUD460800; break; - case 921600: bdt = BAUD921600; break; - #endif - } - - PortSettings settings; - settings.BaudRate = bdt; - settings.DataBits = DATA_8; - settings.Parity = PAR_NONE; - settings.StopBits = STOP_1; - settings.FlowControl = FLOW_OFF; - settings.Timeout_Millisec = 1000; -// settings.setQueryMode(QextSerialBase::EventDriven); - -// QextSerialPort *serial_dev = new QextSerialPort(str, settings, QextSerialPort::Polling); -// QextSerialPort *serial_dev = new QextSerialPort(str, settings, QextSerialPort::EventDriven); - QextSerialPort *serial_dev = new QextSerialPort(str, settings); - if (!serial_dev) - break; - -// if (!serial_dev->open(QIODevice::ReadWrite | QIODevice::Unbuffered)) - if (!serial_dev->open(QIODevice::ReadWrite)) - { - delete serial_dev; - break; - } - - m_ioDevice = serial_dev; - break; - } - - case USB_PORT: // USB port - { - RawHID *usb_dev = new RawHID(device_str); - if (!usb_dev) - break; - -// if (!usb_dev->open(QIODevice::ReadWrite | QIODevice::Unbuffered)) - if (!usb_dev->open(QIODevice::ReadWrite)) - { - delete usb_dev; - break; - } - - m_ioDevice = usb_dev; - break; - } - - default: // unknown port type - break; - } - - if (!m_ioDevice) - { // failed to connect .. restore GCS telemetry and polling - enableTelemetry(); - } - else - { // connected OK - memset(&pipx_config_details, 0, sizeof(pipx_config_details)); - memset(&pipx_config_settings, 0, sizeof(pipx_config_settings)); - - m_widget->connectButton->setText("Disconnect"); - m_widget->comboBox_SerialBaudrate->setEnabled(false); - m_widget->comboBox_Ports->setEnabled(false); - m_widget->refreshPorts->setEnabled(false); - - m_ioDevice->setTextModeEnabled(false); - QTimer::singleShot(100, this, SLOT(processRxStream())); -// connect(m_ioDevice, SIGNAL(readyRead()), this, SLOT(processRxStream())); - - m_stage_retries = 0; - m_stage = PIPX_REQ_DETAILS; - QTimer::singleShot(100, this, SLOT(processStream())); - } -} - -// *************************************************************************************** - -void PipXtremeGadgetWidget::connectDisconnect() -{ - if (m_ioDevice) - disconnectPort(true); // disconnect - else - connectPort(); // connect -} - -// *************************************************************************************** - -void PipXtremeGadgetWidget::importSettings() -{ - QString filename = "pipx_" + QString::number(pipx_config_details.serial_number, 16).rightJustified(8, '0') + ".ini"; - - QFileDialog::Options options; - QString selectedFilter; - filename = QFileDialog::getOpenFileName(this, - tr("Load from PipX settings file"), - filename, - tr("PipX settings (*.ini)"), - &selectedFilter, - options - ).trimmed(); - if (filename.isEmpty()) - return; - - if (!QFileInfo(filename).isReadable()) - { - QMessageBox msgBox; - msgBox.setText(tr("Can't read file ") + QFileInfo(filename).absoluteFilePath()); - msgBox.exec(); - return; - } - - QSettings settings(filename, QSettings::IniFormat); - - uint32_t serial_number = settings.value("details/serial_number", 0).toUInt(); - if (serial_number && serial_number != pipx_config_details.serial_number) - { -// return; - } - - pipx_config_settings.mode = settings.value("settings/mode", 0).toUInt(); - pipx_config_settings.destination_id = settings.value("settings/paired_serial_number", 0).toUInt(); - pipx_config_settings.rf_xtal_cap = settings.value("settings/frequency_calibration", 0x7f).toUInt(); - pipx_config_settings.frequency_Hz = settings.value("settings/frequency", (pipx_config_details.min_frequency_Hz + pipx_config_details.max_frequency_Hz) / 2).toUInt(); - pipx_config_settings.max_rf_bandwidth = settings.value("settings/max_rf_bandwidth", 128000).toUInt(); - pipx_config_settings.max_tx_power = settings.value("settings/max_tx_power", 4).toUInt(); - pipx_config_settings.serial_baudrate = settings.value("settings/serial_baudrate", 57600).toUInt(); - pipx_config_settings.aes_enable = settings.value("settings/aes_enable", false).toBool(); - for (int i = 0; i < (int)sizeof(pipx_config_settings.aes_key); i++) - pipx_config_settings.aes_key[i] = settings.value("settings/aes_key_" + QString::number(i), 0).toUInt(); - pipx_config_settings.rts_time = settings.value("settings/ready_to_send_time", 10).toUInt(); - - m_widget->comboBox_Mode->setCurrentIndex(m_widget->comboBox_Mode->findData(pipx_config_settings.mode)); - m_widget->lineEdit_PairedSerialNumber->setText(QString::number(pipx_config_settings.destination_id, 16).toUpper()); - m_widget->spinBox_FrequencyCalibration->setValue(pipx_config_settings.rf_xtal_cap); - m_widget->doubleSpinBox_Frequency->setValue((double)pipx_config_settings.frequency_Hz / 1e6); - m_widget->comboBox_MaxRFBandwidth->setCurrentIndex(m_widget->comboBox_MaxRFBandwidth->findData(pipx_config_settings.max_rf_bandwidth)); - m_widget->comboBox_MaxRFTxPower->setCurrentIndex(m_widget->comboBox_MaxRFTxPower->findData(pipx_config_settings.max_tx_power)); - m_widget->comboBox_SerialPortSpeed->setCurrentIndex(m_widget->comboBox_SerialPortSpeed->findData(pipx_config_settings.serial_baudrate)); - m_widget->spinBox_RTSTime->setValue(pipx_config_settings.rts_time); - - QString key = ""; - for (int i = 0; i < (int)sizeof(pipx_config_settings.aes_key); i++) - key += QString::number(pipx_config_settings.aes_key[i], 16).rightJustified(2, '0'); - m_widget->lineEdit_AESKey->setText(key); - m_widget->checkBox_AESEnable->setChecked(pipx_config_settings.aes_enable); -} - -void PipXtremeGadgetWidget::exportSettings() -{ - QString filename = "pipx_" + QString::number(pipx_config_details.serial_number, 16).rightJustified(8, '0') + ".ini"; - - filename = QFileDialog::getSaveFileName(this, - tr("Save to PipX settings file"), - filename, - tr("PipX settings (*.ini)") - ).trimmed(); - if (filename.isEmpty()) - return; -/* - if (QFileInfo(filename).exists()) - { - QMessageBox msgBox; - msgBox.setText(tr("File already exists.")); - msgBox.setInformativeText(tr("Do you want to overwrite the existing file?")); - msgBox.setStandardButtons(QMessageBox::Ok | QMessageBox::Cancel); - msgBox.setDefaultButton(QMessageBox::Ok); - if (msgBox.exec() == QMessageBox::Ok) - QFileInfo(filename).absoluteDir().remove(QFileInfo(filename).fileName()); - else - return; - } -*/ QDir dir = QFileInfo(filename).absoluteDir(); - if (!dir.exists()) - { - QMessageBox msgBox; - msgBox.setText(tr("Can't write file ") + QFileInfo(filename).absoluteFilePath() + " since directory " + dir.absolutePath() + " doesn't exist!"); - msgBox.exec(); - return; - } - - QSettings settings(filename, QSettings::IniFormat); - settings.setValue("details/serial_number", pipx_config_details.serial_number); - settings.setValue("details/min_frequency", pipx_config_details.min_frequency_Hz); - settings.setValue("details/max_frequency", pipx_config_details.max_frequency_Hz); - settings.setValue("details/frequency_band", pipx_config_details.frequency_band); - settings.setValue("settings/mode", pipx_config_settings.mode); - settings.setValue("settings/paired_serial_number", pipx_config_settings.destination_id); - settings.setValue("settings/frequency_calibration", pipx_config_settings.rf_xtal_cap); - settings.setValue("settings/frequency", pipx_config_settings.frequency_Hz); - settings.setValue("settings/max_rf_bandwidth", pipx_config_settings.max_rf_bandwidth); - settings.setValue("settings/max_tx_power", pipx_config_settings.max_tx_power); - settings.setValue("settings/serial_baudrate", pipx_config_settings.serial_baudrate); - settings.setValue("settings/aes_enable", pipx_config_settings.aes_enable); - settings.setValue("settings/ready_to_send_time", pipx_config_settings.rts_time); - for (int i = 0; i < (int)sizeof(pipx_config_settings.aes_key); i++) - settings.setValue("settings/aes_key_" + QString::number(i), pipx_config_settings.aes_key[i]); -} - -// *************************************************************************************** -// Shows a message box with an error string. - -void PipXtremeGadgetWidget::error(QString errorString, int errorNumber) -{ - QMessageBox msgBox; - msgBox.setIcon(QMessageBox::Critical); - msgBox.setText(errorString + " [" + QString::number(errorNumber) + "]"); - msgBox.exec(); -} - -// *************************************************************************************** diff --git a/ground/openpilotgcs/src/plugins/pipxtreme/pipxtremegadgetwidget.h b/ground/openpilotgcs/src/plugins/pipxtreme/pipxtremegadgetwidget.h deleted file mode 100644 index 25b0e7ccb..000000000 --- a/ground/openpilotgcs/src/plugins/pipxtreme/pipxtremegadgetwidget.h +++ /dev/null @@ -1,205 +0,0 @@ -/** - ****************************************************************************** - * - * @file pipxtremegadgetwidget.h - * @author The OpenPilot Team, http://www.openpilot.org Copyright (C) 2010. - * @addtogroup GCSPlugins GCS Plugins - * @{ - * @{ - *****************************************************************************/ -/* - * 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 PIPXTREMEGADGETWIDGET_H -#define PIPXTREMEGADGETWIDGET_H - -#include "ui_pipxtreme.h" - -#include -#include - -#include "uavtalk/telemetrymanager.h" -#include "extensionsystem/pluginmanager.h" -#include "uavobjects/uavobjectmanager.h" -#include "uavobjects/uavobject.h" - -#include "coreplugin/icore.h" -#include "coreplugin/connectionmanager.h" - -#include "rawhid/rawhidplugin.h" - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include "widgetbar.h" - -// ************************* -// pipx config comms packets - -#pragma pack(push, 1) - -typedef struct -{ - uint32_t marker; - uint32_t serial_number; - uint8_t type; - uint8_t spare; - uint16_t data_size; - uint32_t header_crc; - uint32_t data_crc; -// uint8_t data[0]; -} t_pipx_config_header; - -typedef struct -{ - uint8_t major_version; - uint8_t minor_version; - uint32_t serial_number; - uint32_t min_frequency_Hz; - uint32_t max_frequency_Hz; - uint8_t frequency_band; - float frequency_step_size; -} t_pipx_config_details; - -typedef struct -{ - uint8_t mode; - uint8_t link_state; - int16_t rssi; - int32_t afc; - uint16_t retries; -} t_pipx_config_state; - -typedef struct -{ - uint8_t mode; - uint32_t serial_baudrate; - uint32_t destination_id; - uint32_t frequency_Hz; - uint32_t max_rf_bandwidth; - uint8_t max_tx_power; - uint8_t rf_xtal_cap; - bool aes_enable; - uint8_t aes_key[16]; - uint8_t rts_time; - uint8_t spare[16]; -} t_pipx_config_settings; - -typedef struct -{ - uint32_t start_frequency; - uint16_t frequency_step_size; - uint16_t magnitudes; -// int8_t magnitude[0]; -} t_pipx_config_spectrum; - -#pragma pack(pop) - -// ************************* - -typedef struct -{ - quint8 *buffer; - int size; - int used; - QMutex mutex; -} t_buffer; - -// ************************* - -class PipXtremeGadgetWidget : public QWidget -{ - Q_OBJECT - -public: - PipXtremeGadgetWidget(QWidget *parent = 0); - ~PipXtremeGadgetWidget(); - -public slots: - void onTelemetryStart(); - void onTelemetryStop(); - void onTelemetryConnect(); - void onTelemetryDisconnect(); - - void onComboBoxPorts_currentIndexChanged(int index); - -protected: - void resizeEvent(QResizeEvent *event); - -private: - typedef enum { PIPX_IDLE, PIPX_REQ_DETAILS, PIPX_REQ_SETTINGS, PIPX_REQ_STATE} PipXStage; - - Ui_PipXtremeWidget *m_widget; - - QIODevice *m_ioDevice; - QMutex device_mutex; - - t_buffer device_input_buffer; - - PipXStage m_stage; - int m_stage_retries; - -// QVector buffer; - - t_pipx_config_details pipx_config_details; - t_pipx_config_settings pipx_config_settings; - t_pipx_config_state pipx_config_state; - t_pipx_config_spectrum pipx_config_spectrum; - - uint32_t updateCRC32(uint32_t crc, uint8_t b); - uint32_t updateCRC32Data(uint32_t crc, void *data, int len); - void makeCRC_Table32(); - - QString getSerialPortDevice(const QString &friendName); - - void disableTelemetry(); - void enableTelemetry(); - - void sendRequestDetails(uint32_t serial_number); - void sendRequestSettings(uint32_t serial_number); - void sendRequestState(uint32_t serial_number); - void sendSettings(uint32_t serial_number, t_pipx_config_settings *settings); - - void processRxBuffer(); - void processRxPacket(quint8 *packet, int packet_size); - - void disconnectPort(bool enable_telemetry, bool lock_stuff = true); - void connectPort(); - -private slots: - void importSettings(); - void exportSettings(); - void connectDisconnect(); - void error(QString errorString, int errorNumber); - void getPorts(); - void randomiseAESKey(); - void scanSpectrum(); - void saveToFlash(); - void textChangedAESKey(const QString &text); - void processStream(); - void processRxStream(); - -}; - -#endif diff --git a/ground/openpilotgcs/src/plugins/pipxtreme/pipxtremeplugin.cpp b/ground/openpilotgcs/src/plugins/pipxtreme/pipxtremeplugin.cpp deleted file mode 100644 index 3f8422a7e..000000000 --- a/ground/openpilotgcs/src/plugins/pipxtreme/pipxtremeplugin.cpp +++ /dev/null @@ -1,61 +0,0 @@ - -/** - ****************************************************************************** - * - * @file pipxtremeplugin.cpp - * @author The OpenPilot Team, http://www.openpilot.org Copyright (C) 2010. - * @addtogroup GCSPlugins GCS Plugins - * @{ - * @{ - *****************************************************************************/ -/* - * 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 "pipxtremeplugin.h" -#include "pipxtremegadgetfactory.h" -#include -#include -#include - -PipXtremePlugin::PipXtremePlugin() -{ - mf = NULL; -} - -PipXtremePlugin::~PipXtremePlugin() -{ -} - -bool PipXtremePlugin::initialize(const QStringList &args, QString *errMsg) -{ - Q_UNUSED(args); - Q_UNUSED(errMsg); - - mf = new PipXtremeGadgetFactory(this); - addAutoReleasedObject(mf); - - return true; -} - -void PipXtremePlugin::extensionsInitialized() -{ -} - -void PipXtremePlugin::shutdown() -{ -} - -Q_EXPORT_PLUGIN(PipXtremePlugin) diff --git a/ground/openpilotgcs/src/plugins/pipxtreme/pipxtremeplugin.h b/ground/openpilotgcs/src/plugins/pipxtreme/pipxtremeplugin.h deleted file mode 100644 index f81ef1933..000000000 --- a/ground/openpilotgcs/src/plugins/pipxtreme/pipxtremeplugin.h +++ /dev/null @@ -1,48 +0,0 @@ -/** - ****************************************************************************** - * - * @file pipxtremeplugin.h - * @author The OpenPilot Team, http://www.openpilot.org Copyright (C) 2010. - * @addtogroup GCSPlugins GCS Plugins - * @{ - * @{ - *****************************************************************************/ -/* - * 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 PIPXTREMEPLUGIN_H -#define PIPXTREMEPLUGIN_H - -#include - -class PipXtremeGadgetFactory; - -class PipXtremePlugin : public ExtensionSystem::IPlugin -{ -public: - PipXtremePlugin(); - ~PipXtremePlugin(); - - void extensionsInitialized(); - bool initialize(const QStringList & arguments, QString * errorString); - void shutdown(); - -private: - PipXtremeGadgetFactory *mf; - -}; - -#endif diff --git a/ground/openpilotgcs/src/plugins/pipxtreme/widgetbar.cpp b/ground/openpilotgcs/src/plugins/pipxtreme/widgetbar.cpp deleted file mode 100644 index cebb68c01..000000000 --- a/ground/openpilotgcs/src/plugins/pipxtreme/widgetbar.cpp +++ /dev/null @@ -1,157 +0,0 @@ -/** - ****************************************************************************** - * - * @file widgetbar.cpp - * @author Cathy Moss Copyright (C) 2011. - * Parts by Nokia Corporation (qt-info@nokia.com) Copyright (C) 2010. - * @addtogroup GCSPlugins GCS Plugins - * @{ - * @addtogroup ConfigPlugin Configuration Plugin - * @{ - * @brief A bar display widget - *****************************************************************************/ -/* - * 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 - - #include "widgetbar.h" - - WidgetBar::WidgetBar(QWidget *parent) - : QWidget(parent) - { - m_maximum = 0; - m_minimum = -120; - m_value = -60; - -// m_orientation = Qt::Vertical; - m_orientation = Qt::Horizontal; - - setBackgroundRole(QPalette::Base); - setAutoFillBackground(true); - } - - QSize WidgetBar::minimumSizeHint() const - { - return QSize(8, 8); - } - -// QSize WidgetBar::sizeHint() const -// { -// return QSize(200, 400); -// } - - void WidgetBar::setMaximum(int value) - { - m_maximum = value; - update(); - } - - void WidgetBar::setMinimum(int value) - { - m_minimum = value; - update(); - } - - void WidgetBar::setValue(int value) - { - if (value < m_minimum) value = m_minimum; - else - if (value > m_maximum) value = m_maximum; - - m_value = value; - update(); - } - -void WidgetBar::setOrientation(Qt::Orientation orientation) -{ - m_orientation = orientation; - update(); -} - -void WidgetBar::paintEvent(QPaintEvent * /* event */) -{ - QPainter painter(this); - painter.setRenderHint(QPainter::Antialiasing, false); - - int range = abs(m_maximum - m_minimum); - if (range < 1) range = 1; - - int value = m_value; - if (value < m_minimum) value = m_minimum; - else - if (value > m_maximum) value = m_maximum; - - float level = (float)(value - m_minimum) / range; // 0.0 to +1.0 - - int length = 0; - QRect rect; - - switch (m_orientation) - { - case Qt::Horizontal: - { - length = (int)((width() - 5) * level + 0.5f); - rect.setLeft(2); - rect.setTop(2); - rect.setWidth(length); - rect.setHeight(height() - 5); - } - break; - - case Qt::Vertical: - { - length = (int)((height() - 5) * level + 0.5f); - rect.setLeft(2); - rect.setTop(height() - 3 - length); - rect.setWidth(width() - 5); - rect.setHeight(length); - } - break; - } - - // background - painter.setPen(QColor(160, 160, 160)); - painter.setBrush(QColor(255, 255, 255)); -// painter.setPen(QColor(80, 80, 80)); -// painter.setPen(QColor(160, 160, 160)); -// painter.setBrush(QColor(160, 160, 160)); - painter.drawRect(QRect(0, 0, width() - 1, height() - 1)); - - if ((m_maximum - m_minimum) > 0) - { - // solid bar - painter.setPen(QColor(128, 128, 255)); - painter.setBrush(QColor(128, 128, 255)); - painter.drawRoundRect(rect, 3, 3); -/* - // colourful bar - for (int i = 0; i < length; i++) - { - if (!(i & 1)) - painter.setPen(QColor(0, 0, 0)); // black - else - painter.setPen(QColor(128, 255, 128)); // green -// painter.setPen(QColor(128, 128, 255)); // blue - - if (m_orientation == Qt::Horizontal) - painter.drawLine(rect.left() + i, rect.top(), rect.left() + i, rect.bottom() + 1); // horizontal bar - else - painter.drawLine(rect.left(), rect.bottom() + 1 - i, rect.right() + 1, rect.bottom() + 1 - i); // vertical bar - } -*/ - } -} diff --git a/ground/openpilotgcs/src/plugins/pipxtreme/widgetbar.h b/ground/openpilotgcs/src/plugins/pipxtreme/widgetbar.h deleted file mode 100644 index 22e84b4d2..000000000 --- a/ground/openpilotgcs/src/plugins/pipxtreme/widgetbar.h +++ /dev/null @@ -1,77 +0,0 @@ -/** - ****************************************************************************** - * - * @file widgetbar.h - * @author Cathy Moss Copyright (C) 2011. - * Parts by Nokia Corporation (qt-info@nokia.com) Copyright (C) 2010. - * @addtogroup GCSPlugins GCS Plugins - * @{ - * @addtogroup ConfigPlugin Configuration Plugin - * @{ - * @brief A bar display widget - *****************************************************************************/ -/* - * 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 WIDGETBAR_H -#define WIDGETBAR_H - -#include -#include -#include -#include - -QT_MODULE(Gui) - -class WidgetBar : public QWidget -{ - Q_OBJECT - - Q_PROPERTY(int maximum READ maximum WRITE setMaximum) - Q_PROPERTY(int minimum READ minimum WRITE setMinimum) - Q_PROPERTY(int value READ value WRITE setValue) - - Q_PROPERTY(Qt::Orientation orientation READ orientation WRITE setOrientation) - -public: - WidgetBar(QWidget *parent = 0); - - QSize minimumSizeHint() const; -// QSize sizeHint() const; - - void setMaximum(int value); - void setMinimum(int value); - void setValue(int value); - - int maximum() { return m_maximum; } - int minimum() { return m_minimum; } - int value() { return m_value; } - - Qt::Orientation orientation() const { return m_orientation; } - void setOrientation(Qt::Orientation orientation); - -protected: - void paintEvent(QPaintEvent *event); - -private: - int m_maximum; - int m_minimum; - int m_value; - - Qt::Orientation m_orientation; -}; - -#endif diff --git a/ground/openpilotgcs/src/plugins/plugins.pro b/ground/openpilotgcs/src/plugins/plugins.pro index b4dd85b5a..b6a9a309d 100644 --- a/ground/openpilotgcs/src/plugins/plugins.pro +++ b/ground/openpilotgcs/src/plugins/plugins.pro @@ -173,13 +173,6 @@ SUBDIRS += plugin_gcscontrol #plugin_antennatrack.depends += plugin_uavtalk #SUBDIRS += plugin_antennatrack -#PipXtreme gadget -plugin_pipxtreme.subdir = pipxtreme -plugin_pipxtreme.depends = plugin_coreplugin -plugin_pipxtreme.depends += plugin_uavobjects -plugin_pipxtreme.depends += plugin_rawhid -SUBDIRS += plugin_pipxtreme - #Scope OpenGL Gadget #plugin_scopeogl.subdir = scopeogl #plugin_scopeogl.depends = plugin_coreplugin diff --git a/ground/openpilotgcs/src/plugins/scope/plotdata.cpp b/ground/openpilotgcs/src/plugins/scope/plotdata.cpp index e05bf7a1b..154a9aa06 100644 --- a/ground/openpilotgcs/src/plugins/scope/plotdata.cpp +++ b/ground/openpilotgcs/src/plugins/scope/plotdata.cpp @@ -53,8 +53,9 @@ PlotData::PlotData(QString p_uavObject, QString p_uavField) curve = 0; scalePower = 0; - interpolationSamples = 1; - interpolationSum = 0.0f; + meanSamples = 1; + meanSum = 0.0f; +// mathFunction=0; correctionSum = 0.0f; correctionCount = 0; yMinimum = 0; @@ -87,7 +88,7 @@ PlotData::~PlotData() } -bool SequencialPlotData::append(UAVObject* obj) +bool SequentialPlotData::append(UAVObject* obj) { if (uavObject == obj->getName()) { @@ -96,28 +97,50 @@ bool SequencialPlotData::append(UAVObject* obj) if (field) { - //Shift data forward and put the new value at the front - - // calculate interpolated (smoothed) value double currentValue = valueAsDouble(obj, field) * pow(10, scalePower); - yDataHistory->append( currentValue ); - interpolationSum += currentValue; - if(yDataHistory->size() > interpolationSamples) { - interpolationSum -= yDataHistory->first(); - yDataHistory->pop_front(); + + //Compute boxcar average + if (mathFunction == "Boxcar average" || mathFunction == "Standard deviation"){ + //Put the new value at the front + yDataHistory->append( currentValue ); + + // calculate average value + meanSum += currentValue; + if(yDataHistory->size() > meanSamples) { + meanSum -= yDataHistory->first(); + yDataHistory->pop_front(); + } + + // make sure to correct the sum every meanSamples steps to prevent it + // from running away due to floating point rounding errors + correctionSum+=currentValue; + if (++correctionCount >= meanSamples) { + meanSum = correctionSum; + correctionSum = 0.0f; + correctionCount = 0; + } + + double boxcarAvg=meanSum/yDataHistory->size(); + + if ( mathFunction == "Standard deviation" ){ + //Calculate square of sample standard deviation, with Bessel's correction + double stdSum=0; + for (int i=0; i < yDataHistory->size(); i++){ + stdSum+= pow(yDataHistory->at(i)- boxcarAvg,2)/(meanSamples-1); + } + yData->append(sqrt(stdSum)); + } + else { + yData->append(boxcarAvg); + } } - // make sure to correct the sum every interpolationSamples steps to prevent it - // from running away due to flouting point rounding errors - correctionSum += currentValue; - if (++correctionCount >= interpolationSamples) { - interpolationSum = correctionSum; - correctionSum = 0.0f; - correctionCount = 0; + else{ + yData->append( currentValue ); } - yData->append(interpolationSum/yDataHistory->size()); - if (yData->size() > m_xWindowSize) { + + if (yData->size() > m_xWindowSize) { //If new data overflows the window, remove old data... yData->pop_front(); - } else + } else //...otherwise, add a new y point at position xData xData->insert(xData->size(), xData->size()); //notify the gui of changes in the data @@ -137,30 +160,49 @@ bool ChronoPlotData::append(UAVObject* obj) //qDebug() << "uavObject: " << uavObject << ", uavField: " << uavField; if (field) { - //Put the new value at the front - QDateTime NOW = QDateTime::currentDateTime(); - - // calculate interpolated (smoothed) value + QDateTime NOW = QDateTime::currentDateTime(); //THINK ABOUT REIMPLEMENTING THIS TO SHOW UAVO TIME, NOT SYSTEM TIME double currentValue = valueAsDouble(obj, field) * pow(10, scalePower); - yDataHistory->append( currentValue ); - interpolationSum += currentValue; - if(yDataHistory->size() > interpolationSamples) { - interpolationSum -= yDataHistory->first(); - yDataHistory->pop_front(); + + //Compute boxcar average + if (meanSamples > 1){ + //Put the new value at the front + yDataHistory->append( currentValue ); + + // calculate average value + meanSum += currentValue; + if(yDataHistory->size() > meanSamples) { + meanSum -= yDataHistory->first(); + yDataHistory->pop_front(); + } + // make sure to correct the sum every meanSamples steps to prevent it + // from running away due to floating point rounding errors + correctionSum+=currentValue; + if (++correctionCount >= meanSamples) { + meanSum = correctionSum; + correctionSum = 0.0f; + correctionCount = 0; + } + + double boxcarAvg=meanSum/yDataHistory->size(); +//qDebug()<size(); i++){ + stdSum+= pow(yDataHistory->at(i)- boxcarAvg,2)/(meanSamples-1); + } + yData->append(sqrt(stdSum)); + } + else { + yData->append(boxcarAvg); + } } - // make sure to correct the sum every interpolationSamples steps to prevent it - // from running away due to flouting point rounding errors - correctionSum += currentValue; - if (++correctionCount >= interpolationSamples) { - interpolationSum = correctionSum; - correctionSum = 0.0f; - correctionCount = 0; + else{ + yData->append( currentValue ); } double valueX = NOW.toTime_t() + NOW.time().msec() / 1000.0; - double valueY = interpolationSum/yDataHistory->size(); xData->append(valueX); - yData->append(valueY); //qDebug() << "Data " << uavObject << "." << field->getName() << " X,Y:" << valueX << "," << valueY; diff --git a/ground/openpilotgcs/src/plugins/scope/plotdata.h b/ground/openpilotgcs/src/plugins/scope/plotdata.h index 76112baf1..204f1a7bd 100644 --- a/ground/openpilotgcs/src/plugins/scope/plotdata.h +++ b/ground/openpilotgcs/src/plugins/scope/plotdata.h @@ -44,7 +44,7 @@ \brief Defines the different type of plots. */ enum PlotType { - SequencialPlot, + SequentialPlot, ChronoPlot, UAVObjectPlot, @@ -67,8 +67,9 @@ public: QString uavSubField; bool haveSubField; int scalePower; //This is the power to which each value must be raised - int interpolationSamples; - double interpolationSum; + int meanSamples; + double meanSum; + QString mathFunction; double correctionSum; int correctionCount; double yMinimum; @@ -93,16 +94,16 @@ signals: }; /*! - \brief The sequencial plot have a fixed size buffer of data. All the curves in one plot + \brief The sequential plot have a fixed size buffer of data. All the curves in one plot have the same size buffer. */ -class SequencialPlotData : public PlotData +class SequentialPlotData : public PlotData { Q_OBJECT public: - SequencialPlotData(QString uavObject, QString uavField) + SequentialPlotData(QString uavObject, QString uavField) : PlotData(uavObject, uavField) {} - ~SequencialPlotData() {} + ~SequentialPlotData() {} /*! \brief Append new data to the plot @@ -113,7 +114,7 @@ public: \brief The type of plot */ virtual PlotType plotType() { - return SequencialPlot; + return SequentialPlot; } /*! diff --git a/ground/openpilotgcs/src/plugins/scope/scopegadget.cpp b/ground/openpilotgcs/src/plugins/scope/scopegadget.cpp index b4b1f24fa..d9b33b185 100644 --- a/ground/openpilotgcs/src/plugins/scope/scopegadget.cpp +++ b/ground/openpilotgcs/src/plugins/scope/scopegadget.cpp @@ -49,8 +49,8 @@ void ScopeGadget::loadConfiguration(IUAVGadgetConfiguration* config) widget->setXWindowSize(sgConfig->dataSize()); widget->setRefreshInterval(sgConfig->refreshInterval()); - if(sgConfig->plotType() == SequencialPlot ) - widget->setupSequencialPlot(); + if(sgConfig->plotType() == SequentialPlot ) + widget->setupSequentialPlot(); else if(sgConfig->plotType() == ChronoPlot) widget->setupChronoPlot(); // else if(sgConfig->plotType() == UAVObjectPlot) @@ -61,14 +61,16 @@ void ScopeGadget::loadConfiguration(IUAVGadgetConfiguration* config) QString uavObject = plotCurveConfig->uavObject; QString uavField = plotCurveConfig->uavField; int scale = plotCurveConfig->yScalePower; - int interpolation = plotCurveConfig->yInterpolationSamples; + int mean = plotCurveConfig->yMeanSamples; + QString mathFunction = plotCurveConfig->mathFunction; QRgb color = plotCurveConfig->color; widget->addCurvePlot( uavObject, uavField, scale, - interpolation, + mean, + mathFunction, QPen( QBrush(QColor(color),Qt::SolidPattern), // (qreal)2, (qreal)1, diff --git a/ground/openpilotgcs/src/plugins/scope/scopegadgetconfiguration.cpp b/ground/openpilotgcs/src/plugins/scope/scopegadgetconfiguration.cpp index 3228497f3..57b1c134f 100644 --- a/ground/openpilotgcs/src/plugins/scope/scopegadgetconfiguration.cpp +++ b/ground/openpilotgcs/src/plugins/scope/scopegadgetconfiguration.cpp @@ -31,7 +31,8 @@ ScopeGadgetConfiguration::ScopeGadgetConfiguration(QString classId, QSettings* q IUAVGadgetConfiguration(classId, parent), m_plotType((int)ChronoPlot), m_dataSize(60), - m_refreshInterval(1000) + m_refreshInterval(1000), + m_mathFunctionType(0) { uint currentStreamVersion = 0; int plotCurveCount = 0; @@ -65,8 +66,11 @@ ScopeGadgetConfiguration::ScopeGadgetConfiguration(QString classId, QSettings* q color = qSettings->value("color").value(); plotCurveConf->color = color; plotCurveConf->yScalePower = qSettings->value("yScalePower").toInt(); - plotCurveConf->yInterpolationSamples = qSettings->value("yInterpolationSamples").toInt(); - if (!plotCurveConf->yInterpolationSamples) plotCurveConf->yInterpolationSamples = 1; // fallback for backward compatibility with earlier versions + plotCurveConf->mathFunction = qSettings->value("mathFunction").toString(); + plotCurveConf->yMeanSamples = qSettings->value("yMeanSamples").toInt(); + + if (!plotCurveConf->yMeanSamples) plotCurveConf->yMeanSamples = 1; // fallback for backward compatibility with earlier versions //IS THIS STILL NECESSARY? + plotCurveConf->yMinimum = qSettings->value("yMinimum").toDouble(); plotCurveConf->yMaximum = qSettings->value("yMaximum").toDouble(); @@ -105,8 +109,9 @@ IUAVGadgetConfiguration *ScopeGadgetConfiguration::clone() int plotDatasLoadIndex = 0; ScopeGadgetConfiguration *m = new ScopeGadgetConfiguration(this->classId()); - m->setPlotType(m_plotType); + m->setPlotType( m_plotType); m->setDataSize( m_dataSize); + m->setMathFunctionType( m_mathFunctionType); m->setRefreashInterval( m_refreshInterval); plotCurveCount = m_PlotCurveConfigs.size(); @@ -120,7 +125,9 @@ IUAVGadgetConfiguration *ScopeGadgetConfiguration::clone() newPlotCurveConf->uavField = currentPlotCurveConf->uavField; newPlotCurveConf->color = currentPlotCurveConf->color; newPlotCurveConf->yScalePower = currentPlotCurveConf->yScalePower; - newPlotCurveConf->yInterpolationSamples = currentPlotCurveConf->yInterpolationSamples; + newPlotCurveConf->yMeanSamples = currentPlotCurveConf->yMeanSamples; + newPlotCurveConf->mathFunction = currentPlotCurveConf->mathFunction; + newPlotCurveConf->yMinimum = currentPlotCurveConf->yMinimum; newPlotCurveConf->yMaximum = currentPlotCurveConf->yMaximum; @@ -136,8 +143,9 @@ IUAVGadgetConfiguration *ScopeGadgetConfiguration::clone() return m; } + /** - * Saves a configuration. + * Saves a configuration. //REDEFINES saveConfig CHILD BEHAVIOR? * */ void ScopeGadgetConfiguration::saveConfig(QSettings* qSettings) const { @@ -159,8 +167,9 @@ void ScopeGadgetConfiguration::saveConfig(QSettings* qSettings) const { qSettings->setValue("uavObject", plotCurveConf->uavObject); qSettings->setValue("uavField", plotCurveConf->uavField); qSettings->setValue("color", plotCurveConf->color); + qSettings->setValue("mathFunction", plotCurveConf->mathFunction); qSettings->setValue("yScalePower", plotCurveConf->yScalePower); - qSettings->setValue("yInterpolationSamples", plotCurveConf->yInterpolationSamples); + qSettings->setValue("yMeanSamples", plotCurveConf->yMeanSamples); qSettings->setValue("yMinimum", plotCurveConf->yMinimum); qSettings->setValue("yMaximum", plotCurveConf->yMaximum); diff --git a/ground/openpilotgcs/src/plugins/scope/scopegadgetconfiguration.h b/ground/openpilotgcs/src/plugins/scope/scopegadgetconfiguration.h index 570ebe1f9..5fcb488e2 100644 --- a/ground/openpilotgcs/src/plugins/scope/scopegadgetconfiguration.h +++ b/ground/openpilotgcs/src/plugins/scope/scopegadgetconfiguration.h @@ -41,7 +41,8 @@ struct PlotCurveConfiguration QString uavField; int yScalePower; //This is the power to which each value must be raised QRgb color; - int yInterpolationSamples; + int yMeanSamples; + QString mathFunction; double yMinimum; double yMaximum; }; @@ -56,6 +57,7 @@ public: //configuration setter functions void setPlotType(int value){m_plotType = value;} + void setMathFunctionType(int value){m_mathFunctionType = value;} void setDataSize(int value){m_dataSize = value;} void setRefreashInterval(int value){m_refreshInterval = value;} void addPlotCurveConfig(PlotCurveConfiguration* value){m_PlotCurveConfigs.append(value);} @@ -64,11 +66,12 @@ public: //configurations getter functions int plotType(){return m_plotType;} + int mathFunctionType(){return m_mathFunctionType;} int dataSize(){return m_dataSize;} int refreshInterval(){return m_refreshInterval;} QList plotCurveConfigs(){return m_PlotCurveConfigs;} - void saveConfig(QSettings* settings) const; + void saveConfig(QSettings* settings) const; //THIS SEEMS TO BE UNUSED IUAVGadgetConfiguration *clone(); bool getLoggingEnabled(){return m_LoggingEnabled;}; @@ -84,6 +87,7 @@ private: int m_plotType; //The type of the plot int m_dataSize; //The size of the data buffer to render in the curve plot int m_refreshInterval; //The interval to replot the curve widget. The data buffer is refresh as the data comes in. + int m_mathFunctionType; //The type of math function to be used in the scope analysis QList m_PlotCurveConfigs; void clearPlotData(); diff --git a/ground/openpilotgcs/src/plugins/scope/scopegadgetoptionspage.cpp b/ground/openpilotgcs/src/plugins/scope/scopegadgetoptionspage.cpp index 8489811a5..06111931f 100644 --- a/ground/openpilotgcs/src/plugins/scope/scopegadgetoptionspage.cpp +++ b/ground/openpilotgcs/src/plugins/scope/scopegadgetoptionspage.cpp @@ -53,7 +53,7 @@ QWidget* ScopeGadgetOptionsPage::createPage(QWidget *parent) //main layout options_page->setupUi(optionsPageWidget); - options_page->cmbPlotType->addItem("Sequencial Plot",""); + options_page->cmbPlotType->addItem("Sequential Plot",""); options_page->cmbPlotType->addItem("Chronological Plot",""); // Fills the combo boxes for the UAVObjects @@ -69,29 +69,34 @@ QWidget* ScopeGadgetOptionsPage::createPage(QWidget *parent) //Connect signals to slots cmbUAVObjects.currentIndexChanged connect(options_page->cmbUAVObjects, SIGNAL(currentIndexChanged(QString)), this, SLOT(on_cmbUAVObjects_currentIndexChanged(QString))); + options_page->mathFunctionComboBox->addItem("None"); + options_page->mathFunctionComboBox->addItem("Boxcar average"); + options_page->mathFunctionComboBox->addItem("Standard deviation"); + if(options_page->cmbUAVObjects->currentIndex() >= 0) on_cmbUAVObjects_currentIndexChanged(options_page->cmbUAVObjects->currentText()); - options_page->cmbScale->addItem("E-9", -9); - options_page->cmbScale->addItem("E-6", -6); - options_page->cmbScale->addItem("E-5",-5); - options_page->cmbScale->addItem("E-4",-4); - options_page->cmbScale->addItem("E-3",-3); - options_page->cmbScale->addItem("E-2",-2); - options_page->cmbScale->addItem("E-1",-1); - options_page->cmbScale->addItem("E0",0); - options_page->cmbScale->addItem("E1",1); - options_page->cmbScale->addItem("E2",2); - options_page->cmbScale->addItem("E3",3); - options_page->cmbScale->addItem("E4",4); - options_page->cmbScale->addItem("E5",5); - options_page->cmbScale->addItem("E6",6); - options_page->cmbScale->addItem("E9",9); - options_page->cmbScale->addItem("E12",12); + options_page->cmbScale->addItem("10^-9", -9); + options_page->cmbScale->addItem("10^-6", -6); + options_page->cmbScale->addItem("10^-5",-5); + options_page->cmbScale->addItem("10^-4",-4); + options_page->cmbScale->addItem("10^-3",-3); + options_page->cmbScale->addItem("10^-2",-2); + options_page->cmbScale->addItem("10^-1",-1); + options_page->cmbScale->addItem("1",0); + options_page->cmbScale->addItem("10^1",1); + options_page->cmbScale->addItem("10^2",2); + options_page->cmbScale->addItem("10^3",3); + options_page->cmbScale->addItem("10^4",4); + options_page->cmbScale->addItem("10^5",5); + options_page->cmbScale->addItem("10^6",6); + options_page->cmbScale->addItem("10^9",9); + options_page->cmbScale->addItem("10^12",12); options_page->cmbScale->setCurrentIndex(7); //Set widget values from settings options_page->cmbPlotType->setCurrentIndex(m_config->plotType()); + options_page->mathFunctionComboBox->setCurrentIndex(m_config->mathFunctionType()); options_page->spnDataSize->setValue(m_config->dataSize()); options_page->spnRefreshInterval->setValue(m_config->refreshInterval()); @@ -101,10 +106,11 @@ QWidget* ScopeGadgetOptionsPage::createPage(QWidget *parent) QString uavObject = plotData->uavObject; QString uavField = plotData->uavField; int scale = plotData->yScalePower; - int interpolation = plotData->yInterpolationSamples; + int mean = plotData->yMeanSamples; + QString mathFunction = plotData->mathFunction; QVariant varColor = plotData->color; - addPlotCurveConfig(uavObject,uavField,scale,interpolation,varColor); + addPlotCurveConfig(uavObject,uavField,scale,mean,mathFunction,varColor); } if(m_config->plotCurveConfigs().count() > 0) @@ -114,6 +120,7 @@ QWidget* ScopeGadgetOptionsPage::createPage(QWidget *parent) connect(options_page->btnRemoveCurve, SIGNAL(clicked()), this, SLOT(on_btnRemoveCurve_clicked())); connect(options_page->lstCurves, SIGNAL(currentRowChanged(int)), this, SLOT(on_lstCurves_currentRowChanged(int))); connect(options_page->btnColor, SIGNAL(clicked()), this, SLOT(on_btnColor_clicked())); + connect(options_page->mathFunctionComboBox, SIGNAL(currentIndexChanged(int)), this, SLOT(on_mathFunctionComboBox_currentIndexChanged(int))); connect(options_page->spnRefreshInterval, SIGNAL(valueChanged(int )), this, SLOT(on_spnRefreshInterval_valueChanged(int))); setYAxisWidgetFromPlotCurve(); @@ -127,11 +134,47 @@ QWidget* ScopeGadgetOptionsPage::createPage(QWidget *parent) connect(options_page->LoggingEnable, SIGNAL(clicked()), this, SLOT(on_loggingEnable_clicked())); on_loggingEnable_clicked(); + //Disable mouse wheel events + foreach( QSpinBox * sp, findChildren() ) { + sp->installEventFilter( this ); + } + foreach( QDoubleSpinBox * sp, findChildren() ) { + sp->installEventFilter( this ); + } + foreach( QSlider * sp, findChildren() ) { + sp->installEventFilter( this ); + } + foreach( QComboBox * sp, findChildren() ) { + sp->installEventFilter( this ); + } return optionsPageWidget; } +bool ScopeGadgetOptionsPage::eventFilter( QObject * obj, QEvent * evt ) { + //Filter all wheel events, and ignore them + if ( evt->type() == QEvent::Wheel && + (qobject_cast( obj ) || + qobject_cast( obj ) || + qobject_cast( obj ) )) + { + evt->ignore(); + return true; + } + return ScopeGadgetOptionsPage::eventFilter( obj, evt ); +} + +void ScopeGadgetOptionsPage::on_mathFunctionComboBox_currentIndexChanged(int currentIndex){ + if (currentIndex > 0){ + options_page->spnMeanSamples->setEnabled(true); + } + else{ + options_page->spnMeanSamples->setEnabled(false); + } + +} + void ScopeGadgetOptionsPage::on_btnColor_clicked() { QColor color = QColorDialog::getColor( QColor(options_page->btnColor->text())); @@ -152,6 +195,7 @@ void ScopeGadgetOptionsPage::setYAxisWidgetFromPlotCurve() if(listItem == 0) return; + //WHAT IS UserRole DOING? int currentIndex = options_page->cmbUAVObjects->findText( listItem->data(Qt::UserRole + 0).toString()); options_page->cmbUAVObjects->setCurrentIndex(currentIndex); @@ -166,9 +210,13 @@ void ScopeGadgetOptionsPage::setYAxisWidgetFromPlotCurve() setButtonColor(QColor((QRgb)rgb)); - int interpolation = listItem->data(Qt::UserRole + 4).toInt(&parseOK); - if(!parseOK) interpolation = 1; - options_page->spnInterpolationSamples->setValue(interpolation); + int mean = listItem->data(Qt::UserRole + 4).toInt(&parseOK); + if(!parseOK) mean = 1; + options_page->spnMeanSamples->setValue(mean); + + currentIndex = options_page->mathFunctionComboBox->findText( listItem->data(Qt::UserRole + 5).toString()); + options_page->mathFunctionComboBox->setCurrentIndex(currentIndex); + } void ScopeGadgetOptionsPage::setButtonColor(const QColor &color) @@ -221,6 +269,7 @@ void ScopeGadgetOptionsPage::apply() //Apply configuration changes m_config->setPlotType(options_page->cmbPlotType->currentIndex()); + m_config->setMathFunctionType(options_page->mathFunctionComboBox->currentIndex()); m_config->setDataSize(options_page->spnDataSize->value()); m_config->setRefreashInterval(options_page->spnRefreshInterval->value()); @@ -241,10 +290,13 @@ void ScopeGadgetOptionsPage::apply() newPlotCurveConfigs->color = QColor(Qt::black).rgb(); else newPlotCurveConfigs->color = (QRgb)rgb; - - newPlotCurveConfigs->yInterpolationSamples = listItem->data(Qt::UserRole + 4).toInt(&parseOK); + + newPlotCurveConfigs->yMeanSamples = listItem->data(Qt::UserRole + 4).toInt(&parseOK); if(!parseOK) - newPlotCurveConfigs->yInterpolationSamples = 1; + newPlotCurveConfigs->yMeanSamples = 1; + + newPlotCurveConfigs->mathFunction = listItem->data(Qt::UserRole + 5).toString(); + plotCurveConfigs.append(newPlotCurveConfigs); } @@ -271,7 +323,9 @@ void ScopeGadgetOptionsPage::on_btnAddCurve_clicked() if(!parseOK) scale = 0; - int interpolation = options_page->spnInterpolationSamples->value(); + int mean = options_page->spnMeanSamples->value(); + QString mathFunction = options_page->mathFunctionComboBox->currentText(); + QVariant varColor = (int)QColor(options_page->btnColor->text()).rgb(); @@ -281,27 +335,27 @@ void ScopeGadgetOptionsPage::on_btnAddCurve_clicked() options_page->lstCurves->currentItem()->text() == uavObject + "." + uavField) { QListWidgetItem *listWidgetItem = options_page->lstCurves->currentItem(); - setCurvePlotProperties(listWidgetItem,uavObject,uavField,scale,interpolation,varColor); + setCurvePlotProperties(listWidgetItem,uavObject,uavField,scale,mean,mathFunction,varColor); }else { - addPlotCurveConfig(uavObject,uavField,scale,interpolation,varColor); + addPlotCurveConfig(uavObject,uavField,scale,mean,mathFunction,varColor); options_page->lstCurves->setCurrentRow(options_page->lstCurves->count() - 1); } } -void ScopeGadgetOptionsPage::addPlotCurveConfig(QString uavObject, QString uavField, int scale, int interpolation, QVariant varColor) +void ScopeGadgetOptionsPage::addPlotCurveConfig(QString uavObject, QString uavField, int scale, int mean, QString mathFunction, QVariant varColor) { //Add a new curve config to the list QString listItemDisplayText = uavObject + "." + uavField; options_page->lstCurves->addItem(listItemDisplayText); QListWidgetItem *listWidgetItem = options_page->lstCurves->item(options_page->lstCurves->count() - 1); - setCurvePlotProperties(listWidgetItem,uavObject,uavField,scale,interpolation,varColor); + setCurvePlotProperties(listWidgetItem,uavObject,uavField,scale,mean,mathFunction,varColor); } -void ScopeGadgetOptionsPage::setCurvePlotProperties(QListWidgetItem *listWidgetItem,QString uavObject, QString uavField, int scale, int interpolation, QVariant varColor) +void ScopeGadgetOptionsPage::setCurvePlotProperties(QListWidgetItem *listWidgetItem,QString uavObject, QString uavField, int scale, int mean, QString mathFunction, QVariant varColor) { bool parseOK = false; @@ -317,7 +371,8 @@ void ScopeGadgetOptionsPage::setCurvePlotProperties(QListWidgetItem *listWidgetI listWidgetItem->setData(Qt::UserRole + 1,QVariant(uavField)); listWidgetItem->setData(Qt::UserRole + 2,QVariant(scale)); listWidgetItem->setData(Qt::UserRole + 3,varColor); - listWidgetItem->setData(Qt::UserRole + 4,QVariant(interpolation)); + listWidgetItem->setData(Qt::UserRole + 4,QVariant(mean)); + listWidgetItem->setData(Qt::UserRole + 5,QVariant(mathFunction)); } /*! diff --git a/ground/openpilotgcs/src/plugins/scope/scopegadgetoptionspage.h b/ground/openpilotgcs/src/plugins/scope/scopegadgetoptionspage.h index 54042741e..009f02337 100644 --- a/ground/openpilotgcs/src/plugins/scope/scopegadgetoptionspage.h +++ b/ground/openpilotgcs/src/plugins/scope/scopegadgetoptionspage.h @@ -66,11 +66,12 @@ private: Ui::ScopeGadgetOptionsPage *options_page; ScopeGadgetConfiguration *m_config; - void addPlotCurveConfig(QString uavObject, QString uavField, int scale, int interpolation, QVariant varColor); - void setCurvePlotProperties(QListWidgetItem *listWidgetItem, QString uavObject, QString uavField, int scale, int interpolation, QVariant varColor); + void addPlotCurveConfig(QString uavObject, QString uavField, int scale, int mean, QString mathFunction, QVariant varColor); + void setCurvePlotProperties(QListWidgetItem *listWidgetItem, QString uavObject, QString uavField, int scale, int mean, QString mathFunction, QVariant varColor); void setYAxisWidgetFromPlotCurve(); void setButtonColor(const QColor &color); void validateRefreshInterval(); + bool eventFilter( QObject * obj, QEvent * evt ); private slots: void on_spnRefreshInterval_valueChanged(int ); @@ -79,6 +80,7 @@ private slots: void on_btnAddCurve_clicked(); void on_cmbUAVObjects_currentIndexChanged(QString val); void on_btnColor_clicked(); + void on_mathFunctionComboBox_currentIndexChanged(int currentIndex); void on_loggingEnable_clicked(); }; diff --git a/ground/openpilotgcs/src/plugins/scope/scopegadgetoptionspage.ui b/ground/openpilotgcs/src/plugins/scope/scopegadgetoptionspage.ui index 320c3d314..c120544aa 100644 --- a/ground/openpilotgcs/src/plugins/scope/scopegadgetoptionspage.ui +++ b/ground/openpilotgcs/src/plugins/scope/scopegadgetoptionspage.ui @@ -6,8 +6,8 @@ 0 0 - 544 - 342 + 548 + 457 @@ -100,7 +100,11 @@ - + + + Qt::StrongFocus + + @@ -111,6 +115,9 @@ + + Qt::StrongFocus + seconds @@ -134,6 +141,9 @@ + + Qt::StrongFocus + ms @@ -161,7 +171,7 @@ - Plot curves + Y-axis @@ -173,7 +183,11 @@ - + + + Qt::StrongFocus + + @@ -183,45 +197,67 @@ - + + + Qt::StrongFocus + + - + Color: - + + + Qt::StrongFocus + Choose - + - Scale: + Y-axis scale factor: - + + + Qt::StrongFocus + false - + - Display smoothed interpolation: + Math window size - - + + + + false + + + + 16777215 + 16777215 + + + + Qt::StrongFocus + samples @@ -239,6 +275,20 @@ + + + + Math function: + + + + + + + Qt::StrongFocus + + + @@ -390,6 +440,22 @@ Update 1 + + cmbPlotType + spnDataSize + spnRefreshInterval + cmbUAVObjects + cmbUAVField + mathFunctionComboBox + spnMeanSamples + btnColor + cmbScale + btnAddCurve + btnRemoveCurve + lstCurves + LoggingEnable + LoggingConnect + diff --git a/ground/openpilotgcs/src/plugins/scope/scopegadgetwidget.cpp b/ground/openpilotgcs/src/plugins/scope/scopegadgetwidget.cpp index 0631e398e..967ede982 100644 --- a/ground/openpilotgcs/src/plugins/scope/scopegadgetwidget.cpp +++ b/ground/openpilotgcs/src/plugins/scope/scopegadgetwidget.cpp @@ -142,7 +142,7 @@ void ScopeGadgetWidget::mouseMoveEvent(QMouseEvent *e) void ScopeGadgetWidget::wheelEvent(QWheelEvent *e) { - QwtPlot::wheelEvent(e); + QwtPlot::wheelEvent(e); } /** @@ -269,9 +269,9 @@ void ScopeGadgetWidget::showCurve(QwtPlotItem *item, bool on) mutex.unlock(); } -void ScopeGadgetWidget::setupSequencialPlot() +void ScopeGadgetWidget::setupSequentialPlot() { - preparePlot(SequencialPlot); + preparePlot(SequentialPlot); // QwtText title("Index"); //// title.setFont(QFont("Helvetica", 20)); @@ -352,12 +352,12 @@ void ScopeGadgetWidget::setupChronoPlot() // scaleWidget->setMinBorderDist(0, fmw); } -void ScopeGadgetWidget::addCurvePlot(QString uavObject, QString uavFieldSubField, int scaleOrderFactor, int interpolationSamples, QPen pen) +void ScopeGadgetWidget::addCurvePlot(QString uavObject, QString uavFieldSubField, int scaleOrderFactor, int meanSamples, QString mathFunction, QPen pen) { PlotData* plotData; - if (m_plotType == SequencialPlot) - plotData = new SequencialPlotData(uavObject, uavFieldSubField); + if (m_plotType == SequentialPlot) + plotData = new SequentialPlotData(uavObject, uavFieldSubField); else if (m_plotType == ChronoPlot) plotData = new ChronoPlotData(uavObject, uavFieldSubField); //else if (m_plotType == UAVObjectPlot) @@ -365,7 +365,8 @@ void ScopeGadgetWidget::addCurvePlot(QString uavObject, QString uavFieldSubField plotData->m_xWindowSize = m_xWindowSize; plotData->scalePower = scaleOrderFactor; - plotData->interpolationSamples = interpolationSamples; + plotData->meanSamples = meanSamples; + plotData->mathFunction = mathFunction; //If the y-bounds are supplied, set them if (plotData->yMinimum != plotData->yMaximum) @@ -471,7 +472,7 @@ void ScopeGadgetWidget::replotNewData() void ScopeGadgetWidget::setupExamplePlot() { - preparePlot(SequencialPlot); + preparePlot(SequentialPlot); // Show the axes diff --git a/ground/openpilotgcs/src/plugins/scope/scopegadgetwidget.h b/ground/openpilotgcs/src/plugins/scope/scopegadgetwidget.h index 4dd3f42ee..f812e6fa6 100644 --- a/ground/openpilotgcs/src/plugins/scope/scopegadgetwidget.h +++ b/ground/openpilotgcs/src/plugins/scope/scopegadgetwidget.h @@ -70,7 +70,7 @@ public: ScopeGadgetWidget(QWidget *parent = 0); ~ScopeGadgetWidget(); - void setupSequencialPlot(); + void setupSequentialPlot(); void setupChronoPlot(); void setupUAVObjectPlot(); PlotType plotType(){return m_plotType;} @@ -81,7 +81,7 @@ public: int refreshInterval(){return m_refreshInterval;} - void addCurvePlot(QString uavObject, QString uavFieldSubField, int scaleOrderFactor = 0, int interpolationSamples = 1, QPen pen = QPen(Qt::black)); + void addCurvePlot(QString uavObject, QString uavFieldSubField, int scaleOrderFactor = 0, int meanSamples = 1, QString mathFunction= "None", QPen pen = QPen(Qt::black)); //void removeCurvePlot(QString uavObject, QString uavField); void clearCurvePlots(); int csvLoggingStart(); diff --git a/ground/openpilotgcs/src/plugins/uavobjects/uavobject.cpp b/ground/openpilotgcs/src/plugins/uavobjects/uavobject.cpp index c1ba625fc..47960b060 100644 --- a/ground/openpilotgcs/src/plugins/uavobjects/uavobject.cpp +++ b/ground/openpilotgcs/src/plugins/uavobjects/uavobject.cpp @@ -531,7 +531,7 @@ void UAVObject::SetGcsAccess(UAVObject::Metadata& metadata, UAVObject::AccessMod * \param[in] metadata The metadata object * \return the telemetry acked boolean */ -uint8_t UAVObject::GetFlightTelemetryAcked(const UAVObject::Metadata& metadata) { +quint8 UAVObject::GetFlightTelemetryAcked(const UAVObject::Metadata& metadata) { return (metadata.flags >> UAVOBJ_TELEMETRY_ACKED_SHIFT) & 1; } @@ -540,7 +540,7 @@ uint8_t UAVObject::GetFlightTelemetryAcked(const UAVObject::Metadata& metadata) * \param[in] metadata The metadata object * \param[in] val The telemetry acked boolean */ -void UAVObject::SetFlightTelemetryAcked(UAVObject::Metadata& metadata, uint8_t val) { +void UAVObject::SetFlightTelemetryAcked(UAVObject::Metadata& metadata, quint8 val) { SET_BITS(metadata.flags, UAVOBJ_TELEMETRY_ACKED_SHIFT, val, 1); } @@ -549,7 +549,7 @@ void UAVObject::SetFlightTelemetryAcked(UAVObject::Metadata& metadata, uint8_t v * \param[in] metadata The metadata object * \return the telemetry acked boolean */ -uint8_t UAVObject::GetGcsTelemetryAcked(const UAVObject::Metadata& metadata) { +quint8 UAVObject::GetGcsTelemetryAcked(const UAVObject::Metadata& metadata) { return (metadata.flags >> UAVOBJ_GCS_TELEMETRY_ACKED_SHIFT) & 1; } @@ -558,7 +558,7 @@ uint8_t UAVObject::GetGcsTelemetryAcked(const UAVObject::Metadata& metadata) { * \param[in] metadata The metadata object * \param[in] val The GCS telemetry acked boolean */ -void UAVObject::SetGcsTelemetryAcked(UAVObject::Metadata& metadata, uint8_t val) { +void UAVObject::SetGcsTelemetryAcked(UAVObject::Metadata& metadata, quint8 val) { SET_BITS(metadata.flags, UAVOBJ_GCS_TELEMETRY_ACKED_SHIFT, val, 1); } diff --git a/ground/openpilotgcs/src/plugins/uavobjects/uavobject.h b/ground/openpilotgcs/src/plugins/uavobjects/uavobject.h index 62b96da02..945672c61 100644 --- a/ground/openpilotgcs/src/plugins/uavobjects/uavobject.h +++ b/ground/openpilotgcs/src/plugins/uavobjects/uavobject.h @@ -36,6 +36,7 @@ #include #include #include +#include #include "uavobjectfield.h" #define UAVOBJ_ACCESS_SHIFT 0 @@ -89,10 +90,10 @@ public: * 6-7 gcsTelemetryUpdateMode Update mode used by the GCS (UAVObjUpdateMode) */ typedef struct { - uint8_t flags; /** Defines flags for update and logging modes and whether an update should be ACK'd (bits defined above) */ - uint16_t flightTelemetryUpdatePeriod; /** Update period used by the telemetry module (only if telemetry mode is PERIODIC) */ - uint16_t gcsTelemetryUpdatePeriod; /** Update period used by the GCS (only if telemetry mode is PERIODIC) */ - uint16_t loggingUpdatePeriod; /** Update period used by the logging module (only if logging mode is PERIODIC) */ + quint8 flags; /** Defines flags for update and logging modes and whether an update should be ACK'd (bits defined above) */ + quint16 flightTelemetryUpdatePeriod; /** Update period used by the telemetry module (only if telemetry mode is PERIODIC) */ + quint16 gcsTelemetryUpdatePeriod; /** Update period used by the GCS (only if telemetry mode is PERIODIC) */ + quint16 loggingUpdatePeriod; /** Update period used by the logging module (only if logging mode is PERIODIC) */ } __attribute__((packed)) Metadata; @@ -131,10 +132,10 @@ public: static void SetFlightAccess(Metadata& meta, AccessMode mode); static AccessMode GetGcsAccess(const Metadata& meta); static void SetGcsAccess(Metadata& meta, AccessMode mode); - static uint8_t GetFlightTelemetryAcked(const Metadata& meta); - static void SetFlightTelemetryAcked(Metadata& meta, uint8_t val); - static uint8_t GetGcsTelemetryAcked(const Metadata& meta); - static void SetGcsTelemetryAcked(Metadata& meta, uint8_t val); + static quint8 GetFlightTelemetryAcked(const Metadata& meta); + static void SetFlightTelemetryAcked(Metadata& meta, quint8 val); + static quint8 GetGcsTelemetryAcked(const Metadata& meta); + static void SetGcsTelemetryAcked(Metadata& meta, quint8 val); static UpdateMode GetFlightTelemetryUpdateMode(const Metadata& meta); static void SetFlightTelemetryUpdateMode(Metadata& meta, UpdateMode val); static UpdateMode GetGcsTelemetryUpdateMode(const Metadata& meta); diff --git a/ground/openpilotgcs/src/plugins/uavobjects/uavobjects.pro b/ground/openpilotgcs/src/plugins/uavobjects/uavobjects.pro old mode 100644 new mode 100755 index 456d25047..bfe2342b3 --- a/ground/openpilotgcs/src/plugins/uavobjects/uavobjects.pro +++ b/ground/openpilotgcs/src/plugins/uavobjects/uavobjects.pro @@ -79,7 +79,9 @@ HEADERS += $$UAVOBJECT_SYNTHETICS/accessorydesired.h \ $$UAVOBJECT_SYNTHETICS/attitudesettings.h \ $$UAVOBJECT_SYNTHETICS/txpidsettings.h \ $$UAVOBJECT_SYNTHETICS/cameradesired.h \ - $$UAVOBJECT_SYNTHETICS/faultsettings.h + $$UAVOBJECT_SYNTHETICS/faultsettings.h \ + $$UAVOBJECT_SYNTHETICS/pipxsettings.h \ + $$UAVOBJECT_SYNTHETICS/pipxstatus.h SOURCES += $$UAVOBJECT_SYNTHETICS/accessorydesired.cpp \ $$UAVOBJECT_SYNTHETICS/baroaltitude.cpp \ @@ -138,4 +140,6 @@ SOURCES += $$UAVOBJECT_SYNTHETICS/accessorydesired.cpp \ $$UAVOBJECT_SYNTHETICS/attitudesettings.cpp \ $$UAVOBJECT_SYNTHETICS/txpidsettings.cpp \ $$UAVOBJECT_SYNTHETICS/cameradesired.cpp \ - $$UAVOBJECT_SYNTHETICS/faultsettings.cpp + $$UAVOBJECT_SYNTHETICS/faultsettings.cpp \ + $$UAVOBJECT_SYNTHETICS/pipxsettings.cpp \ + $$UAVOBJECT_SYNTHETICS/pipxstatus.cpp diff --git a/ground/openpilotgcs/src/plugins/uavobjectutil/uavobjectutilmanager.cpp b/ground/openpilotgcs/src/plugins/uavobjectutil/uavobjectutilmanager.cpp index ac64c61d8..1d1d208a9 100644 --- a/ground/openpilotgcs/src/plugins/uavobjectutil/uavobjectutilmanager.cpp +++ b/ground/openpilotgcs/src/plugins/uavobjectutil/uavobjectutilmanager.cpp @@ -150,7 +150,7 @@ void UAVObjectUtilManager::objectPersistenceTransactionCompleted(UAVObject* obj, // the queue: saveState = AWAITING_COMPLETED; disconnect(obj, SIGNAL(transactionCompleted(UAVObject*,bool)), this, SLOT(objectPersistenceTransactionCompleted(UAVObject*,bool))); - failureTimer.start(1000); // Create a timeout + failureTimer.start(2000); // Create a timeout } else { // Can be caused by timeout errors on sending. Forget it and send next. qDebug() << "objectPersistenceTranscationCompleted (error)"; diff --git a/ground/openpilotgcs/src/plugins/uavobjectwidgetutils/configtaskwidget.cpp b/ground/openpilotgcs/src/plugins/uavobjectwidgetutils/configtaskwidget.cpp index 21d196be8..cceec4216 100644 --- a/ground/openpilotgcs/src/plugins/uavobjectwidgetutils/configtaskwidget.cpp +++ b/ground/openpilotgcs/src/plugins/uavobjectwidgetutils/configtaskwidget.cpp @@ -26,6 +26,7 @@ */ #include "configtaskwidget.h" #include +#include #include "uavsettingsimportexport/uavsettingsimportexportfactory.h" /** @@ -126,7 +127,7 @@ void ConfigTaskWidget::addUAVObjectToWidgetRelation(QString object, QString fiel Q_ASSERT(obj); objectUpdates.insert(obj,true); connect(obj, SIGNAL(objectUpdated(UAVObject*)),this, SLOT(objectUpdated(UAVObject*))); - connect(obj, SIGNAL(objectUpdated(UAVObject*)), this, SLOT(refreshWidgetsValues())); + connect(obj, SIGNAL(objectUpdated(UAVObject*)), this, SLOT(refreshWidgetsValues(UAVObject*))); } if(!field.isEmpty() && obj) _field = obj->getField(QString(field)); @@ -255,7 +256,7 @@ void ConfigTaskWidget::populateWidgets() * object field added to the framework pool * Overwrite this if you need to change the default behavior */ -void ConfigTaskWidget::refreshWidgetsValues() +void ConfigTaskWidget::refreshWidgetsValues(UAVObject * obj) { bool dirtyBack=dirty; emit refreshWidgetsValuesRequested(); @@ -267,8 +268,8 @@ void ConfigTaskWidget::refreshWidgetsValues() } else { - setWidgetFromField(ow->widget,ow->field,ow->index,ow->scale,ow->isLimited); - + if(ow->object==obj || obj==NULL) + setWidgetFromField(ow->widget,ow->field,ow->index,ow->scale,ow->isLimited); } } @@ -465,7 +466,7 @@ void ConfigTaskWidget::enableObjUpdates() foreach(objectToWidget * obj,objOfInterest) { if(obj->object) - connect(obj->object, SIGNAL(objectUpdated(UAVObject*)), this, SLOT(refreshWidgetsValues())); + connect(obj->object, SIGNAL(objectUpdated(UAVObject*)), this, SLOT(refreshWidgetsValues(UAVObject*))); } } /** @@ -958,6 +959,10 @@ QVariant ConfigTaskWidget::getVariantFromWidget(QWidget * widget,double scale) { return (QString)(cb->isChecked()?"TRUE":"FALSE"); } + else if(QLineEdit * cb=qobject_cast(widget)) + { + return (QString)cb->displayText(); + } else return QVariant(); } @@ -1004,6 +1009,14 @@ bool ConfigTaskWidget::setWidgetFromVariant(QWidget *widget, QVariant value, dou cb->setChecked(bvalue); return true; } + else if(QLineEdit * cb=qobject_cast(widget)) + { + if(scale==0) + cb->setText(value.toString()); + else + cb->setText(QString::number((value.toDouble()/scale))); + return true; + } else return false; } @@ -1170,12 +1183,17 @@ void ConfigTaskWidget::disableMouseWheelEvents() foreach( QSlider * sp, findChildren() ) { sp->installEventFilter( this ); } + foreach( QComboBox * sp, findChildren() ) { + sp->installEventFilter( this ); + } } bool ConfigTaskWidget::eventFilter( QObject * obj, QEvent * evt ) { //Filter all wheel events, and ignore them if ( evt->type() == QEvent::Wheel && - (qobject_cast( obj ) || qobject_cast( obj ) )) + (qobject_cast( obj ) || + qobject_cast( obj ) || + qobject_cast( obj ) )) { evt->ignore(); return true; diff --git a/ground/openpilotgcs/src/plugins/uavobjectwidgetutils/configtaskwidget.h b/ground/openpilotgcs/src/plugins/uavobjectwidgetutils/configtaskwidget.h index 1b5e0ca17..3099fa529 100644 --- a/ground/openpilotgcs/src/plugins/uavobjectwidgetutils/configtaskwidget.h +++ b/ground/openpilotgcs/src/plugins/uavobjectwidgetutils/configtaskwidget.h @@ -171,7 +171,7 @@ protected slots: virtual void clearDirty(); virtual void widgetsContentsChanged(); virtual void populateWidgets(); - virtual void refreshWidgetsValues(); + virtual void refreshWidgetsValues(UAVObject * obj=NULL); virtual void updateObjectsFromWidgets(); virtual void helpButtonPressed(); protected: diff --git a/ground/openpilotgcs/src/plugins/uavobjectwidgetutils/smartsavebutton.cpp b/ground/openpilotgcs/src/plugins/uavobjectwidgetutils/smartsavebutton.cpp index 260175a26..9b0268a4e 100644 --- a/ground/openpilotgcs/src/plugins/uavobjectwidgetutils/smartsavebutton.cpp +++ b/ground/openpilotgcs/src/plugins/uavobjectwidgetutils/smartsavebutton.cpp @@ -87,7 +87,7 @@ void smartSaveButton::processOperation(QPushButton * button,bool save) connect(obj,SIGNAL(transactionCompleted(UAVObject*,bool)),this,SLOT(transaction_finished(UAVObject*, bool))); connect(&timer,SIGNAL(timeout()),&loop,SLOT(quit())); obj->updated(); - timer.start(1000); + timer.start(3000); //qDebug()<<"begin loop"; loop.exec(); //qDebug()<<"end loop"; @@ -113,7 +113,7 @@ void smartSaveButton::processOperation(QPushButton * button,bool save) connect(utilMngr,SIGNAL(saveCompleted(int,bool)),this,SLOT(saving_finished(int,bool))); connect(&timer,SIGNAL(timeout()),&loop,SLOT(quit())); utilMngr->saveObjectToSD(obj); - timer.start(1000); + timer.start(3000); loop.exec(); timer.stop(); disconnect(utilMngr,SIGNAL(saveCompleted(int,bool)),this,SLOT(saving_finished(int,bool))); diff --git a/ground/openpilotgcs/src/plugins/uavtalk/telemetry.cpp b/ground/openpilotgcs/src/plugins/uavtalk/telemetry.cpp index f01c66c43..c1463013a 100644 --- a/ground/openpilotgcs/src/plugins/uavtalk/telemetry.cpp +++ b/ground/openpilotgcs/src/plugins/uavtalk/telemetry.cpp @@ -27,6 +27,8 @@ #include "telemetry.h" #include "qxtlogger.h" +#include "pipxsettings.h" +#include "objectpersistence.h" #include #include #include @@ -393,7 +395,7 @@ void Telemetry::processObjectQueue() if ( gcsStats.Status != GCSTelemetryStats::STATUS_CONNECTED ) { objQueue.clear(); - if ( objInfo.obj->getObjID() != GCSTelemetryStats::OBJID ) + if ( objInfo.obj->getObjID() != GCSTelemetryStats::OBJID && objInfo.obj->getObjID() != PipXSettings::OBJID && objInfo.obj->getObjID() != ObjectPersistence::OBJID ) { objInfo.obj->emitTransactionCompleted(false); return; diff --git a/make/boards/coptercontrol/board-info.mk b/make/boards/coptercontrol/board-info.mk index dcad2f43e..674ad4152 100644 --- a/make/boards/coptercontrol/board-info.mk +++ b/make/boards/coptercontrol/board-info.mk @@ -1,6 +1,6 @@ BOARD_TYPE := 0x04 BOARD_REVISION := 0x02 -BOOTLOADER_VERSION := 0x02 +BOOTLOADER_VERSION := 0x03 HW_TYPE := 0x01 MCU := cortex-m3 diff --git a/make/boards/pipxtreme/board-info.mk b/make/boards/pipxtreme/board-info.mk index 19d05baf9..045721092 100644 --- a/make/boards/pipxtreme/board-info.mk +++ b/make/boards/pipxtreme/board-info.mk @@ -1,13 +1,18 @@ BOARD_TYPE := 0x03 BOARD_REVISION := 0x01 -BOOTLOADER_VERSION := 0x01 +BOOTLOADER_VERSION := 0x02 HW_TYPE := 0x01 MCU := cortex-m3 CHIP := STM32F103CBT BOARD := STM32103CB_PIPXTREME MODEL := MD -MODEL_SUFFIX := +MODEL_SUFFIX := _PX + +OPENOCD_CONFIG := stm32f1x.cfg + +OPENOCD_JTAG_CONFIG := foss-jtag.revb.cfg +OPENOCD_CONFIG := stm32f1x.cfg OPENOCD_JTAG_CONFIG := foss-jtag.revb.cfg OPENOCD_CONFIG := stm32f1x.cfg diff --git a/make/boards/simposix/board-info.mk b/make/boards/simposix/board-info.mk new file mode 100644 index 000000000..4a637a53d --- /dev/null +++ b/make/boards/simposix/board-info.mk @@ -0,0 +1,24 @@ +BOARD_TYPE := 0x10 +BOARD_REVISION := 0x01 +BOOTLOADER_VERSION := 0x01 +HW_TYPE := 0x00 + +MCU := +CHIP := +BOARD := SIM_POSIX +MODEL := +MODEL_SUFFIX := + +OPENOCD_JTAG_CONFIG := +OPENOCD_CONFIG := + +# Note: These must match the values in link_$(BOARD)_memory.ld +#BL_BANK_BASE := 0x08000000 # Start of bootloader flash +#BL_BANK_SIZE := 0x00008000 # Should include BD_INFO region +#FW_BANK_BASE := 0x08008000 # Start of firmware flash +#FW_BANK_SIZE := 0x00038000 # Should include FW_DESC_SIZE + +#FW_DESC_SIZE := 0x00000064 + +OSCILLATOR_FREQ := 8000000 +SYSCLK_FREQ := 168000000 diff --git a/make/firmware-defs.mk b/make/firmware-defs.mk index 087792b45..32f2f60bc 100644 --- a/make/firmware-defs.mk +++ b/make/firmware-defs.mk @@ -49,8 +49,6 @@ MSG_OPFIRMWARE := ${quote} OPFW ${quote} MSG_FWINFO := ${quote} FWINFO ${quote} MSG_JTAG_PROGRAM := ${quote} JTAG-PGM ${quote} MSG_JTAG_WIPE := ${quote} JTAG-WIPE ${quote} -MSG_JTAG_RESET := ${quote} JTAG-RST ${quote} -MSG_JTAG_SAFEBOOT := ${quote} JTAG-SAFE ${quote} toprel = $(subst $(realpath $(TOP))/,,$(abspath $(1))) @@ -137,7 +135,7 @@ endef define ASSEMBLE_TEMPLATE $(OUTDIR)/$(notdir $(basename $(1))).o : $(1) @echo $(MSG_ASSEMBLING) $$(call toprel, $$<) - $(V1) $(CC) -c -mthumb $$(ASFLAGS) $$< -o $$@ + $(V1) $(CC) -c $(THUMB) $$(ASFLAGS) $$< -o $$@ endef # Assemble: create object files from assembler source files. ARM-only @@ -151,7 +149,7 @@ endef define COMPILE_C_TEMPLATE $(OUTDIR)/$(notdir $(basename $(1))).o : $(1) @echo $(MSG_COMPILING) $$(call toprel, $$<) - $(V1) $(CC) -c -mthumb $$(CFLAGS) $$(CONLYFLAGS) $$< -o $$@ + $(V1) $(CC) -c $(THUMB) $$(CFLAGS) $$(CONLYFLAGS) $$< -o $$@ endef # Compile: create object files from C source files. ARM-only @@ -165,7 +163,7 @@ endef define COMPILE_CPP_TEMPLATE $(OUTDIR)/$(notdir $(basename $(1))).o : $(1) @echo $(MSG_COMPILINGCPP) $$(call toprel, $$<) - $(V1) $(CC) -c -mthumb $$(CFLAGS) $$(CPPFLAGS) $$< -o $$@ + $(V1) $(CC) -c $(THUMB) $$(CFLAGS) $$(CPPFLAGS) $$< -o $$@ endef # Compile: create object files from C++ source files. ARM-only @@ -183,14 +181,14 @@ define LINK_TEMPLATE .PRECIOUS : $(2) $(1): $(2) @echo $(MSG_LINKING) $$(call toprel, $$@) - $(V1) $(CC) -mthumb $$(CFLAGS) $(2) --output $$@ $$(LDFLAGS) + $(V1) $(CC) $(THUMB) $$(CFLAGS) $(2) --output $$@ $$(LDFLAGS) endef # Compile: create assembler files from C source files. ARM/Thumb define PARTIAL_COMPILE_TEMPLATE $($(1):.c=.s) : %.s : %.c @echo $(MSG_ASMFROMC) $$(call toprel, $$<) - $(V1) $(CC) -mthumb -S $$(CFLAGS) $$(CONLYFLAGS) $$< -o $$@ + $(V1) $(CC) $(THUMB) -S $$(CFLAGS) $$(CONLYFLAGS) $$< -o $$@ endef # Compile: create assembler files from C source files. ARM only @@ -203,8 +201,7 @@ endef # $(1) = Name of binary image to write # $(2) = Base of flash region to write/wipe # $(3) = Size of flash region to write/wipe -# $(4) = OpenOCD JTAG interface configuration file to use -# $(5) = OpenOCD configuration file to use +# $(4) = OpenOCD configuration file to use define JTAG_TEMPLATE # --------------------------------------------------------------------------- # Options for OpenOCD flash-programming @@ -217,7 +214,7 @@ OOCD_EXE ?= openocd OOCD_JTAG_SETUP = -d0 # interface and board/target settings (using the OOCD target-library here) OOCD_JTAG_SETUP += -s $(TOP)/flight/Project/OpenOCD -OOCD_JTAG_SETUP += -f $(4) -f $(5) +OOCD_JTAG_SETUP += -f foss-jtag.revb.cfg -f $(4) # initialize OOCD_BOARD_RESET = -c init @@ -246,34 +243,5 @@ wipe: -c "flash erase_address pad $(2) $(3)" \ -c "reset run" \ -c "shutdown" - -reset: - @echo $(MSG_JTAG_RESET) resetting device - $(V1) $(OOCD_EXE) \ - $$(OOCD_JTAG_SETUP) \ - $$(OOCD_BOARD_RESET) \ - -c "reset run" \ - -c "shutdown" - -# Enable PWR and BKP clocks (set RCC_APB1ENR[PWREN|BKPEN]) -OOCD_WRITE_BKPDR3 = -c "mww 0x4002101C 0x18000000" -# Enable writes to BKP registers (set PWR_CR[DBP] via bit op alias address) -# -# Direct register access would be: -# mww 0x40007000 0x00000100 -# -# Direct _bit_ access is: -# Bit 8 in 0x40007000 = 0x42000000 + 0x7000 * 32 + 8 * 4 = 420E0020 -OOCD_WRITE_BKPDR3 += -c "mww 0x420E0020 0x00000001" -# Set BR3 to max value to force a safe boot -OOCD_WRITE_BKPDR3 += -c "mwh 0x40006C0C 0xFFFF" -safeboot: - @echo $(MSG_JTAG_SAFEBOOT) forcing boot into safe mode - $(V1) $(OOCD_EXE) \ - $$(OOCD_JTAG_SETUP) \ - $$(OOCD_BOARD_RESET) \ - $$(OOCD_WRITE_BKPDR3) \ - -c "reset run" \ - -c "shutdown" endef diff --git a/shared/uavobjectdefinition/gcsreceiver.xml b/shared/uavobjectdefinition/gcsreceiver.xml index ddf514087..9e48e6381 100644 --- a/shared/uavobjectdefinition/gcsreceiver.xml +++ b/shared/uavobjectdefinition/gcsreceiver.xml @@ -2,9 +2,9 @@ A receiver channel group carried over the telemetry link. - + - + diff --git a/shared/uavobjectdefinition/hwsettings.xml b/shared/uavobjectdefinition/hwsettings.xml index 7b6466895..0cee2a6d9 100644 --- a/shared/uavobjectdefinition/hwsettings.xml +++ b/shared/uavobjectdefinition/hwsettings.xml @@ -15,7 +15,6 @@ - diff --git a/shared/uavobjectdefinition/pipxsettings.xml b/shared/uavobjectdefinition/pipxsettings.xml new file mode 100644 index 000000000..a8899ff47 --- /dev/null +++ b/shared/uavobjectdefinition/pipxsettings.xml @@ -0,0 +1,24 @@ + + + PipXtreme configurations options. + + + + + + + + + + + + + + + + + + + + + diff --git a/shared/uavobjectdefinition/pipxstatus.xml b/shared/uavobjectdefinition/pipxstatus.xml new file mode 100755 index 000000000..b99a77c88 --- /dev/null +++ b/shared/uavobjectdefinition/pipxstatus.xml @@ -0,0 +1,30 @@ + + + PipXtreme device status. + + + + + + + + + + + + + + + + + + + + + + + + + + +