From 2a3895662c491ca258d7fa2376cb3a8a1b9190c2 Mon Sep 17 00:00:00 2001 From: Vinith Mundhra Date: Wed, 24 Jul 2013 08:36:31 +0530 Subject: [PATCH 01/45] adding ethernet sleep demo --- .../.cproject | 1014 +++++++++++++++++ .../.project | 75 ++ .../Makefile | 26 + .../XP-SKC-U16.xn | 91 ++ .../src/analog_tile_support/at_periph.h | 57 + .../src/analog_tile_support/at_periph.xc | 220 ++++ .../src/app_a16.xc | 150 +++ .../src/common.h | 46 + .../src/debug_conf.h | 41 + .../src/ethernet_board_conf.h | 84 ++ .../src/util.c | 58 + .../src/util.h | 62 + .../xmos_python_webserver/server.py | 21 + module_analog_tile_support/.DS_Store | Bin 0 -> 6148 bytes module_analog_tile_support/src/at_periph.h | 167 +++ module_analog_tile_support/src/at_periph.xc | 207 ++++ tests/.DS_Store | Bin 0 -> 6148 bytes tests/test_adc_config/.DS_Store | Bin 0 -> 6148 bytes tests/test_sleep_a/.DS_Store | Bin 0 -> 6148 bytes tests/test_sleep_a/Makefile | 33 + tests/test_sleep_a/src/.DS_Store | Bin 0 -> 6148 bytes tests/test_sleep_a/src/XP-SKC-U16.xn | 91 ++ tests/test_sleep_a/src/test_sleep_demo.xc | 110 ++ tests/test_wdt_a/.DS_Store | Bin 0 -> 6148 bytes tests/test_wdt_a/src/.DS_Store | Bin 0 -> 6148 bytes tests/test_wdt_a/src/XP-SKC-U16.xn | 91 ++ tests/test_wdt_a/src/test_wdt.xc | 89 ++ 27 files changed, 2733 insertions(+) create mode 100644 app_a16_slicekit_ethernet_sleep_wake_combo_demo/.cproject create mode 100644 app_a16_slicekit_ethernet_sleep_wake_combo_demo/.project create mode 100644 app_a16_slicekit_ethernet_sleep_wake_combo_demo/Makefile create mode 100644 app_a16_slicekit_ethernet_sleep_wake_combo_demo/XP-SKC-U16.xn create mode 100644 app_a16_slicekit_ethernet_sleep_wake_combo_demo/src/analog_tile_support/at_periph.h create mode 100644 app_a16_slicekit_ethernet_sleep_wake_combo_demo/src/analog_tile_support/at_periph.xc create mode 100644 app_a16_slicekit_ethernet_sleep_wake_combo_demo/src/app_a16.xc create mode 100644 app_a16_slicekit_ethernet_sleep_wake_combo_demo/src/common.h create mode 100644 app_a16_slicekit_ethernet_sleep_wake_combo_demo/src/debug_conf.h create mode 100644 app_a16_slicekit_ethernet_sleep_wake_combo_demo/src/ethernet_board_conf.h create mode 100644 app_a16_slicekit_ethernet_sleep_wake_combo_demo/src/util.c create mode 100644 app_a16_slicekit_ethernet_sleep_wake_combo_demo/src/util.h create mode 100644 app_a16_slicekit_ethernet_sleep_wake_combo_demo/xmos_python_webserver/server.py create mode 100644 module_analog_tile_support/.DS_Store create mode 100644 module_analog_tile_support/src/at_periph.h create mode 100644 module_analog_tile_support/src/at_periph.xc create mode 100644 tests/.DS_Store create mode 100644 tests/test_adc_config/.DS_Store create mode 100644 tests/test_sleep_a/.DS_Store create mode 100644 tests/test_sleep_a/Makefile create mode 100644 tests/test_sleep_a/src/.DS_Store create mode 100644 tests/test_sleep_a/src/XP-SKC-U16.xn create mode 100644 tests/test_sleep_a/src/test_sleep_demo.xc create mode 100644 tests/test_wdt_a/.DS_Store create mode 100644 tests/test_wdt_a/src/.DS_Store create mode 100644 tests/test_wdt_a/src/XP-SKC-U16.xn create mode 100644 tests/test_wdt_a/src/test_wdt.xc diff --git a/app_a16_slicekit_ethernet_sleep_wake_combo_demo/.cproject b/app_a16_slicekit_ethernet_sleep_wake_combo_demo/.cproject new file mode 100644 index 0000000..385e8c2 --- /dev/null +++ b/app_a16_slicekit_ethernet_sleep_wake_combo_demo/.cproject @@ -0,0 +1,1014 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + xmake + CONFIG=Debug + all + true + true + true + + + xmake + CONFIG=Debug + clean + true + true + true + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + xmake + CONFIG=Debug + all + true + true + true + + + xmake + CONFIG=Debug + clean + true + true + true + + + + + + + + + + + diff --git a/app_a16_slicekit_ethernet_sleep_wake_combo_demo/.project b/app_a16_slicekit_ethernet_sleep_wake_combo_demo/.project new file mode 100644 index 0000000..8595f4a --- /dev/null +++ b/app_a16_slicekit_ethernet_sleep_wake_combo_demo/.project @@ -0,0 +1,75 @@ + + + app_a16_slicekit_ethernet_sleep_wake_combo_demo + + + + + + org.eclipse.cdt.managedbuilder.core.genmakebuilder + clean,full,incremental, + + + ?children? + ?name?=outputEntries\|?children?=?name?=entry\\\\\\\|\\\|\|| + + + ?name? + + + + org.eclipse.cdt.make.core.append_environment + true + + + org.eclipse.cdt.make.core.buildArguments + CONFIG=Debug + + + org.eclipse.cdt.make.core.buildCommand + xmake + + + org.eclipse.cdt.make.core.cleanBuildTarget + clean + + + org.eclipse.cdt.make.core.contents + org.eclipse.cdt.make.core.activeConfigSettings + + + org.eclipse.cdt.make.core.enableAutoBuild + false + + + org.eclipse.cdt.make.core.enableCleanBuild + true + + + org.eclipse.cdt.make.core.enableFullBuild + true + + + org.eclipse.cdt.make.core.stopOnError + true + + + org.eclipse.cdt.make.core.useDefaultBuildCmd + false + + + + + org.eclipse.cdt.managedbuilder.core.ScannerConfigBuilder + full,incremental, + + + + + + org.eclipse.cdt.core.cnature + org.eclipse.cdt.managedbuilder.core.managedBuildNature + org.eclipse.cdt.managedbuilder.core.ScannerConfigNature + com.xmos.cdt.core.XdeProjectNature + + diff --git a/app_a16_slicekit_ethernet_sleep_wake_combo_demo/Makefile b/app_a16_slicekit_ethernet_sleep_wake_combo_demo/Makefile new file mode 100644 index 0000000..7ad022b --- /dev/null +++ b/app_a16_slicekit_ethernet_sleep_wake_combo_demo/Makefile @@ -0,0 +1,26 @@ +# The TARGET variable determines what target system the application is +# compiled for. It either refers to an XN file in the source directories +# or a valid argument for the --target option when compiling +TARGET = XP-SKC-U16 + +# The APP_NAME variable determines the name of the final .xe file. It should +# not include the .xe postfix. If left blank the name will default to +# the project name +APP_NAME = app_a16 + +# The USED_MODULES variable lists other module used by the application. +USED_MODULES = module_logging module_otp_board_info module_webclient + +# The flags passed to xcc when building the application +# You can also set the following to override flags for a particular language: +# XCC_XC_FLAGS, XCC_C_FLAGS, XCC_ASM_FLAGS, XCC_CPP_FLAGS +# If the variable XCC_MAP_FLAGS is set it overrides the flags passed to +# xcc for the final link (mapping) stage. +XCC_FLAGS_Debug = -O0 -g +XCC_FLAGS_Release = -O2 -g + +# The VERBOSE variable, if set to 1, enables verbose output from the make system. +VERBOSE = 0 + +XMOS_MAKE_PATH ?= ../.. +-include $(XMOS_MAKE_PATH)/xcommon/module_xcommon/build/Makefile.common diff --git a/app_a16_slicekit_ethernet_sleep_wake_combo_demo/XP-SKC-U16.xn b/app_a16_slicekit_ethernet_sleep_wake_combo_demo/XP-SKC-U16.xn new file mode 100644 index 0000000..e492ca5 --- /dev/null +++ b/app_a16_slicekit_ethernet_sleep_wake_combo_demo/XP-SKC-U16.xn @@ -0,0 +1,91 @@ + + + Device + XS1-U16A-128-FB217-C10 Device + + + tileref tile[2] + tileref xs1_su_periph + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/app_a16_slicekit_ethernet_sleep_wake_combo_demo/src/analog_tile_support/at_periph.h b/app_a16_slicekit_ethernet_sleep_wake_combo_demo/src/analog_tile_support/at_periph.h new file mode 100644 index 0000000..37ba72c --- /dev/null +++ b/app_a16_slicekit_ethernet_sleep_wake_combo_demo/src/analog_tile_support/at_periph.h @@ -0,0 +1,57 @@ +#ifndef AT_PERIPH_H_ +#define AT_PERIPH_H_ + +#include +#include + +//Macro to allow arbitrary struct/array to be passed to sleep mem functions, using XC cast (x, y) +#define at_pm_memory_read(x) at_pm_memory_read_impl((x, char[]), sizeof(x)) +//#define at_pm_memory_write(x) at_pm_memory_write_impl((char *) &x, sizeof(x)) +#define at_pm_memory_write(x) at_pm_memory_write_impl((x, char[]), sizeof(x)) + +#define SI_OSCILLATOR_FREQ_31K 31250 + +typedef enum { +SILICON_OSCILLATOR_20M, +SILICON_OSCILLATOR_31K, +CRYSTAL_OSCILLATOR, +EXTERNAL_OSCILLATOR} osc_sources_t; + +typedef enum { +USB_RESUME, +RTC, +WAKE_PIN_LOW, +WAKE_PIN_HIGH} wake_sources_t; + +//128B deep sleep memory access. See above macro for user API +void at_pm_memory_read_impl(char data[], unsigned char size); +//void at_pm_memory_write_impl(char * data, unsigned char size); +void at_pm_memory_write_impl(char dara[], unsigned char size); + +char at_pm_memory_is_valid(void); +void at_pm_memory_set_valid(char isvalid); + +//Sleep and wake control +void at_pm_enable_wake_source(wake_sources_t wake_source); +void at_pm_disable_wake_source(wake_sources_t wake_source); +void at_pm_set_wake_time(unsigned int alarm_time); +void at_pm_set_min_sleep_time(unsigned int min_sleep_time); +void at_pm_sleep_now(void); + +//RTC (real time clock) +unsigned int at_rtc_read(void); +void at_rtc_clear(void); + +//General power saving options +void at_pm_sswitch_prescaler (int prescaler); +void at_pm_xcore_voltage_set(unsigned int millivolts); //could use RTC clock rather than global timer + + +//Watchdog timer +void at_watchdog_enable(void); +void at_watchdog_disable(void); +void at_watchdog_set_timeout(unsigned short milliseconds); +unsigned short at_watchdog_kick(void); + + +#endif /* AT_PERIPH_H_ */ diff --git a/app_a16_slicekit_ethernet_sleep_wake_combo_demo/src/analog_tile_support/at_periph.xc b/app_a16_slicekit_ethernet_sleep_wake_combo_demo/src/analog_tile_support/at_periph.xc new file mode 100644 index 0000000..d7b548b --- /dev/null +++ b/app_a16_slicekit_ethernet_sleep_wake_combo_demo/src/analog_tile_support/at_periph.xc @@ -0,0 +1,220 @@ +#include "at_periph.h" +#include "debug_print.h" + + +static unsigned int convert_ms_to_ticks (unsigned int milliseconds){ + unsigned int read_val_32; + unsigned long long ticks; + read_node_config_reg(xs1_su_periph, XS1_SU_CFG_SYS_CLK_FREQ_NUM, read_val_32); + read_val_32 = XS1_SU_CFG_SYS_CLK_FREQ(read_val_32); //Mask off upper bits + ticks = (unsigned long long) milliseconds * (unsigned long long) read_val_32 * 1000; + return ticks; +} +static unsigned int convert_ticks_to_ms (unsigned long long ticks){ + unsigned int read_val_32; + unsigned int milliseconds; + read_node_config_reg(xs1_su_periph, XS1_SU_CFG_SYS_CLK_FREQ_NUM, read_val_32); + read_val_32 = XS1_SU_CFG_SYS_CLK_FREQ(read_val_32); //Mask off upper bits + milliseconds = (unsigned int) (ticks / (1000 * read_val_32)); + return milliseconds; +} + + +//128B deep sleep memory access +void at_pm_memory_read_impl(unsigned char data[], unsigned char size){ + if (size > XS1_SU_NUM_GLX_PER_MEMORY_BYTE); //TODO + read_periph_8 (xs1_su_periph, XS1_SU_PER_MEMORY_CHANEND_NUM, XS1_SU_PER_MEMORY_BYTE_0_NUM, + size, data); +} +void at_pm_memory_write_impl(unsigned char data[], unsigned char size){ + write_periph_8 (xs1_su_periph, XS1_SU_PER_MEMORY_CHANEND_NUM, XS1_SU_PER_MEMORY_BYTE_0_NUM, + size, data); +} + +char at_pm_memory_is_valid(void){ + char val[1]; + read_periph_8 (xs1_su_periph, XS1_SU_PER_MEMORY_CHANEND_NUM, XS1_SU_PER_MEMORY_VALID_NUM, 1, val); + return val[0]; +} +void at_pm_memory_set_valid(char isvalid){ + char val[1]; + if (isvalid) val[0] = 0xed; //magic value for valid + else val[0] = 0x00; //magic value for invalid + write_periph_8 (xs1_su_periph, XS1_SU_PER_MEMORY_CHANEND_NUM, XS1_SU_PER_MEMORY_VALID_NUM, 1, val); +} + + +//Sleep and wake control +void at_pm_enable_wake_source(wake_sources_t wake_source){ + unsigned int write_val; + read_periph_32(xs1_su_periph, XS1_SU_PER_PWR_CHANEND_NUM, XS1_SU_PER_PWR_MISC_CTRL_NUM, 1, &write_val); + switch (wake_source){ + case RTC: + write_val = XS1_SU_PWR_TMR_WAKEUP_64_SET(write_val, 1); //Set timer to 64b mode + write_val = XS1_SU_PWR_SLEEP_CLK_SEL_SET(write_val, 0); //Use 31KHz source as clock for timer + write_val = XS1_SU_PWR_TMR_WAKEUP_EN_SET(write_val, 1); //Enable timer wake + break; + + case WAKE_PIN_LOW: + write_val = XS1_SU_PWR_PIN_WAKEUP_EN_SET(write_val, 1); //Enable pin wake + write_val = XS1_SU_PWR_PIN_WAKEUP_ON_SET(write_val, 0); //Wake on low level + break; + + case WAKE_PIN_HIGH: + write_val = XS1_SU_PWR_PIN_WAKEUP_EN_SET(write_val, 1); //Disable pin wake + write_val = XS1_SU_PWR_PIN_WAKEUP_ON_SET(write_val, 1); //Wake on high level + break; + + case USB_RESUME: + write_val = XS1_SU_PWR_USB_PU_EN_SET(write_val, 1); //Enable USB resume wake + break; + } +// debug_printf("Wrting value to power control reg = 0x%x\n", write_val); + write_periph_32(xs1_su_periph, XS1_SU_PER_PWR_CHANEND_NUM, XS1_SU_PER_PWR_MISC_CTRL_NUM, 1, &write_val); +} +void at_pm_disable_wake_source(wake_sources_t wake_source) +{ + unsigned int write_val; + read_periph_32(xs1_su_periph, XS1_SU_PER_PWR_CHANEND_NUM, XS1_SU_PER_PWR_MISC_CTRL_NUM, 1, &write_val); + switch (wake_source){ + case RTC: + write_val = XS1_SU_PWR_TMR_WAKEUP_64_SET(write_val, 1); //Set timer to 64b mode + write_val = XS1_SU_PWR_SLEEP_CLK_SEL_SET(write_val, 0); //Use 31KHz source as clock for timer + write_val = XS1_SU_PWR_TMR_WAKEUP_EN_SET(write_val, 0); //Disable timer wake + break; + + case WAKE_PIN_LOW: + write_val = XS1_SU_PWR_PIN_WAKEUP_EN_SET(write_val, 0); //Disable pin wake + write_val = XS1_SU_PWR_PIN_WAKEUP_ON_SET(write_val, 0); //Wake on low level + break; + + case WAKE_PIN_HIGH: + write_val = XS1_SU_PWR_PIN_WAKEUP_EN_SET(write_val, 0); //Disable pin wake + write_val = XS1_SU_PWR_PIN_WAKEUP_ON_SET(write_val, 1); //Wake on high level + break; + + case USB_RESUME: + write_val = XS1_SU_PWR_USB_PU_EN_SET(write_val, 0); //Disable USB resume wake + break; + } +// debug_printf("Wrting value to power control reg = 0x%x\n", write_val); + write_periph_32(xs1_su_periph, XS1_SU_PER_PWR_CHANEND_NUM, XS1_SU_PER_PWR_MISC_CTRL_NUM, 1, &write_val); +} + +void at_pm_set_wake_time(unsigned int alarm_time){ + unsigned int write_val[2]; + unsigned long long alarm_ticks; + alarm_ticks = convert_ms_to_ticks(alarm_time); + write_val[0] = alarm_ticks & 0xFFFFFFFF; + write_val[1] = alarm_ticks >> 32; + debug_printf("wake_at[1..0] is 0x%x, 0x%x\n", write_val[1], write_val[0]); + write_periph_32(xs1_su_periph, XS1_SU_PER_PWR_CHANEND_NUM, XS1_SU_PER_PWR_WAKEUP_TMR_LWR_NUM, 2, write_val); +} + +void at_pm_sleep_now(void){ + unsigned char write_val, osc_good = 0; + unsigned int read_val_32, write_val_32; + + //Setup 20MHz on chip oscilator + write_val = XS1_SU_GEN_OSC_SEL_SET(0, 1); //Ensure Si OSC is enabled + write_val = XS1_SU_GEN_OSC_RST_EN_SET(write_val, 0); //Select 20MHz osc + write_periph_8(xs1_su_periph, XS1_SU_PER_OSC_CHANEND_NUM, XS1_SU_PER_OSC_ON_SI_CTRL_NUM, 1, &write_val); + + //wait until oscillator is stable + while (!osc_good){ + read_periph_32(xs1_su_periph, XS1_SU_PER_PWR_CHANEND_NUM, XS1_SU_PER_PWR_PMU_DBG_NUM, 1, &read_val_32); + osc_good = XS1_SU_PWR_ON_SI_STBL(read_val_32); + } + + //Switch to silicon oscilator + write_val = XS1_SU_GEN_OSC_RST_EN_SET(0, 0); //Disable reset on clock change + write_val = XS1_SU_GEN_OSC_SEL_SET(write_val, 1); //Switch to silicon oscialtor + write_periph_8(xs1_su_periph, XS1_SU_PER_OSC_CHANEND_NUM, XS1_SU_PER_OSC_GEN_CTRL_NUM, 1, &write_val); + + //Disable XTAL bias and oscillator + write_val = XS1_SU_XTAL_OSC_EN_SET(0, 0); //Switch off crysal oscillator + write_val = XS1_SU_XTAL_OSC_BIAS_EN_SET(write_val, 0); //Disable crystal bias circuit + write_periph_8(xs1_su_periph, XS1_SU_PER_OSC_CHANEND_NUM, XS1_SU_PER_OSC_XTAL_CTRL_NUM, 1, &write_val); + + //Disable all supplies except DC-DC2 (peripheral tile supply) + write_val_32 = XS1_SU_PWR_WAKEUP_TMR_LWR_SET(0, 8); //set to 256 cycles min time asleep + write_val_32 = XS1_SU_PWR_WAKEUP_TMR_UPR_SET(write_val_32, 0);//set to 256 cycles min time asleep + write_val_32 = XS1_SU_PWR_EXT_CLK_MASK_SET(write_val_32, 0); //Disable xCore clock + write_val_32 = XS1_SU_PWR_VOUT1_EN_SET(write_val_32, 0); //Disable DC-DC1 + write_val_32 = XS1_SU_PWR_VOUT1_MOD_SET(write_val_32, 0); //Set to PWM mode + write_val_32 = XS1_SU_PWR_VOUT2_EN_SET(write_val_32, 1); //Enable DC-DC2 + write_val_32 = XS1_SU_PWR_VOUT2_MOD_SET(write_val_32, 1); //Set to PFM mode + write_val_32 = XS1_SU_PWR_VOUT5_EN_SET(write_val_32, 0); //Disable LDO5 + write_val_32 = XS1_SU_PWR_VOUT6_EN_SET(write_val_32, 0); //Disable LDO6 + write_periph_32(xs1_su_periph, XS1_SU_PER_PWR_CHANEND_NUM, XS1_SU_PER_PWR_STATE_ASLEEP_NUM, 1, &write_val_32); + + //go to sleep + read_periph_32(xs1_su_periph, XS1_SU_PER_PWR_CHANEND_NUM, XS1_SU_PER_PWR_MISC_CTRL_NUM, 1, &write_val_32); + write_val_32 = XS1_SU_PWR_SLEEP_INIT_SET(write_val_32, 1); //Initiate sleep bit + write_periph_32(xs1_su_periph, XS1_SU_PER_PWR_CHANEND_NUM, XS1_SU_PER_PWR_MISC_CTRL_NUM, 1, &write_val_32); +} + +void at_pm_set_min_sleep_time(unsigned int min_sleep_time){ + int write_val_32; + unsigned int calc, bit_posn = 0; + calc = ((min_sleep_time * SI_OSCILLATOR_FREQ_31K) / 1000); //sleep time in 31KHz sleep clock ticks + for (int i = 0; i < 32; i++) if ((calc >> i) & 0x1) bit_posn = i; //perform an approximate log2 calculation + read_periph_32(xs1_su_periph, XS1_SU_PER_PWR_CHANEND_NUM, XS1_SU_PER_PWR_STATE_ASLEEP_NUM, 1, &write_val_32); + write_val_32 = XS1_SU_PWR_INT_EXP_SET(write_val_32, bit_posn); + write_periph_32(xs1_su_periph, XS1_SU_PER_PWR_CHANEND_NUM, XS1_SU_PER_PWR_STATE_ASLEEP_NUM, 1, &write_val_32); +} + + +//RTC +unsigned int at_rtc_read(void){ + unsigned int time_now[2] = {0, 0}; + unsigned long long ticks; + read_periph_32(xs1_su_periph, XS1_SU_PER_RTC_CHANEND_NUM, XS1_SU_PER_RTC_LWR_32BIT_NUM, 2, time_now); + debug_printf("ticks_now[1..0] is 0x%x, 0x%x\n", time_now[1], time_now[0]); + ticks = (unsigned long long) ((time_now[1] * 0x100000000) + time_now[0]); + return convert_ticks_to_ms(ticks); +} + +void at_rtc_clear(void){ + unsigned int time_now[2] = {0, 0}; + write_periph_32(xs1_su_periph, XS1_SU_PER_RTC_CHANEND_NUM, XS1_SU_PER_RTC_LWR_32BIT_NUM, 2, time_now); +} + + +//Watchdog timer +void at_watchdog_enable(void){ + unsigned int write_val = 0x00000000; //Magic value ie. not 0x0D15AB1E + write_node_config_reg(xs1_su_periph, XS1_SU_CFG_WDOG_DISABLE_NUM, write_val); +} + +void at_watchdog_disable(void){ + unsigned int write_val = 0x0D15AB1E; //Magic value to disable + write_node_config_reg(xs1_su_periph, XS1_SU_CFG_WDOG_DISABLE_NUM, write_val); +} + + +void at_watchdog_set_timeout(unsigned short milliseconds){ + unsigned int write_val; + unsigned int read_val; + write_val = milliseconds | (~milliseconds << 16); //Set upper 16b to 1's complement of lower + //This is the 'password' for accessing reg + + read_node_config_reg(xs1_su_periph, XS1_SU_CFG_WDOG_TMR_NUM, read_val); + debug_printf("WDT timer before timeout write=%u\n", XS1_SU_CFG_WDOG_TMR(read_val)); + + write_node_config_reg(xs1_su_periph, XS1_SU_CFG_WDOG_TMR_NUM, write_val); //write expiry value + + read_node_config_reg(xs1_su_periph, XS1_SU_CFG_WDOG_TMR_NUM, read_val); + debug_printf("WDT timer after timeout write=%u\n", XS1_SU_CFG_WDOG_TMR(read_val)); + +} +unsigned short at_watchdog_kick(void){ + unsigned short expiry_val, wdt_timer; + unsigned int write_val, read_val; + read_node_config_reg(xs1_su_periph, XS1_SU_CFG_WDOG_TMR_NUM, read_val); //Get current expiry value & timer + expiry_val = (unsigned short) XS1_SU_CFG_WDOG_EXP(read_val); //mask off expiry value + write_val = (unsigned int) expiry_val | (~(unsigned int)expiry_val << 16);//Set the password in upper 16b + wdt_timer = (unsigned short) XS1_SU_CFG_WDOG_TMR(read_val); //mask off and shift timer value + write_node_config_reg(xs1_su_periph, XS1_SU_CFG_WDOG_TMR_NUM, write_val); //rewrite expiry value to reset timer + return wdt_timer; //return wdt value +} diff --git a/app_a16_slicekit_ethernet_sleep_wake_combo_demo/src/app_a16.xc b/app_a16_slicekit_ethernet_sleep_wake_combo_demo/src/app_a16.xc new file mode 100644 index 0000000..3a6b0c0 --- /dev/null +++ b/app_a16_slicekit_ethernet_sleep_wake_combo_demo/src/app_a16.xc @@ -0,0 +1,150 @@ +// Copyright (c) 2011, XMOS Ltd., All rights reserved +// This software is freely distributable under a derivative of the +// University of Illinois/NCSA Open Source License posted in +// LICENSE.txt and at + +/*=========================================================================== + Info + ---- + + ===========================================================================*/ + +/*--------------------------------------------------------------------------- + include files + ---------------------------------------------------------------------------*/ +#include +#include +#include +#include +#include "common.h" +#include "util.h" +#include "webclient.h" +#include "ethernet_board_conf.h" +#include "debug_print.h" +#include "xtcp.h" +#include "at_periph.h" + +/*--------------------------------------------------------------------------- + constants + ---------------------------------------------------------------------------*/ +#define AWAKE_TIME 2000 //Time awake in ms +#define SLEEP_TIME 5000 //Time asleep in ms + +/*--------------------------------------------------------------------------- + ports and clocks + ---------------------------------------------------------------------------*/ +on ETHERNET_DEFAULT_TILE: ethernet_xtcp_ports_t xtcp_ports = { + OTP_PORTS_INITIALIZER, + ETHERNET_DEFAULT_SMI_INIT, + ETHERNET_DEFAULT_MII_INIT_lite, + ETHERNET_DEFAULT_RESET_INTERFACE_INIT +}; + +on tile[1]: out port ptemp = XS1_PORT_1D; + +/*--------------------------------------------------------------------------- + typedefs + ---------------------------------------------------------------------------*/ + +/*--------------------------------------------------------------------------- + global variables + ---------------------------------------------------------------------------*/ +xtcp_ipconfig_t ipconfig = { + {0, 0, 0, 0}, + {0, 0, 0, 0}, + {0, 0, 0, 0} +}; + +server_config_t server_config = { + {169, 254, 202, 189}, + 500, + 501 +}; + +char sleep_mem[XS1_SU_NUM_GLX_PER_MEMORY_BYTE]; +char ws_data_sleep[100] = "Going to Sleep...zzz"; +char ws_data_wake[100] = "Rise and shine...."; + +/*--------------------------------------------------------------------------- + static variables + ---------------------------------------------------------------------------*/ + +/*--------------------------------------------------------------------------- + static prototypes + ---------------------------------------------------------------------------*/ + +/*--------------------------------------------------------------------------- + tcp_handler + ---------------------------------------------------------------------------*/ +static void tcp_handler(chanend c_xtcp) +{ + timer tmr; + int sys_start_time; + unsigned int rtc_start_time, rtc_end_time, alarm_time; + char from_sleep = 0; + + // If just woke up fom sleep, check sleep memory for any data + if(at_pm_memory_is_valid()) + { + // Read server configuration from sleep memory + at_pm_memory_read(sleep_mem); + copy_char_array_to_server_config(server_config, sleep_mem); + from_sleep = 1; + ptemp <: 1; + } + else + { + // Write server configuration to sleep memory + copy_server_config_to_char_array(server_config, sleep_mem); + at_pm_memory_write(sleep_mem); + at_pm_memory_set_valid(1); + ptemp <: 1; + } + + // Set webserver paramters and connect + webclient_set_server_ip(server_config.server_ip); + webclient_set_in_port(server_config.tcp_in_port); + webclient_set_out_port(server_config.tcp_out_port); + webclient_connect_to_server(c_xtcp); + + if(from_sleep) + { + // Inform webserver that I just woke up from sleep + webclient_send_data(c_xtcp, ws_data_wake); + } + + at_watchdog_set_timeout(0xf055); + at_watchdog_enable(); + tmr :> sys_start_time; + rtc_start_time = at_rtc_read(); + tmr when timerafter(sys_start_time + (AWAKE_TIME * 100000)) :> void; + rtc_end_time = at_rtc_read(); + at_watchdog_set_timeout(0xf055); + at_watchdog_disable(); + alarm_time = rtc_end_time + SLEEP_TIME; + at_pm_set_wake_time(alarm_time); + at_pm_enable_wake_source(RTC); + at_pm_enable_wake_source(WAKE_PIN_LOW); + + // Inform webserver that I am going to sleep + webclient_send_data(c_xtcp, ws_data_sleep); + + at_pm_sleep_now(); + +} + +/*--------------------------------------------------------------------------- + main + ---------------------------------------------------------------------------*/ +int main(void) +{ + chan c_xtcp[1]; + par + { + on ETHERNET_DEFAULT_TILE: ethernet_xtcp_server(xtcp_ports, ipconfig, c_xtcp, 1); + on tile[1]: tcp_handler(c_xtcp[0]); + } + return 0; +} + +/*==========================================================================*/ diff --git a/app_a16_slicekit_ethernet_sleep_wake_combo_demo/src/common.h b/app_a16_slicekit_ethernet_sleep_wake_combo_demo/src/common.h new file mode 100644 index 0000000..f6a9ec3 --- /dev/null +++ b/app_a16_slicekit_ethernet_sleep_wake_combo_demo/src/common.h @@ -0,0 +1,46 @@ +// Copyright (c) 2011, XMOS Ltd., All rights reserved +// This software is freely distributable under a derivative of the +// University of Illinois/NCSA Open Source License posted in +// LICENSE.txt and at + +/*=========================================================================== + Info + ---- + + ===========================================================================*/ + +#ifndef __common_h__ +#define __common_h__ + +/*--------------------------------------------------------------------------- + nested include files + ---------------------------------------------------------------------------*/ + +/*--------------------------------------------------------------------------- + constants + ---------------------------------------------------------------------------*/ + +/*--------------------------------------------------------------------------- + typedefs + ---------------------------------------------------------------------------*/ +typedef struct server_config_t_ +{ + char server_ip[4]; // xtcp_ipaddr_t + int tcp_in_port; + int tcp_out_port; +} server_config_t; + +/*--------------------------------------------------------------------------- + global variables + ---------------------------------------------------------------------------*/ + +/*--------------------------------------------------------------------------- + extern variables + ---------------------------------------------------------------------------*/ + +/*--------------------------------------------------------------------------- + prototypes + ---------------------------------------------------------------------------*/ + +#endif // __common_h__ +/*==========================================================================*/ diff --git a/app_a16_slicekit_ethernet_sleep_wake_combo_demo/src/debug_conf.h b/app_a16_slicekit_ethernet_sleep_wake_combo_demo/src/debug_conf.h new file mode 100644 index 0000000..1da6098 --- /dev/null +++ b/app_a16_slicekit_ethernet_sleep_wake_combo_demo/src/debug_conf.h @@ -0,0 +1,41 @@ +// Copyright (c) 2011, XMOS Ltd., All rights reserved +// This software is freely distributable under a derivative of the +// University of Illinois/NCSA Open Source License posted in +// LICENSE.txt and at + +/*=========================================================================== + Info + ---- + + ===========================================================================*/ + +#ifndef __debug_conf_h__ +#define __debug_conf_h__ + +/*--------------------------------------------------------------------------- + nested include files + ---------------------------------------------------------------------------*/ + +/*--------------------------------------------------------------------------- + constants + ---------------------------------------------------------------------------*/ +#define DEBUG_PRINT_ENABLE 1 + +/*--------------------------------------------------------------------------- + typedefs + ---------------------------------------------------------------------------*/ + +/*--------------------------------------------------------------------------- + global variables + ---------------------------------------------------------------------------*/ + +/*--------------------------------------------------------------------------- + extern variables + ---------------------------------------------------------------------------*/ + +/*--------------------------------------------------------------------------- + prototypes + ---------------------------------------------------------------------------*/ + +#endif // __debug_conf_h__ +/*==========================================================================*/ diff --git a/app_a16_slicekit_ethernet_sleep_wake_combo_demo/src/ethernet_board_conf.h b/app_a16_slicekit_ethernet_sleep_wake_combo_demo/src/ethernet_board_conf.h new file mode 100644 index 0000000..c9e3897 --- /dev/null +++ b/app_a16_slicekit_ethernet_sleep_wake_combo_demo/src/ethernet_board_conf.h @@ -0,0 +1,84 @@ +// Copyright (c) 2011, XMOS Ltd., All rights reserved +// This software is freely distributable under a derivative of the +// University of Illinois/NCSA Open Source License posted in +// LICENSE.txt and at + +/*=========================================================================== + Info + ---- + + ===========================================================================*/ + +#ifndef __ethernet_board_conf_h__ +#define __ethernet_board_conf_h__ + +/*--------------------------------------------------------------------------- + nested include files + ---------------------------------------------------------------------------*/ + +/*--------------------------------------------------------------------------- + constants + ---------------------------------------------------------------------------*/ +#define ETHERNET_DEFAULT_PHY_ADDRESS 0 + +#define SMI_COMBINE_MDC_MDIO 1 +#define SMI_MDC_BIT 0 +#define SMI_MDIO_BIT 1 +#define ETHERNET_DEFAULT_TILE tile[1] +#define PORT_ETH_RXCLK on tile[1]: XS1_PORT_1B +#define PORT_ETH_RXD on tile[1]: XS1_PORT_4A +#define PORT_ETH_TXD on tile[1]: XS1_PORT_4B +#define PORT_ETH_RXDV on tile[1]: XS1_PORT_1C +#define PORT_ETH_TXEN on tile[1]: XS1_PORT_1F +#define PORT_ETH_TXCLK on tile[1]: XS1_PORT_1G +#define PORT_ETH_MDIOC on tile[1]: XS1_PORT_4C +#define PORT_ETH_MDIOFAKE on tile[1]: XS1_PORT_8A +#define PORT_ETH_ERR on tile[1]: XS1_PORT_4D + +#ifndef ETHERNET_DEFAULT_CLKBLK_0 +#define ETHERNET_DEFAULT_CLKBLK_0 on ETHERNET_DEFAULT_TILE: XS1_CLKBLK_1 +#endif + +#ifndef ETHERNET_DEFAULT_CLKBLK_1 +#define ETHERNET_DEFAULT_CLKBLK_1 on ETHERNET_DEFAULT_TILE: XS1_CLKBLK_2 +#endif + +#ifndef PORT_ETH_FAKE +#define PORT_ETH_FAKE on ETHERNET_DEFAULT_TILE: XS1_PORT_8C +#endif + +#define ETHERNET_DEFAULT_MII_INIT_lite { \ + ETHERNET_DEFAULT_CLKBLK_0, \ + ETHERNET_DEFAULT_CLKBLK_1, \ +\ + PORT_ETH_RXCLK, \ + PORT_ETH_ERR, \ + PORT_ETH_RXD, \ + PORT_ETH_RXDV, \ + PORT_ETH_TXCLK, \ + PORT_ETH_TXEN, \ + PORT_ETH_TXD, \ + PORT_ETH_FAKE \ +} + +#define ETHERNET_DEFAULT_SMI_INIT {ETHERNET_DEFAULT_PHY_ADDRESS, \ + PORT_ETH_MDIOC} + +/*--------------------------------------------------------------------------- + typedefs + ---------------------------------------------------------------------------*/ + +/*--------------------------------------------------------------------------- + global variables + ---------------------------------------------------------------------------*/ + +/*--------------------------------------------------------------------------- + extern variables + ---------------------------------------------------------------------------*/ + +/*--------------------------------------------------------------------------- + prototypes + ---------------------------------------------------------------------------*/ + +#endif // __ethernet_board_conf_h__ +/*==========================================================================*/ diff --git a/app_a16_slicekit_ethernet_sleep_wake_combo_demo/src/util.c b/app_a16_slicekit_ethernet_sleep_wake_combo_demo/src/util.c new file mode 100644 index 0000000..07675a4 --- /dev/null +++ b/app_a16_slicekit_ethernet_sleep_wake_combo_demo/src/util.c @@ -0,0 +1,58 @@ +// Copyright (c) 2011, XMOS Ltd., All rights reserved +// This software is freely distributable under a derivative of the +// University of Illinois/NCSA Open Source License posted in +// LICENSE.txt and at + +/*=========================================================================== + Info + ---- + + ===========================================================================*/ + +/*--------------------------------------------------------------------------- + include files + ---------------------------------------------------------------------------*/ +#include "util.h" +#include + +/*--------------------------------------------------------------------------- + constants + ---------------------------------------------------------------------------*/ + +/*--------------------------------------------------------------------------- + ports and clocks + ---------------------------------------------------------------------------*/ + +/*--------------------------------------------------------------------------- + typedefs + ---------------------------------------------------------------------------*/ + +/*--------------------------------------------------------------------------- + global variables + ---------------------------------------------------------------------------*/ + +/*--------------------------------------------------------------------------- + static variables + ---------------------------------------------------------------------------*/ + +/*--------------------------------------------------------------------------- + static prototypes + ---------------------------------------------------------------------------*/ + +/*--------------------------------------------------------------------------- + copy_server_config_to_char_array + ---------------------------------------------------------------------------*/ +void copy_server_config_to_char_array(server_config_t *sconfig, char *data) +{ + memcpy(data, (char *)(sconfig), sizeof(server_config_t)); +} + +/*--------------------------------------------------------------------------- + copy_char_array_to_server_config + ---------------------------------------------------------------------------*/ +void copy_char_array_to_server_config(server_config_t *sconfig, char *data) +{ + memcpy((char *)(sconfig), data, sizeof(server_config_t)); +} + +/*==========================================================================*/ diff --git a/app_a16_slicekit_ethernet_sleep_wake_combo_demo/src/util.h b/app_a16_slicekit_ethernet_sleep_wake_combo_demo/src/util.h new file mode 100644 index 0000000..81314ec --- /dev/null +++ b/app_a16_slicekit_ethernet_sleep_wake_combo_demo/src/util.h @@ -0,0 +1,62 @@ +// Copyright (c) 2011, XMOS Ltd., All rights reserved +// This software is freely distributable under a derivative of the +// University of Illinois/NCSA Open Source License posted in +// LICENSE.txt and at + +/*=========================================================================== + Info + ---- + + ===========================================================================*/ + +#ifndef __util_h__ +#define __util_h__ + +/*--------------------------------------------------------------------------- + nested include files + ---------------------------------------------------------------------------*/ +#include +#include "common.h" + +/*--------------------------------------------------------------------------- + constants + ---------------------------------------------------------------------------*/ + +/*--------------------------------------------------------------------------- + typedefs + ---------------------------------------------------------------------------*/ + +/*--------------------------------------------------------------------------- + global variables + ---------------------------------------------------------------------------*/ + +/*--------------------------------------------------------------------------- + extern variables + ---------------------------------------------------------------------------*/ + +/*--------------------------------------------------------------------------- + prototypes + ---------------------------------------------------------------------------*/ + +/*==========================================================================*/ +/** + * Copy Webserver configuration to character array + * + * \param sconfig Ref to webserver configuration (server_config_t) + * \param data[] Ref to character array (char) + * \return None + **/ +void copy_server_config_to_char_array(REFERENCE_PARAM(server_config_t, sconfig), char data[]); + +/*==========================================================================*/ +/** + * Copy character array to Webserver configuration + * + * \param sconfig Ref to webserver configuration (server_config_t) + * \param data[] Ref to character array (char) + * \return None + **/ +void copy_char_array_to_server_config(REFERENCE_PARAM(server_config_t, sconfig), char data[]); + +#endif // __util_h__ +/*==========================================================================*/ diff --git a/app_a16_slicekit_ethernet_sleep_wake_combo_demo/xmos_python_webserver/server.py b/app_a16_slicekit_ethernet_sleep_wake_combo_demo/xmos_python_webserver/server.py new file mode 100644 index 0000000..4dcc5d7 --- /dev/null +++ b/app_a16_slicekit_ethernet_sleep_wake_combo_demo/xmos_python_webserver/server.py @@ -0,0 +1,21 @@ +#!/usr/bin/python +import socket,sys + +server_port = 501 +self_ip = socket.gethostbyname(socket.gethostname()) +print >>sys.stderr, 'Server Address = ', self_ip + +server_sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM) +server_sock.bind((self_ip, server_port)) +server_sock.listen(1) + +while 1: + + print "Waiting for a client connection..." + connection, client_address = server_sock.accept() + print >>sys.stderr, 'connection from', client_address + + data = connection.recv(100) + print >>sys.stderr, '==> "%s"\n' % data + connection.close() + \ No newline at end of file diff --git a/module_analog_tile_support/.DS_Store b/module_analog_tile_support/.DS_Store new file mode 100644 index 0000000000000000000000000000000000000000..5f6ae930dddc5f5079946b4767540c59ebd6cecf GIT binary patch literal 6148 zcmeHK%}T>S5Z-O8MpVc}=yCB}q_u^5@DM@;k3tGPSkc6Y4TPj5sXf$a@F9E+-^S;0 zW_JQsdlr!y*!{lUnc2;Lko^%tNOuwTgs_DW78FE@WP@S%MpuJ^5hae1&x1G(p!FWi z$@kX*zr87Pk%_xt`SttbC@;F*57}t8wzhXHu>I*IO2TyMri&!Zue@2h^rG-S@Uv^p z3%^+8uAgborC-dzqxm>ZW8hPYo|kaEQ!d{Y4T2L%PuA*>AQtph5&KBK>dhz1A*>972TYn&K$9xzi6Koo^ec*U z2rGjoT}VAMj6*Zmj~A(Dhkm8Qg>(#Z%?hvr>k2eY)5i1v9DbRNkNou%Zm|Naz&}$! zwnpB_g+!xKz$d0KM!^68 literal 0 HcmV?d00001 diff --git a/module_analog_tile_support/src/at_periph.h b/module_analog_tile_support/src/at_periph.h new file mode 100644 index 0000000..f28f3af --- /dev/null +++ b/module_analog_tile_support/src/at_periph.h @@ -0,0 +1,167 @@ +#ifndef AT_PERIPH_H_ +#define AT_PERIPH_H_ + +#include +#include + +//Macro to allow arbitrary struct/array to be passed to sleep mem functions +//Uses XC cast (x, y) operation +#define at_pm_memory_read(x) at_pm_memory_read_impl((x, char[]), sizeof(x)) +#define at_pm_memory_write(x) at_pm_memory_write_impl((x, char[]), sizeof(x)) + +//Speed of 31KHz silicon oscialtor (approx) +#define SI_OSCILLATOR_FREQ_31K 31250 + +/** Enumerated type containing possible wake sources from sleep mode + * + * Each source type can be enabled or disabled. + * RTC and WAKE_PIN_x may be used together however, + * WAKE_PIN_LOW or HIGH are mutually exclusive. Ie. enabling wake + * on WAKE_PIN_LOW will disable WAKE_PIN_HIGH + */ +typedef enum { +RTC, +WAKE_PIN_LOW, +WAKE_PIN_HIGH} wake_sources_t; + +//////////128B deep sleep memory access. See above macro for user API////////// + +/** Function that writes an array of size up to 128B to sleep memory. + * Note, for types other than char[], please use above macro + * + * \param reference to the charater array to be written + * + * \param size of array to be written in bytes + */ +void at_pm_memory_read_impl(char data[], unsigned char size); + +/** Function that reads an array of size up to 128B from sleep memory. + * Note, to pass types other than char[], please use above macro + * + * \param reference to the charater array to be written + * + * \param size of array to be written in bytes + */ +void at_pm_memory_write_impl(char dara[], unsigned char size); + +/** Function that test to see if the deep sleep memory contents are valid. + * Use before reading sleep memory to see if it has been previously initialised. + * Note that the chip initialises this to zero on reset. + * + * \returns boolean result. 1 = Valid, 0 = Invalid. + */ +char at_pm_memory_is_valid(void); + +/** Function that sets the validity of the sleep memory + * Use only after a write to sleep memory to set as valid. + * Note that the defaults to invalid on reset. + * + * \param boolean status. 1 = Valid, 0 = Invalid. + */ +void at_pm_memory_set_validation(char isvalid); + +//////////Sleep and wake control////////// + +/** Function that enables the chip to be woken by specific sources + * Each wake source type can be enabled or disabled. + * RTC and WAKE_PIN_x may be used together however, + * WAKE_PIN_LOW or HIGH are mutually exclusive. Ie. enabling wake + * on WAKE_PIN_LOW will disable WAKE_PIN_HIGH and vice versa. + * + * \param enumerated type wake_sources_t specifying wake source to enable + */ +void at_pm_enable_wake_source(wake_sources_t wake_source); + +/** Function that disables the chip to be woken by specific sources + * Each wake source type can be enabled or disabled. + * Disabling either WAKE_PIN_LOW or WAKE_PIN_HIGH will have the same + * effect of diabling wake from pin + * + * \param enumerated type wake_sources_t specifying wake source to disable + */ +void at_pm_disable_wake_source(wake_sources_t wake_source); + +/** Function that sets the wake time in milliseconds, measured by the RTC clock. + * It is recommended to reset the RTC before setting the wake time + * to avoid issues with overflow if the application has been running + * for some time before. + * The time may be up to about 4E6 seconds from reset, or approx 48 days + * before overflow occurs. + * + * \param time to set alarm/wake up in milliseconds + */ +void at_pm_set_wake_time(unsigned int alarm_time); + +/** Function that sets the minimum time to stay asleep in milliseconds. + * Default time on power up is 2^16 sleep clocks, or about 2s. + * Note this function truncates to the value to the nearest + * power of 2, so is +100% - 50% accurate, due to hardware. + * This value is not critical but can be used to ignore pin events until + * a certain time. + * + * \param time to set alarm/wake up in milliseconds + */ +void at_pm_set_min_sleep_time(unsigned int min_sleep_time); + +/** Function that instructs the chip to go to sleep immediately. + * Sleep is a very deep state that switches off everything except + * the RTC and deep sleep memory, so the application should have exited + * gracefully before this function is called, including all peripheral functions. + * This must be the last function to be called before sleep. When waking, the + * chip will go through the reset sequence. Use deep sleep memory to + * steer the application at boot time, to recover from sleep, and determine state. + * + */ +void at_pm_sleep_now(void); + +//////////RTC (real time clock)////////// + +/** Function that reads the rtc value. + * Takes the counter and scales to milliseconds. + * The time may be up to about 4E6 seconds from reset, or approx 48 days + * before overflow occurs. + * + * \returns time in milliseconds. + */ +unsigned int at_rtc_read(void); + +/** Function that clears the rtc value. + * Sets the time to zero. + */ +void at_rtc_reset(void); + + +//////////Watchdog timer////////// + +/** Function that enables the watchdog timer. On overflow, it reset the xCORE + * tile only. The analog tile is not reset. + * By default, the WDT is disabled by the chip. + */ +void at_watchdog_enable(void); + +/** Function that disables the watchdog timer. + * By default, the WDT is disabled by the chip. + * + */ +void at_watchdog_disable(void); + +/** Function that sets the overflow time in milliseconds, from now. + * Calling this function will automatically clear the WDT and start counting from zero ms. + * It is a 16b counter which allows up to 65535 milliseconds, or about 65 seconds. + * + * \param watchdog overflow time in milliseconds + */ +void at_watchdog_set_timeout(unsigned short milliseconds); + +/** Function that kicks the watchdog timer, Ie. sets it counting from zero. + * This function should be periodically called to prevent overflow and system reset, during + * normal operation. + * It returns the current time in the watchdog timer, to allow the application to see + * how close it is to a reset caused by WDT overflow + * + * \returns WDT time in milliseconds. + */ +unsigned short at_watchdog_kick(void); + + +#endif /* AT_PERIPH_H_ */ diff --git a/module_analog_tile_support/src/at_periph.xc b/module_analog_tile_support/src/at_periph.xc new file mode 100644 index 0000000..58501be --- /dev/null +++ b/module_analog_tile_support/src/at_periph.xc @@ -0,0 +1,207 @@ +#include "at_periph.h" +#include "debug_print.h" + + +static unsigned int convert_ms_to_ticks (unsigned int milliseconds){ + unsigned int read_val_32; + unsigned long long ticks; + read_node_config_reg(xs1_su_periph, XS1_SU_CFG_SYS_CLK_FREQ_NUM, read_val_32); + read_val_32 = XS1_SU_CFG_SYS_CLK_FREQ(read_val_32); //Mask off upper bits + ticks = (unsigned long long) milliseconds * (unsigned long long) read_val_32 * 1000; + return ticks; +} + +static unsigned int convert_ticks_to_ms (unsigned long long ticks){ + unsigned int read_val_32; + unsigned int milliseconds; + read_node_config_reg(xs1_su_periph, XS1_SU_CFG_SYS_CLK_FREQ_NUM, read_val_32); + read_val_32 = XS1_SU_CFG_SYS_CLK_FREQ(read_val_32); //Mask off upper bits + milliseconds = (unsigned int) (ticks / (1000 * read_val_32)); + return milliseconds; +} + + +//128B deep sleep memory access +void at_pm_memory_read_impl(unsigned char data[], unsigned char size){ + if (size > XS1_SU_NUM_GLX_PER_MEMORY_BYTE); //TODO + read_periph_8 (xs1_su_periph, XS1_SU_PER_MEMORY_CHANEND_NUM, XS1_SU_PER_MEMORY_BYTE_0_NUM, + size, data); +} +void at_pm_memory_write_impl(unsigned char data[], unsigned char size){ + write_periph_8 (xs1_su_periph, XS1_SU_PER_MEMORY_CHANEND_NUM, XS1_SU_PER_MEMORY_BYTE_0_NUM, + size, data); +} + +char at_pm_memory_is_valid(void){ + char val[1]; + read_periph_8 (xs1_su_periph, XS1_SU_PER_MEMORY_CHANEND_NUM, XS1_SU_PER_MEMORY_VALID_NUM, 1, val); + if (val[0] == 0xed) return 1; //magic value for valid + else return 0; +} +void at_pm_memory_set_validation(char isvalid){ + char val[1]; + if (isvalid) val[0] = 0xed; //magic value for valid + else val[0] = 0x00; //magic value for invalid + write_periph_8 (xs1_su_periph, XS1_SU_PER_MEMORY_CHANEND_NUM, XS1_SU_PER_MEMORY_VALID_NUM, 1, val); +} + + +//Sleep and wake control +void at_pm_enable_wake_source(wake_sources_t wake_source){ + unsigned int write_val; + read_periph_32(xs1_su_periph, XS1_SU_PER_PWR_CHANEND_NUM, XS1_SU_PER_PWR_MISC_CTRL_NUM, 1, &write_val); + switch (wake_source){ + case RTC: + write_val = XS1_SU_PWR_TMR_WAKEUP_64_SET(write_val, 1); //Set timer to 64b mode + write_val = XS1_SU_PWR_SLEEP_CLK_SEL_SET(write_val, 0); //Use 31KHz source as clock for sleep + write_val = XS1_SU_PWR_TMR_WAKEUP_EN_SET(write_val, 1); //Enable timer wake + break; + + case WAKE_PIN_LOW: + write_val = XS1_SU_PWR_PIN_WAKEUP_EN_SET(write_val, 1); //Enable pin wake + write_val = XS1_SU_PWR_PIN_WAKEUP_ON_SET(write_val, 0); //Wake on low level + break; + + case WAKE_PIN_HIGH: + write_val = XS1_SU_PWR_PIN_WAKEUP_EN_SET(write_val, 1); //Disable pin wake + write_val = XS1_SU_PWR_PIN_WAKEUP_ON_SET(write_val, 1); //Wake on high level + break; + } +// debug_printf("Wrting value to power control reg = 0x%x\n", write_val); + write_periph_32(xs1_su_periph, XS1_SU_PER_PWR_CHANEND_NUM, XS1_SU_PER_PWR_MISC_CTRL_NUM, 1, &write_val); +} +void at_pm_disable_wake_source(wake_sources_t wake_source) +{ + unsigned int write_val; + read_periph_32(xs1_su_periph, XS1_SU_PER_PWR_CHANEND_NUM, XS1_SU_PER_PWR_MISC_CTRL_NUM, 1, &write_val); + switch (wake_source){ + case RTC: + write_val = XS1_SU_PWR_TMR_WAKEUP_64_SET(write_val, 1); //Set timer to 64b mode + write_val = XS1_SU_PWR_SLEEP_CLK_SEL_SET(write_val, 0); //Use 31KHz source as clock for sleep + write_val = XS1_SU_PWR_TMR_WAKEUP_EN_SET(write_val, 0); //Disable timer wake + break; + + case WAKE_PIN_LOW: + write_val = XS1_SU_PWR_PIN_WAKEUP_EN_SET(write_val, 0); //Disable pin wake + write_val = XS1_SU_PWR_PIN_WAKEUP_ON_SET(write_val, 0); //Wake on low level + break; + + case WAKE_PIN_HIGH: + write_val = XS1_SU_PWR_PIN_WAKEUP_EN_SET(write_val, 0); //Disable pin wake + write_val = XS1_SU_PWR_PIN_WAKEUP_ON_SET(write_val, 1); //Wake on high level + break; + } +// debug_printf("Wrting value to power control reg = 0x%x\n", write_val); + write_periph_32(xs1_su_periph, XS1_SU_PER_PWR_CHANEND_NUM, XS1_SU_PER_PWR_MISC_CTRL_NUM, 1, &write_val); +} + +void at_pm_set_wake_time(unsigned int alarm_time){ + unsigned int write_val[2]; + unsigned long long alarm_ticks; + alarm_ticks = convert_ms_to_ticks(alarm_time); + write_val[0] = alarm_ticks & 0xFFFFFFFF; + write_val[1] = alarm_ticks >> 32; + debug_printf("wake_at[1..0] is 0x%x, 0x%x\n", write_val[1], write_val[0]); + write_periph_32(xs1_su_periph, XS1_SU_PER_PWR_CHANEND_NUM, XS1_SU_PER_PWR_WAKEUP_TMR_LWR_NUM, 2, write_val); +} + + +void at_pm_set_min_sleep_time(unsigned int min_sleep_time){ + int write_val_32; + unsigned int calc, bit_posn = 0; + calc = ((min_sleep_time * SI_OSCILLATOR_FREQ_31K) / 1000); //sleep time in 31KHz sleep clock ticks + for (int i = 0; i < 32; i++) if ((calc >> i) & 0x1) bit_posn = i; //perform an approximate log2 calculation + read_periph_32(xs1_su_periph, XS1_SU_PER_PWR_CHANEND_NUM, XS1_SU_PER_PWR_STATE_ASLEEP_NUM, 1, &write_val_32); + write_val_32 = XS1_SU_PWR_INT_EXP_SET(write_val_32, bit_posn); + write_periph_32(xs1_su_periph, XS1_SU_PER_PWR_CHANEND_NUM, XS1_SU_PER_PWR_STATE_ASLEEP_NUM, 1, &write_val_32); +} + +void at_pm_sleep_now(void){ + unsigned char write_val, osc_good = 0; + unsigned int read_val_32, write_val_32; + + //Setup 20MHz on chip oscilator + write_val = XS1_SU_GEN_OSC_SEL_SET(0, 1); //Ensure Si OSC is enabled + write_val = XS1_SU_GEN_OSC_RST_EN_SET(write_val, 0); //Select 20MHz osc + write_periph_8(xs1_su_periph, XS1_SU_PER_OSC_CHANEND_NUM, XS1_SU_PER_OSC_ON_SI_CTRL_NUM, 1, &write_val); + + //wait until oscillator is stable + while (!osc_good){ + read_periph_32(xs1_su_periph, XS1_SU_PER_PWR_CHANEND_NUM, XS1_SU_PER_PWR_PMU_DBG_NUM, 1, &read_val_32); + osc_good = XS1_SU_PWR_ON_SI_STBL(read_val_32); + } + + //Switch to silicon oscilator + write_val = XS1_SU_GEN_OSC_RST_EN_SET(0, 0); //Disable reset on clock change + write_val = XS1_SU_GEN_OSC_SEL_SET(write_val, 1); //Switch to silicon oscialtor + write_periph_8(xs1_su_periph, XS1_SU_PER_OSC_CHANEND_NUM, XS1_SU_PER_OSC_GEN_CTRL_NUM, 1, &write_val); + + //Disable XTAL bias and oscillator + write_val = XS1_SU_XTAL_OSC_EN_SET(0, 0); //Switch off crysal oscillator + write_val = XS1_SU_XTAL_OSC_BIAS_EN_SET(write_val, 0); //Disable crystal bias circuit + write_periph_8(xs1_su_periph, XS1_SU_PER_OSC_CHANEND_NUM, XS1_SU_PER_OSC_XTAL_CTRL_NUM, 1, &write_val); + + //Disable all supplies except DC-DC2 (peripheral tile supply) + write_val_32 = XS1_SU_PWR_WAKEUP_TMR_LWR_SET(0, 8); //set to 256 cycles min time asleep + write_val_32 = XS1_SU_PWR_WAKEUP_TMR_UPR_SET(write_val_32, 0);//set to 256 cycles min time asleep + write_val_32 = XS1_SU_PWR_EXT_CLK_MASK_SET(write_val_32, 0); //Disable xCore clock + write_val_32 = XS1_SU_PWR_VOUT1_EN_SET(write_val_32, 0); //Disable DC-DC1 + write_val_32 = XS1_SU_PWR_VOUT1_MOD_SET(write_val_32, 0); //Set to PWM mode + write_val_32 = XS1_SU_PWR_VOUT2_EN_SET(write_val_32, 1); //Enable DC-DC2 + write_val_32 = XS1_SU_PWR_VOUT2_MOD_SET(write_val_32, 1); //Set to PFM mode + write_val_32 = XS1_SU_PWR_VOUT5_EN_SET(write_val_32, 0); //Disable LDO5 + write_val_32 = XS1_SU_PWR_VOUT6_EN_SET(write_val_32, 0); //Disable LDO6 + write_periph_32(xs1_su_periph, XS1_SU_PER_PWR_CHANEND_NUM, XS1_SU_PER_PWR_STATE_ASLEEP_NUM, 1, &write_val_32); + + //go to sleep + read_periph_32(xs1_su_periph, XS1_SU_PER_PWR_CHANEND_NUM, XS1_SU_PER_PWR_MISC_CTRL_NUM, 1, &write_val_32); + write_val_32 = XS1_SU_PWR_SLEEP_INIT_SET(write_val_32, 1); //Initiate sleep bit + write_periph_32(xs1_su_periph, XS1_SU_PER_PWR_CHANEND_NUM, XS1_SU_PER_PWR_MISC_CTRL_NUM, 1, &write_val_32); +} + + +//RTC +unsigned int at_rtc_read(void){ + unsigned int time_now[2] = {0, 0}; + unsigned long long ticks; + read_periph_32(xs1_su_periph, XS1_SU_PER_RTC_CHANEND_NUM, XS1_SU_PER_RTC_LWR_32BIT_NUM, 2, time_now); + debug_printf("ticks_now[1..0] is 0x%x, 0x%x\n", time_now[1], time_now[0]); + ticks = (unsigned long long) ((time_now[1] * 0x100000000) + time_now[0]); + return convert_ticks_to_ms(ticks); +} + +void at_rtc_reset(void){ + unsigned int time_now[2] = {0, 0}; + write_periph_32(xs1_su_periph, XS1_SU_PER_RTC_CHANEND_NUM, XS1_SU_PER_RTC_LWR_32BIT_NUM, 2, time_now); +} + + +//Watchdog timer +void at_watchdog_enable(void){ + unsigned int write_val = 0x00000000; //Magic value ie. not 0x0D15AB1E + write_node_config_reg(xs1_su_periph, XS1_SU_CFG_WDOG_DISABLE_NUM, write_val); +} + +void at_watchdog_disable(void){ + unsigned int write_val = 0x0D15AB1E; //Magic value to disable + write_node_config_reg(xs1_su_periph, XS1_SU_CFG_WDOG_DISABLE_NUM, write_val); +} + + +void at_watchdog_set_timeout(unsigned short milliseconds){ + unsigned int write_val; + write_val = milliseconds | (~milliseconds << 16); //Set upper 16b to 1's complement of lower + //This is the 'password' for accessing reg + write_node_config_reg(xs1_su_periph, XS1_SU_CFG_WDOG_TMR_NUM, write_val); //write expiry value +} + +unsigned short at_watchdog_kick(void){ + unsigned short expiry_val, wdt_timer; + unsigned int write_val, read_val; + read_node_config_reg(xs1_su_periph, XS1_SU_CFG_WDOG_TMR_NUM, read_val); //Get current expiry value & timer + expiry_val = (unsigned short) XS1_SU_CFG_WDOG_EXP(read_val); //mask off expiry value + write_val = (unsigned int) expiry_val | (~(unsigned int)expiry_val << 16);//Set the password in upper 16b + wdt_timer = (unsigned short) XS1_SU_CFG_WDOG_TMR(read_val); //mask off and shift timer value + write_node_config_reg(xs1_su_periph, XS1_SU_CFG_WDOG_TMR_NUM, write_val); //rewrite expiry value to reset timer + return wdt_timer; //return wdt value +} diff --git a/tests/.DS_Store b/tests/.DS_Store new file mode 100644 index 0000000000000000000000000000000000000000..b46d4be5a3c9192fcb3b6ae16eeb2a75b1fe5157 GIT binary patch literal 6148 zcmeHK%}&BV5S|4@RE)itaBMsiQ-uT%9vXs)M-xmuh{4vPG-+BwiyW}p_z=E^Z{zd$ z?T-nFgqsoBNoKy;-I?9Ym+o$th*)#v9T6EsRDyCWY{UE@e4Oi?%1Q z>O!?>1~dbIodLdg_b8zr#jw-+H=>a4$)^W*91q+eauNCN4gx<;EbD{i@`a7!W(iX6 zT=}6FjhoRZ^y2GwKN`1vuje|$8{sETGK!ndP>ftSNgpG^zl@>)en&-L`CiiR8kNc9 zs8+9<^)+OtQ;x_z2lm_yw{_ zJ|L3MQl6qBrU10`XuxS%Z4wri^{xEvsq)7-$;B73+NJ+k(zmj|zLzyawQWi}YgV@| zS2Lg)Sk3@HA517mTVW>jhTL^sqmf$(2LR(=b5hD;LQ-Ly-sV4@L>F76A zoUJgEDAS3Fl`)T6nW+~F6RV@&6yd~diP~xgGy}5?gw9yRw GDg&S1NX+&C literal 0 HcmV?d00001 diff --git a/tests/test_adc_config/.DS_Store b/tests/test_adc_config/.DS_Store new file mode 100644 index 0000000000000000000000000000000000000000..5f6ae930dddc5f5079946b4767540c59ebd6cecf GIT binary patch literal 6148 zcmeHK%}T>S5Z-O8MpVc}=yCB}q_u^5@DM@;k3tGPSkc6Y4TPj5sXf$a@F9E+-^S;0 zW_JQsdlr!y*!{lUnc2;Lko^%tNOuwTgs_DW78FE@WP@S%MpuJ^5hae1&x1G(p!FWi z$@kX*zr87Pk%_xt`SttbC@;F*57}t8wzhXHu>I*IO2TyMri&!Zue@2h^rG-S@Uv^p z3%^+8uAgborC-dzqxm>ZW8hPYo|kaEQ!d{Y4T2L%PuA*>AQtph5&KBK>dhz1A*>972TYn&K$9xzi6Koo^ec*U z2rGjoT}VAMj6*Zmj~A(Dhkm8Qg>(#Z%?hvr>k2eY)5i1v9DbRNkNou%Zm|Naz&}$! zwnpB_g+!xKz$d0KM!^68 literal 0 HcmV?d00001 diff --git a/tests/test_sleep_a/.DS_Store b/tests/test_sleep_a/.DS_Store new file mode 100644 index 0000000000000000000000000000000000000000..5f6ae930dddc5f5079946b4767540c59ebd6cecf GIT binary patch literal 6148 zcmeHK%}T>S5Z-O8MpVc}=yCB}q_u^5@DM@;k3tGPSkc6Y4TPj5sXf$a@F9E+-^S;0 zW_JQsdlr!y*!{lUnc2;Lko^%tNOuwTgs_DW78FE@WP@S%MpuJ^5hae1&x1G(p!FWi z$@kX*zr87Pk%_xt`SttbC@;F*57}t8wzhXHu>I*IO2TyMri&!Zue@2h^rG-S@Uv^p z3%^+8uAgborC-dzqxm>ZW8hPYo|kaEQ!d{Y4T2L%PuA*>AQtph5&KBK>dhz1A*>972TYn&K$9xzi6Koo^ec*U z2rGjoT}VAMj6*Zmj~A(Dhkm8Qg>(#Z%?hvr>k2eY)5i1v9DbRNkNou%Zm|Naz&}$! zwnpB_g+!xKz$d0KM!^68 literal 0 HcmV?d00001 diff --git a/tests/test_sleep_a/Makefile b/tests/test_sleep_a/Makefile new file mode 100644 index 0000000..5aa9711 --- /dev/null +++ b/tests/test_sleep_a/Makefile @@ -0,0 +1,33 @@ +# The TARGET variable determines what target system the application is +# compiled for. It either refers to an XN file in the source directories +# or a valid argument for the --target option when compiling +TARGET = XP-SKC-U16 + +# The APP_NAME variable determines the name of the final .xe file. It should +# not include the .xe postfix. If left blank the name will default to +# the project name +APP_NAME = + +# The USED_MODULES variable lists other module used by the application. +USED_MODULES = module_logging module_analog_tile_support + +# The flags passed to xcc when building the application +# You can also set the following to override flags for a particular language: +# XCC_XC_FLAGS, XCC_C_FLAGS, XCC_ASM_FLAGS, XCC_CPP_FLAGS +# If the variable XCC_MAP_FLAGS is set it overrides the flags passed to +# xcc for the final link (mapping) stage. +XCC_FLAGS_Debug = -O0 -g +XCC_FLAGS_Release = -O2 -g + +# The VERBOSE variable, if set to 1, enables verbose output from the make system. +VERBOSE = 0 + +# This change to the module path is so that this application can be in the +# tests sub-directory in it's git repo +ifeq ($(notdir $(abspath ..)),tests) +PATHSEP = $(if $(findstring Windows, $(OS))$(findstring WINDOWS,$(OS)),;,:) +XMOS_MODULE_PATH := $(XMOS_MODULE_PATH)$(PATHSEP)../../.. +endif + +XMOS_MAKE_PATH ?= ../.. +-include $(XMOS_MAKE_PATH)/xcommon/module_xcommon/build/Makefile.common diff --git a/tests/test_sleep_a/src/.DS_Store b/tests/test_sleep_a/src/.DS_Store new file mode 100644 index 0000000000000000000000000000000000000000..6d27cedc737ef744a17933f5bc1c607f902f3bda GIT binary patch literal 6148 zcmeHKJx{|x41HHR6tNU0#`^_ST^N|6s@)I^Vh(LnL8U^YCXpEP(|Pt;6;%MSfGT8H z_PaRteY`uxJpf_S6k}irU_ce@ozi?F@?NwfJ@W_#?ITBp4OaY>ooII)BLlK`7pS>o z7466U%Tdt#f-SD_hGkhVZkwv!G5!V*j9y_!JHm`{Bh0zur9RIw#x+mD8VmX>EZJ+R z(QD!}ebQ%vMo&u4%vb7$z9&Z3%##x&GikKXEyt;u_49e&**wo}R^P1Z7`MddslhD@I7^^hb-!4BLb$9YIHCKQ?l(8%og8>5m$YkR^2M3^)Ua44kCLq16A`*Z2R! zB!6-SoPmGEK + + Device + XS1-U16A-128-FB217-C10 Device + + + tileref tile[2] + tileref xs1_su_periph + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/tests/test_sleep_a/src/test_sleep_demo.xc b/tests/test_sleep_a/src/test_sleep_demo.xc new file mode 100644 index 0000000..86a8b48 --- /dev/null +++ b/tests/test_sleep_a/src/test_sleep_demo.xc @@ -0,0 +1,110 @@ +#include "at_periph.h" +#define DEBUG_PRINT_ENABLE 1 +#include "debug_print.h" + +#define RTC_TIME 1000 //Time awake in ms +#define SLEEP_TIME 10000 //Time asleep in ms + +//function to initialise the sleep memory test array +void init_sleep_mem(char write_val, char memory[], unsigned char size ){ + for (unsigned i = 0; i < size; i++) + memory[i] = write_val; +} + +int compare_sleep_mem(char memory_w[], char memory_r[], unsigned char size ){ + int are_different = 0; + for (unsigned i = 0; i < size; i++) if (memory_w[i] != memory_r[i]) are_different = 1; + return are_different; +} + +void sleep_demo(void){ + + timer tmr; + int sys_start_time, temp, all_tests_passed = 1; + unsigned int rtc_start_time, rtc_end_time, alarm_time; + + //Declare memory arrays/structures to test sleep memory read/write. Deliberately, they are a different type + //than the sleep memory. It is expected that structures for example, may be stored + int sleep_mem_to_write[XS1_SU_NUM_GLX_PER_MEMORY_BYTE/4], sleep_mem_read[XS1_SU_NUM_GLX_PER_MEMORY_BYTE/4]; + + //initialise sleep memory. Two buffers - one gets written and the other is what's read back + init_sleep_mem(0xed, (sleep_mem_to_write, char[]), sizeof(sleep_mem_to_write)); + init_sleep_mem(0x00, (sleep_mem_read, char[]), sizeof(sleep_mem_read)); + + debug_printf("Sleep function test application started\n"); + + if (!at_pm_memory_is_valid()) debug_printf("PASS: Deep sleep memory not yet validated after reset\n"); + else { + debug_printf("FAIL: Deep sleep memory incorrectly reports being valid\n",temp); + all_tests_passed = 0; + } + at_pm_memory_set_validation(1); + + if (at_pm_memory_is_valid()) debug_printf("PASS: Deep sleep memory correctly set to valid\n"); + else { + debug_printf("FAIL: Deep sleep incorrectly reports being invalid\n",temp); + all_tests_passed = 0; + } + + + //Write the sleep memory and read it back + at_pm_memory_write(sleep_mem_to_write); + at_pm_memory_read(sleep_mem_read); + + if (!compare_sleep_mem((sleep_mem_to_write, char[]), (sleep_mem_read, char[]), sizeof(sleep_mem_to_write))) + debug_printf("PASS: Successfully wrote and read back sleep memory\n"); + else { + debug_printf("FAIL: Sleep memory written/read back contents different\n"); + all_tests_passed = 0; + } + + //Try out the RTC reset and read functions + at_rtc_clear(); + temp = at_rtc_read(); + if (!temp) debug_printf("PASS: RTC reset to zero successfully\n"); + else { + debug_printf("FAIL: RTC should read zero, but instead reads 0x%x\n",temp); + all_tests_passed = 0; + } + + tmr :> sys_start_time; //get current time (xcore timer) + rtc_start_time = at_rtc_read();//read rtc time + + tmr when timerafter(sys_start_time + (RTC_TIME * 100000)) :> void; + rtc_end_time = at_rtc_read(); + if (rtc_end_time-rtc_start_time == RTC_TIME) debug_printf("PASS: RTC timer in synch with xcore timer over %dms\n", RTC_TIME); + else { + debug_printf("FAIL: RTC should have increemented by %d, but instead incremented by %d\n", + RTC_TIME, rtc_end_time-rtc_start_time); + all_tests_passed = 0; + } + + if (all_tests_passed) debug_printf("PASS: All automated tests passed\n"); + else debug_printf("FAIL: One or more automated tests failed\n"); + //The following + at_pm_set_min_sleep_time(150); //Set min sleep period to about 150ms. + alarm_time = at_rtc_read() + SLEEP_TIME; //Calculate wakeup time + at_pm_set_wake_time(alarm_time); //set alarm time (wakeup) + at_pm_enable_wake_source(RTC); //Enable RTC wakeup + at_pm_enable_wake_source(WAKE_PIN_HIGH); //Enable Wake pin = high wakeup + + debug_printf("Going to sleep now for %u ms, alarm time = %ums\n", SLEEP_TIME, alarm_time); + debug_printf("Sleep test passed if sleep is observed for about 10s, or until WAKE pin goes high (XD43)\n", SLEEP_TIME, alarm_time); + + at_pm_sleep_now(); //Go to sleep. Debugger will disconnect after this +} + + +void something(void){ + while(0); +} + +int main (void) +{ + par{ + sleep_demo(); + something(); + } + return 0; +} + diff --git a/tests/test_wdt_a/.DS_Store b/tests/test_wdt_a/.DS_Store new file mode 100644 index 0000000000000000000000000000000000000000..a4437bb202ded882a5dc4164552969a549a9c0e3 GIT binary patch literal 6148 zcmeH~K}*9h6vvZoYDI-zgdKzDDU%iF!9yt%JPIA`;6z(1u29<1cJ45%#Sh`v@Z0!# zd@p$gr#p+tdyxEJ@?MhW2W=W5gmmZOu@G$`garjvqO-=Zdu^ye$*2`*#q_4#SuRiPt~%`7cG*?S!JyYwcK@_2x53(P z*8aiK*~Q3zDxY5}Ls0@`ZF{7(yn;iUc=WO)PLl`dsk7@WRwlp%m;e)C0-69F5Y`U! zU;<2l349}f-vQ4t$`1_3U7AhL}c$Yv`qz-9i6e3{K3CF z0!?RXFxrKs;c@;Wf;II4yKm)%c9UU}rg+Amtq?J*e1^e}IQ2r6n LK)7N8zd+y<01HON literal 0 HcmV?d00001 diff --git a/tests/test_wdt_a/src/.DS_Store b/tests/test_wdt_a/src/.DS_Store new file mode 100644 index 0000000000000000000000000000000000000000..a21b853bf713369fe7a806bcc8e9da71f1a147b4 GIT binary patch literal 6148 zcmeHKJx{|h5PgOYmAaITF~5MS3ji6wg|~q~r>K(JC#<+c&Hiis zMb)ft+qyZ@;sy^~FL7i)!-~&1Lyn3+ndg|}8hh-p=B!4+I90UX5ud1g#(_R9ZAz}? zcwyU9x8IpsYRr%1ck|wj0cYTo0oflCHo?@eQ;b^&yLbg4j;M~pvD_uZCoxP7J4LQgg1Qpb zHP{s+s5|wE*` literal 0 HcmV?d00001 diff --git a/tests/test_wdt_a/src/XP-SKC-U16.xn b/tests/test_wdt_a/src/XP-SKC-U16.xn new file mode 100644 index 0000000..e492ca5 --- /dev/null +++ b/tests/test_wdt_a/src/XP-SKC-U16.xn @@ -0,0 +1,91 @@ + + + Device + XS1-U16A-128-FB217-C10 Device + + + tileref tile[2] + tileref xs1_su_periph + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/tests/test_wdt_a/src/test_wdt.xc b/tests/test_wdt_a/src/test_wdt.xc new file mode 100644 index 0000000..58254fb --- /dev/null +++ b/tests/test_wdt_a/src/test_wdt.xc @@ -0,0 +1,89 @@ +#include "at_periph.h" +#include "debug_print.h" + + +void init_sleep_mem(char write_val, char memory[], unsigned char size ){ + for (unsigned i = 0; i < size; i++){ + memory[i] = write_val; + } +} + +void sleep_demo(void){ + + timer tmr; + int sys_start_time; + unsigned int rtc_start_time, rtc_end_time, alarm_time; + int my_sleep_mem[XS1_SU_NUM_GLX_PER_MEMORY_BYTE/4], my_sleep_mem2[XS1_SU_NUM_GLX_PER_MEMORY_BYTE/4]; + init_sleep_mem(0xed, (my_sleep_mem, char[]), sizeof(my_sleep_mem)); + init_sleep_mem(0x00, (my_sleep_mem2, char[]), sizeof(my_sleep_mem2)); + + struct save_this{ + int foo; + char bar; + long long something; + }; + + + at_pm_memory_write(my_sleep_mem); + at_pm_memory_read(my_sleep_mem2); + + at_watchdog_set_timeout(0xf055); + at_watchdog_enable(); + debug_printf("Sleep demo started, and I'm currently awake\n"); + + at_rtc_clear(); + + tmr :> sys_start_time; + rtc_start_time = at_rtc_read(); + debug_printf("RTC time now = %u ms\n", rtc_start_time); + tmr when timerafter(sys_start_time + (AWAKE_TIME * 100000)) :> void; + rtc_end_time = at_rtc_read(); + + at_pm_set_min_sleep_time(150); //Set min sleep period to about 150ms + + at_watchdog_set_timeout(0xf055); + at_watchdog_disable(); + + debug_printf("RTC elapsed time measured in %ums = %ums\n", AWAKE_TIME, rtc_end_time-rtc_start_time); + + alarm_time = rtc_end_time + SLEEP_TIME; + debug_printf("RTC time now = %u ms\n", rtc_end_time); + debug_printf("Going to sleep now for %u ms, alarm time = %ums\n", SLEEP_TIME, alarm_time); + + at_pm_set_wake_time(alarm_time); + + at_pm_enable_wake_source(RTC); + at_pm_enable_wake_source(WAKE_PIN_HIGH); + at_pm_sleep_now(); +} + + +void something(void){ + while(0); +} + +int main (void) +{ + par{ + sleep_demo(); + something(); + } + return 0; +} +/* what about this in sleep??? from test code + * + * + // Reconfig the X-Link delays to slow the link down +#if ( defined XVBGX1 ) + write_sswitch_reg_noresp(MYID, XS1_SSWITCH_XLINK_3_NUM, ( 0x3 << 30 +| (1023 << 11) | 2047 ) ); +#elif ( defined MCM ) || ( defined XVBS1 ) || ( defined XVBA1 ) + write_sswitch_reg_noresp(MYID, XS1_SSWITCH_XLINK_5_NUM, ( 0x3 << 30 +| (1023 << 11) | 2047 ) ); +#else + write_sswitch_reg_noresp(MYID, XS1_SSWITCH_XLINK_7_NUM, ( 0x3 << 30 +| (1023 << 11) | 2047 ) ); +#endif + +*/ + From a199a92f9539456cf710949154650e109e2e7999 Mon Sep 17 00:00:00 2001 From: Vinith Mundhra Date: Thu, 25 Jul 2013 13:14:32 +0530 Subject: [PATCH 02/45] adding readme --- .../README.rst | 85 +++++++++++++++++++ .../xmos_python_webserver/server.py | 42 +++++---- 2 files changed, 112 insertions(+), 15 deletions(-) create mode 100644 app_a16_slicekit_ethernet_sleep_wake_combo_demo/README.rst diff --git a/app_a16_slicekit_ethernet_sleep_wake_combo_demo/README.rst b/app_a16_slicekit_ethernet_sleep_wake_combo_demo/README.rst new file mode 100644 index 0000000..e4bd5be --- /dev/null +++ b/app_a16_slicekit_ethernet_sleep_wake_combo_demo/README.rst @@ -0,0 +1,85 @@ +sliceKIT Ethernet Sleep Wake Combo Demo +======================================= + +:scope: Example +:description: A simple demo of sleep and wake features +:keywords: sleep + +This is a simple demo using the Sleep and Wake feature of U and A series of XMOS devices. In this +demo, a webclient running on the XMOS device would inform a webserver running on a PC that it is +going to sleep and has woken up from sleep. + +Hardware requirements +--------------------- + +- XP-SKC-U16 1V1 +- XA-SK-E100 1V0 +- XTAG2 +- Ethernet cable and power supplies (12V) + +Software requirements +--------------------- + +- Python installed on the host PC +- xTIMEcomposer Studio version 13.0.0beta2 + +Required Repositories +--------------------- + +- sc_ethernet https://github.com/xcore/sc_ethernet.git +- sc_otp https://github.com/xcore/sc_otp.git +- sc_periph https://github.com/vinithmundhra/sc_periph +- sc_slicekit_support https://github.com/xcore/sc_slicekit_support.git +- sc_util https://github.com/xcore/sc_util.git +- sc_webclient git://git/apps/sc_webclient.git +- sc_xtcp https://github.com/xcore/sc_xtcp.git + +Setup +----- + +- Connect ``XA-SK-E100`` to the ``SQUARE`` slot of the ``XP-SKC-U16`` sliceKIT core board. +- Connect ``XTAG2`` to ``XSYS`` slot on ``XP-SKC-U16`` sliceKIT core board. +- Connect an Ethernet cable between ``XA-SK-E100`` and your PC. +- Connect the 12V power supply to ``XP-SKC-U16`` sliceKIT core board. + +- In the xTIMEcpomposer Studio, import ``app_a16_slicekit_ethernet_sleep_wake_combo_demo`` +- Build the project and run it once on the XMOS device. +- Terminate and close the run and open ``app_a16.xc``. + +- Navigate to ``$\sc_periph\app_a16_slicekit_ethernet_sleep_wake_combo_demo\xmos_python_webserver`` +- Run ``server.py`` and note down the Server IP address. +- Terminate the Python run. + +- In the xTIMEcomposer Studio, navigate to line 59 of ``app_a16.xc`` +- Change the IP address to that noted down previously +- Build the project and *Flash* it on the XMOS device +- After successful flash, power cycle the ``XP-SKC-U16`` sliceKIT core board. +- Remove the ``XTAG2`` from the core board. + +Demo +---- + +#. Switch ON the power supply to ``XP-SKC-U16`` sliceKIT core board. +#. Run ``server.py`` on your PC +#. After a while, below mentioned messages will appear on the Python console:: + + Server Address = 169.254.202.189 + Incoming ('169.254.216.175', 1026) + XMOS: Going to Sleep...zzz + Incoming ('169.254.193.54', 1026) + XMOS: Rise and shine.... + XMOS: Going to Sleep...zzz + Incoming ('169.254.143.18', 1026) + XMOS: Rise and shine.... + XMOS: Going to Sleep...zzz + +What this means is + +#. The XMOS connects to webserver at start +#. Informs webserver that it is going to sleep (Going to Sleep...zzz) +#. Sleeps for some time +#. Wakes up and finds Server IP address in the sleep memory +#. Connects to webserver again +#. Informs that it has woken up from sleep ('Rise and shine....') +#. Informs webserver that it is going to sleep (Going to Sleep...zzz) +#. Loops diff --git a/app_a16_slicekit_ethernet_sleep_wake_combo_demo/xmos_python_webserver/server.py b/app_a16_slicekit_ethernet_sleep_wake_combo_demo/xmos_python_webserver/server.py index 4dcc5d7..2193a14 100644 --- a/app_a16_slicekit_ethernet_sleep_wake_combo_demo/xmos_python_webserver/server.py +++ b/app_a16_slicekit_ethernet_sleep_wake_combo_demo/xmos_python_webserver/server.py @@ -1,21 +1,33 @@ #!/usr/bin/python -import socket,sys +import asyncore +import socket server_port = 501 self_ip = socket.gethostbyname(socket.gethostname()) -print >>sys.stderr, 'Server Address = ', self_ip +print 'Server Address = %s' % self_ip -server_sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM) -server_sock.bind((self_ip, server_port)) -server_sock.listen(1) +class XHandler(asyncore.dispatcher_with_send): -while 1: - - print "Waiting for a client connection..." - connection, client_address = server_sock.accept() - print >>sys.stderr, 'connection from', client_address - - data = connection.recv(100) - print >>sys.stderr, '==> "%s"\n' % data - connection.close() - \ No newline at end of file + def handle_read(self): + data = self.recv(1024) + if data: + print 'XMOS: %s' % data + +class XServer(asyncore.dispatcher): + + def __init__(self, host, port): + asyncore.dispatcher.__init__(self) + self.create_socket(socket.AF_INET, socket.SOCK_STREAM) + self.set_reuse_addr() + self.bind((host, port)) + self.listen(1) + + def handle_accept(self): + pair = self.accept() + if pair is not None: + sock, addr = pair + print 'Incoming %s' % repr(addr) + handler = XHandler(sock) + +server = XServer(self_ip, server_port) +asyncore.loop() From 6831f45c79cc551b4e3fa8c0c2f0b30cca963de7 Mon Sep 17 00:00:00 2001 From: Vinith Mundhra Date: Wed, 31 Jul 2013 10:57:32 +0530 Subject: [PATCH 03/45] updated python scripts, app requesting close connection --- .../.cproject | 6 + .../README.rst | 77 ++-------- .../doc_quickstart/Makefile | 7 + .../doc_quickstart/quickstart.rst | 134 ++++++++++++++++++ .../src/app_a16.xc | 26 ++-- .../src/common.h | 46 ------ .../src/util.c | 58 -------- .../src/util.h | 62 -------- .../xmos_python_webserver/server.py | 36 ++--- 9 files changed, 183 insertions(+), 269 deletions(-) create mode 100644 app_a16_slicekit_ethernet_sleep_wake_combo_demo/doc_quickstart/Makefile create mode 100644 app_a16_slicekit_ethernet_sleep_wake_combo_demo/doc_quickstart/quickstart.rst delete mode 100644 app_a16_slicekit_ethernet_sleep_wake_combo_demo/src/common.h delete mode 100644 app_a16_slicekit_ethernet_sleep_wake_combo_demo/src/util.c delete mode 100644 app_a16_slicekit_ethernet_sleep_wake_combo_demo/src/util.h diff --git a/app_a16_slicekit_ethernet_sleep_wake_combo_demo/.cproject b/app_a16_slicekit_ethernet_sleep_wake_combo_demo/.cproject index 385e8c2..46586ae 100644 --- a/app_a16_slicekit_ethernet_sleep_wake_combo_demo/.cproject +++ b/app_a16_slicekit_ethernet_sleep_wake_combo_demo/.cproject @@ -185,6 +185,7 @@ + @@ -325,6 +326,7 @@ + @@ -471,6 +473,7 @@ + @@ -687,6 +690,7 @@ + @@ -827,6 +831,7 @@ + @@ -973,6 +978,7 @@ + diff --git a/app_a16_slicekit_ethernet_sleep_wake_combo_demo/README.rst b/app_a16_slicekit_ethernet_sleep_wake_combo_demo/README.rst index e4bd5be..48535e8 100644 --- a/app_a16_slicekit_ethernet_sleep_wake_combo_demo/README.rst +++ b/app_a16_slicekit_ethernet_sleep_wake_combo_demo/README.rst @@ -1,85 +1,34 @@ -sliceKIT Ethernet Sleep Wake Combo Demo -======================================= +A16 sliceKIT Ethernet Sleep Wake Combo Demo +=========================================== :scope: Example :description: A simple demo of sleep and wake features :keywords: sleep +:boards: XA-SK-E100 -This is a simple demo using the Sleep and Wake feature of U and A series of XMOS devices. In this -demo, a webclient running on the XMOS device would inform a webserver running on a PC that it is -going to sleep and has woken up from sleep. +Demo Overview +------------- -Hardware requirements ---------------------- - -- XP-SKC-U16 1V1 -- XA-SK-E100 1V0 -- XTAG2 -- Ethernet cable and power supplies (12V) +This is a simple demo using the Sleep and Wake feature of A series XMOS devices. In this demo, a webclient running on the XMOS device informs a webserver running on a host workstation when it is going to sleep and has woken up from sleep. The XMOS device can be woken up using: Timer, pin value, etc... Software requirements --------------------- -- Python installed on the host PC -- xTIMEcomposer Studio version 13.0.0beta2 +- Python installed on host workstation +- xTIMEcomposer Studio version 13.0.0 Required Repositories --------------------- - sc_ethernet https://github.com/xcore/sc_ethernet.git - sc_otp https://github.com/xcore/sc_otp.git -- sc_periph https://github.com/vinithmundhra/sc_periph +- sc_periph https://github.com/xcore/sc_periph.git - sc_slicekit_support https://github.com/xcore/sc_slicekit_support.git - sc_util https://github.com/xcore/sc_util.git -- sc_webclient git://git/apps/sc_webclient.git +- sc_webclient https://github.com/xcore/sc_webclient.git - sc_xtcp https://github.com/xcore/sc_xtcp.git -Setup ------ - -- Connect ``XA-SK-E100`` to the ``SQUARE`` slot of the ``XP-SKC-U16`` sliceKIT core board. -- Connect ``XTAG2`` to ``XSYS`` slot on ``XP-SKC-U16`` sliceKIT core board. -- Connect an Ethernet cable between ``XA-SK-E100`` and your PC. -- Connect the 12V power supply to ``XP-SKC-U16`` sliceKIT core board. - -- In the xTIMEcpomposer Studio, import ``app_a16_slicekit_ethernet_sleep_wake_combo_demo`` -- Build the project and run it once on the XMOS device. -- Terminate and close the run and open ``app_a16.xc``. - -- Navigate to ``$\sc_periph\app_a16_slicekit_ethernet_sleep_wake_combo_demo\xmos_python_webserver`` -- Run ``server.py`` and note down the Server IP address. -- Terminate the Python run. - -- In the xTIMEcomposer Studio, navigate to line 59 of ``app_a16.xc`` -- Change the IP address to that noted down previously -- Build the project and *Flash* it on the XMOS device -- After successful flash, power cycle the ``XP-SKC-U16`` sliceKIT core board. -- Remove the ``XTAG2`` from the core board. - -Demo ----- - -#. Switch ON the power supply to ``XP-SKC-U16`` sliceKIT core board. -#. Run ``server.py`` on your PC -#. After a while, below mentioned messages will appear on the Python console:: - - Server Address = 169.254.202.189 - Incoming ('169.254.216.175', 1026) - XMOS: Going to Sleep...zzz - Incoming ('169.254.193.54', 1026) - XMOS: Rise and shine.... - XMOS: Going to Sleep...zzz - Incoming ('169.254.143.18', 1026) - XMOS: Rise and shine.... - XMOS: Going to Sleep...zzz - -What this means is +Support +------- -#. The XMOS connects to webserver at start -#. Informs webserver that it is going to sleep (Going to Sleep...zzz) -#. Sleeps for some time -#. Wakes up and finds Server IP address in the sleep memory -#. Connects to webserver again -#. Informs that it has woken up from sleep ('Rise and shine....') -#. Informs webserver that it is going to sleep (Going to Sleep...zzz) -#. Loops +Issues may be submitted via the Issues tab in this github repo. Response to any issues submitted as at the discretion of the manitainer for this line. diff --git a/app_a16_slicekit_ethernet_sleep_wake_combo_demo/doc_quickstart/Makefile b/app_a16_slicekit_ethernet_sleep_wake_combo_demo/doc_quickstart/Makefile new file mode 100644 index 0000000..a7b75dd --- /dev/null +++ b/app_a16_slicekit_ethernet_sleep_wake_combo_demo/doc_quickstart/Makefile @@ -0,0 +1,7 @@ +all: html + +SPHINX_PROJECT_NAME = A16 sliceKIT Ethernet Sleep Wake Combo Demo Quickstart Guide +VERSION = 1.0 +SOURCE_INCLUDE_DIRS = ../../app_a16_slicekit_ethernet_sleep_wake_combo_demo +XDOC_DIR ?= ../../../xdoc +include $(XDOC_DIR)/Makefile.inc diff --git a/app_a16_slicekit_ethernet_sleep_wake_combo_demo/doc_quickstart/quickstart.rst b/app_a16_slicekit_ethernet_sleep_wake_combo_demo/doc_quickstart/quickstart.rst new file mode 100644 index 0000000..50780ce --- /dev/null +++ b/app_a16_slicekit_ethernet_sleep_wake_combo_demo/doc_quickstart/quickstart.rst @@ -0,0 +1,134 @@ +A16 sliceKIT Ethernet Sleep Wake Combo Demo Quickstart Guide +============================================================ + +This simple demonstration of xTIMEcomposer Studio functionality that uses the ``XA-SK-E100`` sliceCARD together with the xSOFTip ``module_analog_tile_support`` and ``module_webclient`` to demonstrate how the chip can be made to sleep and wake up using different sources. The app also runs a TCP web client and informs web server before going to sleep and after waking up from sleep. + +Hardware Setup +++++++++++++++ + +The A16 sliceKIT Ethernet Sleep Wake Combo Demo Application requires the following items: + +- XP-SKC-A16 sliceKIT core board. +- XA-SK-E100 Ethernet sliceCARD +- XTAG-2 +- Ethernet and USB cables +- 12V DC power supply + +To setup the system: + +#. Connect the ``XTAG-2`` to sliceKIT Core board. +#. Connect the ``XTAG-2`` to host PC using USB cable. Note that the USB cable is not provided with the sliceKIT starter kit. +#. Connect ``XA-SK-E100`` sliceCARD to the sliceKIT Core board using the connector marked with the ``SQUARE``. +#. Connect ``XA-SK-E100`` sliceCARD and host computer using Ethernet cable. +#. Switch on the power supply to the sliceKIT Core board. + +.. figure:: images/hardware_setup.jpg + :align: center + + Hardware Setup for A16 sliceKIT Ethernet Sleep Wake Combo Demo Application + +Host Computer Setup ++++++++++++++++++++ + +Install Python on the host computer from http://www.python.org/. + +Note for Mac: Have a static Ethernet IP: System Preferences -> Network -> Ethernet -> Configure IPv4: Manually. Give an IP address. + +Import and Build the Application +++++++++++++++++++++++++++++++++ + +#. Open xTIMEcomposer and check that it is operating in online mode. Open the edit perspective (Window->Open Perspective->XMOS Edit). +#. Locate the ``A16 sliceKIT Ethernet Sleep Wake Combo Demo`` item in the xSOFTip pane on the bottom left of the window and drag it into the Project Explorer window in the xTIMEcomposer. This will also cause the modules on which this application depends to be imported as well. +#. Open the file ``$/app_a16_slicekit_ethernet_sleep_wake_combo_demo/src/app_a16.xc`` +#. Go to line:55 and change the IP address (of the web server) that the web client will try to connect to. +#. Save the application using File -> Save. +#. Click on the ``app_a16_slicekit_ethernet_sleep_wake_combo_demo`` item in the Project Explorer pane then click on the build icon (hammer) in xTIMEcomposer. Check the console window to verify that the application has built successfully. + +For help in using xTIMEcomposer, try the xTIMEcomposer tutorial, which you can find by selecting (Help->Tutorials) from the xTIMEcomposer menu. + +Note that the Developer Column in the xTIMEcomposer on the right hand side of your screen provides information on the xSOFTip components you are using. Select the ``module_analog_tile_support`` component in the Project Explorer, and you will see its description together with API documentation. Having done this, click the `back` icon until you return to this quick start guide within the Developer Column. + +Flash the Application ++++++++++++++++++++++ + +Now that the application has been compiled, the next step is to run it on the sliceKIT Core Board using the tools to load the application over JTAG into the xCORE multicore microcontroller. + +- Select the file ``app_a16.xc`` in the ``app_a16_slicekit_ethernet_sleep_wake_combo_demo`` project from the Project Explorer. +- Click on the ``Flash`` icon. +- At the ``Select Device`` dialog select ``XMOS XTAG-2 connect to L1[0..1]`` and click ``OK``. +- Flashing progress messages are displayed in the console. +- After a successful flash, power cycle the sliceKIT core board. + +The Demo +++++++++ + +- Navigate to ``$/app_a16_slicekit_ethernet_sleep_wake_combo_demo/xmos_python_webserver``. +- Double click or Run the python script: ``server.py``. +- The following messages are displayed in the Python console:: + + Server Address = 169.254.202.189 + XMOS: Going to sleep...zzz + Connection closed + XMOS: Rise and shine.... + XMOS: Going to sleep...zzz + Connection closed + XMOS: Rise and shine.... + XMOS: Going to sleep...zzz + Connection closed + XMOS: Rise and shine.... + XMOS: Going to sleep...zzz + Connection closed + XMOS: Rise and shine.... + XMOS: Going to sleep...zzz + Connection closed + +What this means is: + + + +----------------------------------+------------------------------------------------------------+ + | Message in Python console | xCORE app | + +==================================+============================================================+ + | Server Address = 169.254.202.189 | | + +----------------------------------+------------------------------------------------------------+ + | | Program starts | + +----------------------------------+------------------------------------------------------------+ + | | Looks for valid server configuration in sleep memory. | + | | Since, this is power up, it takes the default Server | + | | configuration and saves it to sleep memory. | + +----------------------------------+------------------------------------------------------------+ + | | Initializes web client, and connects to web server | + +----------------------------------+------------------------------------------------------------+ + | | Starts a sleep timer | + +----------------------------------+------------------------------------------------------------+ + | XMOS: Going to sleep...zzz | Timer expires, sends message to web server that it will be | + | | going to sleep | + +----------------------------------+------------------------------------------------------------+ + | Connection closed | Closes the TCP connection | + +----------------------------------+------------------------------------------------------------+ + | | Sleeps | + +----------------------------------+------------------------------------------------------------+ + | | Wakes up upon timer expiry | + +----------------------------------+------------------------------------------------------------+ + | | Looks for valid server configuration in sleep memory. This | + | | time it finds valid data in sleep memory. Uses this server | + | | configuration. | + +----------------------------------+------------------------------------------------------------+ + | | Initializes web client, and connects to web server | + +----------------------------------+------------------------------------------------------------+ + | XMOS: Rise and shine.... | Informs web server that it just woke up from sleep | + +----------------------------------+------------------------------------------------------------+ + | | Starts a sleep timer | + +----------------------------------+------------------------------------------------------------+ + | XMOS: Going to sleep...zzz | Timer expires, sends message to web server that it will be | + | | going to sleep | + +----------------------------------+------------------------------------------------------------+ + | Connection closed | Closes the TCP connection | + +----------------------------------+------------------------------------------------------------+ + | | Sleeps | + +----------------------------------+------------------------------------------------------------+ + + +Next Steps +++++++++++ + +- Review the ``app_a16_slicekit_ethernet_sleep_wake_combo_demo`` application code, ``module_analog_tile_support`` module code and ``module_webclient`` library code. Refer to the documentation for each of them to see the API details and usage. diff --git a/app_a16_slicekit_ethernet_sleep_wake_combo_demo/src/app_a16.xc b/app_a16_slicekit_ethernet_sleep_wake_combo_demo/src/app_a16.xc index 3a6b0c0..a1e93b9 100644 --- a/app_a16_slicekit_ethernet_sleep_wake_combo_demo/src/app_a16.xc +++ b/app_a16_slicekit_ethernet_sleep_wake_combo_demo/src/app_a16.xc @@ -16,8 +16,6 @@ #include #include #include -#include "common.h" -#include "util.h" #include "webclient.h" #include "ethernet_board_conf.h" #include "debug_print.h" @@ -40,8 +38,6 @@ on ETHERNET_DEFAULT_TILE: ethernet_xtcp_ports_t xtcp_ports = { ETHERNET_DEFAULT_RESET_INTERFACE_INIT }; -on tile[1]: out port ptemp = XS1_PORT_1D; - /*--------------------------------------------------------------------------- typedefs ---------------------------------------------------------------------------*/ @@ -61,8 +57,7 @@ server_config_t server_config = { 501 }; -char sleep_mem[XS1_SU_NUM_GLX_PER_MEMORY_BYTE]; -char ws_data_sleep[100] = "Going to Sleep...zzz"; +char ws_data_sleep[100] = "Going to sleep...zzz"; char ws_data_wake[100] = "Rise and shine...."; /*--------------------------------------------------------------------------- @@ -87,24 +82,21 @@ static void tcp_handler(chanend c_xtcp) if(at_pm_memory_is_valid()) { // Read server configuration from sleep memory - at_pm_memory_read(sleep_mem); - copy_char_array_to_server_config(server_config, sleep_mem); + at_pm_memory_read(server_config); from_sleep = 1; - ptemp <: 1; } else { // Write server configuration to sleep memory - copy_server_config_to_char_array(server_config, sleep_mem); - at_pm_memory_write(sleep_mem); + at_pm_memory_write(server_config); at_pm_memory_set_valid(1); - ptemp <: 1; } - // Set webserver paramters and connect - webclient_set_server_ip(server_config.server_ip); - webclient_set_in_port(server_config.tcp_in_port); - webclient_set_out_port(server_config.tcp_out_port); + // Set webserver paramters + webclient_set_server_config(server_config); + // Init web client + webclient_init(c_xtcp); + // Connect to webserver webclient_connect_to_server(c_xtcp); if(from_sleep) @@ -128,6 +120,8 @@ static void tcp_handler(chanend c_xtcp) // Inform webserver that I am going to sleep webclient_send_data(c_xtcp, ws_data_sleep); + // Close connection + webclient_request_close(c_xtcp); at_pm_sleep_now(); diff --git a/app_a16_slicekit_ethernet_sleep_wake_combo_demo/src/common.h b/app_a16_slicekit_ethernet_sleep_wake_combo_demo/src/common.h deleted file mode 100644 index f6a9ec3..0000000 --- a/app_a16_slicekit_ethernet_sleep_wake_combo_demo/src/common.h +++ /dev/null @@ -1,46 +0,0 @@ -// Copyright (c) 2011, XMOS Ltd., All rights reserved -// This software is freely distributable under a derivative of the -// University of Illinois/NCSA Open Source License posted in -// LICENSE.txt and at - -/*=========================================================================== - Info - ---- - - ===========================================================================*/ - -#ifndef __common_h__ -#define __common_h__ - -/*--------------------------------------------------------------------------- - nested include files - ---------------------------------------------------------------------------*/ - -/*--------------------------------------------------------------------------- - constants - ---------------------------------------------------------------------------*/ - -/*--------------------------------------------------------------------------- - typedefs - ---------------------------------------------------------------------------*/ -typedef struct server_config_t_ -{ - char server_ip[4]; // xtcp_ipaddr_t - int tcp_in_port; - int tcp_out_port; -} server_config_t; - -/*--------------------------------------------------------------------------- - global variables - ---------------------------------------------------------------------------*/ - -/*--------------------------------------------------------------------------- - extern variables - ---------------------------------------------------------------------------*/ - -/*--------------------------------------------------------------------------- - prototypes - ---------------------------------------------------------------------------*/ - -#endif // __common_h__ -/*==========================================================================*/ diff --git a/app_a16_slicekit_ethernet_sleep_wake_combo_demo/src/util.c b/app_a16_slicekit_ethernet_sleep_wake_combo_demo/src/util.c deleted file mode 100644 index 07675a4..0000000 --- a/app_a16_slicekit_ethernet_sleep_wake_combo_demo/src/util.c +++ /dev/null @@ -1,58 +0,0 @@ -// Copyright (c) 2011, XMOS Ltd., All rights reserved -// This software is freely distributable under a derivative of the -// University of Illinois/NCSA Open Source License posted in -// LICENSE.txt and at - -/*=========================================================================== - Info - ---- - - ===========================================================================*/ - -/*--------------------------------------------------------------------------- - include files - ---------------------------------------------------------------------------*/ -#include "util.h" -#include - -/*--------------------------------------------------------------------------- - constants - ---------------------------------------------------------------------------*/ - -/*--------------------------------------------------------------------------- - ports and clocks - ---------------------------------------------------------------------------*/ - -/*--------------------------------------------------------------------------- - typedefs - ---------------------------------------------------------------------------*/ - -/*--------------------------------------------------------------------------- - global variables - ---------------------------------------------------------------------------*/ - -/*--------------------------------------------------------------------------- - static variables - ---------------------------------------------------------------------------*/ - -/*--------------------------------------------------------------------------- - static prototypes - ---------------------------------------------------------------------------*/ - -/*--------------------------------------------------------------------------- - copy_server_config_to_char_array - ---------------------------------------------------------------------------*/ -void copy_server_config_to_char_array(server_config_t *sconfig, char *data) -{ - memcpy(data, (char *)(sconfig), sizeof(server_config_t)); -} - -/*--------------------------------------------------------------------------- - copy_char_array_to_server_config - ---------------------------------------------------------------------------*/ -void copy_char_array_to_server_config(server_config_t *sconfig, char *data) -{ - memcpy((char *)(sconfig), data, sizeof(server_config_t)); -} - -/*==========================================================================*/ diff --git a/app_a16_slicekit_ethernet_sleep_wake_combo_demo/src/util.h b/app_a16_slicekit_ethernet_sleep_wake_combo_demo/src/util.h deleted file mode 100644 index 81314ec..0000000 --- a/app_a16_slicekit_ethernet_sleep_wake_combo_demo/src/util.h +++ /dev/null @@ -1,62 +0,0 @@ -// Copyright (c) 2011, XMOS Ltd., All rights reserved -// This software is freely distributable under a derivative of the -// University of Illinois/NCSA Open Source License posted in -// LICENSE.txt and at - -/*=========================================================================== - Info - ---- - - ===========================================================================*/ - -#ifndef __util_h__ -#define __util_h__ - -/*--------------------------------------------------------------------------- - nested include files - ---------------------------------------------------------------------------*/ -#include -#include "common.h" - -/*--------------------------------------------------------------------------- - constants - ---------------------------------------------------------------------------*/ - -/*--------------------------------------------------------------------------- - typedefs - ---------------------------------------------------------------------------*/ - -/*--------------------------------------------------------------------------- - global variables - ---------------------------------------------------------------------------*/ - -/*--------------------------------------------------------------------------- - extern variables - ---------------------------------------------------------------------------*/ - -/*--------------------------------------------------------------------------- - prototypes - ---------------------------------------------------------------------------*/ - -/*==========================================================================*/ -/** - * Copy Webserver configuration to character array - * - * \param sconfig Ref to webserver configuration (server_config_t) - * \param data[] Ref to character array (char) - * \return None - **/ -void copy_server_config_to_char_array(REFERENCE_PARAM(server_config_t, sconfig), char data[]); - -/*==========================================================================*/ -/** - * Copy character array to Webserver configuration - * - * \param sconfig Ref to webserver configuration (server_config_t) - * \param data[] Ref to character array (char) - * \return None - **/ -void copy_char_array_to_server_config(REFERENCE_PARAM(server_config_t, sconfig), char data[]); - -#endif // __util_h__ -/*==========================================================================*/ diff --git a/app_a16_slicekit_ethernet_sleep_wake_combo_demo/xmos_python_webserver/server.py b/app_a16_slicekit_ethernet_sleep_wake_combo_demo/xmos_python_webserver/server.py index 2193a14..f9b98d4 100644 --- a/app_a16_slicekit_ethernet_sleep_wake_combo_demo/xmos_python_webserver/server.py +++ b/app_a16_slicekit_ethernet_sleep_wake_combo_demo/xmos_python_webserver/server.py @@ -1,33 +1,23 @@ #!/usr/bin/python -import asyncore import socket server_port = 501 self_ip = socket.gethostbyname(socket.gethostname()) print 'Server Address = %s' % self_ip -class XHandler(asyncore.dispatcher_with_send): +server_sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM) +server_sock.bind((self_ip, server_port)) +server_sock.listen(1) - def handle_read(self): - data = self.recv(1024) +while 1: + + conn, client_address = server_sock.accept() + + while 1: + data = conn.recv(100) if data: print 'XMOS: %s' % data - -class XServer(asyncore.dispatcher): - - def __init__(self, host, port): - asyncore.dispatcher.__init__(self) - self.create_socket(socket.AF_INET, socket.SOCK_STREAM) - self.set_reuse_addr() - self.bind((host, port)) - self.listen(1) - - def handle_accept(self): - pair = self.accept() - if pair is not None: - sock, addr = pair - print 'Incoming %s' % repr(addr) - handler = XHandler(sock) - -server = XServer(self_ip, server_port) -asyncore.loop() + else: + print 'Connection closed' + conn.close() + break From f79a0843a1b3df18fedc57312c835c42a8607355 Mon Sep 17 00:00:00 2001 From: Vinith Mundhra Date: Thu, 8 Aug 2013 12:06:24 +0530 Subject: [PATCH 04/45] add webclient code, update docs --- CHANGELOG.rst | 4 + README.rst | 4 +- .../.cproject | 882 ++++-------------- .../.project | 4 - .../Makefile | 2 +- .../README.rst | 1 - .../XP-SKC-U16.xn | 4 +- .../doc_quickstart/images/hardware_setup.jpg | Bin 0 -> 127090 bytes .../doc_quickstart/quickstart.rst | 6 +- .../src/analog_tile_support/at_periph.h | 57 -- .../src/analog_tile_support/at_periph.xc | 220 ----- .../src/app_a16.xc | 8 +- .../src/webclient/webclient.h | 103 ++ .../src/webclient/webclient.xc | 229 +++++ app_adc_demo_u/.cproject | 9 +- .../doc_quickstart/images/hw_setup.jpg | Bin 49409 -> 0 bytes app_adc_pwm_demo_a/Makefile | 33 + app_adc_pwm_demo_a/README.rst | 8 + app_adc_pwm_demo_a/doc_quickstart/Makefile | 7 + .../doc_quickstart/quickstart.rst | 9 + app_adc_pwm_demo_a/src/debug_conf.h | 2 + app_adc_pwm_demo_a/src/main.xc | 89 ++ module_analog_tile_support/.DS_Store | Bin 6148 -> 0 bytes module_analog_tile_support/README.rst | 11 + module_analog_tile_support/doc/Makefile | 5 + module_analog_tile_support/doc/api.rst | 47 + module_analog_tile_support/doc/examples.rst | 46 + module_analog_tile_support/doc/hw.rst | 20 + module_analog_tile_support/doc/index.rst | 10 + module_analog_tile_support/doc/overview.rst | 60 ++ .../doc/programming.rst | 127 +++ .../module_analog_tile_support.metainfo | 34 + module_analog_tile_support/module_build_info | 13 + .../src/analog_tile_support.h | 23 + module_analog_tile_support/src/at_adc.h | 147 +++ module_analog_tile_support/src/at_adc.xc | 159 ++++ module_analog_tile_support/src/at_periph.xc | 207 ---- .../src/{at_periph.h => at_sleep.h} | 119 ++- module_analog_tile_support/src/at_sleep.xc | 202 ++++ module_analog_tile_support/src/at_wdt.h | 40 + module_analog_tile_support/src/at_wdt.xc | 33 + module_usb_tile_support/src/adc.h | 9 +- tests/.DS_Store | Bin 6148 -> 0 bytes tests/test_adc_config/.DS_Store | Bin 6148 -> 0 bytes tests/test_sleep_a/.DS_Store | Bin 6148 -> 0 bytes tests/test_sleep_a/Makefile | 7 +- tests/test_sleep_a/src/XP-SKC-U16.xn | 91 -- tests/test_sleep_a/src/debug_conf.h | 4 + tests/test_wdt_a/.DS_Store | Bin 6148 -> 6148 bytes tests/test_wdt_a/Makefile | 33 + .../test_wdt_a/bin/Debug/test_wdt_a_Debug.xe | Bin 0 -> 99520 bytes tests/test_wdt_a/src/XP-SKC-U16.xn | 91 -- tests/test_wdt_a/src/debug_conf.h | 4 + .../src/test_sleep_demo.xc | 28 +- tests/test_wdt_a/src/test_wdt.xc | 104 +-- xpd.xml | 28 +- 56 files changed, 1812 insertions(+), 1571 deletions(-) create mode 100644 app_a16_slicekit_ethernet_sleep_wake_combo_demo/doc_quickstart/images/hardware_setup.jpg delete mode 100644 app_a16_slicekit_ethernet_sleep_wake_combo_demo/src/analog_tile_support/at_periph.h delete mode 100644 app_a16_slicekit_ethernet_sleep_wake_combo_demo/src/analog_tile_support/at_periph.xc create mode 100644 app_a16_slicekit_ethernet_sleep_wake_combo_demo/src/webclient/webclient.h create mode 100644 app_a16_slicekit_ethernet_sleep_wake_combo_demo/src/webclient/webclient.xc delete mode 100644 app_adc_demo_u/doc_quickstart/images/hw_setup.jpg create mode 100644 app_adc_pwm_demo_a/Makefile create mode 100644 app_adc_pwm_demo_a/README.rst create mode 100644 app_adc_pwm_demo_a/doc_quickstart/Makefile create mode 100644 app_adc_pwm_demo_a/doc_quickstart/quickstart.rst create mode 100644 app_adc_pwm_demo_a/src/debug_conf.h create mode 100644 app_adc_pwm_demo_a/src/main.xc delete mode 100644 module_analog_tile_support/.DS_Store create mode 100644 module_analog_tile_support/README.rst create mode 100644 module_analog_tile_support/doc/Makefile create mode 100644 module_analog_tile_support/doc/api.rst create mode 100644 module_analog_tile_support/doc/examples.rst create mode 100644 module_analog_tile_support/doc/hw.rst create mode 100644 module_analog_tile_support/doc/index.rst create mode 100644 module_analog_tile_support/doc/overview.rst create mode 100644 module_analog_tile_support/doc/programming.rst create mode 100644 module_analog_tile_support/module_analog_tile_support.metainfo create mode 100644 module_analog_tile_support/module_build_info create mode 100644 module_analog_tile_support/src/analog_tile_support.h create mode 100644 module_analog_tile_support/src/at_adc.h create mode 100644 module_analog_tile_support/src/at_adc.xc delete mode 100644 module_analog_tile_support/src/at_periph.xc rename module_analog_tile_support/src/{at_periph.h => at_sleep.h} (55%) create mode 100644 module_analog_tile_support/src/at_sleep.xc create mode 100644 module_analog_tile_support/src/at_wdt.h create mode 100644 module_analog_tile_support/src/at_wdt.xc delete mode 100644 tests/.DS_Store delete mode 100644 tests/test_adc_config/.DS_Store delete mode 100644 tests/test_sleep_a/.DS_Store delete mode 100644 tests/test_sleep_a/src/XP-SKC-U16.xn create mode 100644 tests/test_sleep_a/src/debug_conf.h create mode 100644 tests/test_wdt_a/Makefile create mode 100644 tests/test_wdt_a/bin/Debug/test_wdt_a_Debug.xe delete mode 100644 tests/test_wdt_a/src/XP-SKC-U16.xn create mode 100644 tests/test_wdt_a/src/debug_conf.h rename tests/{test_sleep_a => test_wdt_a}/src/test_sleep_demo.xc (86%) diff --git a/CHANGELOG.rst b/CHANGELOG.rst index 6fe4b12..f14ce15 100644 --- a/CHANGELOG.rst +++ b/CHANGELOG.rst @@ -1,5 +1,9 @@ In-Device Peripheral Library Change Log ======================================= +1.1.0 +----- + * Expanded to support XS1-A devices including ADC, WDT, RTC and Sleep mode + * Minor documentation and naming convention updates to XS1-U 1.0.0 ----- diff --git a/README.rst b/README.rst index 90490dd..75edec3 100644 --- a/README.rst +++ b/README.rst @@ -1,7 +1,7 @@ Peripheral Tile Support Library ............................... -:Latest release: 1.0.0rc1 +:Latest release: 1.1.0alpha0 :Maintainer: pthedinger :Description: Collection of functions to support peripheral tiles. @@ -34,4 +34,6 @@ Required software (dependencies) ================================ * sc_util (git://github.com/xcore/sc_util) + * sc_slicekit_support (https://github.com/xcore/sc_slicekit_support.git) + * sc_pwm (https://github.com/xcore/sc_pwm.git) diff --git a/app_a16_slicekit_ethernet_sleep_wake_combo_demo/.cproject b/app_a16_slicekit_ethernet_sleep_wake_combo_demo/.cproject index 46586ae..3d89400 100644 --- a/app_a16_slicekit_ethernet_sleep_wake_combo_demo/.cproject +++ b/app_a16_slicekit_ethernet_sleep_wake_combo_demo/.cproject @@ -1,8 +1,8 @@ - - + + @@ -94,421 +94,140 @@ + + + + + xmake + CONFIG=Debug + all + true + true + true + + + xmake + CONFIG=Debug + clean + true + true + true + + + + - - - - - - - - - - - - - - - - xmake - CONFIG=Debug - all - true - true - true - - - xmake - CONFIG=Debug - clean - true - true - true - - - - - - - + + @@ -600,396 +319,116 @@ - - - - - - - - - - - - + @@ -1010,11 +449,10 @@ - - + diff --git a/app_a16_slicekit_ethernet_sleep_wake_combo_demo/.project b/app_a16_slicekit_ethernet_sleep_wake_combo_demo/.project index 8595f4a..470522c 100644 --- a/app_a16_slicekit_ethernet_sleep_wake_combo_demo/.project +++ b/app_a16_slicekit_ethernet_sleep_wake_combo_demo/.project @@ -9,10 +9,6 @@ org.eclipse.cdt.managedbuilder.core.genmakebuilder clean,full,incremental, - - ?children? - ?name?=outputEntries\|?children?=?name?=entry\\\\\\\|\\\|\|| - ?name? diff --git a/app_a16_slicekit_ethernet_sleep_wake_combo_demo/Makefile b/app_a16_slicekit_ethernet_sleep_wake_combo_demo/Makefile index 7ad022b..cd01390 100644 --- a/app_a16_slicekit_ethernet_sleep_wake_combo_demo/Makefile +++ b/app_a16_slicekit_ethernet_sleep_wake_combo_demo/Makefile @@ -9,7 +9,7 @@ TARGET = XP-SKC-U16 APP_NAME = app_a16 # The USED_MODULES variable lists other module used by the application. -USED_MODULES = module_logging module_otp_board_info module_webclient +USED_MODULES = module_analog_tile_support module_logging module_otp_board_info module_xtcp # The flags passed to xcc when building the application # You can also set the following to override flags for a particular language: diff --git a/app_a16_slicekit_ethernet_sleep_wake_combo_demo/README.rst b/app_a16_slicekit_ethernet_sleep_wake_combo_demo/README.rst index 48535e8..7b4e724 100644 --- a/app_a16_slicekit_ethernet_sleep_wake_combo_demo/README.rst +++ b/app_a16_slicekit_ethernet_sleep_wake_combo_demo/README.rst @@ -25,7 +25,6 @@ Required Repositories - sc_periph https://github.com/xcore/sc_periph.git - sc_slicekit_support https://github.com/xcore/sc_slicekit_support.git - sc_util https://github.com/xcore/sc_util.git -- sc_webclient https://github.com/xcore/sc_webclient.git - sc_xtcp https://github.com/xcore/sc_xtcp.git Support diff --git a/app_a16_slicekit_ethernet_sleep_wake_combo_demo/XP-SKC-U16.xn b/app_a16_slicekit_ethernet_sleep_wake_combo_demo/XP-SKC-U16.xn index e492ca5..f979914 100644 --- a/app_a16_slicekit_ethernet_sleep_wake_combo_demo/XP-SKC-U16.xn +++ b/app_a16_slicekit_ethernet_sleep_wake_combo_demo/XP-SKC-U16.xn @@ -6,7 +6,7 @@ tileref tile[2] - tileref xs1_su_periph + tileref usb_tile @@ -34,7 +34,7 @@ - diff --git a/app_a16_slicekit_ethernet_sleep_wake_combo_demo/doc_quickstart/images/hardware_setup.jpg b/app_a16_slicekit_ethernet_sleep_wake_combo_demo/doc_quickstart/images/hardware_setup.jpg new file mode 100644 index 0000000000000000000000000000000000000000..67eb9d98420f5f07f7b97a2e88f3dabb3e8af362 GIT binary patch literal 127090 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�cT*a(aUlouX^CTa+s^)(h<` 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 UQ9}^J%aKu&^L==tieP{L*_vjxW&i*H literal 0 HcmV?d00001 diff --git a/app_a16_slicekit_ethernet_sleep_wake_combo_demo/doc_quickstart/quickstart.rst b/app_a16_slicekit_ethernet_sleep_wake_combo_demo/doc_quickstart/quickstart.rst index 50780ce..533c7de 100644 --- a/app_a16_slicekit_ethernet_sleep_wake_combo_demo/doc_quickstart/quickstart.rst +++ b/app_a16_slicekit_ethernet_sleep_wake_combo_demo/doc_quickstart/quickstart.rst @@ -1,7 +1,7 @@ A16 sliceKIT Ethernet Sleep Wake Combo Demo Quickstart Guide ============================================================ -This simple demonstration of xTIMEcomposer Studio functionality that uses the ``XA-SK-E100`` sliceCARD together with the xSOFTip ``module_analog_tile_support`` and ``module_webclient`` to demonstrate how the chip can be made to sleep and wake up using different sources. The app also runs a TCP web client and informs web server before going to sleep and after waking up from sleep. +This simple demonstration of xTIMEcomposer Studio functionality that uses the ``XA-SK-E100`` sliceCARD together with the xSOFTip ``module_analog_tile_support`` and ``module_xtcp`` to demonstrate how the chip can be made to sleep and wake up using different sources. The app also runs a TCP web client and informs web server before going to sleep and after waking up from sleep. Hardware Setup ++++++++++++++ @@ -51,7 +51,7 @@ Note that the Developer Column in the xTIMEcomposer on the right hand side of yo Flash the Application +++++++++++++++++++++ -Now that the application has been compiled, the next step is to run it on the sliceKIT Core Board using the tools to load the application over JTAG into the xCORE multicore microcontroller. +Now that the application has been compiled, the next step is to flash it on the sliceKIT Core Board using the tools to load the application over JTAG into the xCORE multicore microcontroller. - Select the file ``app_a16.xc`` in the ``app_a16_slicekit_ethernet_sleep_wake_combo_demo`` project from the Project Explorer. - Click on the ``Flash`` icon. @@ -131,4 +131,4 @@ What this means is: Next Steps ++++++++++ -- Review the ``app_a16_slicekit_ethernet_sleep_wake_combo_demo`` application code, ``module_analog_tile_support`` module code and ``module_webclient`` library code. Refer to the documentation for each of them to see the API details and usage. +- Review the ``app_a16_slicekit_ethernet_sleep_wake_combo_demo`` application code, ``module_analog_tile_support`` module code. Refer to the documentation for each of them to see the API details and usage. diff --git a/app_a16_slicekit_ethernet_sleep_wake_combo_demo/src/analog_tile_support/at_periph.h b/app_a16_slicekit_ethernet_sleep_wake_combo_demo/src/analog_tile_support/at_periph.h deleted file mode 100644 index 37ba72c..0000000 --- a/app_a16_slicekit_ethernet_sleep_wake_combo_demo/src/analog_tile_support/at_periph.h +++ /dev/null @@ -1,57 +0,0 @@ -#ifndef AT_PERIPH_H_ -#define AT_PERIPH_H_ - -#include -#include - -//Macro to allow arbitrary struct/array to be passed to sleep mem functions, using XC cast (x, y) -#define at_pm_memory_read(x) at_pm_memory_read_impl((x, char[]), sizeof(x)) -//#define at_pm_memory_write(x) at_pm_memory_write_impl((char *) &x, sizeof(x)) -#define at_pm_memory_write(x) at_pm_memory_write_impl((x, char[]), sizeof(x)) - -#define SI_OSCILLATOR_FREQ_31K 31250 - -typedef enum { -SILICON_OSCILLATOR_20M, -SILICON_OSCILLATOR_31K, -CRYSTAL_OSCILLATOR, -EXTERNAL_OSCILLATOR} osc_sources_t; - -typedef enum { -USB_RESUME, -RTC, -WAKE_PIN_LOW, -WAKE_PIN_HIGH} wake_sources_t; - -//128B deep sleep memory access. See above macro for user API -void at_pm_memory_read_impl(char data[], unsigned char size); -//void at_pm_memory_write_impl(char * data, unsigned char size); -void at_pm_memory_write_impl(char dara[], unsigned char size); - -char at_pm_memory_is_valid(void); -void at_pm_memory_set_valid(char isvalid); - -//Sleep and wake control -void at_pm_enable_wake_source(wake_sources_t wake_source); -void at_pm_disable_wake_source(wake_sources_t wake_source); -void at_pm_set_wake_time(unsigned int alarm_time); -void at_pm_set_min_sleep_time(unsigned int min_sleep_time); -void at_pm_sleep_now(void); - -//RTC (real time clock) -unsigned int at_rtc_read(void); -void at_rtc_clear(void); - -//General power saving options -void at_pm_sswitch_prescaler (int prescaler); -void at_pm_xcore_voltage_set(unsigned int millivolts); //could use RTC clock rather than global timer - - -//Watchdog timer -void at_watchdog_enable(void); -void at_watchdog_disable(void); -void at_watchdog_set_timeout(unsigned short milliseconds); -unsigned short at_watchdog_kick(void); - - -#endif /* AT_PERIPH_H_ */ diff --git a/app_a16_slicekit_ethernet_sleep_wake_combo_demo/src/analog_tile_support/at_periph.xc b/app_a16_slicekit_ethernet_sleep_wake_combo_demo/src/analog_tile_support/at_periph.xc deleted file mode 100644 index d7b548b..0000000 --- a/app_a16_slicekit_ethernet_sleep_wake_combo_demo/src/analog_tile_support/at_periph.xc +++ /dev/null @@ -1,220 +0,0 @@ -#include "at_periph.h" -#include "debug_print.h" - - -static unsigned int convert_ms_to_ticks (unsigned int milliseconds){ - unsigned int read_val_32; - unsigned long long ticks; - read_node_config_reg(xs1_su_periph, XS1_SU_CFG_SYS_CLK_FREQ_NUM, read_val_32); - read_val_32 = XS1_SU_CFG_SYS_CLK_FREQ(read_val_32); //Mask off upper bits - ticks = (unsigned long long) milliseconds * (unsigned long long) read_val_32 * 1000; - return ticks; -} -static unsigned int convert_ticks_to_ms (unsigned long long ticks){ - unsigned int read_val_32; - unsigned int milliseconds; - read_node_config_reg(xs1_su_periph, XS1_SU_CFG_SYS_CLK_FREQ_NUM, read_val_32); - read_val_32 = XS1_SU_CFG_SYS_CLK_FREQ(read_val_32); //Mask off upper bits - milliseconds = (unsigned int) (ticks / (1000 * read_val_32)); - return milliseconds; -} - - -//128B deep sleep memory access -void at_pm_memory_read_impl(unsigned char data[], unsigned char size){ - if (size > XS1_SU_NUM_GLX_PER_MEMORY_BYTE); //TODO - read_periph_8 (xs1_su_periph, XS1_SU_PER_MEMORY_CHANEND_NUM, XS1_SU_PER_MEMORY_BYTE_0_NUM, - size, data); -} -void at_pm_memory_write_impl(unsigned char data[], unsigned char size){ - write_periph_8 (xs1_su_periph, XS1_SU_PER_MEMORY_CHANEND_NUM, XS1_SU_PER_MEMORY_BYTE_0_NUM, - size, data); -} - -char at_pm_memory_is_valid(void){ - char val[1]; - read_periph_8 (xs1_su_periph, XS1_SU_PER_MEMORY_CHANEND_NUM, XS1_SU_PER_MEMORY_VALID_NUM, 1, val); - return val[0]; -} -void at_pm_memory_set_valid(char isvalid){ - char val[1]; - if (isvalid) val[0] = 0xed; //magic value for valid - else val[0] = 0x00; //magic value for invalid - write_periph_8 (xs1_su_periph, XS1_SU_PER_MEMORY_CHANEND_NUM, XS1_SU_PER_MEMORY_VALID_NUM, 1, val); -} - - -//Sleep and wake control -void at_pm_enable_wake_source(wake_sources_t wake_source){ - unsigned int write_val; - read_periph_32(xs1_su_periph, XS1_SU_PER_PWR_CHANEND_NUM, XS1_SU_PER_PWR_MISC_CTRL_NUM, 1, &write_val); - switch (wake_source){ - case RTC: - write_val = XS1_SU_PWR_TMR_WAKEUP_64_SET(write_val, 1); //Set timer to 64b mode - write_val = XS1_SU_PWR_SLEEP_CLK_SEL_SET(write_val, 0); //Use 31KHz source as clock for timer - write_val = XS1_SU_PWR_TMR_WAKEUP_EN_SET(write_val, 1); //Enable timer wake - break; - - case WAKE_PIN_LOW: - write_val = XS1_SU_PWR_PIN_WAKEUP_EN_SET(write_val, 1); //Enable pin wake - write_val = XS1_SU_PWR_PIN_WAKEUP_ON_SET(write_val, 0); //Wake on low level - break; - - case WAKE_PIN_HIGH: - write_val = XS1_SU_PWR_PIN_WAKEUP_EN_SET(write_val, 1); //Disable pin wake - write_val = XS1_SU_PWR_PIN_WAKEUP_ON_SET(write_val, 1); //Wake on high level - break; - - case USB_RESUME: - write_val = XS1_SU_PWR_USB_PU_EN_SET(write_val, 1); //Enable USB resume wake - break; - } -// debug_printf("Wrting value to power control reg = 0x%x\n", write_val); - write_periph_32(xs1_su_periph, XS1_SU_PER_PWR_CHANEND_NUM, XS1_SU_PER_PWR_MISC_CTRL_NUM, 1, &write_val); -} -void at_pm_disable_wake_source(wake_sources_t wake_source) -{ - unsigned int write_val; - read_periph_32(xs1_su_periph, XS1_SU_PER_PWR_CHANEND_NUM, XS1_SU_PER_PWR_MISC_CTRL_NUM, 1, &write_val); - switch (wake_source){ - case RTC: - write_val = XS1_SU_PWR_TMR_WAKEUP_64_SET(write_val, 1); //Set timer to 64b mode - write_val = XS1_SU_PWR_SLEEP_CLK_SEL_SET(write_val, 0); //Use 31KHz source as clock for timer - write_val = XS1_SU_PWR_TMR_WAKEUP_EN_SET(write_val, 0); //Disable timer wake - break; - - case WAKE_PIN_LOW: - write_val = XS1_SU_PWR_PIN_WAKEUP_EN_SET(write_val, 0); //Disable pin wake - write_val = XS1_SU_PWR_PIN_WAKEUP_ON_SET(write_val, 0); //Wake on low level - break; - - case WAKE_PIN_HIGH: - write_val = XS1_SU_PWR_PIN_WAKEUP_EN_SET(write_val, 0); //Disable pin wake - write_val = XS1_SU_PWR_PIN_WAKEUP_ON_SET(write_val, 1); //Wake on high level - break; - - case USB_RESUME: - write_val = XS1_SU_PWR_USB_PU_EN_SET(write_val, 0); //Disable USB resume wake - break; - } -// debug_printf("Wrting value to power control reg = 0x%x\n", write_val); - write_periph_32(xs1_su_periph, XS1_SU_PER_PWR_CHANEND_NUM, XS1_SU_PER_PWR_MISC_CTRL_NUM, 1, &write_val); -} - -void at_pm_set_wake_time(unsigned int alarm_time){ - unsigned int write_val[2]; - unsigned long long alarm_ticks; - alarm_ticks = convert_ms_to_ticks(alarm_time); - write_val[0] = alarm_ticks & 0xFFFFFFFF; - write_val[1] = alarm_ticks >> 32; - debug_printf("wake_at[1..0] is 0x%x, 0x%x\n", write_val[1], write_val[0]); - write_periph_32(xs1_su_periph, XS1_SU_PER_PWR_CHANEND_NUM, XS1_SU_PER_PWR_WAKEUP_TMR_LWR_NUM, 2, write_val); -} - -void at_pm_sleep_now(void){ - unsigned char write_val, osc_good = 0; - unsigned int read_val_32, write_val_32; - - //Setup 20MHz on chip oscilator - write_val = XS1_SU_GEN_OSC_SEL_SET(0, 1); //Ensure Si OSC is enabled - write_val = XS1_SU_GEN_OSC_RST_EN_SET(write_val, 0); //Select 20MHz osc - write_periph_8(xs1_su_periph, XS1_SU_PER_OSC_CHANEND_NUM, XS1_SU_PER_OSC_ON_SI_CTRL_NUM, 1, &write_val); - - //wait until oscillator is stable - while (!osc_good){ - read_periph_32(xs1_su_periph, XS1_SU_PER_PWR_CHANEND_NUM, XS1_SU_PER_PWR_PMU_DBG_NUM, 1, &read_val_32); - osc_good = XS1_SU_PWR_ON_SI_STBL(read_val_32); - } - - //Switch to silicon oscilator - write_val = XS1_SU_GEN_OSC_RST_EN_SET(0, 0); //Disable reset on clock change - write_val = XS1_SU_GEN_OSC_SEL_SET(write_val, 1); //Switch to silicon oscialtor - write_periph_8(xs1_su_periph, XS1_SU_PER_OSC_CHANEND_NUM, XS1_SU_PER_OSC_GEN_CTRL_NUM, 1, &write_val); - - //Disable XTAL bias and oscillator - write_val = XS1_SU_XTAL_OSC_EN_SET(0, 0); //Switch off crysal oscillator - write_val = XS1_SU_XTAL_OSC_BIAS_EN_SET(write_val, 0); //Disable crystal bias circuit - write_periph_8(xs1_su_periph, XS1_SU_PER_OSC_CHANEND_NUM, XS1_SU_PER_OSC_XTAL_CTRL_NUM, 1, &write_val); - - //Disable all supplies except DC-DC2 (peripheral tile supply) - write_val_32 = XS1_SU_PWR_WAKEUP_TMR_LWR_SET(0, 8); //set to 256 cycles min time asleep - write_val_32 = XS1_SU_PWR_WAKEUP_TMR_UPR_SET(write_val_32, 0);//set to 256 cycles min time asleep - write_val_32 = XS1_SU_PWR_EXT_CLK_MASK_SET(write_val_32, 0); //Disable xCore clock - write_val_32 = XS1_SU_PWR_VOUT1_EN_SET(write_val_32, 0); //Disable DC-DC1 - write_val_32 = XS1_SU_PWR_VOUT1_MOD_SET(write_val_32, 0); //Set to PWM mode - write_val_32 = XS1_SU_PWR_VOUT2_EN_SET(write_val_32, 1); //Enable DC-DC2 - write_val_32 = XS1_SU_PWR_VOUT2_MOD_SET(write_val_32, 1); //Set to PFM mode - write_val_32 = XS1_SU_PWR_VOUT5_EN_SET(write_val_32, 0); //Disable LDO5 - write_val_32 = XS1_SU_PWR_VOUT6_EN_SET(write_val_32, 0); //Disable LDO6 - write_periph_32(xs1_su_periph, XS1_SU_PER_PWR_CHANEND_NUM, XS1_SU_PER_PWR_STATE_ASLEEP_NUM, 1, &write_val_32); - - //go to sleep - read_periph_32(xs1_su_periph, XS1_SU_PER_PWR_CHANEND_NUM, XS1_SU_PER_PWR_MISC_CTRL_NUM, 1, &write_val_32); - write_val_32 = XS1_SU_PWR_SLEEP_INIT_SET(write_val_32, 1); //Initiate sleep bit - write_periph_32(xs1_su_periph, XS1_SU_PER_PWR_CHANEND_NUM, XS1_SU_PER_PWR_MISC_CTRL_NUM, 1, &write_val_32); -} - -void at_pm_set_min_sleep_time(unsigned int min_sleep_time){ - int write_val_32; - unsigned int calc, bit_posn = 0; - calc = ((min_sleep_time * SI_OSCILLATOR_FREQ_31K) / 1000); //sleep time in 31KHz sleep clock ticks - for (int i = 0; i < 32; i++) if ((calc >> i) & 0x1) bit_posn = i; //perform an approximate log2 calculation - read_periph_32(xs1_su_periph, XS1_SU_PER_PWR_CHANEND_NUM, XS1_SU_PER_PWR_STATE_ASLEEP_NUM, 1, &write_val_32); - write_val_32 = XS1_SU_PWR_INT_EXP_SET(write_val_32, bit_posn); - write_periph_32(xs1_su_periph, XS1_SU_PER_PWR_CHANEND_NUM, XS1_SU_PER_PWR_STATE_ASLEEP_NUM, 1, &write_val_32); -} - - -//RTC -unsigned int at_rtc_read(void){ - unsigned int time_now[2] = {0, 0}; - unsigned long long ticks; - read_periph_32(xs1_su_periph, XS1_SU_PER_RTC_CHANEND_NUM, XS1_SU_PER_RTC_LWR_32BIT_NUM, 2, time_now); - debug_printf("ticks_now[1..0] is 0x%x, 0x%x\n", time_now[1], time_now[0]); - ticks = (unsigned long long) ((time_now[1] * 0x100000000) + time_now[0]); - return convert_ticks_to_ms(ticks); -} - -void at_rtc_clear(void){ - unsigned int time_now[2] = {0, 0}; - write_periph_32(xs1_su_periph, XS1_SU_PER_RTC_CHANEND_NUM, XS1_SU_PER_RTC_LWR_32BIT_NUM, 2, time_now); -} - - -//Watchdog timer -void at_watchdog_enable(void){ - unsigned int write_val = 0x00000000; //Magic value ie. not 0x0D15AB1E - write_node_config_reg(xs1_su_periph, XS1_SU_CFG_WDOG_DISABLE_NUM, write_val); -} - -void at_watchdog_disable(void){ - unsigned int write_val = 0x0D15AB1E; //Magic value to disable - write_node_config_reg(xs1_su_periph, XS1_SU_CFG_WDOG_DISABLE_NUM, write_val); -} - - -void at_watchdog_set_timeout(unsigned short milliseconds){ - unsigned int write_val; - unsigned int read_val; - write_val = milliseconds | (~milliseconds << 16); //Set upper 16b to 1's complement of lower - //This is the 'password' for accessing reg - - read_node_config_reg(xs1_su_periph, XS1_SU_CFG_WDOG_TMR_NUM, read_val); - debug_printf("WDT timer before timeout write=%u\n", XS1_SU_CFG_WDOG_TMR(read_val)); - - write_node_config_reg(xs1_su_periph, XS1_SU_CFG_WDOG_TMR_NUM, write_val); //write expiry value - - read_node_config_reg(xs1_su_periph, XS1_SU_CFG_WDOG_TMR_NUM, read_val); - debug_printf("WDT timer after timeout write=%u\n", XS1_SU_CFG_WDOG_TMR(read_val)); - -} -unsigned short at_watchdog_kick(void){ - unsigned short expiry_val, wdt_timer; - unsigned int write_val, read_val; - read_node_config_reg(xs1_su_periph, XS1_SU_CFG_WDOG_TMR_NUM, read_val); //Get current expiry value & timer - expiry_val = (unsigned short) XS1_SU_CFG_WDOG_EXP(read_val); //mask off expiry value - write_val = (unsigned int) expiry_val | (~(unsigned int)expiry_val << 16);//Set the password in upper 16b - wdt_timer = (unsigned short) XS1_SU_CFG_WDOG_TMR(read_val); //mask off and shift timer value - write_node_config_reg(xs1_su_periph, XS1_SU_CFG_WDOG_TMR_NUM, write_val); //rewrite expiry value to reset timer - return wdt_timer; //return wdt value -} diff --git a/app_a16_slicekit_ethernet_sleep_wake_combo_demo/src/app_a16.xc b/app_a16_slicekit_ethernet_sleep_wake_combo_demo/src/app_a16.xc index a1e93b9..2adf7b1 100644 --- a/app_a16_slicekit_ethernet_sleep_wake_combo_demo/src/app_a16.xc +++ b/app_a16_slicekit_ethernet_sleep_wake_combo_demo/src/app_a16.xc @@ -20,7 +20,7 @@ #include "ethernet_board_conf.h" #include "debug_print.h" #include "xtcp.h" -#include "at_periph.h" +#include "analog_tile_support.h" /*--------------------------------------------------------------------------- constants @@ -71,7 +71,7 @@ char ws_data_wake[100] = "Rise and shine...."; /*--------------------------------------------------------------------------- tcp_handler ---------------------------------------------------------------------------*/ -static void tcp_handler(chanend c_xtcp) +static void ethernet_sleep_wake_handler(chanend c_xtcp) { timer tmr; int sys_start_time; @@ -89,7 +89,7 @@ static void tcp_handler(chanend c_xtcp) { // Write server configuration to sleep memory at_pm_memory_write(server_config); - at_pm_memory_set_valid(1); + at_pm_memory_validate(); } // Set webserver paramters @@ -136,7 +136,7 @@ int main(void) par { on ETHERNET_DEFAULT_TILE: ethernet_xtcp_server(xtcp_ports, ipconfig, c_xtcp, 1); - on tile[1]: tcp_handler(c_xtcp[0]); + on tile[1]: ethernet_sleep_wake_handler(c_xtcp[0]); } return 0; } diff --git a/app_a16_slicekit_ethernet_sleep_wake_combo_demo/src/webclient/webclient.h b/app_a16_slicekit_ethernet_sleep_wake_combo_demo/src/webclient/webclient.h new file mode 100644 index 0000000..c80db6b --- /dev/null +++ b/app_a16_slicekit_ethernet_sleep_wake_combo_demo/src/webclient/webclient.h @@ -0,0 +1,103 @@ +// Copyright (c) 2011, XMOS Ltd., All rights reserved +// This software is freely distributable under a derivative of the +// University of Illinois/NCSA Open Source License posted in +// LICENSE.txt and at + +/*=========================================================================== + Info + ---- + + ===========================================================================*/ + +#ifndef __webclient_h__ +#define __webclient_h__ + +/*--------------------------------------------------------------------------- + nested include files + ---------------------------------------------------------------------------*/ +#include +#include "xtcp_client.h" + +#ifdef __webclient_conf_h_exists__ +#include "webclient_conf.h" +#endif + +/*--------------------------------------------------------------------------- + constants + ---------------------------------------------------------------------------*/ + +/*--------------------------------------------------------------------------- + typedefs + ---------------------------------------------------------------------------*/ +/** \struct server_config_t + * \brief Web Server configuration + */ +typedef struct server_config_t_ +{ + xtcp_ipaddr_t server_ip; /** + +/*=========================================================================== + Info + ---- + + ===========================================================================*/ + +/*--------------------------------------------------------------------------- + include files + ---------------------------------------------------------------------------*/ +#include "webclient.h" +#include + +/*--------------------------------------------------------------------------- + constants + ---------------------------------------------------------------------------*/ + +/*--------------------------------------------------------------------------- + ports and clocks + ---------------------------------------------------------------------------*/ + +/*--------------------------------------------------------------------------- + typedefs + ---------------------------------------------------------------------------*/ + +/*--------------------------------------------------------------------------- + global variables + ---------------------------------------------------------------------------*/ +server_config_t server_cfg; +xtcp_connection_t conn; + +/*--------------------------------------------------------------------------- + static variables + ---------------------------------------------------------------------------*/ + +/*--------------------------------------------------------------------------- + static prototypes + ---------------------------------------------------------------------------*/ + +/*==========================================================================*/ +/** + * Send data to the webserver. + * + * \param c_xtcp channel XTCP + * \param buf character array containing data + * \param len data length + * \return 1 for success, 0 for failure + **/ +static int webclient_send(chanend c_xtcp, unsigned char buf[], int len) +{ + int finished = 0; + int success = 1; + int index = 0, prev = 0; + int id = conn.id; + + xtcp_init_send(c_xtcp, conn); + + while(!finished) + { + slave xtcp_event(c_xtcp, conn); + + switch(conn.event) + { + case XTCP_NEW_CONNECTION: xtcp_close(c_xtcp, conn); break; + case XTCP_REQUEST_DATA: + case XTCP_SENT_DATA: + { + int sendlen = (len - index); + if (sendlen > conn.mss) + sendlen = conn.mss; + + xtcp_sendi(c_xtcp, buf, index, sendlen); + prev = index; + index += sendlen; + if (sendlen == 0) + { + finished = 1; + } + break; + } + + case XTCP_RESEND_DATA: xtcp_sendi(c_xtcp, buf, prev, (index-prev)); break; + case XTCP_RECV_DATA: + { + slave + { + c_xtcp <: 0; + } // delay packet receive + + if (prev != len) + success = 0; + finished = 1; + break; + } + case XTCP_TIMED_OUT: + case XTCP_ABORTED: + case XTCP_CLOSED: + { + if (conn.id == id) + { + finished = 1; + success = 0; + } + break; + } + case XTCP_IFDOWN: + { + finished = 1; + success = 0; + break; + } + } + } + return success; +} + +/*==========================================================================*/ +/** + * Receive data from xtcp connection. + * + * \param c_xtcp channel XTCP + * \param buf character array for received data + * \param minlen minimum data length to receive + * \return The number of bytes received + **/ +static int webclient_read(chanend c_xtcp, unsigned char buf[], int minlen) +{ + int rlen = 0; + int id = conn.id; + while(rlen < minlen) + { + slave xtcp_event(c_xtcp, conn); + switch(conn.event) + { + case XTCP_NEW_CONNECTION: xtcp_close(c_xtcp, conn); break; + case XTCP_RECV_DATA: + { + int n; + n = xtcp_recvi(c_xtcp, buf, rlen); + rlen += n; + break; + } + case XTCP_REQUEST_DATA: + case XTCP_SENT_DATA: + case XTCP_RESEND_DATA: xtcp_send(c_xtcp, null, 0); break; + + case XTCP_TIMED_OUT: + case XTCP_ABORTED: + case XTCP_CLOSED: + { + if (conn.id == id) return -1; + break; + } + case XTCP_IFDOWN: return -1; break; + } + } + return rlen; +} + +/*--------------------------------------------------------------------------- + webclient_set_server_config + ---------------------------------------------------------------------------*/ +void webclient_set_server_config(server_config_t server_config) +{ + server_cfg.server_ip[0] = server_config.server_ip[0]; + server_cfg.server_ip[1] = server_config.server_ip[1]; + server_cfg.server_ip[2] = server_config.server_ip[2]; + server_cfg.server_ip[3] = server_config.server_ip[3]; + server_cfg.tcp_in_port = server_config.tcp_in_port; + server_cfg.tcp_out_port = server_config.tcp_out_port; +} + +/*--------------------------------------------------------------------------- + webclient_init + ---------------------------------------------------------------------------*/ +void webclient_init(chanend c_xtcp) +{ + conn.event = XTCP_ALREADY_HANDLED; + do + { + slave xtcp_event(c_xtcp, conn); + } while(conn.event != XTCP_IFUP); +} + +/*--------------------------------------------------------------------------- + webclient_connect_to_server + ---------------------------------------------------------------------------*/ +void webclient_connect_to_server(chanend c_xtcp) +{ + xtcp_listen(c_xtcp, server_cfg.tcp_in_port, XTCP_PROTOCOL_TCP); + xtcp_connect(c_xtcp, server_cfg.tcp_out_port, server_cfg.server_ip, XTCP_PROTOCOL_TCP); + + conn.event = XTCP_ALREADY_HANDLED; + do + { + slave xtcp_event(c_xtcp, conn); + } while(conn.event != XTCP_NEW_CONNECTION); + +} + +/*--------------------------------------------------------------------------- + webclient_send_data + ---------------------------------------------------------------------------*/ +int webclient_send_data(chanend c_xtcp, char data[]) +{ + return webclient_send(c_xtcp, data, strlen(data)); +} + +/*--------------------------------------------------------------------------- + webclient_request_close + ---------------------------------------------------------------------------*/ +void webclient_request_close(chanend c_xtcp) +{ + char dummy_data[1]; + xtcp_write(c_xtcp, conn, dummy_data, 0); + xtcp_close(c_xtcp, conn); + // Wait till the connection is closed + conn.event = XTCP_ALREADY_HANDLED; + do + { + slave xtcp_event(c_xtcp, conn); + } while(conn.event != XTCP_CLOSED); +} + +/*==========================================================================*/ diff --git a/app_adc_demo_u/.cproject b/app_adc_demo_u/.cproject index 2914b3a..1e24c59 100644 --- a/app_adc_demo_u/.cproject +++ b/app_adc_demo_u/.cproject @@ -156,7 +156,8 @@