From cfd1809b2bddb4c44adfd4ac187697dfa8e8cc2b Mon Sep 17 00:00:00 2001 From: Dan Halbert Date: Sun, 15 Oct 2017 16:55:41 -0400 Subject: [PATCH 001/135] Suppress A0 (PA02) as a TouchIn-capable pin on CPX. --- .../boards/circuitplayground_express/mpconfigboard.h | 3 +++ atmel-samd/samd21_pins.c | 8 +++++++- 2 files changed, 10 insertions(+), 1 deletion(-) diff --git a/atmel-samd/boards/circuitplayground_express/mpconfigboard.h b/atmel-samd/boards/circuitplayground_express/mpconfigboard.h index f9ff05084a..2665f300d3 100644 --- a/atmel-samd/boards/circuitplayground_express/mpconfigboard.h +++ b/atmel-samd/boards/circuitplayground_express/mpconfigboard.h @@ -3,6 +3,9 @@ #define MICROPY_HW_BOARD_NAME "Adafruit CircuitPlayground Express" #define MICROPY_HW_MCU_NAME "samd21g18" +// Don't allow touch on A0 (PA02), because it's connected to the speaker. +#define PA02_NO_TOUCH (true) + // Salae reads 12mhz which is the limit even though we set it to the safer 8mhz. #define SPI_FLASH_BAUDRATE (8000000) diff --git a/atmel-samd/samd21_pins.c b/atmel-samd/samd21_pins.c index cd66b41ee7..b9fb17948a 100644 --- a/atmel-samd/samd21_pins.c +++ b/atmel-samd/samd21_pins.c @@ -84,7 +84,13 @@ PIN(PA01, EXTINT_CHANNEL(1), NO_ADC, NO_TOUCH, SERCOM(SERCOM1, 1)); #endif #ifdef PIN_PA02 -PIN(PA02, EXTINT_CHANNEL(2), ADC_INPUT(ADC_POSITIVE_INPUT_PIN0), TOUCH(0), +// Touch is not allowed on A0 (PA02) on Circuit Playground Express. +PIN(PA02, EXTINT_CHANNEL(2), ADC_INPUT(ADC_POSITIVE_INPUT_PIN0), + #ifdef PA02_NO_TOUCH + NO_TOUCH, + #else + TOUCH(0), + #endif NO_TIMER, NO_TIMER, NO_SERCOM, From 8f3be0a0371d5e73930a155298804c61fd0ad902 Mon Sep 17 00:00:00 2001 From: Dan Halbert Date: Sun, 15 Oct 2017 11:49:41 -0400 Subject: [PATCH 002/135] Reinit ADC completely on each call to AnalogIn.value. --- atmel-samd/common-hal/analogio/AnalogIn.c | 76 +++++++---------------- atmel-samd/common-hal/analogio/AnalogIn.h | 2 - atmel-samd/main.c | 1 + 3 files changed, 22 insertions(+), 57 deletions(-) diff --git a/atmel-samd/common-hal/analogio/AnalogIn.c b/atmel-samd/common-hal/analogio/AnalogIn.c index c520b407d0..03c502dff7 100644 --- a/atmel-samd/common-hal/analogio/AnalogIn.c +++ b/atmel-samd/common-hal/analogio/AnalogIn.c @@ -38,13 +38,6 @@ #include "asf/sam0/drivers/adc/adc.h" #include "samd21_pins.h" -// Number of active ADC channels. -volatile uint8_t active_channel_count; - -// Shared between all the instances. Allocated only when needed. -struct adc_module *adc_instance = NULL; -struct adc_config *config_adc = NULL; - void common_hal_analogio_analogin_construct(analogio_analogin_obj_t* self, const mcu_pin_obj_t *pin) { if (!pin->has_adc) { @@ -54,27 +47,6 @@ void common_hal_analogio_analogin_construct(analogio_analogin_obj_t* self, claim_pin(pin); self->pin = pin; - - if (adc_instance == NULL) { - // Allocate strucs on the heap so we only use the memory when we - // need it. - adc_instance = gc_alloc(sizeof(struct adc_module), false); - config_adc = gc_alloc(sizeof(struct adc_config), false); - - adc_get_config_defaults(config_adc); - - config_adc->reference = ADC_REFERENCE_INTVCC1; - config_adc->gain_factor = ADC_GAIN_FACTOR_DIV2; - config_adc->positive_input = self->pin->adc_input; - config_adc->resolution = ADC_RESOLUTION_16BIT; - config_adc->clock_prescaler = ADC_CLOCK_PRESCALER_DIV128; - - adc_init(adc_instance, ADC, config_adc); - } - - self->adc_instance = adc_instance; - self->config_adc = config_adc; - active_channel_count++; } bool common_hal_analogio_analogin_deinited(analogio_analogin_obj_t *self) { @@ -85,36 +57,30 @@ void common_hal_analogio_analogin_deinit(analogio_analogin_obj_t *self) { if (common_hal_analogio_analogin_deinited(self)) { return; } - active_channel_count--; - if (active_channel_count == 0) { - adc_reset(adc_instance); - gc_free(adc_instance); - gc_free(config_adc); - // Set our references to NULL so the GC doesn't mistakenly see the - // pointers in memory. - adc_instance = NULL; - config_adc = NULL; - } reset_pin(self->pin->pin); self->pin = mp_const_none; } void analogin_reset() { - if (adc_instance != NULL) { - adc_reset(adc_instance); - adc_instance = NULL; - } - active_channel_count = 0; } uint16_t common_hal_analogio_analogin_get_value(analogio_analogin_obj_t *self) { // Something else might have used the ADC in a different way, - // so we have to completely re-initialize it. - // ADC must have been disabled before adc_init() is called. - adc_init(adc_instance, ADC, config_adc); - config_adc->positive_input = self->pin->adc_input; + // so we completely re-initialize it. - adc_enable(adc_instance); + struct adc_config config_adc; + adc_get_config_defaults(&config_adc); + + config_adc.reference = ADC_REFERENCE_INTVCC1; + config_adc.gain_factor = ADC_GAIN_FACTOR_DIV2; + config_adc.positive_input = self->pin->adc_input; + config_adc.resolution = ADC_RESOLUTION_16BIT; + config_adc.clock_prescaler = ADC_CLOCK_PRESCALER_DIV128; + + struct adc_module adc_instance; + // ADC must have been disabled before adc_init() is called. + adc_init(&adc_instance, ADC, &config_adc); + adc_enable(&adc_instance); // Read twice and discard first result, as recommended in section 14 of // http://www.atmel.com/images/Atmel-42645-ADC-Configurations-with-Examples_ApplicationNote_AT11481.pdf @@ -125,23 +91,23 @@ uint16_t common_hal_analogio_analogin_get_value(analogio_analogin_obj_t *self) { uint16_t data; enum status_code status; - adc_start_conversion(adc_instance); + adc_start_conversion(&adc_instance); do { - status = adc_read(adc_instance, &data); + status = adc_read(&adc_instance, &data); } while (status == STATUS_BUSY); if (status == STATUS_ERR_OVERFLOW) { - // TODO(tannewt): Throw an error. + mp_raise_RuntimeError("ADC result overwritten before reading"); } - adc_start_conversion(adc_instance); + adc_start_conversion(&adc_instance); do { - status = adc_read(adc_instance, &data); + status = adc_read(&adc_instance, &data); } while (status == STATUS_BUSY); if (status == STATUS_ERR_OVERFLOW) { - // TODO(tannewt): Throw an error. + mp_raise_RuntimeError("ADC result overwritten before reading"); } - adc_disable(adc_instance); + adc_disable(&adc_instance); return data; } diff --git a/atmel-samd/common-hal/analogio/AnalogIn.h b/atmel-samd/common-hal/analogio/AnalogIn.h index 3e9ddd76e4..a4d5b355da 100644 --- a/atmel-samd/common-hal/analogio/AnalogIn.h +++ b/atmel-samd/common-hal/analogio/AnalogIn.h @@ -41,8 +41,6 @@ typedef struct { mp_obj_base_t base; const mcu_pin_obj_t * pin; - struct adc_module * adc_instance; - struct adc_config * config_adc; } analogio_analogin_obj_t; void analogin_reset(void); diff --git a/atmel-samd/main.c b/atmel-samd/main.c index 36d5dde273..fe56410c05 100644 --- a/atmel-samd/main.c +++ b/atmel-samd/main.c @@ -203,6 +203,7 @@ void reset_samd21(void) { analogin_reset(); + // TODO: move this to analogout_reset() // Wait for the DAC to sync then reset. while (DAC->STATUS.reg & DAC_STATUS_SYNCBUSY) {} DAC->CTRLA.reg |= DAC_CTRLA_SWRST; From dbd3f1516854f8609fe886d83b556b73684fdc6a Mon Sep 17 00:00:00 2001 From: Dan Halbert Date: Sun, 15 Oct 2017 14:02:42 -0400 Subject: [PATCH 003/135] 1. Use lib/libm for small (non-Express builds) to gain back a lot of flash space. 2. Add flag INTERNAL_LIBM to mpconfigboard.mk files to signal using lib/libm. 3. Fix floating-point warnings in lib/libm 4. Turn off -finline-limit, no longer needed due to 1. 5. Add explicit flags for SPI_FLASH_FILESYSTEM and INTERNAL_FLASH_FILESYSTEM to mpconfigboard.mk files, so they don't need to know the name of the .c file that implements those. Makefile takes care of checking the flags and including the right files. --- atmel-samd/Makefile | 50 +++++++++++++++++-- .../boards/arduino_zero/mpconfigboard.mk | 3 +- .../mpconfigboard.mk | 2 +- .../feather_m0_adalogger/mpconfigboard.mk | 3 +- .../boards/feather_m0_basic/mpconfigboard.mk | 3 +- .../feather_m0_express/mpconfigboard.mk | 2 +- atmel-samd/boards/gemma_m0/mpconfigboard.mk | 3 +- .../boards/metro_m0_express/mpconfigboard.mk | 2 +- atmel-samd/boards/trinket_m0/mpconfigboard.mk | 3 +- .../trinket_m0_haxpress/mpconfigboard.mk | 2 +- atmel-samd/mpconfigport.h | 2 + lib/libm/ef_rem_pio2.c | 5 +- lib/libm/kf_rem_pio2.c | 6 +++ lib/libm/math.c | 8 +-- lib/libm/nearbyintf.c | 3 ++ lib/libm/sf_ldexp.c | 3 ++ 16 files changed, 82 insertions(+), 18 deletions(-) diff --git a/atmel-samd/Makefile b/atmel-samd/Makefile index 3bbe91ea9a..4a45106db5 100644 --- a/atmel-samd/Makefile +++ b/atmel-samd/Makefile @@ -135,11 +135,12 @@ ifeq ($(DEBUG), 1) # -DMICROPY_DEBUG_MODULES may also be added to an -flto build, if you wish. CFLAGS += -Os -ggdb -DNDEBUG -DENABLE_MICRO_TRACE_BUFFER -DMICROPY_DEBUG_MODULES else -# GCC_INLINE_LIMIT specifies -finline-limit, which can shrink the image size. +# -finline-limit can shrink the image size. # -finline-limit=80 or so is similar to not having it on. # There is no simple default value, though. -ifeq ($(FLASH_IMPL),internal_flash.c) -GCC_INLINE_LIMIT = -finline-limit=19 +ifdef INTERNAL_FLASH_FILESYSTEM + ## Not currently needed + ## CFLAGS += -finline-limit=50 endif CFLAGS += -Os -DNDEBUG -flto $(GCC_INLINE_LIMIT) endif @@ -161,10 +162,14 @@ CFLAGS += -DMICROPY_MODULE_FROZEN_MPY CFLAGS += -Wno-error=lto-type-mismatch endif -#LIBM_FILE_NAME = $(shell $(CC) $(CFLAGS) -print-file-name=libm.a) LDFLAGS = $(CFLAGS) -nostartfiles -fshort-enums -mthumb -mcpu=cortex-m0plus -Lasf/thirdparty/CMSIS/Lib/GCC/ -Wl,-nostdlib -Wl,-T,$(LD_FILE) -Wl,-Map=$@.map -Wl,-cref -Wl,-gc-sections -specs=nano.specs LIBS = -larm_cortexM0l_math -lm -lgcc -lc +# Use toolchain libm if we're not using our own. +ifndef INTERNAL_LIBM +LIBS += -lm +endif + SRC_ASF = $(addprefix asf/sam0/,\ drivers/adc/adc_sam_d_r/adc.c \ drivers/dac/dac_sam_d_c/dac.c \ @@ -237,6 +242,16 @@ SRC_C = \ lib/libc/string0.c \ lib/mp-readline/readline.c +# Choose which flash filesystem impl to use. +# (Right now INTERNAL_FLASH_FILESYSTEM and SPI_FLASH_FILESYSTEM are mutually exclusive. +# But that might not be true in the future.) +ifdef INTERNAL_FLASH_FILESYSTEM +SRC_C += internal_flash.c +endif +ifdef SPI_FLASH_FILESYSTEM +SRC_C += spi_flash.c +endif + SRC_COMMON_HAL = \ analogio/__init__.c \ analogio/AnalogIn.c \ @@ -270,6 +285,30 @@ SRC_COMMON_HAL = \ usb_hid/__init__.c \ usb_hid/Device.c +ifdef INTERNAL_LIBM +SRC_LIBM = $(addprefix lib/,\ + libm/math.c \ + libm/fmodf.c \ + libm/nearbyintf.c \ + libm/ef_sqrt.c \ + libm/kf_rem_pio2.c \ + libm/kf_sin.c \ + libm/kf_cos.c \ + libm/kf_tan.c \ + libm/ef_rem_pio2.c \ + libm/sf_sin.c \ + libm/sf_cos.c \ + libm/sf_tan.c \ + libm/sf_frexp.c \ + libm/sf_modf.c \ + libm/sf_ldexp.c \ + libm/asinfacosf.c \ + libm/atanf.c \ + libm/atan2f.c \ + ) +endif + + # These don't have corresponding files in each port but are still located in # shared-bindings to make it clear what the contents of the modules are. SRC_BINDINGS_ENUMS = \ @@ -304,6 +343,9 @@ OBJ = $(PY_O) $(addprefix $(BUILD)/, $(SRC_C:.c=.o)) OBJ += $(addprefix $(BUILD)/, $(SRC_ASF:.c=.o)) OBJ += $(addprefix $(BUILD)/, $(SRC_COMMON_HAL_EXPANDED:.c=.o)) OBJ += $(addprefix $(BUILD)/, $(SRC_SHARED_MODULE_EXPANDED:.c=.o)) +ifdef INTERNAL_LIBM +OBJ += $(addprefix $(BUILD)/, $(SRC_LIBM:.c=.o)) +endif SRC_QSTR += $(SRC_C) $(SRC_COMMON_HAL_EXPANDED) $(SRC_SHARED_MODULE_EXPANDED) $(STM_SRC_C) diff --git a/atmel-samd/boards/arduino_zero/mpconfigboard.mk b/atmel-samd/boards/arduino_zero/mpconfigboard.mk index 9ea93525df..085619800c 100644 --- a/atmel-samd/boards/arduino_zero/mpconfigboard.mk +++ b/atmel-samd/boards/arduino_zero/mpconfigboard.mk @@ -2,6 +2,7 @@ LD_FILE = boards/samd21x18-bootloader.ld USB_VID = 0x2341 USB_PID = 0x824D -FLASH_IMPL = internal_flash.c +INTERNAL_FLASH_FILESYSTEM = 1 +INTERNAL_LIBM = 1 CHIP_VARIANT = SAMD21G18A diff --git a/atmel-samd/boards/circuitplayground_express/mpconfigboard.mk b/atmel-samd/boards/circuitplayground_express/mpconfigboard.mk index e8195c90da..9a6157ee76 100644 --- a/atmel-samd/boards/circuitplayground_express/mpconfigboard.mk +++ b/atmel-samd/boards/circuitplayground_express/mpconfigboard.mk @@ -2,7 +2,7 @@ LD_FILE = boards/samd21x18-bootloader-external-flash-crystalless.ld USB_VID = 0x239A USB_PID = 0x8019 -FLASH_IMPL = spi_flash.c +SPI_FLASH_FILESYSTEM = 1 CHIP_VARIANT = SAMD21G18A diff --git a/atmel-samd/boards/feather_m0_adalogger/mpconfigboard.mk b/atmel-samd/boards/feather_m0_adalogger/mpconfigboard.mk index 755157cb7e..e77a546a9b 100644 --- a/atmel-samd/boards/feather_m0_adalogger/mpconfigboard.mk +++ b/atmel-samd/boards/feather_m0_adalogger/mpconfigboard.mk @@ -2,6 +2,7 @@ LD_FILE = boards/samd21x18-bootloader.ld USB_VID = 0x239A USB_PID = 0x8015 -FLASH_IMPL = internal_flash.c +INTERNAL_FLASH_FILESYSTEM = 1 +INTERNAL_LIBM = 1 CHIP_VARIANT = SAMD21G18A diff --git a/atmel-samd/boards/feather_m0_basic/mpconfigboard.mk b/atmel-samd/boards/feather_m0_basic/mpconfigboard.mk index c6c64f4a2c..247348c976 100644 --- a/atmel-samd/boards/feather_m0_basic/mpconfigboard.mk +++ b/atmel-samd/boards/feather_m0_basic/mpconfigboard.mk @@ -2,7 +2,8 @@ LD_FILE = boards/samd21x18-bootloader.ld USB_VID = 0x239A USB_PID = 0x8015 -FLASH_IMPL = internal_flash.c +INTERNAL_FLASH_FILESYSTEM = 1 +INTERNAL_LIBM = 1 CHIP_VARIANT = SAMD21G18A diff --git a/atmel-samd/boards/feather_m0_express/mpconfigboard.mk b/atmel-samd/boards/feather_m0_express/mpconfigboard.mk index bf8bd54f2d..a855521eb2 100644 --- a/atmel-samd/boards/feather_m0_express/mpconfigboard.mk +++ b/atmel-samd/boards/feather_m0_express/mpconfigboard.mk @@ -2,6 +2,6 @@ LD_FILE = boards/samd21x18-bootloader-external-flash.ld USB_VID = 0x239A USB_PID = 0x801b -FLASH_IMPL = spi_flash.c +SPI_FLASH_FILESYTEM = 1 CHIP_VARIANT = SAMD21G18A diff --git a/atmel-samd/boards/gemma_m0/mpconfigboard.mk b/atmel-samd/boards/gemma_m0/mpconfigboard.mk index 87a5e93c10..f3a308e48b 100644 --- a/atmel-samd/boards/gemma_m0/mpconfigboard.mk +++ b/atmel-samd/boards/gemma_m0/mpconfigboard.mk @@ -2,6 +2,7 @@ LD_FILE = boards/samd21x18-bootloader.ld USB_VID = 0x239A USB_PID = 0x801D -FLASH_IMPL = internal_flash.c +INTERNAL_FLASH_FILESYSTEM = 1 +INTERNAL_LIBM = 1 CHIP_VARIANT = SAMD21E18A diff --git a/atmel-samd/boards/metro_m0_express/mpconfigboard.mk b/atmel-samd/boards/metro_m0_express/mpconfigboard.mk index 436e56a600..c3720a2441 100644 --- a/atmel-samd/boards/metro_m0_express/mpconfigboard.mk +++ b/atmel-samd/boards/metro_m0_express/mpconfigboard.mk @@ -2,6 +2,6 @@ LD_FILE = boards/samd21x18-bootloader-external-flash.ld USB_VID = 0x239A USB_PID = 0x8014 -FLASH_IMPL = spi_flash.c +SPI_FLASH_FILESYSTEM = 1 CHIP_VARIANT = SAMD21G18A diff --git a/atmel-samd/boards/trinket_m0/mpconfigboard.mk b/atmel-samd/boards/trinket_m0/mpconfigboard.mk index 4d2268c13c..bf96af3a73 100644 --- a/atmel-samd/boards/trinket_m0/mpconfigboard.mk +++ b/atmel-samd/boards/trinket_m0/mpconfigboard.mk @@ -2,6 +2,7 @@ LD_FILE = boards/samd21x18-bootloader.ld USB_VID = 0x239A USB_PID = 0x801F -FLASH_IMPL = internal_flash.c +INTERNAL_FLASH_FILESYSTEM = 1 +INTERNAL_LIBM = 1 CHIP_VARIANT = SAMD21E18A diff --git a/atmel-samd/boards/trinket_m0_haxpress/mpconfigboard.mk b/atmel-samd/boards/trinket_m0_haxpress/mpconfigboard.mk index cfa924b606..788985cacb 100644 --- a/atmel-samd/boards/trinket_m0_haxpress/mpconfigboard.mk +++ b/atmel-samd/boards/trinket_m0_haxpress/mpconfigboard.mk @@ -2,7 +2,7 @@ LD_FILE = boards/samd21x18-bootloader-external-flash-crystalless.ld USB_VID = 0x239A USB_PID = 0x801F -FLASH_IMPL = spi_flash.c +SPI_FLASH_FILESYSTEM = 1 CHIP_VARIANT = SAMD21E18A CHIP_FAMILY = samd21 diff --git a/atmel-samd/mpconfigport.h b/atmel-samd/mpconfigport.h index fc061d1cb8..3a79d33943 100644 --- a/atmel-samd/mpconfigport.h +++ b/atmel-samd/mpconfigport.h @@ -189,6 +189,8 @@ extern const struct _mp_obj_module_t usb_hid_module; #define MICROPY_PY_FRAMEBUF (0) #define EXTRA_BUILTIN_MODULES + #define MICROPY_PY_BUILTINS_COMPLEX (0) + #define MICROPY_BUILTIN_METHOD_CHECK_SELF_ARG (0) #define MICROPY_CPYTHON_COMPAT (0) #endif diff --git a/lib/libm/ef_rem_pio2.c b/lib/libm/ef_rem_pio2.c index ca55243fb4..601f3bac4e 100644 --- a/lib/libm/ef_rem_pio2.c +++ b/lib/libm/ef_rem_pio2.c @@ -151,7 +151,7 @@ pio2_3t = 6.1232342629e-17; /* 0x248d3132 */ fn = (float)n; r = t-fn*pio2_1; w = fn*pio2_1t; /* 1st round good to 40 bit */ - if(n<32&&(ix&0xffffff00)!=npio2_hw[n-1]) { + if(n<32&&(__int32_t)(ix&0xffffff00)!=npio2_hw[n-1]) { y[0] = r-w; /* quick check no cancellation */ } else { __uint32_t high; @@ -195,7 +195,10 @@ pio2_3t = 6.1232342629e-17; /* 0x248d3132 */ } tx[2] = z; nx = 3; +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wfloat-equal" while(tx[nx-1]==zero) nx--; /* skip zero term */ +#pragma GCC diagnostic pop n = __kernel_rem_pio2f(tx,y,e0,nx,2,two_over_pi); if(hx<0) {y[0] = -y[0]; y[1] = -y[1]; return -n;} return n; diff --git a/lib/libm/kf_rem_pio2.c b/lib/libm/kf_rem_pio2.c index c7e9479571..3b09de5fd0 100644 --- a/lib/libm/kf_rem_pio2.c +++ b/lib/libm/kf_rem_pio2.c @@ -138,7 +138,10 @@ recompute: } /* check if recomputation is needed */ +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wfloat-equal" if(z==zero) { +#pragma GCC diagnostic pop j = 0; for (i=jz-1;i>=jk;i--) j |= iq[i]; if(j==0) { /* need recomputation */ @@ -155,7 +158,10 @@ recompute: } /* chop off zero terms */ +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wfloat-equal" if(z==(float)0.0) { +#pragma GCC diagnostic pop jz -= 1; q0 -= 8; while(iq[jz]==0) { jz--; q0-=8;} } else { /* break z into 8-bit if necessary */ diff --git a/lib/libm/math.c b/lib/libm/math.c index 984636627c..a2313fcea8 100644 --- a/lib/libm/math.c +++ b/lib/libm/math.c @@ -338,7 +338,7 @@ float powf(float x, float y) return sn*huge*huge; /* overflow */ } else if ((j&0x7fffffff) > 0x43160000) /* z < -150 */ // FIXME: check should be (uint32_t)j > 0xc3160000 return sn*tiny*tiny; /* underflow */ - else if (j == 0xc3160000) { /* z == -150 */ + else if (j == (int32_t) 0xc3160000) { /* z == -150 */ if (p_l <= z-p_h) return sn*tiny*tiny; /* underflow */ } @@ -585,13 +585,13 @@ float expm1f(float x) /*****************************************************************************/ /*****************************************************************************/ -/* k is such that k*ln2 has minimal relative error and x - kln2 > log(FLT_MIN) */ -static const int k = 235; -static const float kln2 = 0x1.45c778p+7f; /* expf(x)/2 for x >= log(FLT_MAX), slightly better than 0.5f*expf(x/2)*expf(x/2) */ float __expo2f(float x) { + /* k is such that k*ln2 has minimal relative error and x - kln2 > log(FLT_MIN) */ + static const int k = 235; + static const float kln2 = 0x1.45c778p+7f; float scale; /* note that k is odd and scale*scale overflows */ diff --git a/lib/libm/nearbyintf.c b/lib/libm/nearbyintf.c index 1c3545945d..1bb44aa466 100644 --- a/lib/libm/nearbyintf.c +++ b/lib/libm/nearbyintf.c @@ -15,7 +15,10 @@ float nearbyintf(float x) y = x - 0x1p23f + 0x1p23f; else y = x + 0x1p23f - 0x1p23f; +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wfloat-equal" if (y == 0) +#pragma GCC diagnostic pop return s ? -0.0f : 0.0f; return y; } diff --git a/lib/libm/sf_ldexp.c b/lib/libm/sf_ldexp.c index 37968d475a..75cb8b7275 100644 --- a/lib/libm/sf_ldexp.c +++ b/lib/libm/sf_ldexp.c @@ -32,7 +32,10 @@ float value; int exp; #endif { +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wfloat-equal" if(!isfinite(value)||value==(float)0.0) return value; +#pragma GCC diagnostic pop value = scalbnf(value,exp); //if(!finitef(value)||value==(float)0.0) errno = ERANGE; return value; From 274fff4226f36223d15480b8d198d89164b09933 Mon Sep 17 00:00:00 2001 From: Dan Halbert Date: Mon, 16 Oct 2017 11:19:57 -0400 Subject: [PATCH 004/135] Use internal libm for all atmel-samd boards. --- atmel-samd/boards/arduino_zero/mpconfigboard.mk | 1 - atmel-samd/boards/feather_m0_adalogger/mpconfigboard.mk | 1 - atmel-samd/boards/feather_m0_basic/mpconfigboard.mk | 1 - atmel-samd/boards/feather_m0_express/mpconfigboard.mk | 2 +- atmel-samd/boards/gemma_m0/mpconfigboard.mk | 1 - atmel-samd/boards/trinket_m0/mpconfigboard.mk | 1 - atmel-samd/mpconfigport.mk | 3 +++ 7 files changed, 4 insertions(+), 6 deletions(-) diff --git a/atmel-samd/boards/arduino_zero/mpconfigboard.mk b/atmel-samd/boards/arduino_zero/mpconfigboard.mk index 085619800c..9d34aa5f1b 100644 --- a/atmel-samd/boards/arduino_zero/mpconfigboard.mk +++ b/atmel-samd/boards/arduino_zero/mpconfigboard.mk @@ -3,6 +3,5 @@ USB_VID = 0x2341 USB_PID = 0x824D INTERNAL_FLASH_FILESYSTEM = 1 -INTERNAL_LIBM = 1 CHIP_VARIANT = SAMD21G18A diff --git a/atmel-samd/boards/feather_m0_adalogger/mpconfigboard.mk b/atmel-samd/boards/feather_m0_adalogger/mpconfigboard.mk index e77a546a9b..fb3a61fc38 100644 --- a/atmel-samd/boards/feather_m0_adalogger/mpconfigboard.mk +++ b/atmel-samd/boards/feather_m0_adalogger/mpconfigboard.mk @@ -3,6 +3,5 @@ USB_VID = 0x239A USB_PID = 0x8015 INTERNAL_FLASH_FILESYSTEM = 1 -INTERNAL_LIBM = 1 CHIP_VARIANT = SAMD21G18A diff --git a/atmel-samd/boards/feather_m0_basic/mpconfigboard.mk b/atmel-samd/boards/feather_m0_basic/mpconfigboard.mk index 247348c976..22e4c4bfdf 100644 --- a/atmel-samd/boards/feather_m0_basic/mpconfigboard.mk +++ b/atmel-samd/boards/feather_m0_basic/mpconfigboard.mk @@ -3,7 +3,6 @@ USB_VID = 0x239A USB_PID = 0x8015 INTERNAL_FLASH_FILESYSTEM = 1 -INTERNAL_LIBM = 1 CHIP_VARIANT = SAMD21G18A diff --git a/atmel-samd/boards/feather_m0_express/mpconfigboard.mk b/atmel-samd/boards/feather_m0_express/mpconfigboard.mk index a855521eb2..4a8bc31eb5 100644 --- a/atmel-samd/boards/feather_m0_express/mpconfigboard.mk +++ b/atmel-samd/boards/feather_m0_express/mpconfigboard.mk @@ -2,6 +2,6 @@ LD_FILE = boards/samd21x18-bootloader-external-flash.ld USB_VID = 0x239A USB_PID = 0x801b -SPI_FLASH_FILESYTEM = 1 +SPI_FLASH_FILESYSTEM = 1 CHIP_VARIANT = SAMD21G18A diff --git a/atmel-samd/boards/gemma_m0/mpconfigboard.mk b/atmel-samd/boards/gemma_m0/mpconfigboard.mk index f3a308e48b..2d8d97adbe 100644 --- a/atmel-samd/boards/gemma_m0/mpconfigboard.mk +++ b/atmel-samd/boards/gemma_m0/mpconfigboard.mk @@ -3,6 +3,5 @@ USB_VID = 0x239A USB_PID = 0x801D INTERNAL_FLASH_FILESYSTEM = 1 -INTERNAL_LIBM = 1 CHIP_VARIANT = SAMD21E18A diff --git a/atmel-samd/boards/trinket_m0/mpconfigboard.mk b/atmel-samd/boards/trinket_m0/mpconfigboard.mk index bf96af3a73..de07201723 100644 --- a/atmel-samd/boards/trinket_m0/mpconfigboard.mk +++ b/atmel-samd/boards/trinket_m0/mpconfigboard.mk @@ -3,6 +3,5 @@ USB_VID = 0x239A USB_PID = 0x801F INTERNAL_FLASH_FILESYSTEM = 1 -INTERNAL_LIBM = 1 CHIP_VARIANT = SAMD21E18A diff --git a/atmel-samd/mpconfigport.mk b/atmel-samd/mpconfigport.mk index 208064b6c1..acb0916fcc 100644 --- a/atmel-samd/mpconfigport.mk +++ b/atmel-samd/mpconfigport.mk @@ -2,3 +2,6 @@ # $(MPY-TOOL) needs to know what kind of longint to use (if any) to freeze long integers. # This should correspond to the MICROPY_LONGINT_IMPL definition in mpconfigport.h. MPY_TOOL_LONGINT_IMPL = -mlongint-impl=none + +INTERNAL_LIBM = (1) + From 1709fbb65a4ec16dd0b9a8a72514aeb7b0305b9c Mon Sep 17 00:00:00 2001 From: Dan Halbert Date: Sun, 15 Oct 2017 15:11:29 -0400 Subject: [PATCH 005/135] Turn on pulseio now that there's room. https://github.com/adafruit/circuitpython/issues/325#issuecomment-336733842 --- atmel-samd/mpconfigport.h | 2 +- shared-bindings/index.rst | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/atmel-samd/mpconfigport.h b/atmel-samd/mpconfigport.h index 3a79d33943..4cebf356d6 100644 --- a/atmel-samd/mpconfigport.h +++ b/atmel-samd/mpconfigport.h @@ -180,7 +180,6 @@ extern const struct _mp_obj_module_t usb_hid_module; { MP_OBJ_NEW_QSTR(MP_QSTR_audiobusio), (mp_obj_t)&audiobusio_module }, \ { MP_OBJ_NEW_QSTR(MP_QSTR_gamepad),(mp_obj_t)&gamepad_module }, \ { MP_OBJ_NEW_QSTR(MP_QSTR_nvm), (mp_obj_t)&cpy_nvm_module }, \ - { MP_OBJ_NEW_QSTR(MP_QSTR_pulseio), (mp_obj_t)&pulseio_module }, \ { MP_OBJ_NEW_QSTR(MP_QSTR_bitbangio), (mp_obj_t)&bitbangio_module } #define EXPRESS_BOARD #else @@ -201,6 +200,7 @@ extern const struct _mp_obj_module_t usb_hid_module; { MP_OBJ_NEW_QSTR(MP_QSTR_analogio), (mp_obj_t)&analogio_module }, \ { MP_OBJ_NEW_QSTR(MP_QSTR_digitalio), (mp_obj_t)&digitalio_module }, \ { MP_OBJ_NEW_QSTR(MP_QSTR_busio), (mp_obj_t)&busio_module }, \ + { MP_OBJ_NEW_QSTR(MP_QSTR_pulseio), (mp_obj_t)&pulseio_module }, \ { MP_OBJ_NEW_QSTR(MP_QSTR_board), (mp_obj_t)&board_module }, \ { MP_OBJ_NEW_QSTR(MP_QSTR_os), (mp_obj_t)&os_module }, \ { MP_OBJ_NEW_QSTR(MP_QSTR_random), (mp_obj_t)&random_module }, \ diff --git a/shared-bindings/index.rst b/shared-bindings/index.rst index 556626268b..06fcc1188e 100644 --- a/shared-bindings/index.rst +++ b/shared-bindings/index.rst @@ -27,7 +27,7 @@ Module / Port SAMD21 SAMD21 Express ESP8266 `neopixel_write` **Yes** **Yes** **Yes** `nvm` No **Yes** No `os` **Yes** **Yes** **Yes** -`pulseio` No **Yes** No +`pulseio` **Yes** **Yes** No `random` **Yes** **Yes** **Yes** `storage` **Yes** **Yes** **Yes** `time` **Yes** **Yes** **Yes** From 5f6df7f54a06720ff0633639b0c489696f252102 Mon Sep 17 00:00:00 2001 From: Dan Halbert Date: Mon, 16 Oct 2017 15:11:41 -0400 Subject: [PATCH 006/135] More io capability on non-Express boards, so call *_reset() routines appropriately to match board capabilities. --- atmel-samd/main.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/atmel-samd/main.c b/atmel-samd/main.c index fe56410c05..79b5604e83 100644 --- a/atmel-samd/main.c +++ b/atmel-samd/main.c @@ -59,6 +59,7 @@ #include "common-hal/pulseio/PulseIn.h" #include "common-hal/pulseio/PulseOut.h" #include "common-hal/pulseio/PWMOut.h" +#include "common-hal/touchio/TouchIn.h" #include "common-hal/usb_hid/__init__.h" #include "autoreload.h" @@ -69,7 +70,6 @@ #include "tick.h" #ifdef EXPRESS_BOARD -#include "common-hal/touchio/TouchIn.h" #define INTERNAL_CIRCUITPY_CONFIG_START_ADDR (0x00040000 - 0x100 - CIRCUITPY_INTERNAL_NVM_SIZE) #else #define INTERNAL_CIRCUITPY_CONFIG_START_ADDR (0x00040000 - 0x010000 - 0x100 - CIRCUITPY_INTERNAL_NVM_SIZE) @@ -193,13 +193,13 @@ void reset_samd21(void) { #ifdef EXPRESS_BOARD audioout_reset(); +#endif + touchin_reset(); pdmin_reset(); pulsein_reset(); pulseout_reset(); pwmout_reset(); -#endif - analogin_reset(); From 6c7d35c40cb2b498b34befd4dcfc3d6d0bf3208b Mon Sep 17 00:00:00 2001 From: Scott Shawcroft Date: Mon, 16 Oct 2017 14:54:23 -0700 Subject: [PATCH 007/135] esp8266: Correct SPI functionality when write_value is provided. It used to introduce extra clocks to the bus rather than changing the value output. This fixes SD cards. --- esp8266/common-hal/busio/SPI.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/esp8266/common-hal/busio/SPI.c b/esp8266/common-hal/busio/SPI.c index b372d07643..fc8dd348f1 100644 --- a/esp8266/common-hal/busio/SPI.c +++ b/esp8266/common-hal/busio/SPI.c @@ -174,13 +174,13 @@ bool common_hal_busio_spi_read(busio_spi_obj_t *self, write_value; for (size_t j = 0; j < count; ++j) { for (size_t k = 0; k < chunk_size; ++k) { - data[i] = spi_transaction(HSPI, 0, 0, 0, 0, 0, 0, 8, long_write_value); + data[i] = spi_transaction(HSPI, 0, 0, 0, 0, 8, long_write_value, 8, 0); ++i; } ets_loop_iter(); } while (i < len) { - data[i] = spi_transaction(HSPI, 0, 0, 0, 0, 0, 0, 8, long_write_value); + data[i] = spi_transaction(HSPI, 0, 0, 0, 0, 8, long_write_value, 8, 0); ++i; } return true; From c216c2876f46501db62faa133d9ac2c150791814 Mon Sep 17 00:00:00 2001 From: Scott Shawcroft Date: Mon, 16 Oct 2017 15:07:08 -0700 Subject: [PATCH 008/135] esp8266: Actually disable pins when reset on reload. --- esp8266/common-hal/microcontroller/Pin.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/esp8266/common-hal/microcontroller/Pin.c b/esp8266/common-hal/microcontroller/Pin.c index 417ab0c410..5c90f4f1a0 100644 --- a/esp8266/common-hal/microcontroller/Pin.c +++ b/esp8266/common-hal/microcontroller/Pin.c @@ -28,6 +28,8 @@ #include "common-hal/microcontroller/Pin.h" #include "shared-bindings/microcontroller/Pin.h" +#include "py/mphal.h" + #include "eagle_soc.h" extern volatile bool adc_in_use; @@ -48,11 +50,13 @@ bool common_hal_mcu_pin_is_free(const mcu_pin_obj_t* pin) { void reset_pins(void) { for (int i = 0; i < 17; i++) { // 5 is RXD, 6 is TXD - if (i == 0 || (i > 4 && i < 13) || i == 12) { + if ((i > 4 && i < 13) || i == 12) { continue; } uint32_t peripheral = PERIPHS_IO_MUX + i * 4; PIN_FUNC_SELECT(peripheral, 0); PIN_PULLUP_DIS(peripheral); + // Disable the pin. + gpio_output_set(0x0, 0x0, 0x0, 1 << i); } } From c6a15f76adfe0a3627fd42f6a4a5f2c45be51b35 Mon Sep 17 00:00:00 2001 From: jerryneedell Date: Mon, 16 Oct 2017 21:29:42 -0400 Subject: [PATCH 009/135] esp8266: add neopixel_write - remove neopixel.py (#339) For ESP8266, remove frozen module neopixel.py and add neopixel_write to mpconfigport.h. Use [Adafruit_CircuitPython_Neopixel/neopixel.py](https://github.com/adafruit/Adafruit_CircuitPython_NeoPixel) instead. --- esp8266/modules/neopixel.py | 32 -------------------------------- esp8266/mpconfigport.h | 2 ++ 2 files changed, 2 insertions(+), 32 deletions(-) delete mode 100644 esp8266/modules/neopixel.py diff --git a/esp8266/modules/neopixel.py b/esp8266/modules/neopixel.py deleted file mode 100644 index b13424d7d8..0000000000 --- a/esp8266/modules/neopixel.py +++ /dev/null @@ -1,32 +0,0 @@ -# NeoPixel driver for MicroPython on ESP8266 -# MIT license; Copyright (c) 2016 Damien P. George - -from esp import neopixel_write - - -class NeoPixel: - ORDER = (1, 0, 2, 3) - - def __init__(self, pin, n, bpp=3): - self.pin = pin - self.n = n - self.bpp = bpp - self.buf = bytearray(n * bpp) - self.pin.init(pin.OUT) - - def __setitem__(self, index, val): - offset = index * self.bpp - for i in range(self.bpp): - self.buf[offset + self.ORDER[i]] = val[i] - - def __getitem__(self, index): - offset = index * self.bpp - return tuple(self.buf[offset + self.ORDER[i]] - for i in range(self.bpp)) - - def fill(self, color): - for i in range(self.n): - self[i] = color - - def write(self): - neopixel_write(self.pin, self.buf, True) diff --git a/esp8266/mpconfigport.h b/esp8266/mpconfigport.h index 19f80fbb6b..5e9b1e0b64 100644 --- a/esp8266/mpconfigport.h +++ b/esp8266/mpconfigport.h @@ -171,6 +171,7 @@ extern const struct _mp_obj_module_t busio_module; extern const struct _mp_obj_module_t bitbangio_module; extern const struct _mp_obj_module_t time_module; extern const struct _mp_obj_module_t multiterminal_module; +extern const struct _mp_obj_module_t neopixel_write_module; #define MICROPY_PORT_BUILTIN_MODULES \ { MP_OBJ_NEW_QSTR(MP_QSTR_esp), (mp_obj_t)&esp_module }, \ @@ -191,6 +192,7 @@ extern const struct _mp_obj_module_t multiterminal_module; { MP_OBJ_NEW_QSTR(MP_QSTR_random), (mp_obj_t)&random_module }, \ { MP_OBJ_NEW_QSTR(MP_QSTR_time), (mp_obj_t)&time_module }, \ { MP_OBJ_NEW_QSTR(MP_QSTR_multiterminal), (mp_obj_t)&multiterminal_module }, \ + { MP_OBJ_NEW_QSTR(MP_QSTR_neopixel_write),(mp_obj_t)&neopixel_write_module }, \ #define MICROPY_PORT_BUILTIN_MODULE_WEAK_LINKS \ { MP_ROM_QSTR(MP_QSTR_json), MP_ROM_PTR(&mp_module_ujson) }, \ From 4f4ddf00dcce450aaa79da2cdab25fad674926f9 Mon Sep 17 00:00:00 2001 From: Dan Halbert Date: Mon, 16 Oct 2017 18:28:38 -0400 Subject: [PATCH 010/135] Set DRVSTR on output pins to strong (more current capability). --- atmel-samd/common-hal/digitalio/DigitalInOut.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/atmel-samd/common-hal/digitalio/DigitalInOut.c b/atmel-samd/common-hal/digitalio/DigitalInOut.c index abb4547cc1..16654f0fe8 100644 --- a/atmel-samd/common-hal/digitalio/DigitalInOut.c +++ b/atmel-samd/common-hal/digitalio/DigitalInOut.c @@ -80,6 +80,9 @@ void common_hal_digitalio_digitalinout_switch_to_output( pin_conf.input_pull = PORT_PIN_PULL_NONE; port_pin_set_config(self->pin->pin, &pin_conf); + // Turn on "strong" pin driving (more current available). See DRVSTR doc in datasheet. + system_pinmux_pin_set_output_strength(self->pin->pin, SYSTEM_PINMUX_PIN_STRENGTH_HIGH); + self->output = true; self->open_drain = drive_mode == DRIVE_MODE_OPEN_DRAIN; common_hal_digitalio_digitalinout_set_value(self, value); From a1409d1432ea4280293749b3a2bb5c2278fda609 Mon Sep 17 00:00:00 2001 From: Dan Halbert Date: Mon, 16 Oct 2017 23:48:26 -0400 Subject: [PATCH 011/135] redo time.monotonic() to avoid double precision --- shared-bindings/time/__init__.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/shared-bindings/time/__init__.c b/shared-bindings/time/__init__.c index 105758951f..6956cc4e65 100644 --- a/shared-bindings/time/__init__.c +++ b/shared-bindings/time/__init__.c @@ -52,7 +52,9 @@ //| :rtype: float //| STATIC mp_obj_t time_monotonic(void) { - return mp_obj_new_float(common_hal_time_monotonic() / 1000.0); + uint64_t time64 = common_hal_time_monotonic(); + // 4294967296 = 2^32 + return mp_obj_new_float(((uint32_t) (time64 >> 32) * 4294967296.0f + (uint32_t) (time64 & 0xffffffff)) / 1000.0f); } MP_DEFINE_CONST_FUN_OBJ_0(time_monotonic_obj, time_monotonic); From 9bcc1057ca3796e8ba8aa9805cf9d140ee7f51d3 Mon Sep 17 00:00:00 2001 From: Radomir Dopieralski Date: Sun, 22 Oct 2017 04:39:20 +0200 Subject: [PATCH 012/135] Gracefully reset the gamepad module (#356) If a soft reset happens while the gamepad module is scanning for button presses, there is a moment when the pins get de-initialized, but the gamepad module is still trying to read them, which ends in a crash. We can avoid it by disabling scanning on reset. --- atmel-samd/main.c | 4 ++++ shared-module/gamepad/__init__.c | 4 ++++ shared-module/gamepad/__init__.h | 1 + 3 files changed, 9 insertions(+) diff --git a/atmel-samd/main.c b/atmel-samd/main.c index 79b5604e83..7bc4a87ed6 100644 --- a/atmel-samd/main.c +++ b/atmel-samd/main.c @@ -61,6 +61,7 @@ #include "common-hal/pulseio/PWMOut.h" #include "common-hal/touchio/TouchIn.h" #include "common-hal/usb_hid/__init__.h" +#include "shared-module/gamepad/__init__.h" #include "autoreload.h" #include "flash_api.h" @@ -202,6 +203,9 @@ void reset_samd21(void) { pwmout_reset(); analogin_reset(); +#ifdef CIRCUITPY_GAMEPAD_TICKS + gamepad_reset(); +#endif // TODO: move this to analogout_reset() // Wait for the DAC to sync then reset. diff --git a/shared-module/gamepad/__init__.c b/shared-module/gamepad/__init__.c index 1aebf611d3..b6c8be2157 100644 --- a/shared-module/gamepad/__init__.c +++ b/shared-module/gamepad/__init__.c @@ -49,3 +49,7 @@ void gamepad_tick(void) { gamepad_singleton->pressed |= gamepad_singleton->last & gamepad_current; gamepad_singleton->last = gamepad_current; } + +void gamepad_reset(void) { + gamepad_singleton = NULL; +} diff --git a/shared-module/gamepad/__init__.h b/shared-module/gamepad/__init__.h index eacd723669..1fae570f98 100644 --- a/shared-module/gamepad/__init__.h +++ b/shared-module/gamepad/__init__.h @@ -28,5 +28,6 @@ #define MICROPY_INCLUDED_GAMEPAD_H void gamepad_tick(void); +void gamepad_reset(void); #endif // MICROPY_INCLUDED_GAMEPAD_H From e08241de41e07ae5d7b57492a81746002c65c329 Mon Sep 17 00:00:00 2001 From: Dave Astels Date: Sun, 22 Oct 2017 23:56:10 -0400 Subject: [PATCH 013/135] Supersized Feather M0 Express for 2.x (replace the 2Mbyte SPI flash with an 8Mbyte chip) (#355) Add supersized (8Mbyte SPI flash) FeatherM0Express support --- .../boards/feather_m0_supersized/board.c | 38 +++ .../feather_m0_supersized/conf_access.h | 115 +++++++++ .../boards/feather_m0_supersized/conf_board.h | 14 ++ .../feather_m0_supersized/conf_clocks.h | 1 + .../boards/feather_m0_supersized/conf_usb.h | 220 ++++++++++++++++++ .../feather_m0_supersized/mpconfigboard.h | 34 +++ .../feather_m0_supersized/mpconfigboard.mk | 8 + .../boards/feather_m0_supersized/pins.c | 28 +++ atmel-samd/boards/flash_S25FL064L.h | 55 +++++ 9 files changed, 513 insertions(+) create mode 100644 atmel-samd/boards/feather_m0_supersized/board.c create mode 100644 atmel-samd/boards/feather_m0_supersized/conf_access.h create mode 100644 atmel-samd/boards/feather_m0_supersized/conf_board.h create mode 100644 atmel-samd/boards/feather_m0_supersized/conf_clocks.h create mode 100644 atmel-samd/boards/feather_m0_supersized/conf_usb.h create mode 100644 atmel-samd/boards/feather_m0_supersized/mpconfigboard.h create mode 100644 atmel-samd/boards/feather_m0_supersized/mpconfigboard.mk create mode 100644 atmel-samd/boards/feather_m0_supersized/pins.c create mode 100644 atmel-samd/boards/flash_S25FL064L.h diff --git a/atmel-samd/boards/feather_m0_supersized/board.c b/atmel-samd/boards/feather_m0_supersized/board.c new file mode 100644 index 0000000000..c8e20206a1 --- /dev/null +++ b/atmel-samd/boards/feather_m0_supersized/board.c @@ -0,0 +1,38 @@ +/* + * This file is part of the MicroPython project, http://micropython.org/ + * + * The MIT License (MIT) + * + * Copyright (c) 2017 Scott Shawcroft for Adafruit Industries + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +#include "boards/board.h" + +void board_init(void) +{ +} + +bool board_requests_safe_mode(void) { + return false; +} + +void reset_board(void) { +} diff --git a/atmel-samd/boards/feather_m0_supersized/conf_access.h b/atmel-samd/boards/feather_m0_supersized/conf_access.h new file mode 100644 index 0000000000..2326bfcdf2 --- /dev/null +++ b/atmel-samd/boards/feather_m0_supersized/conf_access.h @@ -0,0 +1,115 @@ +/** + * \file + * + * \brief Memory access control configuration file. + * + * Copyright (c) 2014-2015 Atmel Corporation. All rights reserved. + * + * \asf_license_start + * + * \page License + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * 3. The name of Atmel may not be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * 4. This software may only be redistributed and used in connection with an + * Atmel microcontroller product. + * + * THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE + * EXPRESSLY AND SPECIFICALLY DISCLAIMED. IN NO EVENT SHALL ATMEL BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + * \asf_license_stop + * + */ +/* + * Support and FAQ: visit Atmel Support + */ + +#ifndef _CONF_ACCESS_H_ +#define _CONF_ACCESS_H_ + +#include "compiler.h" +#include "board.h" + + +/*! \name Activation of Logical Unit Numbers + */ +//! @{ +#define LUN_0 ENABLE //!< On-Chip Virtual Memory. +#define LUN_1 DISABLE //!< AT45DBX Data Flash. +#define LUN_2 DISABLE //!< SD/MMC Card over SPI. +#define LUN_3 DISABLE //!< SD/MMC Card over MCI Slot 0. +#define LUN_4 DISABLE +#define LUN_5 DISABLE +#define LUN_6 DISABLE +#define LUN_7 DISABLE +#define LUN_USB DISABLE //!< Host Mass-Storage Memory. +//! @} + +/*! \name LUN 0 Definitions + */ +//! @{ +#define LUN_0_INCLUDE "access_vfs.h" +#define Lun_0_test_unit_ready vfs_test_unit_ready +#define Lun_0_read_capacity vfs_read_capacity +#define Lun_0_unload NULL +#define Lun_0_wr_protect vfs_wr_protect +#define Lun_0_removal vfs_removal +#define Lun_0_usb_read_10 vfs_usb_read_10 +#define Lun_0_usb_write_10 vfs_usb_write_10 +#define LUN_0_NAME "\"CircuitPython VFS[0]\"" +//! @} + +#define MEM_USB LUN_USB + +/*! \name Actions Associated with Memory Accesses + * + * Write here the action to associate with each memory access. + * + * \warning Be careful not to waste time in order not to disturb the functions. + */ +//! @{ +#define memory_start_read_action(nb_sectors) +#define memory_stop_read_action() +#define memory_start_write_action(nb_sectors) +#define memory_stop_write_action() +//! @} + +/*! \name Activation of Interface Features + */ +//! @{ +#define ACCESS_USB true //!< MEM <-> USB interface. +#define ACCESS_MEM_TO_RAM false //!< MEM <-> RAM interface. +#define ACCESS_STREAM false //!< Streaming MEM <-> MEM interface. +#define ACCESS_STREAM_RECORD false //!< Streaming MEM <-> MEM interface in record mode. +#define ACCESS_MEM_TO_MEM false //!< MEM <-> MEM interface. +#define ACCESS_CODEC false //!< Codec interface. +//! @} + +/*! \name Specific Options for Access Control + */ +//! @{ +#define GLOBAL_WR_PROTECT false //!< Management of a global write protection. +//! @} + + +#endif // _CONF_ACCESS_H_ diff --git a/atmel-samd/boards/feather_m0_supersized/conf_board.h b/atmel-samd/boards/feather_m0_supersized/conf_board.h new file mode 100644 index 0000000000..7b88c97fc2 --- /dev/null +++ b/atmel-samd/boards/feather_m0_supersized/conf_board.h @@ -0,0 +1,14 @@ +/** + * \file + * + * \brief User board configuration template + * + */ +/* + * Support and FAQ: visit Atmel Support + */ + +#ifndef CONF_BOARD_H +#define CONF_BOARD_H + +#endif // CONF_BOARD_H diff --git a/atmel-samd/boards/feather_m0_supersized/conf_clocks.h b/atmel-samd/boards/feather_m0_supersized/conf_clocks.h new file mode 100644 index 0000000000..d3f3e6496d --- /dev/null +++ b/atmel-samd/boards/feather_m0_supersized/conf_clocks.h @@ -0,0 +1 @@ +#include "conf_clocks_external_32k.h" diff --git a/atmel-samd/boards/feather_m0_supersized/conf_usb.h b/atmel-samd/boards/feather_m0_supersized/conf_usb.h new file mode 100644 index 0000000000..e5e59663c2 --- /dev/null +++ b/atmel-samd/boards/feather_m0_supersized/conf_usb.h @@ -0,0 +1,220 @@ + +#include +#include + +#include "asf/common/services/usb/class/cdc/usb_protocol_cdc.h" + +#ifndef CONF_USB_H_INCLUDED +#define CONF_USB_H_INCLUDED + +#define USB_DEVICE_MAJOR_VERSION 1 +#define USB_DEVICE_MINOR_VERSION 0 +#define USB_DEVICE_POWER 100 // Consumption on Vbus line (mA) +#define USB_DEVICE_ATTR \ + (USB_CONFIG_ATTR_BUS_POWERED) +// (USB_CONFIG_ATTR_REMOTE_WAKEUP|USB_CONFIG_ATTR_SELF_POWERED) +// (USB_CONFIG_ATTR_REMOTE_WAKEUP|USB_CONFIG_ATTR_BUS_POWERED) + +//! USB Device string definitions (Optional) +#ifndef USB_DEVICE_MANUFACTURE_NAME +# define USB_DEVICE_MANUFACTURE_NAME "Dave Astels" +#endif + +#ifndef USB_DEVICE_PRODUCT_NAME +# define USB_DEVICE_PRODUCT_NAME "Hacked Feather M0 Express with 8Mbyte SPI flash" +#endif + +#define USB_DEVICE_GET_SERIAL_NAME_POINTER serial_number +#define USB_DEVICE_GET_SERIAL_NAME_LENGTH 32 +extern char serial_number[USB_DEVICE_GET_SERIAL_NAME_LENGTH]; + +//! Control endpoint size +#define USB_DEVICE_EP_CTRL_SIZE 64 + +//! Interfaces for this device (CDC COM + CDC DATA + MSC + HID mouse + HID kbd) +#define USB_DEVICE_NB_INTERFACE 5 + +// (3 | USB_EP_DIR_IN) // CDC Notify endpoint +// (4 | USB_EP_DIR_IN) // CDC TX +// (5 | USB_EP_DIR_OUT) // CDC RX +// (1 | USB_EP_DIR_IN) // MSC IN +// (2 | USB_EP_DIR_OUT) // MSC OUT +// (6 | USB_EP_DIR_IN) // HID mouse report +// (7 | USB_EP_DIR_IN) // HID keyboard report +#define USB_DEVICE_MAX_EP 7 + +#define UDI_CDC_PORT_NB 1 +#define UDI_CDC_ENABLE_EXT(port) mp_cdc_enable(port) +extern bool mp_cdc_enable(uint8_t port); +#define UDI_CDC_DISABLE_EXT(port) mp_cdc_disable(port) +extern void mp_cdc_disable(uint8_t port); +#define UDI_CDC_LOW_RATE + +#define UDI_CDC_DEFAULT_RATE 115200 +#define UDI_CDC_DEFAULT_STOPBITS CDC_STOP_BITS_1 +#define UDI_CDC_DEFAULT_PARITY CDC_PAR_NONE +#define UDI_CDC_DEFAULT_DATABITS 8 + +#define UDI_CDC_RX_NOTIFY(port) usb_rx_notify() +void usb_rx_notify(void); +#define UDI_CDC_SET_CODING_EXT(port,cfg) usb_coding_notify(port, cfg) +void usb_coding_notify(uint8_t port, usb_cdc_line_coding_t* coding); +#define UDI_CDC_SET_DTR_EXT(port,set) usb_dtr_notify(port, set) +void usb_dtr_notify(uint8_t port, bool set); +#define UDI_CDC_SET_RTS_EXT(port,set) usb_rts_notify(port, set) +void usb_rts_notify(uint8_t port, bool set); + +/** + * USB CDC low level configuration + * In standalone these configurations are defined by the CDC module. + * For composite device, these configuration must be defined here + * @{ + */ +//! Endpoint numbers definition + +#define UDI_CDC_COMM_EP_0 (3 | USB_EP_DIR_IN) // Notify endpoint +#define UDI_CDC_DATA_EP_IN_0 (4 | USB_EP_DIR_IN) // TX +#define UDI_CDC_DATA_EP_OUT_0 (5 | USB_EP_DIR_OUT) // RX + +//! Interface numbers +#define UDI_CDC_COMM_IFACE_NUMBER_0 0 +#define UDI_CDC_DATA_IFACE_NUMBER_0 1 + +/** + * Configuration of MSC interface + * @{ + */ +//! Vendor name and Product version of MSC interface +#define UDI_MSC_GLOBAL_VENDOR_ID \ + 'A', 'T', 'M', 'E', 'L', ' ', ' ', ' ' +#define UDI_MSC_GLOBAL_PRODUCT_VERSION \ + '1', '.', '0', '0' + +//! Interface callback definition +#define UDI_MSC_ENABLE_EXT() mp_msc_enable() +extern bool mp_msc_enable(void); +#define UDI_MSC_DISABLE_EXT() mp_msc_disable() +extern void mp_msc_disable(void); + +//! Enable id string of interface to add an extra USB string +#define UDI_MSC_STRING_ID 5 + +/** + * USB MSC low level configuration + * In standalone these configurations are defined by the MSC module. + * For composite device, these configuration must be defined here + * @{ + */ +//! Endpoint numbers definition +#define UDI_MSC_EP_IN (1 | USB_EP_DIR_IN) +#define UDI_MSC_EP_OUT (2 | USB_EP_DIR_OUT) + +//! Interface number +#define UDI_MSC_IFACE_NUMBER 2 +/** + * Configuration of HID Mouse interface + * @{ + */ +//! Interface callback definition +#define UDI_HID_MOUSE_ENABLE_EXT() mp_mouse_enable() +extern bool mp_mouse_enable(void); +#define UDI_HID_MOUSE_DISABLE_EXT() mp_mouse_disable() +extern void mp_mouse_disable(void); + +//! Enable id string of interface to add an extra USB string +#define UDI_HID_MOUSE_STRING_ID 6 + +/** + * USB HID Mouse low level configuration + * In standalone these configurations are defined by the HID Mouse module. + * For composite device, these configuration must be defined here + * @{ + */ +//! Endpoint numbers definition +#define UDI_HID_MOUSE_EP_IN (6 | USB_EP_DIR_IN) + +//! Interface number +#define UDI_HID_MOUSE_IFACE_NUMBER 3 +//@} +//@} + +/** + * Configuration of HID Keyboard interface + * @{ + */ +//! Interface callback definition +#define UDI_HID_KBD_ENABLE_EXT() mp_keyboard_enable() +extern bool mp_keyboard_enable(void); +#define UDI_HID_KBD_DISABLE_EXT() mp_keyboard_disable() +extern void mp_keyboard_disable(void); +#define UDI_HID_KBD_CHANGE_LED(value) mp_keyboard_led(value) +extern void mp_keyboard_led(uint8_t); + +//! Enable id string of interface to add an extra USB string +#define UDI_HID_KBD_STRING_ID 7 + +/** + * USB HID Keyboard low level configuration + * In standalone these configurations are defined by the HID Keyboard module. + * For composite device, these configuration must be defined here + * @{ + */ +//! Endpoint numbers definition +#define UDI_HID_KBD_EP_IN (7 | USB_EP_DIR_IN) + +//! Interface number +#define UDI_HID_KBD_IFACE_NUMBER 4 + +/** + * Description of Composite Device + * @{ + */ +//! USB Interfaces descriptor structure +#define UDI_COMPOSITE_DESC_T \ + usb_iad_desc_t udi_cdc_iad; \ + udi_cdc_comm_desc_t udi_cdc_comm; \ + udi_cdc_data_desc_t udi_cdc_data; \ + udi_msc_desc_t udi_msc; \ + udi_hid_mouse_desc_t udi_hid_mouse; \ + udi_hid_kbd_desc_t udi_hid_kbd + +//! USB Interfaces descriptor value for Full Speed +#define UDI_COMPOSITE_DESC_FS \ + .udi_cdc_iad = UDI_CDC_IAD_DESC_0, \ + .udi_cdc_comm = UDI_CDC_COMM_DESC_0, \ + .udi_cdc_data = UDI_CDC_DATA_DESC_0_FS, \ + .udi_msc = UDI_MSC_DESC_FS, \ + .udi_hid_mouse = UDI_HID_MOUSE_DESC, \ + .udi_hid_kbd = UDI_HID_KBD_DESC + +//! USB Interfaces descriptor value for High Speed +#define UDI_COMPOSITE_DESC_HS \ + .udi_cdc_iad = UDI_CDC_IAD_DESC_0, \ + .udi_cdc_comm = UDI_CDC_COMM_DESC_0, \ + .udi_cdc_data = UDI_CDC_DATA_DESC_0_HS, \ + .udi_msc = UDI_MSC_DESC_HS, \ + .udi_hid_mouse = UDI_HID_MOUSE_DESC, \ + .udi_hid_kbd = UDI_HID_KBD_DESC + +//! USB Interface APIs +#define UDI_COMPOSITE_API \ + &udi_api_cdc_comm, \ + &udi_api_cdc_data, \ + &udi_api_msc, \ + &udi_api_hid_mouse, \ + &udi_api_hid_kbd +//@} + +/** + * USB Device Driver Configuration + * @{ + */ +//@} + +//! The includes of classes and other headers must be done at the end of this file to avoid compile error +#include "udi_cdc.h" +#include "udi_msc.h" +#include "udi_hid_mouse.h" +#include "udi_hid_kbd.h" + +#endif diff --git a/atmel-samd/boards/feather_m0_supersized/mpconfigboard.h b/atmel-samd/boards/feather_m0_supersized/mpconfigboard.h new file mode 100644 index 0000000000..8eb59d9a0f --- /dev/null +++ b/atmel-samd/boards/feather_m0_supersized/mpconfigboard.h @@ -0,0 +1,34 @@ +/* Adafruit Feather M0 Express with an 8MB SPI flash instead of the usual 2MB */ + +#define USB_REPL + +#define MICROPY_HW_BOARD_NAME "Hacked Feather M0 Express with 8Mbyte SPI flash" +#define MICROPY_HW_MCU_NAME "samd21g18" + +#define MICROPY_HW_NEOPIXEL (&pin_PA06) + +// Salae reads 12mhz which is the limit even though we set it to the safer 8mhz. +#define SPI_FLASH_BAUDRATE (8000000) + +#define SPI_FLASH_MUX_SETTING SPI_SIGNAL_MUX_SETTING_C +#define SPI_FLASH_PAD0_PINMUX PINMUX_PA08D_SERCOM2_PAD0 // MOSI +// Use default pinmux for the chip select since we manage it ourselves. +#define SPI_FLASH_PAD1_PINMUX PINMUX_PA09D_SERCOM2_PAD1 // SCK +#define SPI_FLASH_PAD2_PINMUX PINMUX_PA14C_SERCOM2_PAD2 // MISO +#define SPI_FLASH_PAD3_PINMUX PINMUX_UNUSED // SCK +#define SPI_FLASH_SERCOM SERCOM2 + +#define SPI_FLASH_CS PIN_PA13 + +#define MICROPY_PORT_A (PORT_PA06 | PORT_PA08 | PORT_PA09 | PORT_PA14 | PORT_PA13 | PORT_PA14 | PORT_PA24 | PORT_PA25) +#define MICROPY_PORT_B ( 0 ) + +#include "spi_flash.h" + +// If you change this, then make sure to update the linker scripts as well to +// make sure you don't overwrite code. +#define CIRCUITPY_INTERNAL_NVM_SIZE 256 + +#define BOARD_FLASH_SIZE (0x00040000 - 0x2000 - CIRCUITPY_INTERNAL_NVM_SIZE) + +#include "flash_S25FL064L.h" diff --git a/atmel-samd/boards/feather_m0_supersized/mpconfigboard.mk b/atmel-samd/boards/feather_m0_supersized/mpconfigboard.mk new file mode 100644 index 0000000000..c3d413f358 --- /dev/null +++ b/atmel-samd/boards/feather_m0_supersized/mpconfigboard.mk @@ -0,0 +1,8 @@ +LD_FILE = boards/samd21x18-bootloader-external-flash.ld + +USB_VID = 0x239A +USB_PID = 0x801b + +SPI_FLASH_FILESYSTEM = 1 + +CHIP_VARIANT = SAMD21G18A diff --git a/atmel-samd/boards/feather_m0_supersized/pins.c b/atmel-samd/boards/feather_m0_supersized/pins.c new file mode 100644 index 0000000000..c5c70ee5dc --- /dev/null +++ b/atmel-samd/boards/feather_m0_supersized/pins.c @@ -0,0 +1,28 @@ +#include "samd21_pins.h" + +STATIC const mp_rom_map_elem_t board_global_dict_table[] = { + { MP_ROM_QSTR(MP_QSTR_A0), MP_ROM_PTR(&pin_PA02) }, + { MP_ROM_QSTR(MP_QSTR_A1), MP_ROM_PTR(&pin_PB08) }, + { MP_ROM_QSTR(MP_QSTR_A2), MP_ROM_PTR(&pin_PB09) }, + { MP_ROM_QSTR(MP_QSTR_A3), MP_ROM_PTR(&pin_PA04) }, + { MP_ROM_QSTR(MP_QSTR_A4), MP_ROM_PTR(&pin_PA05) }, + { MP_ROM_QSTR(MP_QSTR_A5), MP_ROM_PTR(&pin_PB02) }, + { MP_ROM_QSTR(MP_QSTR_SCK), MP_ROM_PTR(&pin_PB11) }, + { MP_ROM_QSTR(MP_QSTR_MOSI), MP_ROM_PTR(&pin_PB10) }, + { MP_ROM_QSTR(MP_QSTR_MISO), MP_ROM_PTR(&pin_PA12) }, + { MP_ROM_QSTR(MP_QSTR_D0), MP_ROM_PTR(&pin_PA11) }, + { MP_ROM_QSTR(MP_QSTR_RX), MP_ROM_PTR(&pin_PA11) }, + { MP_ROM_QSTR(MP_QSTR_D1), MP_ROM_PTR(&pin_PA10) }, + { MP_ROM_QSTR(MP_QSTR_TX), MP_ROM_PTR(&pin_PA10) }, + { MP_ROM_QSTR(MP_QSTR_SDA), MP_ROM_PTR(&pin_PA22) }, + { MP_ROM_QSTR(MP_QSTR_SCL), MP_ROM_PTR(&pin_PA23) }, + { MP_ROM_QSTR(MP_QSTR_D5), MP_ROM_PTR(&pin_PA15) }, + { MP_ROM_QSTR(MP_QSTR_D6), MP_ROM_PTR(&pin_PA20) }, + { MP_ROM_QSTR(MP_QSTR_D9), MP_ROM_PTR(&pin_PA07) }, + { MP_ROM_QSTR(MP_QSTR_D10), MP_ROM_PTR(&pin_PA18) }, + { MP_ROM_QSTR(MP_QSTR_D11), MP_ROM_PTR(&pin_PA16) }, + { MP_ROM_QSTR(MP_QSTR_D12), MP_ROM_PTR(&pin_PA19) }, + { MP_ROM_QSTR(MP_QSTR_D13), MP_ROM_PTR(&pin_PA17) }, + { MP_ROM_QSTR(MP_QSTR_NEOPIXEL), MP_ROM_PTR(&pin_PA06) }, +}; +MP_DEFINE_CONST_DICT(board_module_globals, board_global_dict_table); diff --git a/atmel-samd/boards/flash_S25FL064L.h b/atmel-samd/boards/flash_S25FL064L.h new file mode 100644 index 0000000000..40cfa4cf0a --- /dev/null +++ b/atmel-samd/boards/flash_S25FL064L.h @@ -0,0 +1,55 @@ +/* + * This file is part of the MicroPython project, http://micropython.org/ + * + * The MIT License (MIT) + * + * Copyright (c) 2017 Scott Shawcroft for Adafruit Industries + * Copyright (c) 2017 Dave Astels + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +#ifndef MICROPY_INCLUDED_ATMEL_SAMD_BOARD_FLASH_S25FL064L_H +#define MICROPY_INCLUDED_ATMEL_SAMD_BOARD_FLASH_S25FL064L_H + +// Settings for the Cypress (was Spansion) S25FL064L 8MiB SPI flash. +// Datasheet: http://www.cypress.com/file/316661/download + +// The total flash size in bytes. +#define SPI_FLASH_TOTAL_SIZE (1 << 23) // 8 MiB + +// The size of the smallest erase unit thats erased with command 0x20. +#define SPI_FLASH_ERASE_SIZE (1 << 12) // 4 KiB + +// The size of a page that is programmed with page program command 0x02. +#define SPI_FLASH_PAGE_SIZE (256) // 256 bytes + +// These are the first three response bytes to the JEDEC ID command 0x9f that is +// used to confirm we're talking to the flash we expect. +#ifndef SPI_FLASH_JEDEC_MANUFACTURER +#define SPI_FLASH_JEDEC_MANUFACTURER 0x01 +#define SPI_FLASH_SECTOR_PROTECTION false +#else +#define SPI_FLASH_JEDEC_MANUFACTURER_2 0x013 +#define SPI_FLASH_SECTOR_PROTECTION_2 false +#endif +#define SPI_FLASH_JEDEC_MEMORY_TYPE 0x60 +#define SPI_FLASH_JEDEC_CAPACITY 0x17 + +#endif // MICROPY_INCLUDED_ATMEL_SAMD_BOARD_FLASH_S25FL216K_H From bd7abcda970e4e6ecd0f64621536870b49185594 Mon Sep 17 00:00:00 2001 From: Scott Shawcroft Date: Wed, 25 Oct 2017 14:28:23 -0700 Subject: [PATCH 014/135] shared-bindings: Check that I2C and SPI reads and writes are given a buffer of at least 1. (#370) Fixes #358 --- shared-bindings/busio/I2C.c | 8 ++++++++ shared-bindings/busio/SPI.c | 8 ++++++++ 2 files changed, 16 insertions(+) diff --git a/shared-bindings/busio/I2C.c b/shared-bindings/busio/I2C.c index cdc960f803..dc19970344 100644 --- a/shared-bindings/busio/I2C.c +++ b/shared-bindings/busio/I2C.c @@ -201,6 +201,10 @@ STATIC mp_obj_t busio_i2c_readfrom_into(size_t n_args, const mp_obj_t *pos_args, int32_t start = args[ARG_start].u_int; uint32_t length = bufinfo.len; normalize_buffer_bounds(&start, args[ARG_end].u_int, &length); + if (length == 0) { + mp_raise_ValueError("Buffer must be at least length 1"); + } + uint8_t status = common_hal_busio_i2c_read(self, args[ARG_address].u_int, ((uint8_t*)bufinfo.buf) + start, length); if (status != 0) { mp_raise_OSError(status); @@ -250,6 +254,10 @@ STATIC mp_obj_t busio_i2c_writeto(size_t n_args, const mp_obj_t *pos_args, mp_ma uint32_t length = bufinfo.len; normalize_buffer_bounds(&start, args[ARG_end].u_int, &length); + if (length == 0) { + mp_raise_ValueError("Buffer must be at least length 1"); + } + // do the transfer uint8_t status = common_hal_busio_i2c_write(self, args[ARG_address].u_int, ((uint8_t*) bufinfo.buf) + start, length, args[ARG_stop].u_bool); diff --git a/shared-bindings/busio/SPI.c b/shared-bindings/busio/SPI.c index 12f888f23d..dc136564d9 100644 --- a/shared-bindings/busio/SPI.c +++ b/shared-bindings/busio/SPI.c @@ -231,6 +231,10 @@ STATIC mp_obj_t busio_spi_write(size_t n_args, const mp_obj_t *pos_args, mp_map_ uint32_t length = bufinfo.len; normalize_buffer_bounds(&start, args[ARG_end].u_int, &length); + if (length == 0) { + mp_raise_ValueError("Buffer must be at least length 1"); + } + bool ok = common_hal_busio_spi_write(self, ((uint8_t*)bufinfo.buf) + start, length); if (!ok) { mp_raise_OSError(MP_EIO); @@ -269,6 +273,10 @@ STATIC mp_obj_t busio_spi_readinto(size_t n_args, const mp_obj_t *pos_args, mp_m uint32_t length = bufinfo.len; normalize_buffer_bounds(&start, args[ARG_end].u_int, &length); + if (length == 0) { + mp_raise_ValueError("Buffer must be at least length 1"); + } + bool ok = common_hal_busio_spi_read(self, ((uint8_t*)bufinfo.buf) + start, length, args[ARG_write_value].u_int); if (!ok) { mp_raise_OSError(MP_EIO); From f738996164fc270015fdb53ee38b24f7823cbbd8 Mon Sep 17 00:00:00 2001 From: Dan Halbert Date: Mon, 30 Oct 2017 19:32:03 -0400 Subject: [PATCH 015/135] Allow writing buffer of length zero to I2C device; it can be used to poll for existence. --- shared-bindings/busio/I2C.c | 8 ++++---- shared-bindings/busio/SPI.c | 2 ++ 2 files changed, 6 insertions(+), 4 deletions(-) diff --git a/shared-bindings/busio/I2C.c b/shared-bindings/busio/I2C.c index dc19970344..b0954d6c8a 100644 --- a/shared-bindings/busio/I2C.c +++ b/shared-bindings/busio/I2C.c @@ -171,6 +171,7 @@ MP_DEFINE_CONST_FUN_OBJ_1(busio_i2c_unlock_obj, busio_i2c_obj_unlock); //| //| Read into ``buffer`` from the slave specified by ``address``. //| The number of bytes read will be the length of ``buffer``. +//| At least one byte must be read. //| //| If ``start`` or ``end`` is provided, then the buffer will be sliced //| as if ``buffer[start:end]``. This will not cause an allocation like @@ -223,6 +224,9 @@ MP_DEFINE_CONST_FUN_OBJ_KW(busio_i2c_readfrom_into_obj, 3, busio_i2c_readfrom_in //| as if ``buffer[start:end]``. This will not cause an allocation like //| ``buffer[start:end]`` will so it saves memory. //| +//| Writing a buffer or slice of length zero is permitted, as it can be used +//| to poll for the existence of a device. +//| //| :param int address: 7-bit device address //| :param bytearray buffer: buffer containing the bytes to write //| :param int start: Index to start writing from @@ -254,10 +258,6 @@ STATIC mp_obj_t busio_i2c_writeto(size_t n_args, const mp_obj_t *pos_args, mp_ma uint32_t length = bufinfo.len; normalize_buffer_bounds(&start, args[ARG_end].u_int, &length); - if (length == 0) { - mp_raise_ValueError("Buffer must be at least length 1"); - } - // do the transfer uint8_t status = common_hal_busio_i2c_write(self, args[ARG_address].u_int, ((uint8_t*) bufinfo.buf) + start, length, args[ARG_stop].u_bool); diff --git a/shared-bindings/busio/SPI.c b/shared-bindings/busio/SPI.c index dc136564d9..add541aa70 100644 --- a/shared-bindings/busio/SPI.c +++ b/shared-bindings/busio/SPI.c @@ -207,6 +207,7 @@ MP_DEFINE_CONST_FUN_OBJ_1(busio_spi_unlock_obj, busio_spi_obj_unlock); //| .. method:: SPI.write(buffer, \*, start=0, end=len(buffer)) //| //| Write the data contained in ``buf``. Requires the SPI being locked. +//| At least one byte must be written. //| //| :param bytearray buffer: buffer containing the bytes to write //| :param int start: Index to start writing from @@ -247,6 +248,7 @@ MP_DEFINE_CONST_FUN_OBJ_KW(busio_spi_write_obj, 2, busio_spi_write); //| .. method:: SPI.readinto(buffer, \*, start=0, end=len(buffer), write_value=0) //| //| Read into the buffer specified by ``buf`` while writing zeroes. Requires the SPI being locked. +//| At least one byte must be read. //| //| :param bytearray buffer: buffer to write into //| :param int start: Index to start writing at From c066e4da8b515c39ffe18a0fc7bd31ef5a68b0db Mon Sep 17 00:00:00 2001 From: Radomir Dopieralski Date: Wed, 1 Nov 2017 22:38:16 +0100 Subject: [PATCH 016/135] Add board definition for the uGame handheld console This is a board definition for the uGame project: https://hackaday.io/project/27629-game uGame is a small handheld game console programmable with CircuitPython. The hardware part of the project is pretty much stable by now. --- atmel-samd/boards/ugame/board.c | 37 ++++ atmel-samd/boards/ugame/conf_access.h | 115 ++++++++++++ atmel-samd/boards/ugame/conf_board.h | 14 ++ atmel-samd/boards/ugame/conf_clocks.h | 1 + atmel-samd/boards/ugame/conf_usb.h | 221 +++++++++++++++++++++++ atmel-samd/boards/ugame/mpconfigboard.h | 48 +++++ atmel-samd/boards/ugame/mpconfigboard.mk | 10 + atmel-samd/boards/ugame/pins.c | 18 ++ 8 files changed, 464 insertions(+) create mode 100644 atmel-samd/boards/ugame/board.c create mode 100644 atmel-samd/boards/ugame/conf_access.h create mode 100644 atmel-samd/boards/ugame/conf_board.h create mode 100644 atmel-samd/boards/ugame/conf_clocks.h create mode 100644 atmel-samd/boards/ugame/conf_usb.h create mode 100644 atmel-samd/boards/ugame/mpconfigboard.h create mode 100644 atmel-samd/boards/ugame/mpconfigboard.mk create mode 100644 atmel-samd/boards/ugame/pins.c diff --git a/atmel-samd/boards/ugame/board.c b/atmel-samd/boards/ugame/board.c new file mode 100644 index 0000000000..d7e856d611 --- /dev/null +++ b/atmel-samd/boards/ugame/board.c @@ -0,0 +1,37 @@ +/* + * This file is part of the MicroPython project, http://micropython.org/ + * + * The MIT License (MIT) + * + * Copyright (c) 2017 Scott Shawcroft for Adafruit Industries + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +#include "boards/board.h" + +void board_init(void) { +} + +bool board_requests_safe_mode(void) { + return false; +} + +void reset_board(void) { +} diff --git a/atmel-samd/boards/ugame/conf_access.h b/atmel-samd/boards/ugame/conf_access.h new file mode 100644 index 0000000000..2326bfcdf2 --- /dev/null +++ b/atmel-samd/boards/ugame/conf_access.h @@ -0,0 +1,115 @@ +/** + * \file + * + * \brief Memory access control configuration file. + * + * Copyright (c) 2014-2015 Atmel Corporation. All rights reserved. + * + * \asf_license_start + * + * \page License + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * 3. The name of Atmel may not be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * 4. This software may only be redistributed and used in connection with an + * Atmel microcontroller product. + * + * THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE + * EXPRESSLY AND SPECIFICALLY DISCLAIMED. IN NO EVENT SHALL ATMEL BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + * \asf_license_stop + * + */ +/* + * Support and FAQ: visit Atmel Support + */ + +#ifndef _CONF_ACCESS_H_ +#define _CONF_ACCESS_H_ + +#include "compiler.h" +#include "board.h" + + +/*! \name Activation of Logical Unit Numbers + */ +//! @{ +#define LUN_0 ENABLE //!< On-Chip Virtual Memory. +#define LUN_1 DISABLE //!< AT45DBX Data Flash. +#define LUN_2 DISABLE //!< SD/MMC Card over SPI. +#define LUN_3 DISABLE //!< SD/MMC Card over MCI Slot 0. +#define LUN_4 DISABLE +#define LUN_5 DISABLE +#define LUN_6 DISABLE +#define LUN_7 DISABLE +#define LUN_USB DISABLE //!< Host Mass-Storage Memory. +//! @} + +/*! \name LUN 0 Definitions + */ +//! @{ +#define LUN_0_INCLUDE "access_vfs.h" +#define Lun_0_test_unit_ready vfs_test_unit_ready +#define Lun_0_read_capacity vfs_read_capacity +#define Lun_0_unload NULL +#define Lun_0_wr_protect vfs_wr_protect +#define Lun_0_removal vfs_removal +#define Lun_0_usb_read_10 vfs_usb_read_10 +#define Lun_0_usb_write_10 vfs_usb_write_10 +#define LUN_0_NAME "\"CircuitPython VFS[0]\"" +//! @} + +#define MEM_USB LUN_USB + +/*! \name Actions Associated with Memory Accesses + * + * Write here the action to associate with each memory access. + * + * \warning Be careful not to waste time in order not to disturb the functions. + */ +//! @{ +#define memory_start_read_action(nb_sectors) +#define memory_stop_read_action() +#define memory_start_write_action(nb_sectors) +#define memory_stop_write_action() +//! @} + +/*! \name Activation of Interface Features + */ +//! @{ +#define ACCESS_USB true //!< MEM <-> USB interface. +#define ACCESS_MEM_TO_RAM false //!< MEM <-> RAM interface. +#define ACCESS_STREAM false //!< Streaming MEM <-> MEM interface. +#define ACCESS_STREAM_RECORD false //!< Streaming MEM <-> MEM interface in record mode. +#define ACCESS_MEM_TO_MEM false //!< MEM <-> MEM interface. +#define ACCESS_CODEC false //!< Codec interface. +//! @} + +/*! \name Specific Options for Access Control + */ +//! @{ +#define GLOBAL_WR_PROTECT false //!< Management of a global write protection. +//! @} + + +#endif // _CONF_ACCESS_H_ diff --git a/atmel-samd/boards/ugame/conf_board.h b/atmel-samd/boards/ugame/conf_board.h new file mode 100644 index 0000000000..7b88c97fc2 --- /dev/null +++ b/atmel-samd/boards/ugame/conf_board.h @@ -0,0 +1,14 @@ +/** + * \file + * + * \brief User board configuration template + * + */ +/* + * Support and FAQ: visit Atmel Support + */ + +#ifndef CONF_BOARD_H +#define CONF_BOARD_H + +#endif // CONF_BOARD_H diff --git a/atmel-samd/boards/ugame/conf_clocks.h b/atmel-samd/boards/ugame/conf_clocks.h new file mode 100644 index 0000000000..9e4f7876be --- /dev/null +++ b/atmel-samd/boards/ugame/conf_clocks.h @@ -0,0 +1 @@ +#include "conf_clocks_crystalless.h" diff --git a/atmel-samd/boards/ugame/conf_usb.h b/atmel-samd/boards/ugame/conf_usb.h new file mode 100644 index 0000000000..b881ed1499 --- /dev/null +++ b/atmel-samd/boards/ugame/conf_usb.h @@ -0,0 +1,221 @@ + +#include +#include + +#include "asf/common/services/usb/class/cdc/usb_protocol_cdc.h" + +#ifndef CONF_USB_H_INCLUDED +#define CONF_USB_H_INCLUDED + +#define USB_DEVICE_MAJOR_VERSION 1 +#define USB_DEVICE_MINOR_VERSION 0 +#define USB_DEVICE_POWER 100 // Consumption on Vbus line (mA) +#define USB_DEVICE_ATTR \ + (USB_CONFIG_ATTR_BUS_POWERED) +// (USB_CONFIG_ATTR_REMOTE_WAKEUP|USB_CONFIG_ATTR_SELF_POWERED) +// (USB_CONFIG_ATTR_REMOTE_WAKEUP|USB_CONFIG_ATTR_BUS_POWERED) + +//! USB Device string definitions (Optional) +#ifndef USB_DEVICE_MANUFACTURE_NAME +# define USB_DEVICE_MANUFACTURE_NAME "Radomir Dopieralski" +#endif + +#ifndef USB_DEVICE_PRODUCT_NAME +# define USB_DEVICE_PRODUCT_NAME "uGame" +#endif +// #define USB_DEVICE_SERIAL_NAME "12...EF" +#define USB_DEVICE_GET_SERIAL_NAME_POINTER serial_number +#define USB_DEVICE_GET_SERIAL_NAME_LENGTH 32 +extern char serial_number[USB_DEVICE_GET_SERIAL_NAME_LENGTH]; + +//! Control endpoint size +#define USB_DEVICE_EP_CTRL_SIZE 64 + +//! Interfaces for this device (CDC COM + CDC DATA + MSC + HID mouse + HID kbd) +#define USB_DEVICE_NB_INTERFACE 5 + +// (3 | USB_EP_DIR_IN) // CDC Notify endpoint +// (4 | USB_EP_DIR_IN) // CDC TX +// (5 | USB_EP_DIR_OUT) // CDC RX +// (1 | USB_EP_DIR_IN) // MSC IN +// (2 | USB_EP_DIR_OUT) // MSC OUT +// (6 | USB_EP_DIR_IN) // HID mouse report +// (7 | USB_EP_DIR_IN) // HID keyboard report +#define USB_DEVICE_MAX_EP 7 + +#define UDI_CDC_PORT_NB 1 +#define UDI_CDC_ENABLE_EXT(port) mp_cdc_enable(port) +extern bool mp_cdc_enable(uint8_t port); +#define UDI_CDC_DISABLE_EXT(port) mp_cdc_disable(port) +extern void mp_cdc_disable(uint8_t port); +#define UDI_CDC_LOW_RATE + +#define UDI_CDC_DEFAULT_RATE 115200 +#define UDI_CDC_DEFAULT_STOPBITS CDC_STOP_BITS_1 +#define UDI_CDC_DEFAULT_PARITY CDC_PAR_NONE +#define UDI_CDC_DEFAULT_DATABITS 8 + +#define UDI_CDC_RX_NOTIFY(port) usb_rx_notify() +void usb_rx_notify(void); + +#define UDI_CDC_SET_CODING_EXT(port,cfg) usb_coding_notify(port, cfg) +void usb_coding_notify(uint8_t port, usb_cdc_line_coding_t* coding); +#define UDI_CDC_SET_DTR_EXT(port,set) usb_dtr_notify(port, set) +void usb_dtr_notify(uint8_t port, bool set); +#define UDI_CDC_SET_RTS_EXT(port,set) usb_rts_notify(port, set) +void usb_rts_notify(uint8_t port, bool set); + +/** + * USB CDC low level configuration + * In standalone these configurations are defined by the CDC module. + * For composite device, these configuration must be defined here + * @{ + */ +//! Endpoint numbers definition + +#define UDI_CDC_COMM_EP_0 (3 | USB_EP_DIR_IN) // Notify endpoint +#define UDI_CDC_DATA_EP_IN_0 (4 | USB_EP_DIR_IN) // TX +#define UDI_CDC_DATA_EP_OUT_0 (5 | USB_EP_DIR_OUT) // RX + +//! Interface numbers +#define UDI_CDC_COMM_IFACE_NUMBER_0 0 +#define UDI_CDC_DATA_IFACE_NUMBER_0 1 + +/** + * Configuration of MSC interface + * @{ + */ +//! Vendor name and Product version of MSC interface +#define UDI_MSC_GLOBAL_VENDOR_ID \ + 'A', 'T', 'M', 'E', 'L', ' ', ' ', ' ' +#define UDI_MSC_GLOBAL_PRODUCT_VERSION \ + '1', '.', '0', '0' + +//! Interface callback definition +#define UDI_MSC_ENABLE_EXT() mp_msc_enable() +extern bool mp_msc_enable(void); +#define UDI_MSC_DISABLE_EXT() mp_msc_disable() +extern void mp_msc_disable(void); + +//! Enable id string of interface to add an extra USB string +#define UDI_MSC_STRING_ID 5 + +/** + * USB MSC low level configuration + * In standalone these configurations are defined by the MSC module. + * For composite device, these configuration must be defined here + * @{ + */ +//! Endpoint numbers definition +#define UDI_MSC_EP_IN (1 | USB_EP_DIR_IN) +#define UDI_MSC_EP_OUT (2 | USB_EP_DIR_OUT) + +//! Interface number +#define UDI_MSC_IFACE_NUMBER 2 +/** + * Configuration of HID Mouse interface + * @{ + */ +//! Interface callback definition +#define UDI_HID_MOUSE_ENABLE_EXT() mp_mouse_enable() +extern bool mp_mouse_enable(void); +#define UDI_HID_MOUSE_DISABLE_EXT() mp_mouse_disable() +extern void mp_mouse_disable(void); + +//! Enable id string of interface to add an extra USB string +#define UDI_HID_MOUSE_STRING_ID 6 + +/** + * USB HID Mouse low level configuration + * In standalone these configurations are defined by the HID Mouse module. + * For composite device, these configuration must be defined here + * @{ + */ +//! Endpoint numbers definition +#define UDI_HID_MOUSE_EP_IN (6 | USB_EP_DIR_IN) + +//! Interface number +#define UDI_HID_MOUSE_IFACE_NUMBER 3 +//@} +//@} + +/** + * Configuration of HID Keyboard interface + * @{ + */ +//! Interface callback definition +#define UDI_HID_KBD_ENABLE_EXT() mp_keyboard_enable() +extern bool mp_keyboard_enable(void); +#define UDI_HID_KBD_DISABLE_EXT() mp_keyboard_disable() +extern void mp_keyboard_disable(void); +#define UDI_HID_KBD_CHANGE_LED(value) mp_keyboard_led(value) +extern void mp_keyboard_led(uint8_t); + +//! Enable id string of interface to add an extra USB string +#define UDI_HID_KBD_STRING_ID 7 + +/** + * USB HID Keyboard low level configuration + * In standalone these configurations are defined by the HID Keyboard module. + * For composite device, these configuration must be defined here + * @{ + */ +//! Endpoint numbers definition +#define UDI_HID_KBD_EP_IN (7 | USB_EP_DIR_IN) + +//! Interface number +#define UDI_HID_KBD_IFACE_NUMBER 4 + +/** + * Description of Composite Device + * @{ + */ +//! USB Interfaces descriptor structure +#define UDI_COMPOSITE_DESC_T \ + usb_iad_desc_t udi_cdc_iad; \ + udi_cdc_comm_desc_t udi_cdc_comm; \ + udi_cdc_data_desc_t udi_cdc_data; \ + udi_msc_desc_t udi_msc; \ + udi_hid_mouse_desc_t udi_hid_mouse; \ + udi_hid_kbd_desc_t udi_hid_kbd + +//! USB Interfaces descriptor value for Full Speed +#define UDI_COMPOSITE_DESC_FS \ + .udi_cdc_iad = UDI_CDC_IAD_DESC_0, \ + .udi_cdc_comm = UDI_CDC_COMM_DESC_0, \ + .udi_cdc_data = UDI_CDC_DATA_DESC_0_FS, \ + .udi_msc = UDI_MSC_DESC_FS, \ + .udi_hid_mouse = UDI_HID_MOUSE_DESC, \ + .udi_hid_kbd = UDI_HID_KBD_DESC + +//! USB Interfaces descriptor value for High Speed +#define UDI_COMPOSITE_DESC_HS \ + .udi_cdc_iad = UDI_CDC_IAD_DESC_0, \ + .udi_cdc_comm = UDI_CDC_COMM_DESC_0, \ + .udi_cdc_data = UDI_CDC_DATA_DESC_0_HS, \ + .udi_msc = UDI_MSC_DESC_HS, \ + .udi_hid_mouse = UDI_HID_MOUSE_DESC, \ + .udi_hid_kbd = UDI_HID_KBD_DESC + +//! USB Interface APIs +#define UDI_COMPOSITE_API \ + &udi_api_cdc_comm, \ + &udi_api_cdc_data, \ + &udi_api_msc, \ + &udi_api_hid_mouse, \ + &udi_api_hid_kbd +//@} + +/** + * USB Device Driver Configuration + * @{ + */ +//@} + +//! The includes of classes and other headers must be done at the end of this file to avoid compile error +#include "udi_cdc.h" +#include "udi_msc.h" +#include "udi_hid_mouse.h" +#include "udi_hid_kbd.h" + +#endif diff --git a/atmel-samd/boards/ugame/mpconfigboard.h b/atmel-samd/boards/ugame/mpconfigboard.h new file mode 100644 index 0000000000..17baf9b0f8 --- /dev/null +++ b/atmel-samd/boards/ugame/mpconfigboard.h @@ -0,0 +1,48 @@ +#define USB_REPL + +#define MICROPY_HW_BOARD_NAME "uGame" +#define MICROPY_HW_MCU_NAME "samd21e18" + +#if 1 +// Salae reads 12mhz which is the limit even though we set it to the +// safer 8mhz. +#define SPI_FLASH_BAUDRATE (8000000) + +#define SPI_FLASH_MUX_SETTING SPI_SIGNAL_MUX_SETTING_D +#define SPI_FLASH_PAD0_PINMUX PINMUX_PA16D_SERCOM3_PAD0 // MOSI +#define SPI_FLASH_PAD1_PINMUX PINMUX_PA17D_SERCOM3_PAD1 // SCK +#define SPI_FLASH_PAD2_PINMUX PINMUX_UNUSED // Use default pinmux for the chip + // select since we manage it + // ourselves. +#define SPI_FLASH_PAD3_PINMUX PINMUX_PA19D_SERCOM3_PAD3 // MISO +#define SPI_FLASH_SERCOM SERCOM3 + +#define SPI_FLASH_CS PIN_PA11 + +#define MICROPY_PORT_A (PORT_PA11 | PORT_PA16 |\ + PORT_PA17 | PORT_PA18 | PORT_PA19 | PORT_PA24 |\ + PORT_PA25) +#define MICROPY_PORT_B (0) + +#define CALIBRATE_CRYSTALLESS 1 + +#include "spi_flash.h" + +#define CIRCUITPY_INTERNAL_NVM_SIZE 256 +#define BOARD_FLASH_SIZE (0x00040000 - 0x2000 - CIRCUITPY_INTERNAL_NVM_SIZE) + +//#include "flash_W25Q32BV.h" +#include "flash_S25FL216K.h" + +#else + +#define MICROPY_PORT_A (PORT_PA24 | PORT_PA25) +#define MICROPY_PORT_B (0) + +#include "internal_flash.h" + +#define CIRCUITPY_INTERNAL_NVM_SIZE 0 +#define BOARD_FLASH_SIZE (0x00040000 - 0x2000 - 0x010000) + +#endif + diff --git a/atmel-samd/boards/ugame/mpconfigboard.mk b/atmel-samd/boards/ugame/mpconfigboard.mk new file mode 100644 index 0000000000..1fa7e99fd6 --- /dev/null +++ b/atmel-samd/boards/ugame/mpconfigboard.mk @@ -0,0 +1,10 @@ +LD_FILE = boards/samd21x18-bootloader-external-flash-crystalless.ld +#LD_FILE = boards/samd21x18-bootloader.ld +USB_VID = 0x239A +USB_PID = 0x801F + +#FLASH_IMPL = internal_flash.c +FLASH_IMPL = spi_flash.c + +CHIP_VARIANT = SAMD21E18A +CHIP_FAMILY = samd21 diff --git a/atmel-samd/boards/ugame/pins.c b/atmel-samd/boards/ugame/pins.c new file mode 100644 index 0000000000..b9c8f2386e --- /dev/null +++ b/atmel-samd/boards/ugame/pins.c @@ -0,0 +1,18 @@ +#include "samd21_pins.h" + +STATIC const mp_rom_map_elem_t board_global_dict_table[] = { + { MP_ROM_QSTR(MP_QSTR_X), MP_ROM_PTR(&pin_PA00) }, + { MP_ROM_QSTR(MP_QSTR_O), MP_ROM_PTR(&pin_PA01) }, + + { MP_ROM_QSTR(MP_QSTR_SPEAKER), MP_ROM_PTR(&pin_PA02) }, + + { MP_ROM_QSTR(MP_QSTR_UP), MP_ROM_PTR(&pin_PA03) }, + { MP_ROM_QSTR(MP_QSTR_LEFT), MP_ROM_PTR(&pin_PA04) }, + { MP_ROM_QSTR(MP_QSTR_DOWN), MP_ROM_PTR(&pin_PA23) }, + { MP_ROM_QSTR(MP_QSTR_RIGHT), MP_ROM_PTR(&pin_PA05) }, + + { MP_ROM_QSTR(MP_QSTR_MOSI), MP_ROM_PTR(&pin_PA06) }, + { MP_ROM_QSTR(MP_QSTR_SCK), MP_ROM_PTR(&pin_PA07) }, + { MP_ROM_QSTR(MP_QSTR_DC), MP_ROM_PTR(&pin_PA08) }, +}; +MP_DEFINE_CONST_DICT(board_module_globals, board_global_dict_table); From 78f6c2232ca08f80ed96d2f1ef365f5f749fec1c Mon Sep 17 00:00:00 2001 From: Radomir Dopieralski Date: Fri, 3 Nov 2017 15:44:13 +0100 Subject: [PATCH 017/135] Allow empty reads and writes for busio.SPI This is mostly for convenience, so that user code doesn't need to add additional checks. Also, bring the bitbangio into compatibility with busio wrt. empty buffers. --- shared-bindings/bitbangio/I2C.c | 7 +++++++ shared-bindings/bitbangio/SPI.c | 11 ++++++++++- shared-bindings/busio/SPI.c | 11 ++++++----- 3 files changed, 23 insertions(+), 6 deletions(-) diff --git a/shared-bindings/bitbangio/I2C.c b/shared-bindings/bitbangio/I2C.c index 80718090ab..f8f60210e6 100644 --- a/shared-bindings/bitbangio/I2C.c +++ b/shared-bindings/bitbangio/I2C.c @@ -157,6 +157,7 @@ MP_DEFINE_CONST_FUN_OBJ_1(bitbangio_i2c_unlock_obj, bitbangio_i2c_obj_unlock); //| //| Read into ``buffer`` from the slave specified by ``address``. //| The number of bytes read will be the length of ``buffer``. +//| At least one byte must be read. //| //| If ``start`` or ``end`` is provided, then the buffer will be sliced //| as if ``buffer[start:end]``. This will not cause an allocation like @@ -186,6 +187,9 @@ STATIC mp_obj_t bitbangio_i2c_readfrom_into(size_t n_args, const mp_obj_t *pos_a int32_t start = args[ARG_start].u_int; uint32_t length = bufinfo.len; normalize_buffer_bounds(&start, args[ARG_end].u_int, &length); + if (length == 0) { + mp_raise_ValueError("Buffer must be at least length 1"); + } uint8_t status = shared_module_bitbangio_i2c_read(self, args[ARG_address].u_int, ((uint8_t*)bufinfo.buf) + start, @@ -206,6 +210,9 @@ MP_DEFINE_CONST_FUN_OBJ_KW(bitbangio_i2c_readfrom_into_obj, 3, bitbangio_i2c_rea //| as if ``buffer[start:end]``. This will not cause an allocation like //| ``buffer[start:end]`` will so it saves memory. //| +//| Writing a buffer or slice of length zero is permitted, as it can be used +//| to poll for the existence of a device. +//| //| :param int address: 7-bit device address //| :param bytearray buffer: buffer containing the bytes to write //| :param int start: Index to start writing from diff --git a/shared-bindings/bitbangio/SPI.c b/shared-bindings/bitbangio/SPI.c index 6c7bac3e51..5442b9ea26 100644 --- a/shared-bindings/bitbangio/SPI.c +++ b/shared-bindings/bitbangio/SPI.c @@ -191,6 +191,7 @@ MP_DEFINE_CONST_FUN_OBJ_1(bitbangio_spi_unlock_obj, bitbangio_spi_obj_unlock); //| .. method:: SPI.write(buf) //| //| Write the data contained in ``buf``. Requires the SPI being locked. +//| If the buffer is empty, nothing happens. //| // TODO(tannewt): Add support for start and end kwargs. STATIC mp_obj_t bitbangio_spi_write(mp_obj_t self_in, mp_obj_t wr_buf) { @@ -198,6 +199,9 @@ STATIC mp_obj_t bitbangio_spi_write(mp_obj_t self_in, mp_obj_t wr_buf) { raise_error_if_deinited(shared_module_bitbangio_spi_deinited(self)); mp_buffer_info_t src; mp_get_buffer_raise(wr_buf, &src, MP_BUFFER_READ); + if (src.len == 0) { + return mp_const_none; + } check_lock(self); bool ok = shared_module_bitbangio_spi_write(self, src.buf, src.len); if (!ok) { @@ -210,7 +214,9 @@ MP_DEFINE_CONST_FUN_OBJ_2(bitbangio_spi_write_obj, bitbangio_spi_write); //| .. method:: SPI.readinto(buf) //| -//| Read into the buffer specified by ``buf`` while writing zeroes. Requires the SPI being locked. +//| Read into the buffer specified by ``buf`` while writing zeroes. +//| Requires the SPI being locked. +//| If the number of bytes to read is 0, nothing happens. //| // TODO(tannewt): Add support for start and end kwargs. STATIC mp_obj_t bitbangio_spi_readinto(size_t n_args, const mp_obj_t *args) { @@ -218,6 +224,9 @@ STATIC mp_obj_t bitbangio_spi_readinto(size_t n_args, const mp_obj_t *args) { raise_error_if_deinited(shared_module_bitbangio_spi_deinited(self)); mp_buffer_info_t bufinfo; mp_get_buffer_raise(args[1], &bufinfo, MP_BUFFER_WRITE); + if (bufinfo.len == 0) { + return mp_const_none; + } check_lock(args[0]); bool ok = shared_module_bitbangio_spi_read(self, bufinfo.buf, bufinfo.len); if (!ok) { diff --git a/shared-bindings/busio/SPI.c b/shared-bindings/busio/SPI.c index add541aa70..72787af30b 100644 --- a/shared-bindings/busio/SPI.c +++ b/shared-bindings/busio/SPI.c @@ -207,7 +207,7 @@ MP_DEFINE_CONST_FUN_OBJ_1(busio_spi_unlock_obj, busio_spi_obj_unlock); //| .. method:: SPI.write(buffer, \*, start=0, end=len(buffer)) //| //| Write the data contained in ``buf``. Requires the SPI being locked. -//| At least one byte must be written. +//| If the buffer is empty, nothing happens. //| //| :param bytearray buffer: buffer containing the bytes to write //| :param int start: Index to start writing from @@ -233,7 +233,7 @@ STATIC mp_obj_t busio_spi_write(size_t n_args, const mp_obj_t *pos_args, mp_map_ normalize_buffer_bounds(&start, args[ARG_end].u_int, &length); if (length == 0) { - mp_raise_ValueError("Buffer must be at least length 1"); + return mp_const_none; } bool ok = common_hal_busio_spi_write(self, ((uint8_t*)bufinfo.buf) + start, length); @@ -247,8 +247,9 @@ MP_DEFINE_CONST_FUN_OBJ_KW(busio_spi_write_obj, 2, busio_spi_write); //| .. method:: SPI.readinto(buffer, \*, start=0, end=len(buffer), write_value=0) //| -//| Read into the buffer specified by ``buf`` while writing zeroes. Requires the SPI being locked. -//| At least one byte must be read. +//| Read into the buffer specified by ``buf`` while writing zeroes. +//| Requires the SPI being locked. +//| If the number of bytes to read is 0, nothing happens. //| //| :param bytearray buffer: buffer to write into //| :param int start: Index to start writing at @@ -276,7 +277,7 @@ STATIC mp_obj_t busio_spi_readinto(size_t n_args, const mp_obj_t *pos_args, mp_m normalize_buffer_bounds(&start, args[ARG_end].u_int, &length); if (length == 0) { - mp_raise_ValueError("Buffer must be at least length 1"); + return mp_const_none; } bool ok = common_hal_busio_spi_read(self, ((uint8_t*)bufinfo.buf) + start, length, args[ARG_write_value].u_int); From 3c1486a5c77ef2eb79e468bfc50f731cef933eb1 Mon Sep 17 00:00:00 2001 From: jerryneedell Date: Mon, 6 Nov 2017 19:00:03 +0000 Subject: [PATCH 018/135] esp8266 enable framebuf (#408) enable framebuf for ESP8266 --- esp8266/mpconfigport.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/esp8266/mpconfigport.h b/esp8266/mpconfigport.h index 5e9b1e0b64..1542147ad6 100644 --- a/esp8266/mpconfigport.h +++ b/esp8266/mpconfigport.h @@ -84,7 +84,7 @@ #define MICROPY_PY_WEBSOCKET (1) #define MICROPY_PY_WEBREPL (1) #define MICROPY_PY_WEBREPL_DELAY (20) -#define MICROPY_PY_FRAMEBUF (0) +#define MICROPY_PY_FRAMEBUF (1) #define MICROPY_PY_MICROPYTHON_MEM_INFO (1) #define MICROPY_PY_OS_DUPTERM (1) #define MICROPY_CPYTHON_COMPAT (1) From ddc85701372f8537aff85d7cf23ef0a18f25038f Mon Sep 17 00:00:00 2001 From: Dan Halbert Date: Mon, 6 Nov 2017 19:55:58 -0500 Subject: [PATCH 019/135] Fix round(). Don't split a statement with a #pragma. It breaks the compiled output. --- lib/libm/nearbyintf.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/libm/nearbyintf.c b/lib/libm/nearbyintf.c index 1bb44aa466..5ac3178b51 100644 --- a/lib/libm/nearbyintf.c +++ b/lib/libm/nearbyintf.c @@ -18,7 +18,7 @@ float nearbyintf(float x) #pragma GCC diagnostic push #pragma GCC diagnostic ignored "-Wfloat-equal" if (y == 0) -#pragma GCC diagnostic pop return s ? -0.0f : 0.0f; +#pragma GCC diagnostic pop return y; } From 216fcedfbbe3df3f9a224da83df40c5cced90ae3 Mon Sep 17 00:00:00 2001 From: Radomir Dopieralski Date: Tue, 7 Nov 2017 19:05:25 +0100 Subject: [PATCH 020/135] Add a _stage module (#398) This is a C module with some low-level functions required for the CircuitPython "stage" library. It provides support for fast rendering of tile grids and sprites on SPI-based RGB displays. --- atmel-samd/Makefile | 3 + shared-bindings/_stage/Layer.c | 130 ++++++++++++++++++++++++++++++ shared-bindings/_stage/Layer.h | 34 ++++++++ shared-bindings/_stage/Text.c | 109 +++++++++++++++++++++++++ shared-bindings/_stage/Text.h | 34 ++++++++ shared-bindings/_stage/__init__.c | 97 ++++++++++++++++++++++ shared-bindings/_stage/__init__.h | 32 ++++++++ shared-module/_stage/Layer.c | 105 ++++++++++++++++++++++++ shared-module/_stage/Layer.h | 48 +++++++++++ shared-module/_stage/Text.c | 67 +++++++++++++++ shared-module/_stage/Text.h | 46 +++++++++++ shared-module/_stage/__init__.c | 76 +++++++++++++++++ shared-module/_stage/__init__.h | 42 ++++++++++ 13 files changed, 823 insertions(+) create mode 100644 shared-bindings/_stage/Layer.c create mode 100644 shared-bindings/_stage/Layer.h create mode 100644 shared-bindings/_stage/Text.c create mode 100644 shared-bindings/_stage/Text.h create mode 100644 shared-bindings/_stage/__init__.c create mode 100644 shared-bindings/_stage/__init__.h create mode 100644 shared-module/_stage/Layer.c create mode 100644 shared-module/_stage/Layer.h create mode 100644 shared-module/_stage/Text.c create mode 100644 shared-module/_stage/Text.h create mode 100644 shared-module/_stage/__init__.c create mode 100644 shared-module/_stage/__init__.h diff --git a/atmel-samd/Makefile b/atmel-samd/Makefile index 4a45106db5..f6c183ba92 100644 --- a/atmel-samd/Makefile +++ b/atmel-samd/Makefile @@ -333,6 +333,9 @@ SRC_SHARED_MODULE = \ os/__init__.c \ random/__init__.c \ storage/__init__.c \ + _stage/__init__.c \ + _stage/Layer.c \ + _stage/Text.c \ uheap/__init__.c \ ustack/__init__.c diff --git a/shared-bindings/_stage/Layer.c b/shared-bindings/_stage/Layer.c new file mode 100644 index 0000000000..3e615c4977 --- /dev/null +++ b/shared-bindings/_stage/Layer.c @@ -0,0 +1,130 @@ +/* + * This file is part of the MicroPython project, http://micropython.org/ + * + * The MIT License (MIT) + * + * Copyright (c) 2017 Radomir Dopieralski + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +#include + +#include "__init__.h" +#include "Layer.h" + +//| .. currentmodule:: _stage +//| +//| :class:`Layer` -- Keep information about a single layer of graphics +//| =================================================================== +//| +//| .. class:: Layer(width, height, graphic, palette, [grid]) +//| +//| Keep internal information about a layer of graphics (either a +//| ``Grid`` or a ``Sprite``) in a format suitable for fast rendering +//| with the ``render()`` function. +//| +//| :param int width: The width of the grid in tiles, or 1 for sprites. +//| :param int height: The height of the grid in tiles, or 1 for sprites. +//| :param bytearray graphic: The graphic data of the tiles. +//| :param bytearray palette: The color palette to be used. +//| :param bytearray grid: The contents of the grid map. +//| +//| This class is intended for internal use in the ``stage`` library and +//| it shouldn't be used on its own. +//| +STATIC mp_obj_t layer_make_new(const mp_obj_type_t *type, size_t n_args, + size_t n_kw, const mp_obj_t *args) { + mp_arg_check_num(n_args, n_kw, 4, 5, false); + + layer_obj_t *self = m_new_obj(layer_obj_t); + self->base.type = type; + + self->width = mp_obj_get_int(args[0]); + self->height = mp_obj_get_int(args[1]); + self->x = 0; + self->y = 0; + self->frame = 0; + self->rotation = false; + + mp_buffer_info_t bufinfo; + mp_get_buffer_raise(args[2], &bufinfo, MP_BUFFER_READ); + self->graphic = bufinfo.buf; + if (bufinfo.len != 2048) { + mp_raise_ValueError("graphic must be 2048 bytes long"); + } + + mp_get_buffer_raise(args[3], &bufinfo, MP_BUFFER_READ); + self->palette = bufinfo.buf; + if (bufinfo.len != 32) { + mp_raise_ValueError("palette must be 32 bytes long"); + } + + if (n_args > 4) { + mp_get_buffer_raise(args[4], &bufinfo, MP_BUFFER_READ); + self->map = bufinfo.buf; + if (bufinfo.len < (self->width * self->height) / 2) { + mp_raise_ValueError("map buffer too small"); + } + } else { + self-> map = NULL; + } + + return MP_OBJ_FROM_PTR(self); +} + +//| .. method:: move(x, y) +//| +//| Set the offset of the layer to the specified values. +//| +STATIC mp_obj_t layer_move(mp_obj_t self_in, mp_obj_t x_in, mp_obj_t y_in) { + layer_obj_t *self = MP_OBJ_TO_PTR(self_in); + self->x = mp_obj_get_int(x_in); + self->y = mp_obj_get_int(y_in); + return mp_const_none; +} +STATIC MP_DEFINE_CONST_FUN_OBJ_3(layer_move_obj, layer_move); + +//| .. method:: frame(frame, rotation) +//| +//| Set the animation frame of the sprite, and optionally rotation its +//| graphic. +//| +STATIC mp_obj_t layer_frame(mp_obj_t self_in, mp_obj_t frame_in, + mp_obj_t rotation_in) { + layer_obj_t *self = MP_OBJ_TO_PTR(self_in); + self->frame = mp_obj_get_int(frame_in); + self->rotation = mp_obj_get_int(rotation_in); + return mp_const_none; +} +STATIC MP_DEFINE_CONST_FUN_OBJ_3(layer_frame_obj, layer_frame); + + +STATIC const mp_rom_map_elem_t layer_locals_dict_table[] = { + { MP_ROM_QSTR(MP_QSTR_move), MP_ROM_PTR(&layer_move_obj) }, + { MP_ROM_QSTR(MP_QSTR_frame), MP_ROM_PTR(&layer_frame_obj) }, +}; +STATIC MP_DEFINE_CONST_DICT(layer_locals_dict, layer_locals_dict_table); + +const mp_obj_type_t mp_type_layer = { + { &mp_type_type }, + .name = MP_QSTR_Layer, + .make_new = layer_make_new, + .locals_dict = (mp_obj_dict_t*)&layer_locals_dict, +}; diff --git a/shared-bindings/_stage/Layer.h b/shared-bindings/_stage/Layer.h new file mode 100644 index 0000000000..6d15dfb288 --- /dev/null +++ b/shared-bindings/_stage/Layer.h @@ -0,0 +1,34 @@ +/* + * This file is part of the MicroPython project, http://micropython.org/ + * + * The MIT License (MIT) + * + * Copyright (c) 2017 Radomir Dopieralski + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +#ifndef MICROPY_INCLUDED__STAGE_LAYER_H +#define MICROPY_INCLUDED__STAGE_LAYER_H + +#include "shared-module/_stage/Layer.h" + +extern const mp_obj_type_t mp_type_layer; + +#endif // MICROPY_INCLUDED__STAGE_LAYER diff --git a/shared-bindings/_stage/Text.c b/shared-bindings/_stage/Text.c new file mode 100644 index 0000000000..c62d22afee --- /dev/null +++ b/shared-bindings/_stage/Text.c @@ -0,0 +1,109 @@ +/* + * This file is part of the MicroPython project, http://micropython.org/ + * + * The MIT License (MIT) + * + * Copyright (c) 2017 Radomir Dopieralski + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +#include + +#include "__init__.h" +#include "Text.h" + +//| .. currentmodule:: _stage +//| +//| :class:`Text` -- Keep information about a single text of text +//| ============================================================== +//| +//| .. class:: Text(width, height, font, palette, chars) +//| +//| Keep internal information about a text of text +//| in a format suitable for fast rendering +//| with the ``render()`` function. +//| +//| :param int width: The width of the grid in tiles, or 1 for sprites. +//| :param int height: The height of the grid in tiles, or 1 for sprites. +//| :param bytearray font: The font data of the characters. +//| :param bytearray palette: The color palette to be used. +//| :param bytearray chars: The contents of the character grid. +//| +//| This class is intended for internal use in the ``stage`` library and +//| it shouldn't be used on its own. +//| +STATIC mp_obj_t text_make_new(const mp_obj_type_t *type, size_t n_args, + size_t n_kw, const mp_obj_t *args) { + mp_arg_check_num(n_args, n_kw, 5, 5, false); + + text_obj_t *self = m_new_obj(text_obj_t); + self->base.type = type; + + self->width = mp_obj_get_int(args[0]); + self->height = mp_obj_get_int(args[1]); + self->x = 0; + self->y = 0; + + mp_buffer_info_t bufinfo; + mp_get_buffer_raise(args[2], &bufinfo, MP_BUFFER_READ); + self->font = bufinfo.buf; + if (bufinfo.len != 2048) { + mp_raise_ValueError("font must be 2048 bytes long"); + } + + mp_get_buffer_raise(args[3], &bufinfo, MP_BUFFER_READ); + self->palette = bufinfo.buf; + if (bufinfo.len != 32) { + mp_raise_ValueError("palette must be 32 bytes long"); + } + + mp_get_buffer_raise(args[4], &bufinfo, MP_BUFFER_READ); + self->chars = bufinfo.buf; + if (bufinfo.len < self->width * self->height) { + mp_raise_ValueError("chars buffer too small"); + } + + return MP_OBJ_FROM_PTR(self); +} + +//| .. method:: move(x, y) +//| +//| Set the offset of the text to the specified values. +//| +STATIC mp_obj_t text_move(mp_obj_t self_in, mp_obj_t x_in, mp_obj_t y_in) { + text_obj_t *self = MP_OBJ_TO_PTR(self_in); + self->x = mp_obj_get_int(x_in); + self->y = mp_obj_get_int(y_in); + return mp_const_none; +} +STATIC MP_DEFINE_CONST_FUN_OBJ_3(text_move_obj, text_move); + + +STATIC const mp_rom_map_elem_t text_locals_dict_table[] = { + { MP_ROM_QSTR(MP_QSTR_move), MP_ROM_PTR(&text_move_obj) }, +}; +STATIC MP_DEFINE_CONST_DICT(text_locals_dict, text_locals_dict_table); + +const mp_obj_type_t mp_type_text = { + { &mp_type_type }, + .name = MP_QSTR_Text, + .make_new = text_make_new, + .locals_dict = (mp_obj_dict_t*)&text_locals_dict, +}; diff --git a/shared-bindings/_stage/Text.h b/shared-bindings/_stage/Text.h new file mode 100644 index 0000000000..77de62a110 --- /dev/null +++ b/shared-bindings/_stage/Text.h @@ -0,0 +1,34 @@ +/* + * This file is part of the MicroPython project, http://micropython.org/ + * + * The MIT License (MIT) + * + * Copyright (c) 2017 Radomir Dopieralski + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +#ifndef MICROPY_INCLUDED__STAGE_TEXT_H +#define MICROPY_INCLUDED__STAGE_TEXT_H + +#include "shared-module/_stage/Text.h" + +extern const mp_obj_type_t mp_type_text; + +#endif // MICROPY_INCLUDED__STAGE_TEXT diff --git a/shared-bindings/_stage/__init__.c b/shared-bindings/_stage/__init__.c new file mode 100644 index 0000000000..16e0b58d94 --- /dev/null +++ b/shared-bindings/_stage/__init__.c @@ -0,0 +1,97 @@ +/* + * This file is part of the MicroPython project, http://micropython.org/ + * + * The MIT License (MIT) + * + * Copyright (c) 2017 Radomir Dopieralski + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +#include "__init__.h" +#include "py/mperrno.h" +#include "py/runtime.h" +#include "shared-bindings/busio/SPI.h" +#include "shared-module/_stage/__init__.h" +#include "Layer.h" +#include "Text.h" + +//| .. currentmodule:: _stage +//| +//| .. function:: render(x0, y0, x1, y1, layers, buffer, spi) +//| +//| Render and send to the display a fragment of the screen. +//| +//| :param int x0: Left edge of the fragment. +//| :param int y0: Top edge of the fragment. +//| :param int x1: Right edge of the fragment. +//| :param int y1: Bottom edge of the fragment. +//| :param list layers: A list of the `Layer` objects. +//| :param bytearray buffer: A buffer to use for rendering. +//| :param SPI spi: The SPI device to use. +//| +//| Note that this function only sends the raw pixel data. Setting up +//| the display for receiving it and handling the chip-select and +//| data-command pins has to be done outside of it. +//| There are also no sanity checks, outside of the basic overflow +//| checking. The caller is responsible for making the passed parameters +//| valid. +//| +//| This function is intended for internal use in the ``stage`` library +//| and all the necessary checks are performed there. +STATIC mp_obj_t stage_render(size_t n_args, const mp_obj_t *args) { + uint8_t x0 = mp_obj_get_int(args[0]); + uint8_t y0 = mp_obj_get_int(args[1]); + uint8_t x1 = mp_obj_get_int(args[2]); + uint8_t y1 = mp_obj_get_int(args[3]); + + size_t layers_size = 0; + mp_obj_t *layers; + mp_obj_get_array(args[4], &layers_size, &layers); + + mp_buffer_info_t bufinfo; + mp_get_buffer_raise(args[5], &bufinfo, MP_BUFFER_WRITE); + uint16_t *buffer = bufinfo.buf; + size_t buffer_size = bufinfo.len / 2; // 16-bit indexing + + busio_spi_obj_t *spi = MP_OBJ_TO_PTR(args[6]); + + if (!render_stage(x0, y0, x1, y1, layers, layers_size, + buffer, buffer_size, spi)) { + mp_raise_OSError(MP_EIO); + } + + return mp_const_none; +} +MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(stage_render_obj, 7, 7, stage_render); + + +STATIC const mp_rom_map_elem_t stage_module_globals_table[] = { + { MP_ROM_QSTR(MP_QSTR___name__), MP_ROM_QSTR(MP_QSTR__stage) }, + { MP_ROM_QSTR(MP_QSTR_Layer), MP_ROM_PTR(&mp_type_layer) }, + { MP_ROM_QSTR(MP_QSTR_Text), MP_ROM_PTR(&mp_type_text) }, + { MP_ROM_QSTR(MP_QSTR_render), MP_ROM_PTR(&stage_render_obj) }, +}; + +STATIC MP_DEFINE_CONST_DICT(stage_module_globals, stage_module_globals_table); + +const mp_obj_module_t stage_module = { + .base = { &mp_type_module }, + .globals = (mp_obj_dict_t*)&stage_module_globals, +}; diff --git a/shared-bindings/_stage/__init__.h b/shared-bindings/_stage/__init__.h new file mode 100644 index 0000000000..2df81cb3b2 --- /dev/null +++ b/shared-bindings/_stage/__init__.h @@ -0,0 +1,32 @@ +/* + * This file is part of the MicroPython project, http://micropython.org/ + * + * The MIT License (MIT) + * + * Copyright (c) 2017 Radomir Dopieralski + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +#ifndef MICROPY_INCLUDED__STAGE_H +#define MICROPY_INCLUDED__STAGE_H + +#include "shared-module/_stage/__init__.h" + +#endif // MICROPY_INCLUDED__STAGE diff --git a/shared-module/_stage/Layer.c b/shared-module/_stage/Layer.c new file mode 100644 index 0000000000..3315ac69e1 --- /dev/null +++ b/shared-module/_stage/Layer.c @@ -0,0 +1,105 @@ +/* + * This file is part of the MicroPython project, http://micropython.org/ + * + * The MIT License (MIT) + * + * Copyright (c) 2017 Radomir Dopieralski + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +#include "Layer.h" +#include "__init__.h" + + +// Get the color of the pixel on the layer. +uint16_t get_layer_pixel(layer_obj_t *layer, int16_t x, uint16_t y) { + + // Shift by the layer's position offset. + x -= layer->x; + y -= layer->y; + + // Bounds check. + if ((x < 0) || (x >= layer->width << 4) || + (y < 0) || (y >= layer->height << 4)) { + return TRANSPARENT; + } + + // Get the tile from the grid location or from sprite frame. + uint8_t frame = layer->frame; + if (layer->map) { + uint8_t tx = x >> 4; + uint8_t ty = y >> 4; + + frame = layer->map[(tx * layer->width + ty) >> 1]; + if (ty & 0x01) { + frame &= 0x0f; + } else { + frame >>= 4; + } + } + + // Get the position within the tile. + x &= 0x0f; + y &= 0x0f; + + // Rotate the image. + uint8_t tx = x; // Temporary variable for swapping. + switch (layer->rotation) { + case 1: // 90 degrees clockwise + x = 15 - y; + y = tx; + break; + case 2: // 180 degrees + x = 15 - tx; + y = 15 - y; + break; + case 3: // 90 degrees counter-clockwise + x = y; + y = 15 - tx; + break; + case 4: // 0 degrees, mirrored + y = 15 - y; + break; + case 5: // 90 degrees clockwise, mirrored + x = y; + y = tx; + break; + case 6: // 180 degrees, mirrored + x = 15 - tx; + break; + case 7: // 90 degrees counter-clockwise, mirrored + x = 15 - y; + y = 15 - tx; + break; + default: // 0 degrees + break; + } + + // Get the value of the pixel. + uint8_t pixel = layer->graphic[(frame << 7) + (x << 3) + (y >> 1)]; + if (y & 0x01) { + pixel &= 0x0f; + } else { + pixel >>= 4; + } + + // Convert to 16-bit color using the palette. + return layer->palette[pixel << 1] | layer->palette[(pixel << 1) + 1] << 8; +} diff --git a/shared-module/_stage/Layer.h b/shared-module/_stage/Layer.h new file mode 100644 index 0000000000..c46f71349f --- /dev/null +++ b/shared-module/_stage/Layer.h @@ -0,0 +1,48 @@ +/* + * This file is part of the MicroPython project, http://micropython.org/ + * + * The MIT License (MIT) + * + * Copyright (c) 2017 Radomir Dopieralski + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +#ifndef MICROPY_INCLUDED_SHARED_MODULE__STAGE_LAYER_H +#define MICROPY_INCLUDED_SHARED_MODULE__STAGE_LAYER_H + +#include +#include + +#include "py/obj.h" + +typedef struct { + mp_obj_base_t base; + uint8_t *map; + uint8_t *graphic; + uint8_t *palette; + int16_t x, y; + uint8_t width, height; + uint8_t frame; + uint8_t rotation; +} layer_obj_t; + +uint16_t get_layer_pixel(layer_obj_t *layer, int16_t x, uint16_t y); + +#endif // MICROPY_INCLUDED_SHARED_MODULE__STAGE_LAYER diff --git a/shared-module/_stage/Text.c b/shared-module/_stage/Text.c new file mode 100644 index 0000000000..6c451bf38f --- /dev/null +++ b/shared-module/_stage/Text.c @@ -0,0 +1,67 @@ +/* + * This file is part of the MicroPython project, http://micropython.org/ + * + * The MIT License (MIT) + * + * Copyright (c) 2017 Radomir Dopieralski + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +#include "Text.h" +#include "__init__.h" + + +// Get the color of the pixel on the text. +uint16_t get_text_pixel(text_obj_t *text, int16_t x, uint16_t y) { + + // Shift by the text's position offset. + x -= text->x; + y -= text->y; + + // Bounds check. + if ((x < 0) || (x >= text->width << 3) || + (y < 0) || (y >= text->height << 3)) { + return TRANSPARENT; + } + + // Get the tile from the grid location or from sprite frame. + uint8_t tx = x >> 3; + uint8_t ty = y >> 3; + uint8_t c = text->chars[ty * text->width + tx]; + uint8_t color_offset = 0; + if (c & 0x80) { + color_offset = 4; + } + c &= 0x7f; + if (!c) { + return TRANSPARENT; + } + + // Get the position within the char. + x &= 0x07; + y &= 0x07; + + // Get the value of the pixel. + uint8_t pixel = text->font[(c << 4) + (x << 1) + (y >> 2)]; + pixel = ((pixel >> ((y & 0x03) << 1)) & 0x03) + color_offset; + + // Convert to 16-bit color using the palette. + return text->palette[pixel << 1] | text->palette[(pixel << 1) + 1] << 8; +} diff --git a/shared-module/_stage/Text.h b/shared-module/_stage/Text.h new file mode 100644 index 0000000000..bc111e49c1 --- /dev/null +++ b/shared-module/_stage/Text.h @@ -0,0 +1,46 @@ +/* + * This file is part of the MicroPython project, http://micropython.org/ + * + * The MIT License (MIT) + * + * Copyright (c) 2017 Radomir Dopieralski + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +#ifndef MICROPY_INCLUDED_SHARED_MODULE__STAGE_TEXT_H +#define MICROPY_INCLUDED_SHARED_MODULE__STAGE_TEXT_H + +#include +#include + +#include "py/obj.h" + +typedef struct { + mp_obj_base_t base; + uint8_t *chars; + uint8_t *font; + uint8_t *palette; + int16_t x, y; + uint8_t width, height; +} text_obj_t; + +uint16_t get_text_pixel(text_obj_t *text, int16_t x, uint16_t y); + +#endif // MICROPY_INCLUDED_SHARED_MODULE__STAGE_TEXT diff --git a/shared-module/_stage/__init__.c b/shared-module/_stage/__init__.c new file mode 100644 index 0000000000..1931b89407 --- /dev/null +++ b/shared-module/_stage/__init__.c @@ -0,0 +1,76 @@ +/* + * This file is part of the MicroPython project, http://micropython.org/ + * + * The MIT License (MIT) + * + * Copyright (c) 2017 Radomir Dopieralski + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +#include "Layer.h" +#include "Text.h" +#include "__init__.h" +#include "shared-bindings/_stage/Layer.h" +#include "shared-bindings/_stage/Text.h" + + +bool render_stage(uint8_t x0, uint8_t y0, uint8_t x1, uint8_t y1, + mp_obj_t *layers, size_t layers_size, + uint16_t *buffer, size_t buffer_size, + busio_spi_obj_t *spi) { + + // TODO(deshipu): Do a collision check of each layer with the + // rectangle, and only process the layers that overlap with it. + + size_t index = 0; + for (uint8_t y = y0; y < y1; ++y) { + for (uint8_t x = x0; x < x1; ++x) { + for (size_t layer = 0; layer < layers_size; ++layer) { + uint16_t c = TRANSPARENT; + layer_obj_t *obj = MP_OBJ_TO_PTR(layers[layer]); + if (obj->base.type == &mp_type_layer) { + c = get_layer_pixel(obj, x, y); + } else if (obj->base.type == &mp_type_text) { + c = get_text_pixel((text_obj_t *)obj, x, y); + } + if (c != TRANSPARENT) { + buffer[index] = c; + break; + } + } + index += 1; + // The buffer is full, send it. + if (index >= buffer_size) { + if (!common_hal_busio_spi_write(spi, + ((uint8_t*)buffer), buffer_size * 2)) { + return false; + } + index = 0; + } + } + } + // Send the remaining data. + if (index) { + if (!common_hal_busio_spi_write(spi, ((uint8_t*)buffer), index * 2)) { + return false; + } + } + return true; +} diff --git a/shared-module/_stage/__init__.h b/shared-module/_stage/__init__.h new file mode 100644 index 0000000000..326c725599 --- /dev/null +++ b/shared-module/_stage/__init__.h @@ -0,0 +1,42 @@ +/* + * This file is part of the MicroPython project, http://micropython.org/ + * + * The MIT License (MIT) + * + * Copyright (c) 2017 Radomir Dopieralski + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +#ifndef MICROPY_INCLUDED_SHARED_MODULE__STAGE_H +#define MICROPY_INCLUDED_SHARED_MODULE__STAGE_H + +#include "shared-bindings/busio/SPI.h" +#include +#include +#include "py/obj.h" + +#define TRANSPARENT (0x1ff8) + +bool render_stage(uint8_t x0, uint8_t y0, uint8_t x1, uint8_t y1, + mp_obj_t *layers, size_t layers_size, + uint16_t *buffer, size_t buffer_size, + busio_spi_obj_t *spi); + +#endif // MICROPY_INCLUDED_SHARED_MODULE__STAGE From aa817de7f004a4b8646f68394ec8540eaf207b1c Mon Sep 17 00:00:00 2001 From: Scott Shawcroft Date: Tue, 7 Nov 2017 14:32:58 -0800 Subject: [PATCH 021/135] atmel-samd: Update Feather M0 Express USB PID This makes it different from the bootloaders and Arduino. Fixes #324. --- atmel-samd/boards/feather_m0_express/mpconfigboard.mk | 2 +- atmel-samd/boards/feather_m0_supersized/mpconfigboard.mk | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/atmel-samd/boards/feather_m0_express/mpconfigboard.mk b/atmel-samd/boards/feather_m0_express/mpconfigboard.mk index 4a8bc31eb5..750b8d5f71 100644 --- a/atmel-samd/boards/feather_m0_express/mpconfigboard.mk +++ b/atmel-samd/boards/feather_m0_express/mpconfigboard.mk @@ -1,6 +1,6 @@ LD_FILE = boards/samd21x18-bootloader-external-flash.ld USB_VID = 0x239A -USB_PID = 0x801b +USB_PID = 0x8023 SPI_FLASH_FILESYSTEM = 1 diff --git a/atmel-samd/boards/feather_m0_supersized/mpconfigboard.mk b/atmel-samd/boards/feather_m0_supersized/mpconfigboard.mk index c3d413f358..bebedb0742 100644 --- a/atmel-samd/boards/feather_m0_supersized/mpconfigboard.mk +++ b/atmel-samd/boards/feather_m0_supersized/mpconfigboard.mk @@ -1,7 +1,7 @@ LD_FILE = boards/samd21x18-bootloader-external-flash.ld USB_VID = 0x239A -USB_PID = 0x801b +USB_PID = 0x8023 SPI_FLASH_FILESYSTEM = 1 From 065a319100db97a8d969eb048b73a2bde75c4cef Mon Sep 17 00:00:00 2001 From: Dan Halbert Date: Tue, 14 Nov 2017 10:58:26 -0500 Subject: [PATCH 022/135] =?UTF-8?q?Update=20info=20about=20erasing=20CIRCU?= =?UTF-8?q?ITPY=20to=20include=20flash=20erasers=20for=20non-=E2=80=A6=20(?= =?UTF-8?q?#427)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Update info about erasing CIRCUITPY to include flash erasers for non-Express boards. --- docs/troubleshooting.rst | 24 +++++++++++++++++------- 1 file changed, 17 insertions(+), 7 deletions(-) diff --git a/docs/troubleshooting.rst b/docs/troubleshooting.rst index 34ee392d25..1c7e87f61b 100644 --- a/docs/troubleshooting.rst +++ b/docs/troubleshooting.rst @@ -15,19 +15,29 @@ This often happens on Windows when the ``CIRCUITPY`` disk is not safely ejected before being reset by the button or being disconnected from USB. This can also happen on Linux and Mac OSX but its less likely. -.. caution:: Delete ``CIRCUITPY`` filesystem and reload CircuitPython. +.. caution:: To erase and re-create ``CIRCUITPY`` (for example, to correct a corrupted filesystem), + follow one of the procedures below. It's important to note that **any files stored on the** + ``CIRCUITPY`` **drive will be erased**. - To reload CircuitPython (for example, to correct a corrupted filesystem), - follow the process below. It's important to note that **any files stored on the - ``CIRCUITPY`` drive will be erased**. +**For boards with** ``CIRCUITPY`` **stored on a separate SPI flash chip, +such as Feather M0 Express, Metro M0 Express and Circuit Playground Express:** -#. Download the appropriate flash erase uf2 from `here `_. + +#. Download the appropriate flash .erase uf2 from `here `_. #. Double-click the reset button. #. Copy the appropriate .uf2 to the xxxBOOT drive. #. The on-board NeoPixel will turn blue, indicating the erase has started. #. After about 15 seconds, the NexoPixel will start flashing green. If it flashes red, the erase failed. #. Double-click again and load the appropriate `CircuitPython .uf2 `_. +**For boards without SPI flash, such as Feather M0 Proto, Gemma M0 and, Trinket M0:** + +#. Download the appropriate erase .uf2 from `here `_. +#. Double-click the reset button. +#. Copy the appropriate .uf2 to the xxxBOOT drive. +#. The boot LED will start pulsing again, and the xxxBOOT drive will appear again. +#. Load the appropriate `CircuitPython .uf2 `_. + ValueError: Incompatible ``.mpy`` file. --------------------------------------- @@ -35,9 +45,9 @@ This error occurs when importing a module that is stored as a ``mpy`` binary fil (rather than a ``py`` text file) that was generated by a different version of CircuitPython than the one its being loaded into. Most versions are compatible but, rarely they aren't. In particular, the ``mpy`` binary format changed between -CircuitPython versions 1.x and 2.x. +CircuitPython versions 1.x and 2.x, and will change again between 2.x and 3.x. -So, if you just upgraded to CircuitPython 2.x from 1.x you'll need to download a +So, for instance, if you just upgraded to CircuitPython 2.x from 1.x you'll need to download a newer version of the library that triggered the error on ``import``. They are all available in the `Adafruit bundle `_ From 27d5f27831abfa4df928423ccf75baf2dd0ff6a7 Mon Sep 17 00:00:00 2001 From: "Limor \"Ladyada\" Fried" Date: Fri, 17 Nov 2017 12:25:36 -0500 Subject: [PATCH 023/135] Add ItsyBitsy M0 support with 1MB flash support (#445) --- .../boards/feather_m0_express/mpconfigboard.h | 2 +- atmel-samd/boards/flash_W25Q80DV.h | 51 ++++ atmel-samd/boards/itsybitsy_m0/board.c | 37 +++ atmel-samd/boards/itsybitsy_m0/conf_access.h | 115 +++++++++ atmel-samd/boards/itsybitsy_m0/conf_board.h | 14 ++ atmel-samd/boards/itsybitsy_m0/conf_clocks.h | 1 + atmel-samd/boards/itsybitsy_m0/conf_usb.h | 221 ++++++++++++++++++ .../boards/itsybitsy_m0/mpconfigboard.h | 36 +++ .../boards/itsybitsy_m0/mpconfigboard.mk | 7 + atmel-samd/boards/itsybitsy_m0/pins.c | 42 ++++ tools/build_adafruit_bins.sh | 2 +- 11 files changed, 526 insertions(+), 2 deletions(-) create mode 100644 atmel-samd/boards/flash_W25Q80DV.h create mode 100644 atmel-samd/boards/itsybitsy_m0/board.c create mode 100644 atmel-samd/boards/itsybitsy_m0/conf_access.h create mode 100644 atmel-samd/boards/itsybitsy_m0/conf_board.h create mode 100644 atmel-samd/boards/itsybitsy_m0/conf_clocks.h create mode 100644 atmel-samd/boards/itsybitsy_m0/conf_usb.h create mode 100644 atmel-samd/boards/itsybitsy_m0/mpconfigboard.h create mode 100644 atmel-samd/boards/itsybitsy_m0/mpconfigboard.mk create mode 100644 atmel-samd/boards/itsybitsy_m0/pins.c diff --git a/atmel-samd/boards/feather_m0_express/mpconfigboard.h b/atmel-samd/boards/feather_m0_express/mpconfigboard.h index 896a04dd83..817f93f687 100644 --- a/atmel-samd/boards/feather_m0_express/mpconfigboard.h +++ b/atmel-samd/boards/feather_m0_express/mpconfigboard.h @@ -18,7 +18,7 @@ #define SPI_FLASH_CS PIN_PA13 -#define MICROPY_PORT_A (PORT_PA06 | PORT_PA08 | PORT_PA09 | PORT_PA14 | PORT_PA13 | PORT_PA14 | PORT_PA24 | PORT_PA25) +#define MICROPY_PORT_A (PORT_PA06 | PORT_PA08 | PORT_PA09 | PORT_PA13 | PORT_PA14 | PORT_PA24 | PORT_PA25) #define MICROPY_PORT_B ( 0 ) #include "spi_flash.h" diff --git a/atmel-samd/boards/flash_W25Q80DV.h b/atmel-samd/boards/flash_W25Q80DV.h new file mode 100644 index 0000000000..1e8003867f --- /dev/null +++ b/atmel-samd/boards/flash_W25Q80DV.h @@ -0,0 +1,51 @@ +/* + * This file is part of the MicroPython project, http://micropython.org/ + * + * The MIT License (MIT) + * + * Copyright (c) 2017 Scott Shawcroft for Adafruit Industries + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +#ifndef MICROPY_INCLUDED_ATMEL_SAMD_BOARD_FLASH_W25Q80DV_H +#define MICROPY_INCLUDED_ATMEL_SAMD_BOARD_FLASH_W25Q80DV_H + +// The total flash size in bytes. +#define SPI_FLASH_TOTAL_SIZE (1 << 20) // 1 MiB + +// The size of the smallest erase unit thats erased with command 0x20. +#define SPI_FLASH_ERASE_SIZE (1 << 12) // 4 KiB + +// The size of a page that is programmed with page program command 0x02. +#define SPI_FLASH_PAGE_SIZE (256) // 256 bytes + +// These are the first three response bytes to the JEDEC ID command 0x9f that is +// used to confirm we're talking to the flash we expect. +#ifndef SPI_FLASH_JEDEC_MANUFACTURER +#define SPI_FLASH_JEDEC_MANUFACTURER 0xef +#define SPI_FLASH_SECTOR_PROTECTION false +#else +#define SPI_FLASH_JEDEC_MANUFACTURER_2 0xef +#define SPI_FLASH_SECTOR_PROTECTION_2 false +#endif +#define SPI_FLASH_JEDEC_MEMORY_TYPE 0x40 +#define SPI_FLASH_JEDEC_CAPACITY 0x14 + +#endif // MICROPY_INCLUDED_ATMEL_SAMD_BOARD_FLASH_W25Q80DV_H diff --git a/atmel-samd/boards/itsybitsy_m0/board.c b/atmel-samd/boards/itsybitsy_m0/board.c new file mode 100644 index 0000000000..d7e856d611 --- /dev/null +++ b/atmel-samd/boards/itsybitsy_m0/board.c @@ -0,0 +1,37 @@ +/* + * This file is part of the MicroPython project, http://micropython.org/ + * + * The MIT License (MIT) + * + * Copyright (c) 2017 Scott Shawcroft for Adafruit Industries + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +#include "boards/board.h" + +void board_init(void) { +} + +bool board_requests_safe_mode(void) { + return false; +} + +void reset_board(void) { +} diff --git a/atmel-samd/boards/itsybitsy_m0/conf_access.h b/atmel-samd/boards/itsybitsy_m0/conf_access.h new file mode 100644 index 0000000000..25109b75ca --- /dev/null +++ b/atmel-samd/boards/itsybitsy_m0/conf_access.h @@ -0,0 +1,115 @@ +/** + * \file + * + * \brief Memory access control configuration file. + * + * Copyright (c) 2014-2015 Atmel Corporation. All rights reserved. + * + * \asf_license_start + * + * \page License + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * 3. The name of Atmel may not be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * 4. This software may only be redistributed and used in connection with an + * Atmel microcontroller product. + * + * THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE + * EXPRESSLY AND SPECIFICALLY DISCLAIMED. IN NO EVENT SHALL ATMEL BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + * \asf_license_stop + * + */ +/* + * Support and FAQ: visit Atmel Support + */ + +#ifndef _CONF_ACCESS_H_ +#define _CONF_ACCESS_H_ + +#include "compiler.h" +#include "board.h" + + +/*! \name Activation of Logical Unit Numbers + */ +//! @{ +#define LUN_0 ENABLE //!< On-Chip Virtual Memory. +#define LUN_1 DISABLE //!< AT45DBX Data Flash. +#define LUN_2 DISABLE //!< SD/MMC Card over SPI. +#define LUN_3 DISABLE //!< SD/MMC Card over MCI Slot 0. +#define LUN_4 DISABLE +#define LUN_5 DISABLE +#define LUN_6 DISABLE +#define LUN_7 DISABLE +#define LUN_USB DISABLE //!< Host Mass-Storage Memory. +//! @} + +/*! \name LUN 0 Definitions + */ +//! @{ +#define LUN_0_INCLUDE "access_vfs.h" +#define Lun_0_test_unit_ready vfs_test_unit_ready +#define Lun_0_read_capacity vfs_read_capacity +#define Lun_0_unload NULL +#define Lun_0_wr_protect vfs_wr_protect +#define Lun_0_removal vfs_removal +#define Lun_0_usb_read_10 vfs_usb_read_10 +#define Lun_0_usb_write_10 vfs_usb_write_10 +#define LUN_0_NAME "\"MicroPython VFS[0]\"" +//! @} + +#define MEM_USB LUN_USB + +/*! \name Actions Associated with Memory Accesses + * + * Write here the action to associate with each memory access. + * + * \warning Be careful not to waste time in order not to disturb the functions. + */ +//! @{ +#define memory_start_read_action(nb_sectors) +#define memory_stop_read_action() +#define memory_start_write_action(nb_sectors) +#define memory_stop_write_action() +//! @} + +/*! \name Activation of Interface Features + */ +//! @{ +#define ACCESS_USB true //!< MEM <-> USB interface. +#define ACCESS_MEM_TO_RAM false //!< MEM <-> RAM interface. +#define ACCESS_STREAM false //!< Streaming MEM <-> MEM interface. +#define ACCESS_STREAM_RECORD false //!< Streaming MEM <-> MEM interface in record mode. +#define ACCESS_MEM_TO_MEM false //!< MEM <-> MEM interface. +#define ACCESS_CODEC false //!< Codec interface. +//! @} + +/*! \name Specific Options for Access Control + */ +//! @{ +#define GLOBAL_WR_PROTECT false //!< Management of a global write protection. +//! @} + + +#endif // _CONF_ACCESS_H_ diff --git a/atmel-samd/boards/itsybitsy_m0/conf_board.h b/atmel-samd/boards/itsybitsy_m0/conf_board.h new file mode 100644 index 0000000000..7b88c97fc2 --- /dev/null +++ b/atmel-samd/boards/itsybitsy_m0/conf_board.h @@ -0,0 +1,14 @@ +/** + * \file + * + * \brief User board configuration template + * + */ +/* + * Support and FAQ: visit Atmel Support + */ + +#ifndef CONF_BOARD_H +#define CONF_BOARD_H + +#endif // CONF_BOARD_H diff --git a/atmel-samd/boards/itsybitsy_m0/conf_clocks.h b/atmel-samd/boards/itsybitsy_m0/conf_clocks.h new file mode 100644 index 0000000000..9e4f7876be --- /dev/null +++ b/atmel-samd/boards/itsybitsy_m0/conf_clocks.h @@ -0,0 +1 @@ +#include "conf_clocks_crystalless.h" diff --git a/atmel-samd/boards/itsybitsy_m0/conf_usb.h b/atmel-samd/boards/itsybitsy_m0/conf_usb.h new file mode 100644 index 0000000000..5e8a61b884 --- /dev/null +++ b/atmel-samd/boards/itsybitsy_m0/conf_usb.h @@ -0,0 +1,221 @@ + +#include +#include + +#include "asf/common/services/usb/class/cdc/usb_protocol_cdc.h" + +#ifndef CONF_USB_H_INCLUDED +#define CONF_USB_H_INCLUDED + +#define USB_DEVICE_MAJOR_VERSION 1 +#define USB_DEVICE_MINOR_VERSION 0 +#define USB_DEVICE_POWER 100 // Consumption on Vbus line (mA) +#define USB_DEVICE_ATTR \ + (USB_CONFIG_ATTR_BUS_POWERED) +// (USB_CONFIG_ATTR_REMOTE_WAKEUP|USB_CONFIG_ATTR_SELF_POWERED) +// (USB_CONFIG_ATTR_REMOTE_WAKEUP|USB_CONFIG_ATTR_BUS_POWERED) + +//! USB Device string definitions (Optional) +#ifndef USB_DEVICE_MANUFACTURE_NAME +# define USB_DEVICE_MANUFACTURE_NAME "Adafruit Industries" +#endif + +#ifndef USB_DEVICE_PRODUCT_NAME +# define USB_DEVICE_PRODUCT_NAME "ItsyBitsy M0" +#endif +// #define USB_DEVICE_SERIAL_NAME "12...EF" +#define USB_DEVICE_GET_SERIAL_NAME_POINTER serial_number +#define USB_DEVICE_GET_SERIAL_NAME_LENGTH 32 +extern char serial_number[USB_DEVICE_GET_SERIAL_NAME_LENGTH]; + +//! Control endpoint size +#define USB_DEVICE_EP_CTRL_SIZE 64 + +//! Interfaces for this device (CDC COM + CDC DATA + MSC + HID mouse + HID kbd) +#define USB_DEVICE_NB_INTERFACE 5 + +// (3 | USB_EP_DIR_IN) // CDC Notify endpoint +// (4 | USB_EP_DIR_IN) // CDC TX +// (5 | USB_EP_DIR_OUT) // CDC RX +// (1 | USB_EP_DIR_IN) // MSC IN +// (2 | USB_EP_DIR_OUT) // MSC OUT +// (6 | USB_EP_DIR_IN) // HID mouse report +// (7 | USB_EP_DIR_IN) // HID keyboard report +#define USB_DEVICE_MAX_EP 7 + +#define UDI_CDC_PORT_NB 1 +#define UDI_CDC_ENABLE_EXT(port) mp_cdc_enable(port) +extern bool mp_cdc_enable(uint8_t port); +#define UDI_CDC_DISABLE_EXT(port) mp_cdc_disable(port) +extern void mp_cdc_disable(uint8_t port); +#define UDI_CDC_LOW_RATE + +#define UDI_CDC_DEFAULT_RATE 115200 +#define UDI_CDC_DEFAULT_STOPBITS CDC_STOP_BITS_1 +#define UDI_CDC_DEFAULT_PARITY CDC_PAR_NONE +#define UDI_CDC_DEFAULT_DATABITS 8 + +#define UDI_CDC_RX_NOTIFY(port) usb_rx_notify() +void usb_rx_notify(void); + +#define UDI_CDC_SET_CODING_EXT(port,cfg) usb_coding_notify(port, cfg) +void usb_coding_notify(uint8_t port, usb_cdc_line_coding_t* coding); +#define UDI_CDC_SET_DTR_EXT(port,set) usb_dtr_notify(port, set) +void usb_dtr_notify(uint8_t port, bool set); +#define UDI_CDC_SET_RTS_EXT(port,set) usb_rts_notify(port, set) +void usb_rts_notify(uint8_t port, bool set); + +/** + * USB CDC low level configuration + * In standalone these configurations are defined by the CDC module. + * For composite device, these configuration must be defined here + * @{ + */ +//! Endpoint numbers definition + +#define UDI_CDC_COMM_EP_0 (3 | USB_EP_DIR_IN) // Notify endpoint +#define UDI_CDC_DATA_EP_IN_0 (4 | USB_EP_DIR_IN) // TX +#define UDI_CDC_DATA_EP_OUT_0 (5 | USB_EP_DIR_OUT) // RX + +//! Interface numbers +#define UDI_CDC_COMM_IFACE_NUMBER_0 0 +#define UDI_CDC_DATA_IFACE_NUMBER_0 1 + +/** + * Configuration of MSC interface + * @{ + */ +//! Vendor name and Product version of MSC interface +#define UDI_MSC_GLOBAL_VENDOR_ID \ + 'A', 'T', 'M', 'E', 'L', ' ', ' ', ' ' +#define UDI_MSC_GLOBAL_PRODUCT_VERSION \ + '1', '.', '0', '0' + +//! Interface callback definition +#define UDI_MSC_ENABLE_EXT() mp_msc_enable() +extern bool mp_msc_enable(void); +#define UDI_MSC_DISABLE_EXT() mp_msc_disable() +extern void mp_msc_disable(void); + +//! Enable id string of interface to add an extra USB string +#define UDI_MSC_STRING_ID 5 + +/** + * USB MSC low level configuration + * In standalone these configurations are defined by the MSC module. + * For composite device, these configuration must be defined here + * @{ + */ +//! Endpoint numbers definition +#define UDI_MSC_EP_IN (1 | USB_EP_DIR_IN) +#define UDI_MSC_EP_OUT (2 | USB_EP_DIR_OUT) + +//! Interface number +#define UDI_MSC_IFACE_NUMBER 2 +/** + * Configuration of HID Mouse interface + * @{ + */ +//! Interface callback definition +#define UDI_HID_MOUSE_ENABLE_EXT() mp_mouse_enable() +extern bool mp_mouse_enable(void); +#define UDI_HID_MOUSE_DISABLE_EXT() mp_mouse_disable() +extern void mp_mouse_disable(void); + +//! Enable id string of interface to add an extra USB string +#define UDI_HID_MOUSE_STRING_ID 6 + +/** + * USB HID Mouse low level configuration + * In standalone these configurations are defined by the HID Mouse module. + * For composite device, these configuration must be defined here + * @{ + */ +//! Endpoint numbers definition +#define UDI_HID_MOUSE_EP_IN (6 | USB_EP_DIR_IN) + +//! Interface number +#define UDI_HID_MOUSE_IFACE_NUMBER 3 +//@} +//@} + +/** + * Configuration of HID Keyboard interface + * @{ + */ +//! Interface callback definition +#define UDI_HID_KBD_ENABLE_EXT() mp_keyboard_enable() +extern bool mp_keyboard_enable(void); +#define UDI_HID_KBD_DISABLE_EXT() mp_keyboard_disable() +extern void mp_keyboard_disable(void); +#define UDI_HID_KBD_CHANGE_LED(value) mp_keyboard_led(value) +extern void mp_keyboard_led(uint8_t); + +//! Enable id string of interface to add an extra USB string +#define UDI_HID_KBD_STRING_ID 7 + +/** + * USB HID Keyboard low level configuration + * In standalone these configurations are defined by the HID Keyboard module. + * For composite device, these configuration must be defined here + * @{ + */ +//! Endpoint numbers definition +#define UDI_HID_KBD_EP_IN (7 | USB_EP_DIR_IN) + +//! Interface number +#define UDI_HID_KBD_IFACE_NUMBER 4 + +/** + * Description of Composite Device + * @{ + */ +//! USB Interfaces descriptor structure +#define UDI_COMPOSITE_DESC_T \ + usb_iad_desc_t udi_cdc_iad; \ + udi_cdc_comm_desc_t udi_cdc_comm; \ + udi_cdc_data_desc_t udi_cdc_data; \ + udi_msc_desc_t udi_msc; \ + udi_hid_mouse_desc_t udi_hid_mouse; \ + udi_hid_kbd_desc_t udi_hid_kbd + +//! USB Interfaces descriptor value for Full Speed +#define UDI_COMPOSITE_DESC_FS \ + .udi_cdc_iad = UDI_CDC_IAD_DESC_0, \ + .udi_cdc_comm = UDI_CDC_COMM_DESC_0, \ + .udi_cdc_data = UDI_CDC_DATA_DESC_0_FS, \ + .udi_msc = UDI_MSC_DESC_FS, \ + .udi_hid_mouse = UDI_HID_MOUSE_DESC, \ + .udi_hid_kbd = UDI_HID_KBD_DESC + +//! USB Interfaces descriptor value for High Speed +#define UDI_COMPOSITE_DESC_HS \ + .udi_cdc_iad = UDI_CDC_IAD_DESC_0, \ + .udi_cdc_comm = UDI_CDC_COMM_DESC_0, \ + .udi_cdc_data = UDI_CDC_DATA_DESC_0_HS, \ + .udi_msc = UDI_MSC_DESC_HS, \ + .udi_hid_mouse = UDI_HID_MOUSE_DESC, \ + .udi_hid_kbd = UDI_HID_KBD_DESC + +//! USB Interface APIs +#define UDI_COMPOSITE_API \ + &udi_api_cdc_comm, \ + &udi_api_cdc_data, \ + &udi_api_msc, \ + &udi_api_hid_mouse, \ + &udi_api_hid_kbd +//@} + +/** + * USB Device Driver Configuration + * @{ + */ +//@} + +//! The includes of classes and other headers must be done at the end of this file to avoid compile error +#include "udi_cdc.h" +#include "udi_msc.h" +#include "udi_hid_mouse.h" +#include "udi_hid_kbd.h" + +#endif diff --git a/atmel-samd/boards/itsybitsy_m0/mpconfigboard.h b/atmel-samd/boards/itsybitsy_m0/mpconfigboard.h new file mode 100644 index 0000000000..e9fd08a5f6 --- /dev/null +++ b/atmel-samd/boards/itsybitsy_m0/mpconfigboard.h @@ -0,0 +1,36 @@ +#define USB_REPL + +#define MICROPY_HW_BOARD_NAME "Adafruit ItsyBitsy M0" +#define MICROPY_HW_MCU_NAME "samd21g18" + +#define CIRCUITPY_BITBANG_APA102 +#define MICROPY_HW_APA102_MOSI (&pin_PA01) +#define MICROPY_HW_APA102_SCK (&pin_PA00) + +#define MICROPY_PORT_A (PORT_PA00 | PORT_PA01 | PORT_PA27 | PORT_PA24 | PORT_PA25) +#define MICROPY_PORT_B (PORT_PB22 | PORT_PB23 | PORT_PB03 ) + +// Salae reads 12mhz which is the limit even though we set it to the safer 8mhz. +#define SPI_FLASH_BAUDRATE (8000000) + +#define SPI_FLASH_MUX_SETTING SPI_SIGNAL_MUX_SETTING_F +#define SPI_FLASH_PAD2_PINMUX PINMUX_PB22D_SERCOM5_PAD2 // MOSI +// Use default pinmux for the chip select since we manage it ourselves. +#define SPI_FLASH_PAD3_PINMUX PINMUX_PB23D_SERCOM5_PAD3 // SCK +#define SPI_FLASH_PAD1_PINMUX PINMUX_PB03D_SERCOM5_PAD1 // MISO +#define SPI_FLASH_PAD0_PINMUX PINMUX_UNUSED // +#define SPI_FLASH_SERCOM SERCOM5 + +#define SPI_FLASH_CS PIN_PA27 + + +#include "spi_flash.h" + +// If you change this, then make sure to update the linker scripts as well to +// make sure you don't overwrite code. +#define CIRCUITPY_INTERNAL_NVM_SIZE 256 +#define BOARD_FLASH_SIZE (0x00040000 - 0x2000 - CIRCUITPY_INTERNAL_NVM_SIZE) + +//#include "flash_S25FL216K.h" +#include "flash_W25Q80DV.h" +//#include "flash_GD25Q16C.h" diff --git a/atmel-samd/boards/itsybitsy_m0/mpconfigboard.mk b/atmel-samd/boards/itsybitsy_m0/mpconfigboard.mk new file mode 100644 index 0000000000..167d445954 --- /dev/null +++ b/atmel-samd/boards/itsybitsy_m0/mpconfigboard.mk @@ -0,0 +1,7 @@ +LD_FILE = boards/samd21x18-bootloader-external-flash-crystalless.ld +USB_VID = 0x239A +USB_PID = 0x8012 + +SPI_FLASH_FILESYSTEM = 1 + +CHIP_VARIANT = SAMD21G18A diff --git a/atmel-samd/boards/itsybitsy_m0/pins.c b/atmel-samd/boards/itsybitsy_m0/pins.c new file mode 100644 index 0000000000..b70bb6a76c --- /dev/null +++ b/atmel-samd/boards/itsybitsy_m0/pins.c @@ -0,0 +1,42 @@ +#include "samd21_pins.h" + +STATIC const mp_rom_map_elem_t board_global_dict_table[] = { + { MP_ROM_QSTR(MP_QSTR_D0), MP_ROM_PTR(&pin_PA11) }, + { MP_ROM_QSTR(MP_QSTR_RX), MP_ROM_PTR(&pin_PA11) }, + + { MP_ROM_QSTR(MP_QSTR_D1), MP_ROM_PTR(&pin_PA10) }, + { MP_ROM_QSTR(MP_QSTR_TX), MP_ROM_PTR(&pin_PA10) }, + + { MP_ROM_QSTR(MP_QSTR_D2), MP_ROM_PTR(&pin_PA14) }, + { MP_ROM_QSTR(MP_QSTR_D3), MP_ROM_PTR(&pin_PA09) }, + { MP_ROM_QSTR(MP_QSTR_D4), MP_ROM_PTR(&pin_PA08) }, + { MP_ROM_QSTR(MP_QSTR_D5), MP_ROM_PTR(&pin_PA15) }, + { MP_ROM_QSTR(MP_QSTR_D6), MP_ROM_PTR(&pin_PA20) }, + { MP_ROM_QSTR(MP_QSTR_D7), MP_ROM_PTR(&pin_PA21) }, + { MP_ROM_QSTR(MP_QSTR_D8), MP_ROM_PTR(&pin_PA06) }, + { MP_ROM_QSTR(MP_QSTR_D9), MP_ROM_PTR(&pin_PA07) }, + { MP_ROM_QSTR(MP_QSTR_D10), MP_ROM_PTR(&pin_PA18) }, + { MP_ROM_QSTR(MP_QSTR_D11), MP_ROM_PTR(&pin_PA16) }, + { MP_ROM_QSTR(MP_QSTR_D12), MP_ROM_PTR(&pin_PA19) }, + + { MP_ROM_QSTR(MP_QSTR_D13), MP_ROM_PTR(&pin_PA17) }, + { MP_ROM_QSTR(MP_QSTR_L), MP_ROM_PTR(&pin_PA17) }, // a.k.a D13 + + { MP_ROM_QSTR(MP_QSTR_A0), MP_ROM_PTR(&pin_PA02) }, + { MP_ROM_QSTR(MP_QSTR_A1), MP_ROM_PTR(&pin_PB08) }, + { MP_ROM_QSTR(MP_QSTR_A2), MP_ROM_PTR(&pin_PB09) }, + { MP_ROM_QSTR(MP_QSTR_A3), MP_ROM_PTR(&pin_PA04) }, + { MP_ROM_QSTR(MP_QSTR_A4), MP_ROM_PTR(&pin_PA05) }, + { MP_ROM_QSTR(MP_QSTR_A5), MP_ROM_PTR(&pin_PB02) }, + + { MP_ROM_QSTR(MP_QSTR_MOSI), MP_ROM_PTR(&pin_PB10) }, + { MP_ROM_QSTR(MP_QSTR_MISO), MP_ROM_PTR(&pin_PA12) }, + { MP_ROM_QSTR(MP_QSTR_SCK), MP_ROM_PTR(&pin_PB11) }, + + { MP_ROM_QSTR(MP_QSTR_SCL), MP_ROM_PTR(&pin_PA23) }, + { MP_ROM_QSTR(MP_QSTR_SDA), MP_ROM_PTR(&pin_PA22) }, + + { MP_ROM_QSTR(MP_QSTR_APA102_MOSI), MP_ROM_PTR(&pin_PA01) }, + { MP_ROM_QSTR(MP_QSTR_APA102_SCK), MP_ROM_PTR(&pin_PA00) }, +}; +MP_DEFINE_CONST_DICT(board_module_globals, board_global_dict_table); diff --git a/tools/build_adafruit_bins.sh b/tools/build_adafruit_bins.sh index 462ec97113..f8789b9fb6 100755 --- a/tools/build_adafruit_bins.sh +++ b/tools/build_adafruit_bins.sh @@ -1,7 +1,7 @@ rm -rf atmel-samd/build* rm -rf esp8266/build* -ATMEL_BOARDS="arduino_zero circuitplayground_express feather_m0_basic feather_m0_adalogger feather_m0_express metro_m0_express trinket_m0 gemma_m0" +ATMEL_BOARDS="arduino_zero circuitplayground_express feather_m0_basic feather_m0_adalogger feather_m0_express metro_m0_express trinket_m0 gemma_m0 itsybitsy_m0" ROSIE_SETUPS="rosie-ci" for board in $ATMEL_BOARDS; do From 1276ce59c33338e9dee604068092af067c25e5f2 Mon Sep 17 00:00:00 2001 From: Radomir Dopieralski Date: Tue, 21 Nov 2017 23:12:55 +0100 Subject: [PATCH 024/135] Fix display orientation for _stage module Initially this library assumed the display is rotated by 90 degrees, so the x and y were swapped. I'm now handling the display rotation in the driver, with the hardware display settings, so the library should use a sane order of x and y. This way it will work with any display orientation. --- shared-module/_stage/Layer.c | 34 +++++++++++++++++----------------- shared-module/_stage/Text.c | 4 ++-- 2 files changed, 19 insertions(+), 19 deletions(-) diff --git a/shared-module/_stage/Layer.c b/shared-module/_stage/Layer.c index 3315ac69e1..4c9c46d7c6 100644 --- a/shared-module/_stage/Layer.c +++ b/shared-module/_stage/Layer.c @@ -47,8 +47,8 @@ uint16_t get_layer_pixel(layer_obj_t *layer, int16_t x, uint16_t y) { uint8_t tx = x >> 4; uint8_t ty = y >> 4; - frame = layer->map[(tx * layer->width + ty) >> 1]; - if (ty & 0x01) { + frame = layer->map[(ty * layer->width + tx) >> 1]; + if (tx & 0x01) { frame &= 0x0f; } else { frame >>= 4; @@ -60,41 +60,41 @@ uint16_t get_layer_pixel(layer_obj_t *layer, int16_t x, uint16_t y) { y &= 0x0f; // Rotate the image. - uint8_t tx = x; // Temporary variable for swapping. + uint8_t ty = y; // Temporary variable for swapping. switch (layer->rotation) { case 1: // 90 degrees clockwise - x = 15 - y; - y = tx; + y = 15 - x; + x = ty; break; case 2: // 180 degrees - x = 15 - tx; - y = 15 - y; + y = 15 - ty; + x = 15 - x; break; case 3: // 90 degrees counter-clockwise - x = y; - y = 15 - tx; + y = x; + x = 15 - ty; break; case 4: // 0 degrees, mirrored - y = 15 - y; + x = 15 - x; break; case 5: // 90 degrees clockwise, mirrored - x = y; - y = tx; + y = x; + x = ty; break; case 6: // 180 degrees, mirrored - x = 15 - tx; + y = 15 - ty; break; case 7: // 90 degrees counter-clockwise, mirrored - x = 15 - y; - y = 15 - tx; + y = 15 - x; + x = 15 - ty; break; default: // 0 degrees break; } // Get the value of the pixel. - uint8_t pixel = layer->graphic[(frame << 7) + (x << 3) + (y >> 1)]; - if (y & 0x01) { + uint8_t pixel = layer->graphic[(frame << 7) + (y << 3) + (x >> 1)]; + if (x & 0x01) { pixel &= 0x0f; } else { pixel >>= 4; diff --git a/shared-module/_stage/Text.c b/shared-module/_stage/Text.c index 6c451bf38f..307f9bbfa7 100644 --- a/shared-module/_stage/Text.c +++ b/shared-module/_stage/Text.c @@ -59,8 +59,8 @@ uint16_t get_text_pixel(text_obj_t *text, int16_t x, uint16_t y) { y &= 0x07; // Get the value of the pixel. - uint8_t pixel = text->font[(c << 4) + (x << 1) + (y >> 2)]; - pixel = ((pixel >> ((y & 0x03) << 1)) & 0x03) + color_offset; + uint8_t pixel = text->font[(c << 4) + (y << 1) + (x >> 2)]; + pixel = ((pixel >> ((x & 0x03) << 1)) & 0x03) + color_offset; // Convert to 16-bit color using the palette. return text->palette[pixel << 1] | text->palette[(pixel << 1) + 1] << 8; From a41272dcd372d5603f8f4a49e7b608775ac1251c Mon Sep 17 00:00:00 2001 From: Stewart Date: Mon, 27 Nov 2017 00:08:27 -0500 Subject: [PATCH 025/135] atmel-samd: Added missing adalogger pins (#461) - Added D4 and moved associated SD_CS so that they are paired within list - Added D7 and SD_CD which is the SD Card Detect pin - Added D8 and GREEN_LED - Added RED_LED associated with D13 - Added Setup information regarding arm complier packages --- README.md | 2 +- atmel-samd/README.rst | 17 +++++++++++++---- atmel-samd/boards/feather_m0_adalogger/pins.c | 8 +++++++- 3 files changed, 21 insertions(+), 6 deletions(-) diff --git a/README.md b/README.md index 5c4fc236e8..dedafb96b6 100644 --- a/README.md +++ b/README.md @@ -38,7 +38,7 @@ This project is in beta. Most APIs should be stable going forward. * [Adafruit Feather HUZZAH][] * [Adafruit Feather M0 Basic][] * [Adafruit Feather M0 Bluefruit LE][] (uses M0 Basic binaries) -* [Adafruit Feather M0 Adalogger][] (MicroSD card not supported yet.) +* [Adafruit Feather M0 Adalogger][] (MicroSD card supported using the [Adafruit CircuitPython SD library](https://github.com/adafruit/Adafruit_CircuitPython_SD)) * [Arduino Zero][] ## Download diff --git a/atmel-samd/README.rst b/atmel-samd/README.rst index 9352f47d67..5c314c53f6 100644 --- a/atmel-samd/README.rst +++ b/atmel-samd/README.rst @@ -28,9 +28,9 @@ PB08 ``A1`` ``A7`` / ``TX`` ``A1`` PB09 ``A2`` ``A6`` / ``RX`` ``A2`` ``A2`` ``A2`` ``A2`` PA04 ``A3`` ``IR_PROXIMITY`` ``A3`` ``A3`` ``A3`` ``D0`` / ``TX`` / ``SDA`` ``A3`` PA05 ``A4`` ``A1`` ``A4`` ``A4`` ``A4`` ``D2`` / ``RX`` / ``SCL`` ``A4`` -PA06 ``D8`` ``A2`` ``NEOPIXEL`` ``D8`` ``D4`` / ``TX`` +PA06 ``D8`` ``A2`` ``D8`` / ``GREEN_LED`` ``NEOPIXEL`` ``D8`` ``D4`` / ``TX`` PA07 ``D9`` ``A3`` ``D9`` ``D9`` ``D9`` ``D9`` ``D3`` / ``RX`` -PA08 ``D4`` ``MICROPHONE_DO`` ``SD_CS`` ``D4`` ``D0`` / ``SDA`` +PA08 ``D4`` ``MICROPHONE_DO`` ``D4`` / ``SD_CS`` ``D4`` ``D0`` / ``SDA`` PA09 ``D3`` ``TEMPERATURE`` / ``A9`` ``D3`` ``D2`` / ``SCL`` PA10 ``D1`` / ``TX`` ``MICROPHONE_SCK`` ``D1`` / ``TX`` ``D1`` / ``TX`` ``D1`` / ``TX`` ``D1`` / ``TX`` ``D13`` PA11 ``D0`` / ``RX`` ``LIGHT`` / ``A8`` ``D0`` / ``RX`` ``D0`` / ``RX`` ``D0`` / ``RX`` ``D0`` / ``RX`` @@ -41,11 +41,11 @@ PA13 ``ACCELEROMETER_INTERRUPT`` PA14 ``D2`` ``BUTTON_B`` / ``D5`` ``D2`` PA15 ``D5`` ``SLIDE_SWITCH`` / ``D7`` ``D5`` ``D5`` ``D5`` ``D5`` PA16 ``D11`` ``MISO`` ``D11`` ``D11`` ``D11`` ``D11`` -PA17 ``D13`` ``D13`` ``D13`` ``D13`` ``D13`` ``D13`` +PA17 ``D13`` ``D13`` ``D13`` / ``RED_LED`` ``D13`` ``D13`` ``D13`` PA18 ``D10`` ``D10`` ``D10`` ``D10`` ``D10`` PA19 ``D12`` ``D12`` ``D12`` ``D12`` ``D12`` PA20 ``D6`` ``MOSI`` ``D6`` ``D6`` ``D6`` ``D6`` -PA21 ``D7`` ``SCK`` ``D7`` +PA21 ``D7`` ``SCK`` ``D7`` / ``SD_CD`` ``D7`` PA22 ``SDA`` ``SDA`` ``SDA`` ``SDA`` ``SDA`` PA23 ``SCL`` ``REMOTEOUT`` / ``IR_TX`` ``SCL`` ``SCL`` ``SCL`` ``L`` / ``D13`` ``SCL`` PA24 @@ -113,6 +113,15 @@ PB02 **Yes** **Yes** **Yes** **Yes** PB03 **Yes** **Yes** **Yes** **Yes** **Yes** **Yes** **Yes** **Yes** **Yes** **Yes** **Yes** **Yes** ===================== ======== ========= ========= ======= ======= ======= ========= ========= ======= ========== ========== ========= ========= ========= ============ ======= ======= ========= +Setup +----- +Install required compiler packages: + +.. code-block:: shell + + sudo add-apt-repository ppa:team-gcc-arm-embedded/ppa + sudo apt-get install gcc-arm-embedded + Building -------- diff --git a/atmel-samd/boards/feather_m0_adalogger/pins.c b/atmel-samd/boards/feather_m0_adalogger/pins.c index 6b2094b72c..a229b6bab1 100644 --- a/atmel-samd/boards/feather_m0_adalogger/pins.c +++ b/atmel-samd/boards/feather_m0_adalogger/pins.c @@ -6,7 +6,6 @@ STATIC const mp_rom_map_elem_t board_global_dict_table[] = { { MP_ROM_QSTR(MP_QSTR_A2), MP_ROM_PTR(&pin_PB09) }, { MP_ROM_QSTR(MP_QSTR_A3), MP_ROM_PTR(&pin_PA04) }, { MP_ROM_QSTR(MP_QSTR_A4), MP_ROM_PTR(&pin_PA05) }, - { MP_ROM_QSTR(MP_QSTR_SD_CS), MP_ROM_PTR(&pin_PA08) }, { MP_ROM_QSTR(MP_QSTR_A5), MP_ROM_PTR(&pin_PB02) }, { MP_ROM_QSTR(MP_QSTR_SCK), MP_ROM_PTR(&pin_PB11) }, { MP_ROM_QSTR(MP_QSTR_MOSI), MP_ROM_PTR(&pin_PB10) }, @@ -17,12 +16,19 @@ STATIC const mp_rom_map_elem_t board_global_dict_table[] = { { MP_ROM_QSTR(MP_QSTR_TX), MP_ROM_PTR(&pin_PA10) }, { MP_ROM_QSTR(MP_QSTR_SDA), MP_ROM_PTR(&pin_PA22) }, { MP_ROM_QSTR(MP_QSTR_SCL), MP_ROM_PTR(&pin_PA23) }, + { MP_ROM_QSTR(MP_QSTR_D4), MP_ROM_PTR(&pin_PA08) }, + { MP_ROM_QSTR(MP_QSTR_SD_CS), MP_ROM_PTR(&pin_PA08) }, { MP_ROM_QSTR(MP_QSTR_D5), MP_ROM_PTR(&pin_PA15) }, { MP_ROM_QSTR(MP_QSTR_D6), MP_ROM_PTR(&pin_PA20) }, + { MP_ROM_QSTR(MP_QSTR_D7), MP_ROM_PTR(&pin_PA21) }, + { MP_ROM_QSTR(MP_QSTR_SD_CD), MP_ROM_PTR(&pin_PA21) }, + { MP_ROM_QSTR(MP_QSTR_D8), MP_ROM_PTR(&pin_PA06) }, + { MP_ROM_QSTR(MP_QSTR_GREEN_LED), MP_ROM_PTR(&pin_PA06) }, { MP_ROM_QSTR(MP_QSTR_D9), MP_ROM_PTR(&pin_PA07) }, { MP_ROM_QSTR(MP_QSTR_D10), MP_ROM_PTR(&pin_PA18) }, { MP_ROM_QSTR(MP_QSTR_D11), MP_ROM_PTR(&pin_PA16) }, { MP_ROM_QSTR(MP_QSTR_D12), MP_ROM_PTR(&pin_PA19) }, { MP_ROM_QSTR(MP_QSTR_D13), MP_ROM_PTR(&pin_PA17) }, + { MP_ROM_QSTR(MP_QSTR_RED_LED), MP_ROM_PTR(&pin_PA17) }, }; MP_DEFINE_CONST_DICT(board_module_globals, board_global_dict_table); From 9ac6890d209ed2055321b39b5ae0d95709b076ea Mon Sep 17 00:00:00 2001 From: Dan Halbert Date: Thu, 30 Nov 2017 19:27:30 -0500 Subject: [PATCH 026/135] update CPX frozen modules to latest versions --- .gitignore | 9 +++++++++ frozen/Adafruit_CircuitPython_BusDevice | 2 +- frozen/Adafruit_CircuitPython_LIS3DH | 2 +- frozen/Adafruit_CircuitPython_NeoPixel | 2 +- frozen/Adafruit_CircuitPython_Thermistor | 2 +- 5 files changed, 13 insertions(+), 4 deletions(-) diff --git a/.gitignore b/.gitignore index 6f19fe788e..61219390e7 100644 --- a/.gitignore +++ b/.gitignore @@ -48,3 +48,12 @@ _build # Generated rst files ###################### genrst/ + +# ctags and similar +################### +TAGS + +# Merge leftovers +################# +*.orig + diff --git a/frozen/Adafruit_CircuitPython_BusDevice b/frozen/Adafruit_CircuitPython_BusDevice index 39f28ed4e0..be325b94a3 160000 --- a/frozen/Adafruit_CircuitPython_BusDevice +++ b/frozen/Adafruit_CircuitPython_BusDevice @@ -1 +1 @@ -Subproject commit 39f28ed4e0e5a06fc33fd01c1efc8c52c4140f03 +Subproject commit be325b94a3254cc1dc8deccfcab8942b3d915774 diff --git a/frozen/Adafruit_CircuitPython_LIS3DH b/frozen/Adafruit_CircuitPython_LIS3DH index fa00b61d1b..8a7d9d99d2 160000 --- a/frozen/Adafruit_CircuitPython_LIS3DH +++ b/frozen/Adafruit_CircuitPython_LIS3DH @@ -1 +1 @@ -Subproject commit fa00b61d1bde90c3cf9cce74388cb9717058b2be +Subproject commit 8a7d9d99d2157376679735130b97bf236ccf755f diff --git a/frozen/Adafruit_CircuitPython_NeoPixel b/frozen/Adafruit_CircuitPython_NeoPixel index 1142f1c7fd..cafc445f08 160000 --- a/frozen/Adafruit_CircuitPython_NeoPixel +++ b/frozen/Adafruit_CircuitPython_NeoPixel @@ -1 +1 @@ -Subproject commit 1142f1c7fdc232a46d74dd4f1946a5f462ae2555 +Subproject commit cafc445f080736beefb1694ae79359a3be0c7bbb diff --git a/frozen/Adafruit_CircuitPython_Thermistor b/frozen/Adafruit_CircuitPython_Thermistor index 2d57c0ba9a..0339da36f7 160000 --- a/frozen/Adafruit_CircuitPython_Thermistor +++ b/frozen/Adafruit_CircuitPython_Thermistor @@ -1 +1 @@ -Subproject commit 2d57c0ba9a09d6d30f0ae2b98aba9567c25e6fb6 +Subproject commit 0339da36f78d2a598c559c26df4b60245f34a545 From e75fd0e166375727fbb4c054478c9c8d329477c4 Mon Sep 17 00:00:00 2001 From: Dan Halbert Date: Mon, 4 Dec 2017 21:49:31 -0500 Subject: [PATCH 027/135] add SPI.write_readinto() - bidirectional SPI --- atmel-samd/common-hal/busio/SPI.c | 13 +++++ atmel-samd/shared_dma.c | 18 +++++-- atmel-samd/shared_dma.h | 1 + shared-bindings/busio/SPI.c | 83 +++++++++++++++++++++++++++---- shared-bindings/busio/SPI.h | 3 ++ 5 files changed, 103 insertions(+), 15 deletions(-) diff --git a/atmel-samd/common-hal/busio/SPI.c b/atmel-samd/common-hal/busio/SPI.c index c1b13cec88..e5a945df2f 100644 --- a/atmel-samd/common-hal/busio/SPI.c +++ b/atmel-samd/common-hal/busio/SPI.c @@ -257,3 +257,16 @@ bool common_hal_busio_spi_read(busio_spi_obj_t *self, } return status == STATUS_OK; } + +bool common_hal_busio_spi_transfer(busio_spi_obj_t *self, uint8_t *data_out, uint8_t *data_in, size_t len) { + if (len == 0) { + return true; + } + enum status_code status; + if (len >= 16) { + status = shared_dma_transfer(self->spi_master_instance.hw, data_out, data_in, len, 0 /*ignored*/); + } else { + status = spi_transceive_buffer_wait(&self->spi_master_instance, data_out, data_in, len); + } + return status == STATUS_OK; +} diff --git a/atmel-samd/shared_dma.c b/atmel-samd/shared_dma.c index 4617983666..c0f0d4672c 100644 --- a/atmel-samd/shared_dma.c +++ b/atmel-samd/shared_dma.c @@ -103,7 +103,7 @@ enum status_code shared_dma_write(Sercom* sercom, const uint8_t* buffer, uint32_ } dma_configure(general_dma_tx.channel_id, sercom_index(sercom) * 2 + 2, false); - // Set up TX second. + // Set up TX. There is no RX job. struct dma_descriptor_config descriptor_config; dma_descriptor_get_config_defaults(&descriptor_config); descriptor_config.beat_size = DMA_BEAT_SIZE_BYTE; @@ -137,6 +137,12 @@ enum status_code shared_dma_write(Sercom* sercom, const uint8_t* buffer, uint32_ } enum status_code shared_dma_read(Sercom* sercom, uint8_t* buffer, uint32_t length, uint8_t tx) { + return shared_dma_transfer(sercom, NULL, buffer, length, tx); +} + +// Do write and read simultaneously. If buffer_out is NULL, write the tx byte over and over. +// If buffer_out is a real buffer, ignore tx. +enum status_code shared_dma_transfer(Sercom* sercom, uint8_t* buffer_out, uint8_t* buffer_in, uint32_t length, uint8_t tx) { if (general_dma_tx.job_status != STATUS_OK) { return general_dma_tx.job_status; } @@ -153,17 +159,19 @@ enum status_code shared_dma_read(Sercom* sercom, uint8_t* buffer, uint32_t lengt descriptor_config.block_transfer_count = length; // DATA register is consistently addressed across all SERCOM modes. descriptor_config.source_address = ((uint32_t)&sercom->SPI.DATA.reg); - descriptor_config.destination_address = ((uint32_t)buffer + length); + descriptor_config.destination_address = ((uint32_t)buffer_in + length); dma_descriptor_create(general_dma_rx.descriptor, &descriptor_config); - // Set up TX to retransmit the same byte over and over. + // Set up TX second. dma_descriptor_get_config_defaults(&descriptor_config); descriptor_config.beat_size = DMA_BEAT_SIZE_BYTE; - descriptor_config.src_increment_enable = false; + // Increment write address only if we have a real buffer. + descriptor_config.src_increment_enable = buffer_out != NULL; descriptor_config.dst_increment_enable = false; descriptor_config.block_transfer_count = length; - descriptor_config.source_address = ((uint32_t)&tx); + // + descriptor_config.source_address = ((uint32_t) (buffer_out != NULL ? buffer_out + length : &tx)); // DATA register is consistently addressed across all SERCOM modes. descriptor_config.destination_address = ((uint32_t)&sercom->SPI.DATA.reg); diff --git a/atmel-samd/shared_dma.h b/atmel-samd/shared_dma.h index 7aa45547d0..251b8357b6 100644 --- a/atmel-samd/shared_dma.h +++ b/atmel-samd/shared_dma.h @@ -39,6 +39,7 @@ void init_shared_dma(void); enum status_code shared_dma_write(Sercom* sercom, const uint8_t* buffer, uint32_t length); enum status_code shared_dma_read(Sercom* sercom, uint8_t* buffer, uint32_t length, uint8_t tx); +enum status_code shared_dma_transfer(Sercom* sercom, uint8_t* buffer_out, uint8_t* buffer_in, uint32_t length, uint8_t tx); // Allocate a counter to track how far along we are in a DMA double buffer. bool allocate_block_counter(void); diff --git a/shared-bindings/busio/SPI.c b/shared-bindings/busio/SPI.c index 72787af30b..c4c139105f 100644 --- a/shared-bindings/busio/SPI.c +++ b/shared-bindings/busio/SPI.c @@ -206,12 +206,12 @@ MP_DEFINE_CONST_FUN_OBJ_1(busio_spi_unlock_obj, busio_spi_obj_unlock); //| .. method:: SPI.write(buffer, \*, start=0, end=len(buffer)) //| -//| Write the data contained in ``buf``. Requires the SPI being locked. +//| Write the data contained in ``buffer``. The SPI object must be locked. //| If the buffer is empty, nothing happens. //| -//| :param bytearray buffer: buffer containing the bytes to write -//| :param int start: Index to start writing from -//| :param int end: Index to read up to but not include +//| :param bytearray buffer: Write out the data in this buffer +//| :param int start: Start of the slice of ``buffer`` to write out: ``buffer[start:end]`` +//| :param int end: End of the slice; this index is not included //| STATIC mp_obj_t busio_spi_write(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) { enum { ARG_buffer, ARG_start, ARG_end }; @@ -247,14 +247,14 @@ MP_DEFINE_CONST_FUN_OBJ_KW(busio_spi_write_obj, 2, busio_spi_write); //| .. method:: SPI.readinto(buffer, \*, start=0, end=len(buffer), write_value=0) //| -//| Read into the buffer specified by ``buf`` while writing zeroes. -//| Requires the SPI being locked. +//| Read into ``buffer`` while writing ``write_value`` for each byte read. +//| The SPI object must be locked. //| If the number of bytes to read is 0, nothing happens. //| -//| :param bytearray buffer: buffer to write into -//| :param int start: Index to start writing at -//| :param int end: Index to write up to but not include -//| :param int write_value: Value to write reading. (Usually ignored.) +//| :param bytearray buffer: Read data into this buffer +//| :param int start: Start of the slice of ``buffer`` to read into: ``buffer[start:end]`` +//| :param int end: End of the slice; this index is not included +//| :param int write_value: Value to write while reading. (Usually ignored.) //| STATIC mp_obj_t busio_spi_readinto(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) { enum { ARG_buffer, ARG_start, ARG_end, ARG_write_value }; @@ -288,6 +288,68 @@ STATIC mp_obj_t busio_spi_readinto(size_t n_args, const mp_obj_t *pos_args, mp_m } MP_DEFINE_CONST_FUN_OBJ_KW(busio_spi_readinto_obj, 2, busio_spi_readinto); +//| .. method:: SPI.write_readinto(buffer_out, buffer_in, \*, out_start=0, out_end=len(buffer_out), in_start=0, in_end=len(buffer_in)) +//| +//| Write out the data in ``buffer_out`` while simultaneously reading data into ``buffer_in``. +//| The SPI object must be locked. +//| The lengths of the slices defined by ``buffer_out[out_start:out_end]`` and ``buffer_in[in_start:in_end]`` +//| must be equal. +//| If buffer slice lengths are both 0, nothing happens. +//| +//| :param bytearray buffer_out: Write out the data in this buffer +//| :param bytearray buffer_in: Read data into this buffer +//| :param int out_start: Start of the slice of buffer_out to write out: ``buffer_out[out_start:out_end]`` +//| :param int out_end: End of the slice; this index is not included +//| :param int in_start: Start of the slice of ``buffer_in`` to read into: ``buffer_in[in_start:in_end]`` +//| :param int in_end: End of the slice; this index is not included +//| +STATIC mp_obj_t busio_spi_write_readinto(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) { + enum { ARG_buffer_out, ARG_buffer_in, ARG_out_start, ARG_out_end, ARG_in_start, ARG_in_end }; + static const mp_arg_t allowed_args[] = { + { MP_QSTR_buffer_out, MP_ARG_REQUIRED | MP_ARG_OBJ, {.u_obj = MP_OBJ_NULL} }, + { MP_QSTR_buffer_in, MP_ARG_REQUIRED | MP_ARG_OBJ, {.u_obj = MP_OBJ_NULL} }, + { MP_QSTR_out_start, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = 0} }, + { MP_QSTR_out_end, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = INT_MAX} }, + { MP_QSTR_in_start, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = 0} }, + { MP_QSTR_in_end, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = INT_MAX} }, + }; + busio_spi_obj_t *self = MP_OBJ_TO_PTR(pos_args[0]); + raise_error_if_deinited(common_hal_busio_spi_deinited(self)); + check_lock(self); + mp_arg_val_t args[MP_ARRAY_SIZE(allowed_args)]; + mp_arg_parse_all(n_args - 1, pos_args + 1, kw_args, MP_ARRAY_SIZE(allowed_args), allowed_args, args); + + mp_buffer_info_t buf_out_info; + mp_get_buffer_raise(args[ARG_buffer_out].u_obj, &buf_out_info, MP_BUFFER_READ); + int32_t out_start = args[ARG_out_start].u_int; + uint32_t out_length = buf_out_info.len; + normalize_buffer_bounds(&out_start, args[ARG_out_end].u_int, &out_length); + + mp_buffer_info_t buf_in_info; + mp_get_buffer_raise(args[ARG_buffer_in].u_obj, &buf_in_info, MP_BUFFER_WRITE); + int32_t in_start = args[ARG_in_start].u_int; + uint32_t in_length = buf_in_info.len; + normalize_buffer_bounds(&in_start, args[ARG_in_end].u_int, &in_length); + + if (out_length != in_length) { + mp_raise_ValueError("buffer slices must be of equal length"); + } + + if (out_length == 0) { + return mp_const_none; + } + + bool ok = common_hal_busio_spi_transfer(self, + ((uint8_t*)buf_out_info.buf) + out_start, + ((uint8_t*)buf_in_info.buf) + in_start, + out_length); + if (!ok) { + mp_raise_OSError(MP_EIO); + } + return mp_const_none; +} +MP_DEFINE_CONST_FUN_OBJ_KW(busio_spi_write_readinto_obj, 2, busio_spi_write_readinto); + STATIC const mp_rom_map_elem_t busio_spi_locals_dict_table[] = { { MP_ROM_QSTR(MP_QSTR_deinit), MP_ROM_PTR(&busio_spi_deinit_obj) }, { MP_ROM_QSTR(MP_QSTR___enter__), MP_ROM_PTR(&default___enter___obj) }, @@ -299,6 +361,7 @@ STATIC const mp_rom_map_elem_t busio_spi_locals_dict_table[] = { { MP_ROM_QSTR(MP_QSTR_readinto), MP_ROM_PTR(&busio_spi_readinto_obj) }, { MP_ROM_QSTR(MP_QSTR_write), MP_ROM_PTR(&busio_spi_write_obj) }, + { MP_ROM_QSTR(MP_QSTR_write_readinto), MP_ROM_PTR(&busio_spi_write_readinto_obj) }, }; STATIC MP_DEFINE_CONST_DICT(busio_spi_locals_dict, busio_spi_locals_dict_table); diff --git a/shared-bindings/busio/SPI.h b/shared-bindings/busio/SPI.h index ac31d5060d..b6e5c9b1b3 100644 --- a/shared-bindings/busio/SPI.h +++ b/shared-bindings/busio/SPI.h @@ -55,4 +55,7 @@ extern bool common_hal_busio_spi_write(busio_spi_obj_t *self, const uint8_t *dat // Reads in len bytes while outputting zeroes. extern bool common_hal_busio_spi_read(busio_spi_obj_t *self, uint8_t *data, size_t len, uint8_t write_value); +// Reads and write len bytes simultaneously. +extern bool common_hal_busio_spi_transfer(busio_spi_obj_t *self, uint8_t *data_out, uint8_t *data_in, size_t len); + #endif // MICROPY_INCLUDED_SHARED_BINDINGS_BUSIO_SPI_H From 2900ed22e714b64c8bb7c41b0f06bb57c4d237c2 Mon Sep 17 00:00:00 2001 From: Dan Halbert Date: Tue, 5 Dec 2017 16:03:22 -0500 Subject: [PATCH 028/135] add SPI.write_readinto() to esp8266 port --- esp8266/common-hal/busio/SPI.c | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/esp8266/common-hal/busio/SPI.c b/esp8266/common-hal/busio/SPI.c index fc8dd348f1..3117c80e10 100644 --- a/esp8266/common-hal/busio/SPI.c +++ b/esp8266/common-hal/busio/SPI.c @@ -185,3 +185,23 @@ bool common_hal_busio_spi_read(busio_spi_obj_t *self, } return true; } + +bool common_hal_busio_spi_transfer(busio_spi_obj_t *self, uint8_t *data_out, uint8_t *data_in, size_t len) { + // Process data in chunks, let the pending tasks run in between + size_t chunk_size = 1024; // TODO this should depend on baudrate + size_t count = len / chunk_size; + size_t i = 0; + for (size_t j = 0; j < count; ++j) { + for (size_t k = 0; k < chunk_size; ++k) { + data_in[i] = spi_transaction(HSPI, 0, 0, 0, 0, 8, data_out[i], 8, 0); + ++i; + } + ets_loop_iter(); + } + while (i < len) { + data_in[i] = spi_transaction(HSPI, 0, 0, 0, 0, 8, data_out[i], 8, 0); + ++i; + } + return true; + +} From b4d36990479888a0be503383367fbd1bd9b6976b Mon Sep 17 00:00:00 2001 From: Scott Shawcroft Date: Tue, 5 Dec 2017 14:50:58 -0800 Subject: [PATCH 029/135] Introduce reset mechanics to microcontroller. This allows one to configure how a subsequent reset will behave and also trigger a reset. Fixes #350 and fixes #173 --- atmel-samd/Makefile | 2 + .../samd21x18-bootloader-crystalless.ld | 3 +- ...8-bootloader-external-flash-crystalless.ld | 3 +- .../samd21x18-bootloader-external-flash.ld | 3 +- atmel-samd/boards/samd21x18-bootloader.ld | 3 +- atmel-samd/boards/samd21x18-external-flash.ld | 1 + atmel-samd/boards/samd21x18.ld | 1 + .../common-hal/digitalio/DigitalInOut.c | 14 +-- .../common-hal/microcontroller/__init__.c | 31 ++++++- atmel-samd/main.c | 20 ++++- atmel-samd/mphalport.c | 2 +- atmel-samd/reset.c | 12 +-- atmel-samd/reset.h | 6 ++ esp8266/Makefile | 1 + esp8266/common-hal/digitalio/DigitalInOut.c | 14 +-- esp8266/common-hal/microcontroller/__init__.c | 18 +++- shared-bindings/digitalio/DigitalInOut.c | 14 +-- shared-bindings/digitalio/DigitalInOut.h | 14 +-- shared-bindings/digitalio/Direction.h | 4 +- shared-bindings/digitalio/DriveMode.h | 4 +- shared-bindings/digitalio/Pull.h | 4 +- shared-bindings/microcontroller/RunMode.c | 90 +++++++++++++++++++ shared-bindings/microcontroller/RunMode.h | 47 ++++++++++ shared-bindings/microcontroller/__init__.c | 44 +++++++++ shared-bindings/microcontroller/__init__.h | 5 ++ 25 files changed, 308 insertions(+), 52 deletions(-) create mode 100644 shared-bindings/microcontroller/RunMode.c create mode 100644 shared-bindings/microcontroller/RunMode.h diff --git a/atmel-samd/Makefile b/atmel-samd/Makefile index f6c183ba92..b5d2037a24 100644 --- a/atmel-samd/Makefile +++ b/atmel-samd/Makefile @@ -123,6 +123,7 @@ CFLAGS_CORTEX_M0 = \ -DI2S_CALLBACK_MODE=false \ -DTC_ASYNC=true \ -DUSB_DEVICE_LPM_SUPPORT \ + -DCIRCUITPY_SOFTWARE_SAFE_MODE=0x0ADABEEF \ -DCIRCUITPY_CANARY_WORD=0xADAF00 \ -DCIRCUITPY_SAFE_RESTART_WORD=0xDEADBEEF \ --param max-inline-insns-single=500 @@ -315,6 +316,7 @@ SRC_BINDINGS_ENUMS = \ digitalio/Direction.c \ digitalio/DriveMode.c \ digitalio/Pull.c \ + microcontroller/RunMode.c \ help.c \ util.c diff --git a/atmel-samd/boards/samd21x18-bootloader-crystalless.ld b/atmel-samd/boards/samd21x18-bootloader-crystalless.ld index 56ae5feb46..1d54bb88ca 100644 --- a/atmel-samd/boards/samd21x18-bootloader-crystalless.ld +++ b/atmel-samd/boards/samd21x18-bootloader-crystalless.ld @@ -11,7 +11,8 @@ MEMORY } /* top end of the stack */ -_estack = ORIGIN(RAM) + LENGTH(RAM); +_estack = ORIGIN(RAM) + LENGTH(RAM) - 4; +_bootloader_dbl_tap = _estack; /* define output sections */ SECTIONS diff --git a/atmel-samd/boards/samd21x18-bootloader-external-flash-crystalless.ld b/atmel-samd/boards/samd21x18-bootloader-external-flash-crystalless.ld index 1c04247473..81c1e84501 100644 --- a/atmel-samd/boards/samd21x18-bootloader-external-flash-crystalless.ld +++ b/atmel-samd/boards/samd21x18-bootloader-external-flash-crystalless.ld @@ -11,7 +11,8 @@ MEMORY } /* top end of the stack */ -_estack = ORIGIN(RAM) + LENGTH(RAM); +_estack = ORIGIN(RAM) + LENGTH(RAM) - 4; +_bootloader_dbl_tap = _estack; /* define output sections */ SECTIONS diff --git a/atmel-samd/boards/samd21x18-bootloader-external-flash.ld b/atmel-samd/boards/samd21x18-bootloader-external-flash.ld index 4346c170ce..8563ed3cb3 100644 --- a/atmel-samd/boards/samd21x18-bootloader-external-flash.ld +++ b/atmel-samd/boards/samd21x18-bootloader-external-flash.ld @@ -10,7 +10,8 @@ MEMORY } /* top end of the stack */ -_estack = ORIGIN(RAM) + LENGTH(RAM); +_estack = ORIGIN(RAM) + LENGTH(RAM) - 4; +_bootloader_dbl_tap = _estack; /* define output sections */ SECTIONS diff --git a/atmel-samd/boards/samd21x18-bootloader.ld b/atmel-samd/boards/samd21x18-bootloader.ld index 13a3f75c18..4d2005518f 100644 --- a/atmel-samd/boards/samd21x18-bootloader.ld +++ b/atmel-samd/boards/samd21x18-bootloader.ld @@ -11,7 +11,8 @@ MEMORY } /* top end of the stack */ -_estack = ORIGIN(RAM) + LENGTH(RAM); +_estack = ORIGIN(RAM) + LENGTH(RAM) - 4; +_bootloader_dbl_tap = _estack; /* define output sections */ SECTIONS diff --git a/atmel-samd/boards/samd21x18-external-flash.ld b/atmel-samd/boards/samd21x18-external-flash.ld index f5797cf6f5..629e190b1c 100644 --- a/atmel-samd/boards/samd21x18-external-flash.ld +++ b/atmel-samd/boards/samd21x18-external-flash.ld @@ -12,6 +12,7 @@ MEMORY /* top end of the stack */ _estack = ORIGIN(RAM) + LENGTH(RAM); +_bootloader_dbl_tap = 0; /* define output sections */ SECTIONS diff --git a/atmel-samd/boards/samd21x18.ld b/atmel-samd/boards/samd21x18.ld index a68094758f..9e318e9482 100644 --- a/atmel-samd/boards/samd21x18.ld +++ b/atmel-samd/boards/samd21x18.ld @@ -12,6 +12,7 @@ MEMORY /* top end of the stack */ _estack = ORIGIN(RAM) + LENGTH(RAM); +_bootloader_dbl_tap = 0; /* define output sections */ SECTIONS diff --git a/atmel-samd/common-hal/digitalio/DigitalInOut.c b/atmel-samd/common-hal/digitalio/DigitalInOut.c index 16654f0fe8..b14d20c2d2 100644 --- a/atmel-samd/common-hal/digitalio/DigitalInOut.c +++ b/atmel-samd/common-hal/digitalio/DigitalInOut.c @@ -64,7 +64,7 @@ void common_hal_digitalio_digitalinout_deinit(digitalio_digitalinout_obj_t* self } void common_hal_digitalio_digitalinout_switch_to_input( - digitalio_digitalinout_obj_t* self, enum digitalio_pull_t pull) { + digitalio_digitalinout_obj_t* self, digitalio_pull_t pull) { self->output = false; common_hal_digitalio_digitalinout_set_pull(self, pull); @@ -72,7 +72,7 @@ void common_hal_digitalio_digitalinout_switch_to_input( void common_hal_digitalio_digitalinout_switch_to_output( digitalio_digitalinout_obj_t* self, bool value, - enum digitalio_drive_mode_t drive_mode) { + digitalio_drive_mode_t drive_mode) { struct port_config pin_conf; port_get_config_defaults(&pin_conf); @@ -88,7 +88,7 @@ void common_hal_digitalio_digitalinout_switch_to_output( common_hal_digitalio_digitalinout_set_value(self, value); } -enum digitalio_direction_t common_hal_digitalio_digitalinout_get_direction( +digitalio_direction_t common_hal_digitalio_digitalinout_get_direction( digitalio_digitalinout_obj_t* self) { return self->output? DIRECTION_OUTPUT : DIRECTION_INPUT; } @@ -131,7 +131,7 @@ bool common_hal_digitalio_digitalinout_get_value( void common_hal_digitalio_digitalinout_set_drive_mode( digitalio_digitalinout_obj_t* self, - enum digitalio_drive_mode_t drive_mode) { + digitalio_drive_mode_t drive_mode) { bool value = common_hal_digitalio_digitalinout_get_value(self); self->open_drain = drive_mode == DRIVE_MODE_OPEN_DRAIN; // True is implemented differently between modes so reset the value to make @@ -141,7 +141,7 @@ void common_hal_digitalio_digitalinout_set_drive_mode( } } -enum digitalio_drive_mode_t common_hal_digitalio_digitalinout_get_drive_mode( +digitalio_drive_mode_t common_hal_digitalio_digitalinout_get_drive_mode( digitalio_digitalinout_obj_t* self) { if (self->open_drain) { return DRIVE_MODE_OPEN_DRAIN; @@ -151,7 +151,7 @@ enum digitalio_drive_mode_t common_hal_digitalio_digitalinout_get_drive_mode( } void common_hal_digitalio_digitalinout_set_pull( - digitalio_digitalinout_obj_t* self, enum digitalio_pull_t pull) { + digitalio_digitalinout_obj_t* self, digitalio_pull_t pull) { enum port_pin_pull asf_pull = PORT_PIN_PULL_NONE; switch (pull) { case PULL_UP: @@ -172,7 +172,7 @@ void common_hal_digitalio_digitalinout_set_pull( port_pin_set_config(self->pin->pin, &pin_conf); } -enum digitalio_pull_t common_hal_digitalio_digitalinout_get_pull( +digitalio_pull_t common_hal_digitalio_digitalinout_get_pull( digitalio_digitalinout_obj_t* self) { uint32_t pin = self->pin->pin; PortGroup *const port_base = port_get_group_from_gpio_pin(pin); diff --git a/atmel-samd/common-hal/microcontroller/__init__.c b/atmel-samd/common-hal/microcontroller/__init__.c index 84cea008b8..b90c38b604 100644 --- a/atmel-samd/common-hal/microcontroller/__init__.c +++ b/atmel-samd/common-hal/microcontroller/__init__.c @@ -26,10 +26,13 @@ #include "py/mphal.h" #include "py/obj.h" +#include "py/runtime.h" +#include "reset.h" #include "samd21_pins.h" #include "shared-bindings/nvm/ByteArray.h" +#include "shared-bindings/microcontroller/__init__.h" #include "shared-bindings/microcontroller/Processor.h" void common_hal_mcu_delay_us(uint32_t delay) { @@ -51,9 +54,33 @@ void common_hal_mcu_enable_interrupts(void) { cpu_irq_restore(irq_flags); } +extern uint32_t _ezero; +extern uint32_t _srelocate; + +void common_hal_mcu_on_next_reset(mcu_runmode_t runmode) { + // Set up the defaults. + _bootloader_dbl_tap = DBL_TAP_MAGIC; + _ezero = CIRCUITPY_CANARY_WORD; + + if (runmode == RUNMODE_BOOTLOADER) { + if (&_bootloader_dbl_tap < &_srelocate) { + mp_raise_ValueError("Cannot reset into bootloader because no bootloader is present."); + } + // Pretend to be the first of the two reset presses needed to enter the + // bootloader. That way one reset will end in the bootloader. + _bootloader_dbl_tap = DBL_TAP_MAGIC; + } else if (runmode == RUNMODE_SAFE_MODE) { + _ezero = CIRCUITPY_SOFTWARE_SAFE_MODE; + } +} + +void common_hal_mcu_reset(void) { + reset(); +} + // The singleton microcontroller.Processor object, bound to microcontroller.cpu // It currently only has properties, and no state. -mcu_processor_obj_t common_hal_mcu_processor_obj = { +const mcu_processor_obj_t common_hal_mcu_processor_obj = { .base = { .type = &mcu_processor_type, }, @@ -62,7 +89,7 @@ mcu_processor_obj_t common_hal_mcu_processor_obj = { // NVM is only available on Express boards for now. #if CIRCUITPY_INTERNAL_NVM_SIZE > 0 // The singleton nvm.ByteArray object. -nvm_bytearray_obj_t common_hal_mcu_nvm_obj = { +const nvm_bytearray_obj_t common_hal_mcu_nvm_obj = { .base = { .type = &nvm_bytearray_type, }, diff --git a/atmel-samd/main.c b/atmel-samd/main.c index 7bc4a87ed6..539ac3cb9b 100644 --- a/atmel-samd/main.c +++ b/atmel-samd/main.c @@ -84,6 +84,7 @@ typedef enum { BROWNOUT, HARD_CRASH, USER_SAFE_MODE, + SOFTWARE_SAFE_MODE } safe_mode_t; void do_str(const char *src, mp_parse_input_kind_t input_kind) { @@ -375,7 +376,10 @@ bool start_mp(safe_mode_t safe_mode) { mp_hal_stdout_tx_str(".\r\n"); } else #endif - if (safe_mode != NO_SAFE_MODE) { + if (safe_mode == SOFTWARE_SAFE_MODE) { + mp_hal_stdout_tx_str("\r\nYou requested starting in safe mode from your software."); + mp_hal_stdout_tx_str(".\r\nTo exit, please reset the board.\r\n"); + } else if (safe_mode != NO_SAFE_MODE) { mp_hal_stdout_tx_str("\r\nYou are running in safe mode which means something really bad happened.\r\n"); if (safe_mode == HARD_CRASH) { mp_hal_stdout_tx_str("Looks like our core CircuitPython code crashed hard. Whoops!\r\n"); @@ -524,10 +528,14 @@ safe_mode_t samd21_init(void) { REG_MTB_MASTER = 0x00000000 + 6; #endif + // CIRCUITPY_SOFTWARE_SAFE_MODE works just like the canary except if it + // survives we enter safe mode with a friendlier message. + bool software_safe_mode = _ezero == CIRCUITPY_SOFTWARE_SAFE_MODE; + // On power on start or external reset, set _ezero to the canary word. If it -// gets killed, we boot in safe mod. _ezero is the boundary between statically -// allocated memory including the fixed MicroPython heap and the stack. If either -// misbehaves, the canary will not be in tact after soft reset. +// gets killed, we boot in safe mode. _ezero is the boundary between statically +// allocated memory including the fixed MicroPython heap and the stack. If +// either misbehaves, the canary will not be in tact after soft reset. #ifdef CIRCUITPY_CANARY_WORD if (PM->RCAUSE.bit.POR == 1 || PM->RCAUSE.bit.EXT == 1) { _ezero = CIRCUITPY_CANARY_WORD; @@ -607,6 +615,10 @@ safe_mode_t samd21_init(void) { return USER_SAFE_MODE; } + if (software_safe_mode) { + return SOFTWARE_SAFE_MODE; + } + #if CIRCUITPY_INTERNAL_NVM_SIZE > 0 // Upgrade the nvm flash to include one sector for eeprom emulation. struct nvm_fusebits fuses; diff --git a/atmel-samd/mphalport.c b/atmel-samd/mphalport.c index c1aebe08a4..4d597be6b2 100644 --- a/atmel-samd/mphalport.c +++ b/atmel-samd/mphalport.c @@ -62,7 +62,7 @@ volatile bool reset_on_disconnect = false; void usb_dtr_notify(uint8_t port, bool set) { mp_cdc_enabled = set; - if (!set && reset_on_disconnect) { + if (!set && reset_on_disconnect && _bootloader_dbl_tap != 0) { reset_to_bootloader(); } } diff --git a/atmel-samd/reset.c b/atmel-samd/reset.c index 442774a5f4..822789b472 100644 --- a/atmel-samd/reset.c +++ b/atmel-samd/reset.c @@ -29,12 +29,12 @@ #include "asf/sam0/utils/cmsis/samd21/include/samd21.h" -// Copied from inc/uf2.h in https://github.com/Microsoft/uf2-samd21 -#define DBL_TAP_PTR ((volatile uint32_t *)(HMCRAMC0_ADDR + HMCRAMC0_SIZE - 4)) -#define DBL_TAP_MAGIC 0xf01669ef // Randomly selected, adjusted to have first and last bit set - -void reset_to_bootloader(void) { +void reset(void) { flash_flush(); - *DBL_TAP_PTR = DBL_TAP_MAGIC; NVIC_SystemReset(); } + +void reset_to_bootloader(void) { + _bootloader_dbl_tap = DBL_TAP_MAGIC; + reset(); +} diff --git a/atmel-samd/reset.h b/atmel-samd/reset.h index 88140f3b83..00b2312bb7 100644 --- a/atmel-samd/reset.h +++ b/atmel-samd/reset.h @@ -26,6 +26,12 @@ #ifndef MICROPY_INCLUDED_ATMEL_SAMD_RESET_H #define MICROPY_INCLUDED_ATMEL_SAMD_RESET_H +// Copied from inc/uf2.h in https://github.com/Microsoft/uf2-samd21 +#define DBL_TAP_MAGIC 0xf01669ef // Randomly selected, adjusted to have first and last bit set + +extern uint32_t _bootloader_dbl_tap; + void reset_to_bootloader(void); +void reset(void); #endif // MICROPY_INCLUDED_ATMEL_SAMD_RESET_H diff --git a/esp8266/Makefile b/esp8266/Makefile index bfaefb4651..d177bee58c 100644 --- a/esp8266/Makefile +++ b/esp8266/Makefile @@ -128,6 +128,7 @@ SRC_BINDINGS_ENUMS = \ digitalio/Direction.c \ digitalio/DriveMode.c \ digitalio/Pull.c \ + microcontroller/RunMode.c \ util.c SRC_COMMON_HAL_EXPANDED = $(addprefix shared-bindings/, $(SRC_COMMON_HAL)) \ diff --git a/esp8266/common-hal/digitalio/DigitalInOut.c b/esp8266/common-hal/digitalio/DigitalInOut.c index 70ed207d59..7101e64145 100644 --- a/esp8266/common-hal/digitalio/DigitalInOut.c +++ b/esp8266/common-hal/digitalio/DigitalInOut.c @@ -59,7 +59,7 @@ void common_hal_digitalio_digitalinout_deinit(digitalio_digitalinout_obj_t* self } void common_hal_digitalio_digitalinout_switch_to_input( - digitalio_digitalinout_obj_t* self, enum digitalio_pull_t pull) { + digitalio_digitalinout_obj_t* self, digitalio_pull_t pull) { self->output = false; if (self->pin->gpio_number == 16) { @@ -75,7 +75,7 @@ void common_hal_digitalio_digitalinout_switch_to_input( void common_hal_digitalio_digitalinout_switch_to_output( digitalio_digitalinout_obj_t* self, bool value, - enum digitalio_drive_mode_t drive_mode) { + digitalio_drive_mode_t drive_mode) { self->output = true; self->open_drain = drive_mode == DRIVE_MODE_OPEN_DRAIN; if (self->pin->gpio_number == 16) { @@ -89,7 +89,7 @@ void common_hal_digitalio_digitalinout_switch_to_output( common_hal_digitalio_digitalinout_set_value(self, value); } -enum digitalio_direction_t common_hal_digitalio_digitalinout_get_direction( +digitalio_direction_t common_hal_digitalio_digitalinout_get_direction( digitalio_digitalinout_obj_t* self) { return self->output? DIRECTION_OUTPUT : DIRECTION_INPUT; } @@ -136,7 +136,7 @@ bool common_hal_digitalio_digitalinout_get_value( void common_hal_digitalio_digitalinout_set_drive_mode( digitalio_digitalinout_obj_t* self, - enum digitalio_drive_mode_t drive_mode) { + digitalio_drive_mode_t drive_mode) { bool value = common_hal_digitalio_digitalinout_get_value(self); self->open_drain = drive_mode == DRIVE_MODE_OPEN_DRAIN; // True is implemented differently between modes so reset the value to make @@ -146,7 +146,7 @@ void common_hal_digitalio_digitalinout_set_drive_mode( } } -enum digitalio_drive_mode_t common_hal_digitalio_digitalinout_get_drive_mode( +digitalio_drive_mode_t common_hal_digitalio_digitalinout_get_drive_mode( digitalio_digitalinout_obj_t* self) { if (self->open_drain) { return DRIVE_MODE_OPEN_DRAIN; @@ -156,7 +156,7 @@ enum digitalio_drive_mode_t common_hal_digitalio_digitalinout_get_drive_mode( } void common_hal_digitalio_digitalinout_set_pull( - digitalio_digitalinout_obj_t* self, enum digitalio_pull_t pull) { + digitalio_digitalinout_obj_t* self, digitalio_pull_t pull) { if (pull == PULL_DOWN) { nlr_raise(mp_obj_new_exception_msg(&mp_type_OSError, "ESP8266 does not support pull down.")); @@ -174,7 +174,7 @@ void common_hal_digitalio_digitalinout_set_pull( } } -enum digitalio_pull_t common_hal_digitalio_digitalinout_get_pull( +digitalio_pull_t common_hal_digitalio_digitalinout_get_pull( digitalio_digitalinout_obj_t* self) { if (self->pin->gpio_number < 16 && (READ_PERI_REG(self->pin->peripheral) & PERIPHS_IO_MUX_PULLUP) != 0) { diff --git a/esp8266/common-hal/microcontroller/__init__.c b/esp8266/common-hal/microcontroller/__init__.c index 6aef23761c..6d446ceacb 100644 --- a/esp8266/common-hal/microcontroller/__init__.c +++ b/esp8266/common-hal/microcontroller/__init__.c @@ -24,9 +24,12 @@ * THE SOFTWARE. */ +#include "py/runtime.h" + #include "common-hal/microcontroller/Pin.h" #include "common-hal/microcontroller/Processor.h" +#include "shared-bindings/microcontroller/__init__.h" #include "shared-bindings/microcontroller/Pin.h" #include "shared-bindings/microcontroller/Processor.h" @@ -34,6 +37,7 @@ #include "ets_alt_task.h" #include "etshal.h" #include "osapi.h" +#include "user_interface.h" #include "xtirq.h" #define ETS_LOOP_ITER_BIT (12) @@ -54,9 +58,21 @@ void common_hal_mcu_enable_interrupts() { enable_irq(saved_interrupt_state & ~(1 << ETS_LOOP_ITER_BIT)); } +void common_hal_mcu_on_next_reset(mcu_runmode_t runmode) { + if (runmode == RUNMODE_BOOTLOADER) { + mp_raise_ValueError("Cannot reset into bootloader because no bootloader is present."); + } else if (runmode == RUNMODE_SAFE_MODE) { + mp_raise_ValueError("ESP8226 does not support safe mode."); + } +} + +void common_hal_mcu_reset(void) { + system_restart(); +} + // The singleton microcontroller.Processor object, returned by microcontroller.cpu // It currently only has properties, and no state. -mcu_processor_obj_t common_hal_mcu_processor_obj = { +const mcu_processor_obj_t common_hal_mcu_processor_obj = { .base = { .type = &mcu_processor_type, }, diff --git a/shared-bindings/digitalio/DigitalInOut.c b/shared-bindings/digitalio/DigitalInOut.c index ea2ba0b893..008883b8bd 100644 --- a/shared-bindings/digitalio/DigitalInOut.c +++ b/shared-bindings/digitalio/DigitalInOut.c @@ -124,7 +124,7 @@ STATIC mp_obj_t digitalio_digitalinout_switch_to_output(size_t n_args, const mp_ mp_arg_val_t args[MP_ARRAY_SIZE(allowed_args)]; mp_arg_parse_all(n_args - 1, pos_args + 1, kw_args, MP_ARRAY_SIZE(allowed_args), allowed_args, args); - enum digitalio_drive_mode_t drive_mode = DRIVE_MODE_PUSH_PULL; + digitalio_drive_mode_t drive_mode = DRIVE_MODE_PUSH_PULL; if (args[ARG_drive_mode].u_rom_obj == &digitalio_drive_mode_open_drain_obj) { drive_mode = DRIVE_MODE_OPEN_DRAIN; } @@ -161,7 +161,7 @@ STATIC mp_obj_t digitalio_digitalinout_switch_to_input(size_t n_args, const mp_o mp_arg_val_t args[MP_ARRAY_SIZE(allowed_args)]; mp_arg_parse_all(n_args - 1, pos_args + 1, kw_args, MP_ARRAY_SIZE(allowed_args), allowed_args, args); - enum digitalio_pull_t pull = PULL_NONE; + digitalio_pull_t pull = PULL_NONE; if (args[ARG_pull].u_rom_obj == &digitalio_pull_up_obj) { pull = PULL_UP; }else if (args[ARG_pull].u_rom_obj == &digitalio_pull_down_obj) { @@ -191,7 +191,7 @@ extern const digitalio_digitalio_direction_obj_t digitalio_digitalio_direction_o STATIC mp_obj_t digitalio_digitalinout_obj_get_direction(mp_obj_t self_in) { digitalio_digitalinout_obj_t *self = MP_OBJ_TO_PTR(self_in); raise_error_if_deinited(common_hal_digitalio_digitalinout_deinited(self)); - enum digitalio_direction_t direction = common_hal_digitalio_digitalinout_get_direction(self); + digitalio_direction_t direction = common_hal_digitalio_digitalinout_get_direction(self); if (direction == DIRECTION_INPUT) { return (mp_obj_t)&digitalio_direction_input_obj; } @@ -262,7 +262,7 @@ STATIC mp_obj_t digitalio_digitalinout_obj_get_drive_mode(mp_obj_t self_in) { mp_raise_AttributeError("Drive mode not used when direction is input."); return mp_const_none; } - enum digitalio_drive_mode_t drive_mode = common_hal_digitalio_digitalinout_get_drive_mode(self); + digitalio_drive_mode_t drive_mode = common_hal_digitalio_digitalinout_get_drive_mode(self); if (drive_mode == DRIVE_MODE_PUSH_PULL) { return (mp_obj_t)&digitalio_drive_mode_push_pull_obj; } @@ -277,7 +277,7 @@ STATIC mp_obj_t digitalio_digitalinout_obj_set_drive_mode(mp_obj_t self_in, mp_o mp_raise_AttributeError("Drive mode not used when direction is input."); return mp_const_none; } - enum digitalio_drive_mode_t c_drive_mode = DRIVE_MODE_PUSH_PULL; + digitalio_drive_mode_t c_drive_mode = DRIVE_MODE_PUSH_PULL; if (drive_mode == &digitalio_drive_mode_open_drain_obj) { c_drive_mode = DRIVE_MODE_OPEN_DRAIN; } @@ -307,7 +307,7 @@ STATIC mp_obj_t digitalio_digitalinout_obj_get_pull(mp_obj_t self_in) { mp_raise_AttributeError("Pull not used when direction is output."); return mp_const_none; } - enum digitalio_pull_t pull = common_hal_digitalio_digitalinout_get_pull(self); + digitalio_pull_t pull = common_hal_digitalio_digitalinout_get_pull(self); if (pull == PULL_UP) { return (mp_obj_t)&digitalio_pull_up_obj; } else if (pull == PULL_DOWN) { @@ -324,7 +324,7 @@ STATIC mp_obj_t digitalio_digitalinout_obj_set_pull(mp_obj_t self_in, mp_obj_t p mp_raise_AttributeError("Pull not used when direction is output."); return mp_const_none; } - enum digitalio_pull_t pull = PULL_NONE; + digitalio_pull_t pull = PULL_NONE; if (pull_obj == &digitalio_pull_up_obj) { pull = PULL_UP; } else if (pull_obj == &digitalio_pull_down_obj) { diff --git a/shared-bindings/digitalio/DigitalInOut.h b/shared-bindings/digitalio/DigitalInOut.h index 74970881b8..2aaa31b7f4 100644 --- a/shared-bindings/digitalio/DigitalInOut.h +++ b/shared-bindings/digitalio/DigitalInOut.h @@ -43,14 +43,14 @@ typedef enum { digitalinout_result_t common_hal_digitalio_digitalinout_construct(digitalio_digitalinout_obj_t* self, const mcu_pin_obj_t* pin); void common_hal_digitalio_digitalinout_deinit(digitalio_digitalinout_obj_t* self); bool common_hal_digitalio_digitalinout_deinited(digitalio_digitalinout_obj_t* self); -void common_hal_digitalio_digitalinout_switch_to_input(digitalio_digitalinout_obj_t* self, enum digitalio_pull_t pull); -void common_hal_digitalio_digitalinout_switch_to_output(digitalio_digitalinout_obj_t* self, bool value, enum digitalio_drive_mode_t drive_mode); -enum digitalio_direction_t common_hal_digitalio_digitalinout_get_direction(digitalio_digitalinout_obj_t* self); +void common_hal_digitalio_digitalinout_switch_to_input(digitalio_digitalinout_obj_t* self, digitalio_pull_t pull); +void common_hal_digitalio_digitalinout_switch_to_output(digitalio_digitalinout_obj_t* self, bool value, digitalio_drive_mode_t drive_mode); +digitalio_direction_t common_hal_digitalio_digitalinout_get_direction(digitalio_digitalinout_obj_t* self); void common_hal_digitalio_digitalinout_set_value(digitalio_digitalinout_obj_t* self, bool value); bool common_hal_digitalio_digitalinout_get_value(digitalio_digitalinout_obj_t* self); -void common_hal_digitalio_digitalinout_set_drive_mode(digitalio_digitalinout_obj_t* self, enum digitalio_drive_mode_t drive_mode); -enum digitalio_drive_mode_t common_hal_digitalio_digitalinout_get_drive_mode(digitalio_digitalinout_obj_t* self); -void common_hal_digitalio_digitalinout_set_pull(digitalio_digitalinout_obj_t* self, enum digitalio_pull_t pull); -enum digitalio_pull_t common_hal_digitalio_digitalinout_get_pull(digitalio_digitalinout_obj_t* self); +void common_hal_digitalio_digitalinout_set_drive_mode(digitalio_digitalinout_obj_t* self, digitalio_drive_mode_t drive_mode); +digitalio_drive_mode_t common_hal_digitalio_digitalinout_get_drive_mode(digitalio_digitalinout_obj_t* self); +void common_hal_digitalio_digitalinout_set_pull(digitalio_digitalinout_obj_t* self, digitalio_pull_t pull); +digitalio_pull_t common_hal_digitalio_digitalinout_get_pull(digitalio_digitalinout_obj_t* self); #endif // MICROPY_INCLUDED_SHARED_BINDINGS_DIGITALIO_DIGITALINOUT_H diff --git a/shared-bindings/digitalio/Direction.h b/shared-bindings/digitalio/Direction.h index e8fbf181d2..d71f48c2ed 100644 --- a/shared-bindings/digitalio/Direction.h +++ b/shared-bindings/digitalio/Direction.h @@ -29,10 +29,10 @@ #include "py/obj.h" -enum digitalio_direction_t { +typedef enum { DIRECTION_INPUT, DIRECTION_OUTPUT -}; +} digitalio_direction_t; typedef struct { mp_obj_base_t base; } digitalio_direction_obj_t; diff --git a/shared-bindings/digitalio/DriveMode.h b/shared-bindings/digitalio/DriveMode.h index 959885b1b9..47d036b3ae 100644 --- a/shared-bindings/digitalio/DriveMode.h +++ b/shared-bindings/digitalio/DriveMode.h @@ -29,10 +29,10 @@ #include "py/obj.h" -enum digitalio_drive_mode_t { +typedef enum { DRIVE_MODE_PUSH_PULL, DRIVE_MODE_OPEN_DRAIN -}; +} digitalio_drive_mode_t; typedef struct { mp_obj_base_t base; diff --git a/shared-bindings/digitalio/Pull.h b/shared-bindings/digitalio/Pull.h index 8c88d8673e..22fb6cd0e7 100644 --- a/shared-bindings/digitalio/Pull.h +++ b/shared-bindings/digitalio/Pull.h @@ -29,11 +29,11 @@ #include "py/obj.h" -enum digitalio_pull_t { +typedef enum _digitalio_pull_t { PULL_NONE, PULL_UP, PULL_DOWN -}; +} digitalio_pull_t; const mp_obj_type_t digitalio_pull_type; diff --git a/shared-bindings/microcontroller/RunMode.c b/shared-bindings/microcontroller/RunMode.c new file mode 100644 index 0000000000..b8b66a4572 --- /dev/null +++ b/shared-bindings/microcontroller/RunMode.c @@ -0,0 +1,90 @@ +/* + * This file is part of the Micro Python project, http://micropython.org/ + * + * The MIT License (MIT) + * + * Copyright (c) 2017 Scott Shawcroft for Adafruit Industries + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +#include "shared-bindings/microcontroller/RunMode.h" + +//| .. currentmodule:: microcontroller +//| +//| :class:`RunMode` -- run state of the microcontroller +//| ============================================================= +//| +//| .. class:: mcirocontroller.RunMode +//| +//| Enum-like class to define the run mode of the microcontroller and +//| CircuitPython. +//| +//| .. data:: NORMAL +//| +//| Run CircuitPython as normal. +//| +//| .. data:: SAFE_MODE +//| +//| Run CircuitPython in safe mode. User code will not be run and the +//| file system will be writeable over USB. +//| +//| .. data:: BOOTLOADER +//| +//| Run the bootloader. +//| +const mp_obj_type_t mcu_runmode_type; + +const mcu_runmode_obj_t mcu_runmode_normal_obj = { + { &mcu_runmode_type }, +}; + +const mcu_runmode_obj_t mcu_runmode_safe_mode_obj = { + { &mcu_runmode_type }, +}; + +const mcu_runmode_obj_t mcu_runmode_bootloader_obj = { + { &mcu_runmode_type }, +}; + +STATIC const mp_rom_map_elem_t mcu_runmode_locals_dict_table[] = { + {MP_ROM_QSTR(MP_QSTR_NORMAL), MP_ROM_PTR(&mcu_runmode_normal_obj)}, + {MP_ROM_QSTR(MP_QSTR_SAFE_MODE), MP_ROM_PTR(&mcu_runmode_safe_mode_obj)}, + {MP_ROM_QSTR(MP_QSTR_BOOTLOADER), MP_ROM_PTR(&mcu_runmode_bootloader_obj)}, +}; +STATIC MP_DEFINE_CONST_DICT(mcu_runmode_locals_dict, mcu_runmode_locals_dict_table); + +STATIC void mcu_runmode_print(const mp_print_t *print, mp_obj_t self_in, mp_print_kind_t kind) { + qstr runmode = MP_QSTR_NORMAL; + if (MP_OBJ_TO_PTR(self_in) == MP_ROM_PTR(&mcu_runmode_safe_mode_obj)) { + runmode = MP_QSTR_SAFE_MODE; + } else if (MP_OBJ_TO_PTR(self_in) == + MP_ROM_PTR(&mcu_runmode_bootloader_obj)) { + runmode = MP_QSTR_SAFE_MODE; + } + mp_printf(print, "%q.%q.%q", MP_QSTR_microcontroller, MP_QSTR_RunMode, + runmode); +} + +const mp_obj_type_t mcu_runmode_type = { + { &mp_type_type }, + .name = MP_QSTR_RunMode, + .print = mcu_runmode_print, + .locals_dict = (mp_obj_t)&mcu_runmode_locals_dict, +}; diff --git a/shared-bindings/microcontroller/RunMode.h b/shared-bindings/microcontroller/RunMode.h new file mode 100644 index 0000000000..5e8b6e6465 --- /dev/null +++ b/shared-bindings/microcontroller/RunMode.h @@ -0,0 +1,47 @@ +/* + * This file is part of the Micro Python project, http://micropython.org/ + * + * The MIT License (MIT) + * + * Copyright (c) 2017 Scott Shawcroft for Adafruit Industries + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +#ifndef MICROPY_INCLUDED_SHARED_BINDINGS_MICROCONTROLLER_RUNMODE_H +#define MICROPY_INCLUDED_SHARED_BINDINGS_MICROCONTROLLER_RUNMODE_H + +#include "py/obj.h" + +typedef enum { + RUNMODE_NORMAL, + RUNMODE_SAFE_MODE, + RUNMODE_BOOTLOADER +} mcu_runmode_t; + +const mp_obj_type_t mcu_runmode_type; + +typedef struct { + mp_obj_base_t base; +} mcu_runmode_obj_t; +extern const mcu_runmode_obj_t mcu_runmode_normal_obj; +extern const mcu_runmode_obj_t mcu_runmode_safe_mode_obj; +extern const mcu_runmode_obj_t mcu_runmode_bootloader_obj; + +#endif // MICROPY_INCLUDED_SHARED_BINDINGS_MICROCONTROLLER_RUNMODE_H diff --git a/shared-bindings/microcontroller/__init__.c b/shared-bindings/microcontroller/__init__.c index d2567bd65a..cc091591f4 100644 --- a/shared-bindings/microcontroller/__init__.c +++ b/shared-bindings/microcontroller/__init__.c @@ -102,6 +102,47 @@ STATIC mp_obj_t mcu_enable_interrupts(void) { } STATIC MP_DEFINE_CONST_FUN_OBJ_0(mcu_enable_interrupts_obj, mcu_enable_interrupts); +//| .. method:: on_next_reset(run_mode) +//| +//| Configure the run mode used the next time the microcontroller is reset but +//| not powered down. +//| +//| :param ~microcontroller.RunMode run_mode: The next run mode +//| +STATIC mp_obj_t mcu_on_next_reset(mp_obj_t run_mode_obj) { + mcu_runmode_t run_mode; + if (run_mode_obj == &mcu_runmode_normal_obj) { + run_mode = RUNMODE_NORMAL; + } else if (run_mode_obj == &mcu_runmode_safe_mode_obj) { + run_mode = RUNMODE_SAFE_MODE; + } else if (run_mode_obj == &mcu_runmode_bootloader_obj) { + run_mode = RUNMODE_BOOTLOADER; + } else { + mp_raise_ValueError("Invalid run mode."); + } + + common_hal_mcu_on_next_reset(run_mode); + + return mp_const_none; +} +STATIC MP_DEFINE_CONST_FUN_OBJ_1(mcu_on_next_reset_obj, mcu_on_next_reset); + +//| .. method:: reset() +//| +//| Reset the microcontroller. After reset, the microcontroller will enter the +//| run mode last set by `one_next_reset`. +//| +//| .. warning:: This may result in file system corruption when connected to a +//| host computer. Be very careful when calling this! Make sure the device +//| "Safely removed" on Windows or "ejected" on Mac OSX and Linux. +//| +STATIC mp_obj_t mcu_reset(void) { + common_hal_mcu_reset(); + // We won't actually get here because we're resetting. + return mp_const_none; +} +STATIC MP_DEFINE_CONST_FUN_OBJ_0(mcu_reset_obj, mcu_reset); + //| .. attribute:: nvm //| //| Available non-volatile memory. @@ -128,11 +169,14 @@ STATIC const mp_rom_map_elem_t mcu_module_globals_table[] = { { MP_ROM_QSTR(MP_QSTR_delay_us), MP_ROM_PTR(&mcu_delay_us_obj) }, { MP_ROM_QSTR(MP_QSTR_disable_interrupts), MP_ROM_PTR(&mcu_disable_interrupts_obj) }, { MP_ROM_QSTR(MP_QSTR_enable_interrupts), MP_ROM_PTR(&mcu_enable_interrupts_obj) }, + { MP_ROM_QSTR(MP_QSTR_on_next_reset), MP_ROM_PTR(&mcu_on_next_reset_obj) }, + { MP_ROM_QSTR(MP_QSTR_reset), MP_ROM_PTR(&mcu_reset_obj) }, #if CIRCUITPY_INTERNAL_NVM_SIZE > 0 { MP_ROM_QSTR(MP_QSTR_nvm), MP_ROM_PTR(&common_hal_mcu_nvm_obj) }, #else { MP_ROM_QSTR(MP_QSTR_nvm), MP_ROM_PTR(&mp_const_none_obj) }, #endif + { MP_ROM_QSTR(MP_QSTR_RunMode), MP_ROM_PTR(&mcu_runmode_type) }, { MP_ROM_QSTR(MP_QSTR_Pin), MP_ROM_PTR(&mcu_pin_type) }, { MP_ROM_QSTR(MP_QSTR_pin), MP_ROM_PTR(&mcu_pin_module) }, { MP_ROM_QSTR(MP_QSTR_Processor), MP_ROM_PTR(&mcu_processor_type) }, diff --git a/shared-bindings/microcontroller/__init__.h b/shared-bindings/microcontroller/__init__.h index d43db4bf45..e1487c555a 100644 --- a/shared-bindings/microcontroller/__init__.h +++ b/shared-bindings/microcontroller/__init__.h @@ -33,11 +33,16 @@ #include "common-hal/microcontroller/Processor.h" +#include "shared-bindings/microcontroller/RunMode.h" + extern void common_hal_mcu_delay_us(uint32_t); extern void common_hal_mcu_disable_interrupts(void); extern void common_hal_mcu_enable_interrupts(void); +extern void common_hal_mcu_on_next_reset(mcu_runmode_t runmode); +extern void common_hal_mcu_reset(void); + extern const mp_obj_dict_t mcu_pin_globals; extern const mcu_processor_obj_t common_hal_mcu_processor_obj; From a91e1cb68271ae2acc3d65ece1d781d6077e4138 Mon Sep 17 00:00:00 2001 From: Scott Shawcroft Date: Tue, 5 Dec 2017 16:04:47 -0800 Subject: [PATCH 030/135] Fix a couple spelling errors. --- atmel-samd/main.c | 2 +- shared-bindings/microcontroller/RunMode.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/atmel-samd/main.c b/atmel-samd/main.c index 539ac3cb9b..880a0e1709 100644 --- a/atmel-samd/main.c +++ b/atmel-samd/main.c @@ -535,7 +535,7 @@ safe_mode_t samd21_init(void) { // On power on start or external reset, set _ezero to the canary word. If it // gets killed, we boot in safe mode. _ezero is the boundary between statically // allocated memory including the fixed MicroPython heap and the stack. If -// either misbehaves, the canary will not be in tact after soft reset. +// either misbehaves, the canary will not be intact after soft reset. #ifdef CIRCUITPY_CANARY_WORD if (PM->RCAUSE.bit.POR == 1 || PM->RCAUSE.bit.EXT == 1) { _ezero = CIRCUITPY_CANARY_WORD; diff --git a/shared-bindings/microcontroller/RunMode.c b/shared-bindings/microcontroller/RunMode.c index b8b66a4572..b27a3c0909 100644 --- a/shared-bindings/microcontroller/RunMode.c +++ b/shared-bindings/microcontroller/RunMode.c @@ -31,7 +31,7 @@ //| :class:`RunMode` -- run state of the microcontroller //| ============================================================= //| -//| .. class:: mcirocontroller.RunMode +//| .. class:: microcontroller.RunMode //| //| Enum-like class to define the run mode of the microcontroller and //| CircuitPython. From 43650b689674a18b95d520921d10a91b67f64c84 Mon Sep 17 00:00:00 2001 From: Dan Halbert Date: Wed, 13 Dec 2017 13:12:49 -0500 Subject: [PATCH 031/135] Fix PDMIn MEMS microphone support (#479) Changes: * New faster filter loop, by @ladyada. New filter coefficients as well. * Turn on microphone clock when PDMIn object is created, and run it all the time, so the user code doesn't have to wait for microphone startup, which can be 10ms or even 100ms. * Wait for microphone startup when PDMIn is first created, based on new optional parameter microphone_startup in seconds (takes a float). * record() returns number of samples actually recorded, so you can see if it's not keeping up. * Fix buffer overflow errors when buffer size was not a multiple of 16 or something like that. * Tweak a few peripheral settings. * Minimum sampling frequency is now 16kHZ or so, because 8kHz runs microphone at only 0.5MHz, which is too slow for many mics. Note: I tried 128x oversampling instead of 64x, but the code cannot keep up at 24kHz or above sampling. 128x would reduce the high-frequency noise by 6db. --- atmel-samd/common-hal/audiobusio/PDMIn.c | 153 ++++++++++++++--------- shared-bindings/audiobusio/PDMIn.c | 53 +++++--- 2 files changed, 129 insertions(+), 77 deletions(-) diff --git a/atmel-samd/common-hal/audiobusio/PDMIn.c b/atmel-samd/common-hal/audiobusio/PDMIn.c index db671f213f..8263ac7d20 100644 --- a/atmel-samd/common-hal/audiobusio/PDMIn.c +++ b/atmel-samd/common-hal/audiobusio/PDMIn.c @@ -26,6 +26,7 @@ #include #include +#include #include "py/gc.h" #include "py/mperrno.h" @@ -42,6 +43,12 @@ #include "shared_dma.h" #include "tick.h" +#define OVERSAMPLING 64 +#define SAMPLES_PER_BUFFER 32 + +// MEMS microphones must be clocked at at least 1MHz. +#define MIN_MIC_CLOCK 1000000 + void pdmin_reset(void) { while (I2S->SYNCBUSY.reg & I2S_SYNCBUSY_ENABLE) {} I2S->INTENCLR.reg = I2S_INTENCLR_MASK; @@ -96,8 +103,8 @@ void common_hal_audiobusio_pdmin_construct(audiobusio_pdmin_obj_t* self, mp_raise_RuntimeError("Unable to allocate audio DMA block counter."); } - if (!(bit_depth == 16 || bit_depth == 8) || !mono || oversample != 64) { - mp_raise_NotImplementedError("Only 8 or 16 bit mono with 64 oversample is supported."); + if (!(bit_depth == 16 || bit_depth == 8) || !mono || oversample != OVERSAMPLING) { + mp_raise_NotImplementedError("Only 8 or 16 bit mono with " MP_STRINGIFY(OVERSAMPLING) "x oversampling is supported."); } // TODO(tannewt): Use the DPLL to get a more precise sampling rate. @@ -112,12 +119,17 @@ void common_hal_audiobusio_pdmin_construct(audiobusio_pdmin_obj_t* self, config_clock_unit.clock.mck_out_enable = false; config_clock_unit.clock.sck_src = I2S_SERIAL_CLOCK_SOURCE_MCKDIV; - config_clock_unit.clock.sck_div = 8000000 / frequency / oversample; - self->frequency = 8000000 / config_clock_unit.clock.sck_div / oversample; + uint32_t clock_divisor = (uint32_t) roundf( 8000000.0f / frequency / oversample); + config_clock_unit.clock.sck_div = clock_divisor; + float mic_clock_freq = 8000000.0f / clock_divisor; + self->frequency = mic_clock_freq / oversample; + if (mic_clock_freq < MIN_MIC_CLOCK || clock_divisor == 0 || clock_divisor > 255) { + mp_raise_ValueError("sampling frequency out of range"); + } config_clock_unit.frame.number_slots = 2; config_clock_unit.frame.slot_size = I2S_SLOT_SIZE_16_BIT; - config_clock_unit.frame.data_delay = I2S_DATA_DELAY_1; + config_clock_unit.frame.data_delay = I2S_DATA_DELAY_0; config_clock_unit.frame.frame_sync.width = I2S_FRAME_SYNC_WIDTH_SLOT; @@ -141,6 +153,10 @@ void common_hal_audiobusio_pdmin_construct(audiobusio_pdmin_obj_t* self, i2s_serializer_set_config(&self->i2s_instance, self->serializer, &config_serializer); i2s_enable(&self->i2s_instance); + // Run the serializer all the time. This eliminates startup delay for the microphone. + i2s_clock_unit_enable(&self->i2s_instance, self->clock_unit); + i2s_serializer_enable(&self->i2s_instance, self->serializer); + self->bytes_per_sample = oversample >> 3; self->bit_depth = bit_depth; } @@ -154,6 +170,8 @@ void common_hal_audiobusio_pdmin_deinit(audiobusio_pdmin_obj_t* self) { return; } i2s_disable(&self->i2s_instance); + i2s_serializer_disable(&self->i2s_instance, self->serializer); + i2s_clock_unit_disable(&self->i2s_instance, self->clock_unit); i2s_reset(&self->i2s_instance); reset_pin(self->clock_pin->pin); reset_pin(self->data_pin->pin); @@ -213,74 +231,82 @@ static void setup_dma(audiobusio_pdmin_obj_t* self, uint32_t length, void start_dma(audiobusio_pdmin_obj_t* self) { dma_start_transfer_job(&audio_dma); tc_start_counter(MP_STATE_VM(audiodma_block_counter)); - i2s_clock_unit_enable(&self->i2s_instance, self->clock_unit); - i2s_serializer_enable(&self->i2s_instance, self->serializer); I2S->DATA[1].reg = I2S->DATA[1].reg; } void stop_dma(audiobusio_pdmin_obj_t* self) { - // Turn off the I2S clock and serializer. Peripheral is still enabled. - i2s_serializer_disable(&self->i2s_instance, self->serializer); - i2s_clock_unit_disable(&self->i2s_instance, self->clock_unit); - - // Shutdown the DMA + // Shutdown the DMA: serializer keeps running. tc_stop_counter(MP_STATE_VM(audiodma_block_counter)); dma_abort_job(&audio_dma); } -static const uint16_t sinc_filter[64] = { - 0, 1, 6, 16, 29, 49, 75, 108, - 149, 200, 261, 334, 418, 514, 622, 742, - 872, 1012, 1161, 1315, 1472, 1631, 1787, 1938, - 2081, 2212, 2329, 2429, 2509, 2568, 2604, 2616, - 2604, 2568, 2509, 2429, 2329, 2212, 2081, 1938, - 1787, 1631, 1472, 1315, 1161, 1012, 872, 742, - 622, 514, 418, 334, 261, 200, 149, 108, - 75, 49, 29, 16, 6, 1, 0, 0 +// a windowed sinc filter for 44 khz, 64 samples +// +// This filter is good enough to use for lower sample rates as +// well. It does not increase the noise enough to be a problem. +// +// In the long run we could use a fast filter like this to do the +// decimation and initial filtering in real time, filtering to a +// higher sample rate than specified. Then after the audio is +// recorded, a more expensive filter non-real-time filter could be +// used to down-sample and low-pass. +uint16_t sinc_filter [OVERSAMPLING] = { + 0, 2, 9, 21, 39, 63, 94, 132, + 179, 236, 302, 379, 467, 565, 674, 792, + 920, 1055, 1196, 1341, 1487, 1633, 1776, 1913, + 2042, 2159, 2263, 2352, 2422, 2474, 2506, 2516, + 2506, 2474, 2422, 2352, 2263, 2159, 2042, 1913, + 1776, 1633, 1487, 1341, 1196, 1055, 920, 792, + 674, 565, 467, 379, 302, 236, 179, 132, + 94, 63, 39, 21, 9, 2, 0, 0 }; +#define REPEAT_16_TIMES(X) X X X X X X X X X X X X X X X X + static uint16_t filter_sample(uint32_t pdm_samples[4]) { - uint16_t sample = 0; - for (uint8_t i = 0; i < 4; i++) { - uint16_t pdm = pdm_samples[i] & 0xffff; - for (uint8_t j = 0; j < 16; j++) { - if ((pdm & 0x8000) != 0) { - sample += sinc_filter[i * 16 + j]; + uint16_t running_sum = 0; + const uint16_t *filter_ptr = sinc_filter; + for (uint8_t i = 0; i < OVERSAMPLING/16; i++) { + // The sample is 16-bits right channel in the upper two bytes and 16-bits left channel + // in the lower two bytes. + // We just ignore the upper bits + uint32_t pdm_sample = pdm_samples[i]; + REPEAT_16_TIMES( { + if (pdm_sample & 0x8000) { + running_sum += *filter_ptr++; + } + pdm_sample <<= 1; } - pdm <<= 1; - } + ) } - return sample; + return running_sum; } +// output_buffer may be a byte buffer or a halfword buffer. +// output_buffer_length is the number of slots, not the number of bytes. uint32_t common_hal_audiobusio_pdmin_record_to_buffer(audiobusio_pdmin_obj_t* self, - uint16_t* output_buffer, uint32_t length) { - // Write the wave file header. - - // We allocate two 256 byte buffers on the stack to use for double buffering. - // Our oversample rate is 64 (bits) so each buffer produces 32 samples. - // TODO(tannewt): Can the compiler optimize better if we fix the size of - // these buffers? - uint8_t samples_per_buffer = 32; + uint16_t* output_buffer, uint32_t output_buffer_length) { + // We allocate two buffers on the stack to use for double buffering. + const uint8_t samples_per_buffer = SAMPLES_PER_BUFFER; // For every word we record, we throw away 2 bytes of a phantom second channel. - uint8_t words_per_sample = self->bytes_per_sample / 2; - uint8_t words_per_buffer = samples_per_buffer * words_per_sample; + const uint8_t words_per_sample = self->bytes_per_sample / 2; + const uint8_t words_per_buffer = samples_per_buffer * words_per_sample; uint32_t first_buffer[words_per_buffer]; uint32_t second_buffer[words_per_buffer]; COMPILER_ALIGNED(16) DmacDescriptor second_descriptor; - setup_dma(self, length, &second_descriptor, words_per_buffer, + setup_dma(self, output_buffer_length, &second_descriptor, words_per_buffer, words_per_sample, first_buffer, second_buffer); start_dma(self); // Record uint32_t buffers_processed = 0; - uint32_t total_bytes = 0; + uint32_t values_output = 0; - uint64_t start_ticks = ticks_ms; - while (total_bytes < length) { + uint32_t remaining_samples_needed = output_buffer_length; + while (values_output < output_buffer_length) { // Wait for the next buffer to fill while (tc_get_count_value(MP_STATE_VM(audiodma_block_counter)) == buffers_processed) { #ifdef MICROPY_VM_HOOK_LOOP @@ -290,40 +316,45 @@ uint32_t common_hal_audiobusio_pdmin_record_to_buffer(audiobusio_pdmin_obj_t* se if (tc_get_count_value(MP_STATE_VM(audiodma_block_counter)) != (buffers_processed + 1)) { break; } - // Throw away the first ~10ms of data because thats during mic start up. - if (ticks_ms - start_ticks < 10) { - buffers_processed++; - continue; - } - uint32_t* buffer = first_buffer; + + // The mic is running all the time, so we don't need to wait the usual 10msec or 100msec + // for it to start up. + + uint32_t *buffer = first_buffer; DmacDescriptor* descriptor = audio_dma.descriptor; if (buffers_processed % 2 == 1) { buffer = second_buffer; descriptor = &second_descriptor; } // Decimate and filter the last buffer - int32_t samples_gathered = descriptor->BTCNT.reg / words_per_sample; - for (uint16_t i = 0; i < samples_gathered; i++) { + uint32_t samples_gathered = descriptor->BTCNT.reg / words_per_sample; + // Don't run off the end of output buffer. Process only as many as needed. + uint32_t samples_to_process = min(remaining_samples_needed, samples_gathered); + for (uint32_t i = 0; i < samples_to_process; i++) { + // Call filter_sample just one place so it can be inlined. + uint16_t value = filter_sample(buffer + i * words_per_sample); if (self->bit_depth == 8) { - ((uint8_t*) output_buffer)[total_bytes] = filter_sample(buffer + i * words_per_sample) >> 8; - total_bytes += 1; - } else if (self->bit_depth == 16) { - output_buffer[total_bytes / 2] = filter_sample(buffer + i * words_per_sample); - total_bytes += 2; + // Truncate to 8 bits. + ((uint8_t*) output_buffer)[values_output] = value >> 8; + } else { + output_buffer[values_output] = value; } + values_output++; } buffers_processed++; - if (length - total_bytes < samples_per_buffer) { - descriptor->BTCNT.reg = (length - total_bytes) * words_per_sample; - descriptor->DSTADDR.reg = ((uint32_t) buffer) + (length - total_bytes) * self->bytes_per_sample; + // See if we need to transfer less than a full buffer for the remaining needed samples. + remaining_samples_needed = output_buffer_length - values_output; + if (remaining_samples_needed > 0 && remaining_samples_needed < samples_per_buffer) { + descriptor->BTCNT.reg = remaining_samples_needed; + descriptor->DSTADDR.reg = ((uint32_t) buffer) + remaining_samples_needed * words_per_sample; descriptor->DESCADDR.reg = 0; } } stop_dma(self); - return total_bytes; + return values_output; } void common_hal_audiobusio_pdmin_record_to_file(audiobusio_pdmin_obj_t* self, uint8_t* buffer, uint32_t length) { diff --git a/shared-bindings/audiobusio/PDMIn.c b/shared-bindings/audiobusio/PDMIn.c index e13e09d64e..c71f44679a 100644 --- a/shared-bindings/audiobusio/PDMIn.c +++ b/shared-bindings/audiobusio/PDMIn.c @@ -28,6 +28,7 @@ #include "lib/utils/context_manager_helpers.h" #include "py/binary.h" +#include "py/mphal.h" #include "py/objproperty.h" #include "py/runtime.h" #include "shared-bindings/microcontroller/Pin.h" @@ -41,7 +42,7 @@ //| //| PDMIn can be used to record an input audio signal on a given set of pins. //| -//| .. class:: PDMIn(clock_pin, data_pin, \*, frequency=8000, bit_depth=8, mono=True, oversample=64) +//| .. class:: PDMIn(clock_pin, data_pin, \*, frequency=16000, bit_depth=8, mono=True, oversample=64, startup_delay=0.11) //| //| Create a PDMIn object associated with the given pins. This allows you to //| record audio signals from the given pins. Individual ports may put further @@ -49,11 +50,16 @@ //| //| :param ~microcontroller.Pin clock_pin: The pin to output the clock to //| :param ~microcontroller.Pin data_pin: The pin to read the data from -//| :param int frequency: Target frequency of the resulting samples. Check `frequency` for real value. +//| :param int frequency: Target frequency of the resulting samples. Check `frequency` for actual value. +//| Minimum frequency is about 16000 Hz. //| :param int bit_depth: Final number of bits per sample. Must be divisible by 8 //| :param bool mono: True when capturing a single channel of audio, captures two channels otherwise //| :param int oversample: Number of single bit samples to decimate into a final sample. Must be divisible by 8 +//| :param float startup_delay: seconds to wait after starting microphone clock +//| to allow microphone to turn on. Most require only 0.01s; some require 0.1s. Longer is safer. +//| Must be in range 0.0-1.0 seconds. //| + //| Record 8-bit unsigned samples to buffer:: //| //| import audiobusio @@ -79,15 +85,19 @@ //| mic.record(b, len(b)) //| STATIC mp_obj_t audiobusio_pdmin_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *pos_args) { - enum { ARG_frequency, ARG_bit_depth, ARG_mono, ARG_oversample }; + enum { ARG_frequency, ARG_bit_depth, ARG_mono, ARG_oversample, ARG_startup_delay }; mp_map_t kw_args; mp_map_init_fixed_table(&kw_args, n_kw, pos_args + n_args); static const mp_arg_t allowed_args[] = { - { MP_QSTR_frequency, MP_ARG_INT, {.u_int = 8000} }, - { MP_QSTR_bit_depth, MP_ARG_INT, {.u_int = 8} }, - { MP_QSTR_mono, MP_ARG_BOOL,{.u_bool = true} }, - { MP_QSTR_oversample, MP_ARG_INT, {.u_int = 64} }, + { MP_QSTR_frequency, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = 16000} }, + { MP_QSTR_bit_depth, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = 8} }, + { MP_QSTR_mono, MP_ARG_KW_ONLY | MP_ARG_BOOL,{.u_bool = true} }, + { MP_QSTR_oversample, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = 64} }, + { MP_QSTR_startup_delay, MP_ARG_KW_ONLY | MP_ARG_OBJ, {.u_obj = MP_OBJ_NULL} }, }; + // Default microphone startup delay is 110msecs. Have seen mics that need 100 msecs plus a bit. + static const float STARTUP_DELAY_DEFAULT = 0.110F; + mp_arg_val_t args[MP_ARRAY_SIZE(allowed_args)]; mp_arg_parse_all(n_args - 2, pos_args + 2, &kw_args, MP_ARRAY_SIZE(allowed_args), allowed_args, args); @@ -116,8 +126,18 @@ STATIC mp_obj_t audiobusio_pdmin_make_new(const mp_obj_type_t *type, size_t n_ar } bool mono = args[ARG_mono].u_bool; + float startup_delay = (args[ARG_startup_delay].u_obj == MP_OBJ_NULL) + ? STARTUP_DELAY_DEFAULT + : mp_obj_get_float(args[ARG_startup_delay].u_obj); + if (startup_delay < 0.0 || startup_delay > 1.0) { + mp_raise_ValueError("Microphone startup delay must be in range 0.0 to 1.0"); + } + common_hal_audiobusio_pdmin_construct(self, clock_pin, data_pin, frequency, - bit_depth, mono, oversample); + bit_depth, mono, oversample); + + // Wait for the microphone to start up. Some start in 10 msecs; some take as much as 100 msecs. + mp_hal_delay_ms(startup_delay * 1000); return MP_OBJ_FROM_PTR(self); } @@ -160,11 +180,14 @@ STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(audiobusio_pdmin___exit___obj, 4, 4, //| audio at the given rate. For internal flash, writing all 1s to the file //| before recording is recommended to speed up writes. //| +//| :return: The number of samples recorded. If this is less than `destination_length`, +//| some samples were missed due to processing time. +//| STATIC mp_obj_t audiobusio_pdmin_obj_record(mp_obj_t self_obj, mp_obj_t destination, mp_obj_t destination_length) { audiobusio_pdmin_obj_t *self = MP_OBJ_TO_PTR(self_obj); raise_error_if_deinited(common_hal_audiobusio_pdmin_deinited(self)); - if (!MP_OBJ_IS_SMALL_INT(destination_length)) { - mp_raise_TypeError("destination_length must be int"); + if (!MP_OBJ_IS_SMALL_INT(destination_length) || MP_OBJ_SMALL_INT_VALUE(destination_length) < 0) { + mp_raise_TypeError("destination_length must be an int >= 0"); } uint32_t length = MP_OBJ_SMALL_INT_VALUE(destination_length); @@ -172,8 +195,8 @@ STATIC mp_obj_t audiobusio_pdmin_obj_record(mp_obj_t self_obj, mp_obj_t destinat if (MP_OBJ_IS_TYPE(destination, &fatfs_type_fileio)) { mp_raise_NotImplementedError(""); } else if (mp_get_buffer(destination, &bufinfo, MP_BUFFER_WRITE)) { - if (bufinfo.len < length) { - mp_raise_ValueError("Target buffer cannot hold destination_length bytes."); + if (bufinfo.len / mp_binary_get_size('@', bufinfo.typecode, NULL) < length) { + mp_raise_ValueError("Destination capacity is smaller than destination_length."); } uint8_t bit_depth = common_hal_audiobusio_pdmin_get_bit_depth(self); if (bufinfo.typecode != 'H' && bit_depth == 16) { @@ -181,12 +204,10 @@ STATIC mp_obj_t audiobusio_pdmin_obj_record(mp_obj_t self_obj, mp_obj_t destinat } else if (bufinfo.typecode != 'B' && bufinfo.typecode != BYTEARRAY_TYPECODE && bit_depth == 8) { mp_raise_ValueError("destination buffer must be a bytearray or array of type 'B' for bit_depth = 8"); } - length *= bit_depth / 8; + // length is the buffer length in slots, not bytes. uint32_t length_written = common_hal_audiobusio_pdmin_record_to_buffer(self, bufinfo.buf, length); - if (length_written != length) { - mp_printf(&mp_plat_print, "length mismatch %d %d\n", length_written, length); - } + return MP_OBJ_NEW_SMALL_INT(length_written); } return mp_const_none; } From f2ad1a36799a65ef27a1ee46c772043d97cd0011 Mon Sep 17 00:00:00 2001 From: Dan Halbert Date: Thu, 14 Dec 2017 11:51:49 -0500 Subject: [PATCH 032/135] Write version info to boot_out.txt. --- atmel-samd/main.c | 4 ++++ lib/utils/pyexec.c | 7 +++++-- py/makeversionhdr.py | 1 + 3 files changed, 10 insertions(+), 2 deletions(-) diff --git a/atmel-samd/main.c b/atmel-samd/main.c index 880a0e1709..091dfa447f 100644 --- a/atmel-samd/main.c +++ b/atmel-samd/main.c @@ -27,6 +27,7 @@ #include #include +#include "genhdr/mpversion.h" #include "py/nlr.h" #include "py/compile.h" #include "py/frozenmod.h" @@ -700,6 +701,9 @@ int main(void) { f_open(&((fs_user_mount_t *) MP_STATE_VM(vfs_mount_table)->obj)->fatfs, boot_output_file, CIRCUITPY_BOOT_OUTPUT_FILE, FA_WRITE | FA_CREATE_ALWAYS); flash_set_usb_writeable(true); + // Write version info to boot_out.txt. + mp_hal_stdout_tx_str(MICROPY_FULL_VERSION_INFO); + mp_hal_stdout_tx_str("\r\n"); #endif // TODO(tannewt): Re-add support for flashing boot error output. diff --git a/lib/utils/pyexec.c b/lib/utils/pyexec.c index d95084624c..66ccad3b63 100644 --- a/lib/utils/pyexec.c +++ b/lib/utils/pyexec.c @@ -256,7 +256,8 @@ STATIC int pyexec_friendly_repl_process_char(int c) { } else if (ret == CHAR_CTRL_B) { // reset friendly REPL mp_hal_stdout_tx_str("\r\n"); - mp_hal_stdout_tx_str("Adafruit CircuitPython " MICROPY_GIT_TAG " on " MICROPY_BUILD_DATE "; " MICROPY_HW_BOARD_NAME " with " MICROPY_HW_MCU_NAME "\r\n"); + mp_hal_stdout_tx_str(MICROPY_FULL_VERSION_INFO); + mp_hal_stdout_tx_str("\r\n"); // mp_hal_stdout_tx_str("Type \"help()\" for more information.\r\n"); goto input_restart; } else if (ret == CHAR_CTRL_C) { @@ -395,7 +396,9 @@ int pyexec_friendly_repl(void) { #endif friendly_repl_reset: - mp_hal_stdout_tx_str("\r\nAdafruit CircuitPython " MICROPY_GIT_TAG " on " MICROPY_BUILD_DATE "; " MICROPY_HW_BOARD_NAME " with " MICROPY_HW_MCU_NAME "\r\n"); + mp_hal_stdout_tx_str("\r\n"); + mp_hal_stdout_tx_str(MICROPY_FULL_VERSION_INFO); + mp_hal_stdout_tx_str("\r\n"); // mp_hal_stdout_tx_str("Type \"help()\" for more information.\r\n"); // to test ctrl-C diff --git a/py/makeversionhdr.py b/py/makeversionhdr.py index 30995f9372..ebd887445b 100644 --- a/py/makeversionhdr.py +++ b/py/makeversionhdr.py @@ -86,6 +86,7 @@ def make_version_header(filename): #define MICROPY_VERSION_MINOR (%s) #define MICROPY_VERSION_MICRO (%s) #define MICROPY_VERSION_STRING "%s" +#define MICROPY_FULL_VERSION_INFO ("Adafruit CircuitPython " MICROPY_GIT_TAG " on " MICROPY_BUILD_DATE "; " MICROPY_HW_BOARD_NAME " with " MICROPY_HW_MCU_NAME) """ % (git_tag, git_hash, datetime.date.today().strftime("%Y-%m-%d"), ver[0].replace('v', ''), ver[1], ver[2], version_string) From a37cc171e83d7236684a777ea08241db2712f909 Mon Sep 17 00:00:00 2001 From: Dan Halbert Date: Thu, 14 Dec 2017 17:43:59 -0500 Subject: [PATCH 033/135] bring CPX frozen modules up to date --- frozen/Adafruit_CircuitPython_LIS3DH | 2 +- frozen/Adafruit_CircuitPython_NeoPixel | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/frozen/Adafruit_CircuitPython_LIS3DH b/frozen/Adafruit_CircuitPython_LIS3DH index 8a7d9d99d2..278bef3532 160000 --- a/frozen/Adafruit_CircuitPython_LIS3DH +++ b/frozen/Adafruit_CircuitPython_LIS3DH @@ -1 +1 @@ -Subproject commit 8a7d9d99d2157376679735130b97bf236ccf755f +Subproject commit 278bef35321443319cb02dfe4bb8014b21974c8d diff --git a/frozen/Adafruit_CircuitPython_NeoPixel b/frozen/Adafruit_CircuitPython_NeoPixel index cafc445f08..fe8eb66b08 160000 --- a/frozen/Adafruit_CircuitPython_NeoPixel +++ b/frozen/Adafruit_CircuitPython_NeoPixel @@ -1 +1 @@ -Subproject commit cafc445f080736beefb1694ae79359a3be0c7bbb +Subproject commit fe8eb66b0870d8bd30d5de87f36b3cccb56b2f08 From 0c0a09aeb6ec0357acbe64b034c162c805e07c9e Mon Sep 17 00:00:00 2001 From: Dan Halbert Date: Fri, 15 Dec 2017 11:40:35 -0500 Subject: [PATCH 034/135] Speed up AnalogIn.value. --- atmel-samd/common-hal/analogio/AnalogIn.c | 9 ++++++--- atmel-samd/common-hal/microcontroller/Processor.c | 4 +++- 2 files changed, 9 insertions(+), 4 deletions(-) diff --git a/atmel-samd/common-hal/analogio/AnalogIn.c b/atmel-samd/common-hal/analogio/AnalogIn.c index 03c502dff7..cbb9f5de51 100644 --- a/atmel-samd/common-hal/analogio/AnalogIn.c +++ b/atmel-samd/common-hal/analogio/AnalogIn.c @@ -74,8 +74,10 @@ uint16_t common_hal_analogio_analogin_get_value(analogio_analogin_obj_t *self) { config_adc.reference = ADC_REFERENCE_INTVCC1; config_adc.gain_factor = ADC_GAIN_FACTOR_DIV2; config_adc.positive_input = self->pin->adc_input; - config_adc.resolution = ADC_RESOLUTION_16BIT; - config_adc.clock_prescaler = ADC_CLOCK_PRESCALER_DIV128; + config_adc.resolution = ADC_RESOLUTION_12BIT; + // Default input clock is GCLK0 (48 MHz) + // 48Mhz / 32 = 1.5MHz. Max ADC clock is 2.1MHz + config_adc.clock_prescaler = ADC_CLOCK_PRESCALER_DIV32; struct adc_module adc_instance; // ADC must have been disabled before adc_init() is called. @@ -108,7 +110,8 @@ uint16_t common_hal_analogio_analogin_get_value(analogio_analogin_obj_t *self) { } adc_disable(&adc_instance); - return data; + // Scale to 16 bits. In the future we might make this be this be under API control. + return data * 16; } float common_hal_analogio_analogin_get_reference_voltage(analogio_analogin_obj_t *self) { diff --git a/atmel-samd/common-hal/microcontroller/Processor.c b/atmel-samd/common-hal/microcontroller/Processor.c index c398c5e6fb..15bfb510b8 100644 --- a/atmel-samd/common-hal/microcontroller/Processor.c +++ b/atmel-samd/common-hal/microcontroller/Processor.c @@ -111,7 +111,9 @@ STATIC void configure_adc_temp(struct adc_module *adc_instance) { // "Discard the first conversion result whenever there is a change // in ADC configuration like voltage reference / ADC channel change." - config_adc.clock_prescaler = ADC_CLOCK_PRESCALER_DIV16; + // Default input clock is GCLK0 (48 MHz) + // 48Mhz / 32 = 1.5MHz. Max ADC clock is 2.1MHz + config_adc.clock_prescaler = ADC_CLOCK_PRESCALER_DIV32; config_adc.reference = ADC_REFERENCE_INT1V; config_adc.positive_input = ADC_POSITIVE_INPUT_TEMP; config_adc.negative_input = ADC_NEGATIVE_INPUT_GND; From 054cac3e4b910ed5201484990602c20a139a9d8d Mon Sep 17 00:00:00 2001 From: Dan Halbert Date: Fri, 15 Dec 2017 13:25:46 -0500 Subject: [PATCH 035/135] update CPX frozen Adafruit_CircuitPython_LIS3DH to library version 3.0.0 --- frozen/Adafruit_CircuitPython_LIS3DH | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/frozen/Adafruit_CircuitPython_LIS3DH b/frozen/Adafruit_CircuitPython_LIS3DH index 278bef3532..02e57df82d 160000 --- a/frozen/Adafruit_CircuitPython_LIS3DH +++ b/frozen/Adafruit_CircuitPython_LIS3DH @@ -1 +1 @@ -Subproject commit 278bef35321443319cb02dfe4bb8014b21974c8d +Subproject commit 02e57df82dcf0594cef220f73d3dcfadc295b607 From e3df0104b0aab0c400b0529340f23cd10402640e Mon Sep 17 00:00:00 2001 From: Scott Shawcroft Date: Tue, 19 Dec 2017 09:24:12 -0800 Subject: [PATCH 036/135] Add root readthedocs.yml file. --- .readthedocs.yml | 2 ++ requirements.txt | 1 - 2 files changed, 2 insertions(+), 1 deletion(-) create mode 100644 .readthedocs.yml delete mode 100644 requirements.txt diff --git a/.readthedocs.yml b/.readthedocs.yml new file mode 100644 index 0000000000..8b77f690a1 --- /dev/null +++ b/.readthedocs.yml @@ -0,0 +1,2 @@ +python: + version: 3 diff --git a/requirements.txt b/requirements.txt deleted file mode 100644 index 75df61718c..0000000000 --- a/requirements.txt +++ /dev/null @@ -1 +0,0 @@ -# dummy file to work around readthedocs bug: https://github.com/rtfd/readthedocs.org/issues/2855 From 22bbb6ab86fd1b843e03fb2474f69e6118c8aaad Mon Sep 17 00:00:00 2001 From: Dan Halbert Date: Wed, 20 Dec 2017 11:01:58 -0500 Subject: [PATCH 037/135] Don't include examples directories in frozen libraries --- py/mkrules.mk | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/py/mkrules.mk b/py/mkrules.mk index 656ffd03cb..1b33555128 100644 --- a/py/mkrules.mk +++ b/py/mkrules.mk @@ -115,12 +115,13 @@ $(MPY_CROSS): $(TOP)/py/*.[ch] $(TOP)/mpy-cross/*.[ch] $(TOP)/windows/fmode.c # Copy all the modules and single python files to freeze to a common area, omitting top-level dirs (the repo names). # Remove any conf.py (sphinx config) and setup.py (module install info) files, which are not meant to be frozen. +# Also remove the library examples directory, so it won't be included. # Then compile .mpy files from all the .py files, placing them in the same directories as the .py files. $(BUILD)/frozen_mpy: $(FROZEN_MPY_DIRS) $(ECHO) FREEZE $(FROZEN_MPY_DIRS) $(Q)$(MKDIR) -p $@ $(Q)$(RSYNC) -rL --include="*/" --include='*.py' --exclude="*" $(addsuffix /*,$(FROZEN_MPY_DIRS)) $@ - $(Q)$(RM) -f $@/conf.py $@/setup.py + $(Q)$(RM) -rf $@/conf.py $@/setup.py $@/examples $(Q)$(CD) $@ && \ $(FIND) -L . -type f -name '*.py' | sed 's=^\./==' | \ xargs -n1 $(abspath $(MPY_CROSS)) $(MPY_CROSS_FLAGS) From 23dd19757aadbb64112b882cd4ee2082d04791ee Mon Sep 17 00:00:00 2001 From: Dan Halbert Date: Tue, 7 Nov 2017 21:05:49 -0500 Subject: [PATCH 038/135] Wait 2 secs before creating new filesystem in case power is jittery --- atmel-samd/main.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/atmel-samd/main.c b/atmel-samd/main.c index 091dfa447f..0013f3e207 100644 --- a/atmel-samd/main.c +++ b/atmel-samd/main.c @@ -122,6 +122,11 @@ void init_flash_fs(bool create_allowed) { if (res == FR_NO_FILESYSTEM && create_allowed) { // no filesystem so create a fresh one + // Wait two seconds before creating. Jittery power might + // fail before we're ready. This can happen if someone + // is bobbling a bit when plugging in a battery. + mp_hal_delay_ms(2000); + uint8_t working_buf[_MAX_SS]; res = f_mkfs(&vfs_fat->fatfs, FM_FAT, 0, working_buf, sizeof(working_buf)); // Flush the new file system to make sure its repaired immediately. From ec1d29f4aeab2f611f288a11e94adbf39655340f Mon Sep 17 00:00:00 2001 From: Dan Halbert Date: Wed, 29 Nov 2017 22:23:13 -0500 Subject: [PATCH 039/135] check twice for bad filesystem --- atmel-samd/main.c | 22 +++++++++++++--------- 1 file changed, 13 insertions(+), 9 deletions(-) diff --git a/atmel-samd/main.c b/atmel-samd/main.c index 0013f3e207..2cbe6f88d2 100644 --- a/atmel-samd/main.c +++ b/atmel-samd/main.c @@ -127,16 +127,20 @@ void init_flash_fs(bool create_allowed) { // is bobbling a bit when plugging in a battery. mp_hal_delay_ms(2000); - uint8_t working_buf[_MAX_SS]; - res = f_mkfs(&vfs_fat->fatfs, FM_FAT, 0, working_buf, sizeof(working_buf)); - // Flush the new file system to make sure its repaired immediately. - flash_flush(); - if (res != FR_OK) { - return; - } + // Then try one more time to mount the flash in case it was late coming up. + res = f_mount(&vfs_fat->fatfs); + if (res == FR_NO_FILESYSTEM) { + uint8_t working_buf[_MAX_SS]; + res = f_mkfs(&vfs_fat->fatfs, FM_FAT, 0, working_buf, sizeof(working_buf)); + // Flush the new file system to make sure its repaired immediately. + flash_flush(); + if (res != FR_OK) { + return; + } - // set label - f_setlabel(&vfs_fat->fatfs, "CIRCUITPY"); + // set label + f_setlabel(&vfs_fat->fatfs, "CIRCUITPY"); + } } else if (res != FR_OK) { return; } From 39f30aeec699944da096107cc930c783f61f7712 Mon Sep 17 00:00:00 2001 From: Scott Shawcroft Date: Wed, 20 Dec 2017 15:17:06 -0800 Subject: [PATCH 040/135] Fix 1200 baud reset. Fixes #494 --- atmel-samd/common-hal/microcontroller/__init__.c | 3 +-- atmel-samd/mphalport.c | 2 +- atmel-samd/reset.c | 5 +++++ atmel-samd/reset.h | 1 + 4 files changed, 8 insertions(+), 3 deletions(-) diff --git a/atmel-samd/common-hal/microcontroller/__init__.c b/atmel-samd/common-hal/microcontroller/__init__.c index b90c38b604..26f09a8ade 100644 --- a/atmel-samd/common-hal/microcontroller/__init__.c +++ b/atmel-samd/common-hal/microcontroller/__init__.c @@ -55,7 +55,6 @@ void common_hal_mcu_enable_interrupts(void) { } extern uint32_t _ezero; -extern uint32_t _srelocate; void common_hal_mcu_on_next_reset(mcu_runmode_t runmode) { // Set up the defaults. @@ -63,7 +62,7 @@ void common_hal_mcu_on_next_reset(mcu_runmode_t runmode) { _ezero = CIRCUITPY_CANARY_WORD; if (runmode == RUNMODE_BOOTLOADER) { - if (&_bootloader_dbl_tap < &_srelocate) { + if (!bootloader_available()) { mp_raise_ValueError("Cannot reset into bootloader because no bootloader is present."); } // Pretend to be the first of the two reset presses needed to enter the diff --git a/atmel-samd/mphalport.c b/atmel-samd/mphalport.c index 4d597be6b2..24126b1e81 100644 --- a/atmel-samd/mphalport.c +++ b/atmel-samd/mphalport.c @@ -62,7 +62,7 @@ volatile bool reset_on_disconnect = false; void usb_dtr_notify(uint8_t port, bool set) { mp_cdc_enabled = set; - if (!set && reset_on_disconnect && _bootloader_dbl_tap != 0) { + if (!set && reset_on_disconnect && bootloader_available()) { reset_to_bootloader(); } } diff --git a/atmel-samd/reset.c b/atmel-samd/reset.c index 822789b472..8fb7696974 100644 --- a/atmel-samd/reset.c +++ b/atmel-samd/reset.c @@ -38,3 +38,8 @@ void reset_to_bootloader(void) { _bootloader_dbl_tap = DBL_TAP_MAGIC; reset(); } + +extern uint32_t _srelocate; +bool bootloader_available(void) { + return &_bootloader_dbl_tap >= &_srelocate; +} diff --git a/atmel-samd/reset.h b/atmel-samd/reset.h index 00b2312bb7..4d04c11ce2 100644 --- a/atmel-samd/reset.h +++ b/atmel-samd/reset.h @@ -33,5 +33,6 @@ extern uint32_t _bootloader_dbl_tap; void reset_to_bootloader(void); void reset(void); +bool bootloader_available(void); #endif // MICROPY_INCLUDED_ATMEL_SAMD_RESET_H From 2d2735c9d431f41ee4eaafcc6d62e24befa14773 Mon Sep 17 00:00:00 2001 From: Dan Halbert Date: Thu, 21 Dec 2017 16:43:03 -0500 Subject: [PATCH 041/135] Error in PDMIn filter loop. --- atmel-samd/common-hal/audiobusio/PDMIn.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/atmel-samd/common-hal/audiobusio/PDMIn.c b/atmel-samd/common-hal/audiobusio/PDMIn.c index 8263ac7d20..6cc493aedd 100644 --- a/atmel-samd/common-hal/audiobusio/PDMIn.c +++ b/atmel-samd/common-hal/audiobusio/PDMIn.c @@ -273,8 +273,9 @@ static uint16_t filter_sample(uint32_t pdm_samples[4]) { uint32_t pdm_sample = pdm_samples[i]; REPEAT_16_TIMES( { if (pdm_sample & 0x8000) { - running_sum += *filter_ptr++; + running_sum += *filter_ptr; } + filter_ptr++; pdm_sample <<= 1; } ) From 79187140436d9ef8659b526d58340ac666aad4b2 Mon Sep 17 00:00:00 2001 From: Dan Halbert Date: Sat, 23 Dec 2017 00:15:16 -0500 Subject: [PATCH 042/135] certain odd-sized PDMIn record buffers would crash or not fill properly --- atmel-samd/common-hal/audiobusio/PDMIn.c | 23 ++++++++++++++--------- 1 file changed, 14 insertions(+), 9 deletions(-) diff --git a/atmel-samd/common-hal/audiobusio/PDMIn.c b/atmel-samd/common-hal/audiobusio/PDMIn.c index 6cc493aedd..f108a30622 100644 --- a/atmel-samd/common-hal/audiobusio/PDMIn.c +++ b/atmel-samd/common-hal/audiobusio/PDMIn.c @@ -213,11 +213,15 @@ static void setup_dma(audiobusio_pdmin_obj_t* self, uint32_t length, } dma_descriptor_create(audio_dma.descriptor, &descriptor_config); + // Do we need more values than will fit in the first buffer? + // If so, set up a second buffer chained to be filled after the first buffer. if (length * words_per_sample > words_per_buffer) { block_transfer_count = words_per_buffer; descriptor_config.next_descriptor_address = ((uint32_t)audio_dma.descriptor); if (length * words_per_sample < 2 * words_per_buffer) { - block_transfer_count = 2 * words_per_buffer - length * words_per_sample; + // Length needed is more than one buffer but less than two. + // Subtract off the size of the first buffer, and what remains is the count we need. + block_transfer_count = length * words_per_sample - words_per_buffer; descriptor_config.next_descriptor_address = 0; } descriptor_config.block_transfer_count = block_transfer_count; @@ -309,18 +313,21 @@ uint32_t common_hal_audiobusio_pdmin_record_to_buffer(audiobusio_pdmin_obj_t* se uint32_t remaining_samples_needed = output_buffer_length; while (values_output < output_buffer_length) { // Wait for the next buffer to fill - while (tc_get_count_value(MP_STATE_VM(audiodma_block_counter)) == buffers_processed) { + uint32_t block_counter; + while ((block_counter = tc_get_count_value(MP_STATE_VM(audiodma_block_counter))) == buffers_processed) { #ifdef MICROPY_VM_HOOK_LOOP MICROPY_VM_HOOK_LOOP #endif } - if (tc_get_count_value(MP_STATE_VM(audiodma_block_counter)) != (buffers_processed + 1)) { + if (block_counter != (buffers_processed + 1)) { + // Looks like we aren't keeping up. We shouldn't skip a buffer. break; } // The mic is running all the time, so we don't need to wait the usual 10msec or 100msec // for it to start up. + // Flip back and forth between processing the first and second buffers. uint32_t *buffer = first_buffer; DmacDescriptor* descriptor = audio_dma.descriptor; if (buffers_processed % 2 == 1) { @@ -342,15 +349,13 @@ uint32_t common_hal_audiobusio_pdmin_record_to_buffer(audiobusio_pdmin_obj_t* se } values_output++; } + buffers_processed++; - // See if we need to transfer less than a full buffer for the remaining needed samples. + // We might need fewer than an entire of samples, but we won't try to alter the + // last DMA, which might already be in progress, so we'll just throw away some + // samples at the end. remaining_samples_needed = output_buffer_length - values_output; - if (remaining_samples_needed > 0 && remaining_samples_needed < samples_per_buffer) { - descriptor->BTCNT.reg = remaining_samples_needed; - descriptor->DSTADDR.reg = ((uint32_t) buffer) + remaining_samples_needed * words_per_sample; - descriptor->DESCADDR.reg = 0; - } } stop_dma(self); From e44fbca272471939b20f5c72530fb402836d24ad Mon Sep 17 00:00:00 2001 From: Dan Halbert Date: Sat, 23 Dec 2017 11:56:10 -0500 Subject: [PATCH 043/135] PDMIn: Make last DMA buffer be exactly the right length. --- atmel-samd/common-hal/audiobusio/PDMIn.c | 26 ++++++++++++++++++++---- 1 file changed, 22 insertions(+), 4 deletions(-) diff --git a/atmel-samd/common-hal/audiobusio/PDMIn.c b/atmel-samd/common-hal/audiobusio/PDMIn.c index f108a30622..50d3b180ce 100644 --- a/atmel-samd/common-hal/audiobusio/PDMIn.c +++ b/atmel-samd/common-hal/audiobusio/PDMIn.c @@ -334,7 +334,7 @@ uint32_t common_hal_audiobusio_pdmin_record_to_buffer(audiobusio_pdmin_obj_t* se buffer = second_buffer; descriptor = &second_descriptor; } - // Decimate and filter the last buffer + // Decimate and filter the buffer that was just filled. uint32_t samples_gathered = descriptor->BTCNT.reg / words_per_sample; // Don't run off the end of output buffer. Process only as many as needed. uint32_t samples_to_process = min(remaining_samples_needed, samples_gathered); @@ -352,10 +352,28 @@ uint32_t common_hal_audiobusio_pdmin_record_to_buffer(audiobusio_pdmin_obj_t* se buffers_processed++; - // We might need fewer than an entire of samples, but we won't try to alter the - // last DMA, which might already be in progress, so we'll just throw away some - // samples at the end. + // Compute how many more samples we need, and if the last buffer is the last + // set of samples needed, adjust the DMA count to only fetch as necessary. remaining_samples_needed = output_buffer_length - values_output; + if (remaining_samples_needed <= samples_per_buffer*2 && + remaining_samples_needed > samples_per_buffer) { + // Adjust the DMA settings for the current buffer, which will be processed + // after the other buffer, which is now receiving samples via DMA. + // We don't adjust the DMA in progress, but the one after that. + // Timeline: + // 1. current buffer (already processed) + // 2. alternate buffer (DMA in progress) + // 3. current buffer (last set of samples needed) + + // Set up to receive the last set of samples (don't include the alternate buffer, now in use). + uint32_t samples_needed_for_last_buffer = remaining_samples_needed - samples_per_buffer; + descriptor->BTCNT.reg = samples_needed_for_last_buffer * words_per_sample; + descriptor->DSTADDR.reg = ((uint32_t) buffer) + + samples_needed_for_last_buffer * words_per_sample * sizeof(buffer[0]); + + // Break chain to alternate buffer. + descriptor->DESCADDR.reg = 0; + } } stop_dma(self); From 2dcb2f06cbfaacb5cf362cac1ba547dd45d13e9a Mon Sep 17 00:00:00 2001 From: Dan Halbert Date: Sat, 23 Dec 2017 23:46:19 -0500 Subject: [PATCH 044/135] Add git version info to frozen modules. --- .gitmodules | 3 ++ py/mkenv.mk | 1 + py/mkrules.mk | 7 ++- tools/preprocess_frozen_modules.py | 69 ++++++++++++++++++++++++++++++ tools/python-semver | 1 + 5 files changed, 77 insertions(+), 4 deletions(-) create mode 100755 tools/preprocess_frozen_modules.py create mode 160000 tools/python-semver diff --git a/.gitmodules b/.gitmodules index faad88a857..ef87dd1ba1 100644 --- a/.gitmodules +++ b/.gitmodules @@ -29,3 +29,6 @@ [submodule "frozen/Adafruit_CircuitPython_BusDevice"] path = frozen/Adafruit_CircuitPython_BusDevice url = https://github.com/adafruit/Adafruit_CircuitPython_BusDevice.git +[submodule "tools/python-semver"] + path = tools/python-semver + url = https://github.com/k-bx/python-semver.git diff --git a/py/mkenv.mk b/py/mkenv.mk index 5a118854aa..5f8cd902bf 100644 --- a/py/mkenv.mk +++ b/py/mkenv.mk @@ -70,6 +70,7 @@ endif MAKE_FROZEN = $(TOP)/tools/make-frozen.py MPY_CROSS = $(TOP)/mpy-cross/mpy-cross MPY_TOOL = $(TOP)/tools/mpy-tool.py +PREPROCESS_FROZEN_MODULES = PYTHONPATH=$(TOP)/tools/python-semver $(TOP)/tools/preprocess_frozen_modules.py all: .PHONY: all diff --git a/py/mkrules.mk b/py/mkrules.mk index 1b33555128..713e69c622 100644 --- a/py/mkrules.mk +++ b/py/mkrules.mk @@ -114,14 +114,13 @@ $(MPY_CROSS): $(TOP)/py/*.[ch] $(TOP)/mpy-cross/*.[ch] $(TOP)/windows/fmode.c $(Q)$(MAKE) -C $(TOP)/mpy-cross # Copy all the modules and single python files to freeze to a common area, omitting top-level dirs (the repo names). -# Remove any conf.py (sphinx config) and setup.py (module install info) files, which are not meant to be frozen. -# Also remove the library examples directory, so it won't be included. +# Do any preprocessing necessary: currently, this adds version information, removes examples, and +# non-library .py files in the modules (setup.py and conf.py) # Then compile .mpy files from all the .py files, placing them in the same directories as the .py files. $(BUILD)/frozen_mpy: $(FROZEN_MPY_DIRS) $(ECHO) FREEZE $(FROZEN_MPY_DIRS) $(Q)$(MKDIR) -p $@ - $(Q)$(RSYNC) -rL --include="*/" --include='*.py' --exclude="*" $(addsuffix /*,$(FROZEN_MPY_DIRS)) $@ - $(Q)$(RM) -rf $@/conf.py $@/setup.py $@/examples + $(Q)$(PREPROCESS_FROZEN_MODULES) -o $@ $(FROZEN_MPY_DIRS) $(Q)$(CD) $@ && \ $(FIND) -L . -type f -name '*.py' | sed 's=^\./==' | \ xargs -n1 $(abspath $(MPY_CROSS)) $(MPY_CROSS_FLAGS) diff --git a/tools/preprocess_frozen_modules.py b/tools/preprocess_frozen_modules.py new file mode 100755 index 0000000000..e29b54b16f --- /dev/null +++ b/tools/preprocess_frozen_modules.py @@ -0,0 +1,69 @@ +#!/usr/bin/env python3 +import argparse +import os +import os.path +from pathlib import Path +import semver +import subprocess + +def version_string(path=None, *, valid_semver=False): + version = None + tag = subprocess.run('git describe --tags --exact-match', shell=True, + stdout=subprocess.PIPE, stderr=subprocess.PIPE, cwd=path) + if tag.returncode == 0: + version = tag.stdout.strip().decode("utf-8", "strict") + else: + describe = subprocess.run("git describe --tags", shell=True, stdout=subprocess.PIPE, cwd=path) + tag, additional_commits, commitish = describe.stdout.strip().decode("utf-8", "strict").rsplit("-", maxsplit=2) + commitish = commitish[1:] + if valid_semver: + version_info = semver.parse_version_info(tag) + if not version_info.prerelease: + version = semver.bump_patch(tag) + "-alpha.0.plus." + additional_commits + "+" + commitish + else: + version = tag + ".plus." + additional_commits + "+" + commitish + else: + version = commitish + return version + +# Visit all the .py files in topdir. Replace any __version__ = "0.0.0-auto.0" type of info +# with actual version info derived from git. +def copy_and_process(in_dir, out_dir): + for root, subdirs, files in os.walk(in_dir): + + # Skip library examples directories. + if Path(root).name == 'examples': + continue + + for file in files: + # Skip top-level setup.py (module install info) and conf.py (sphinx config), + # which are not part of the library + if (root == in_dir) and file in ('conf.py', 'setup.py'): + continue + + input_file_path = Path(root, file) + output_file_path = Path(out_dir, input_file_path.relative_to(in_dir)) + + if file.endswith(".py"): + output_file_path.parent.mkdir(parents=True, exist_ok=True) + with input_file_path.open("r") as input, output_file_path.open("w") as output: + for line in input: + if line.startswith("__version__"): + module_version = version_string(root, valid_semver=True) + line = line.replace("0.0.0-auto.0", module_version) + output.write(line) + +if __name__ == '__main__': + argparser = argparse.ArgumentParser(description="""\ + Copy and pre-process .py files into output directory, before freezing. + 1. Remove top-level repo directory. + 2. Update __version__ info. + 3. Remove examples. + 4. Remove non-library setup.py and conf.py""") + argparser.add_argument("in_dirs", metavar="input-dir", nargs="+", + help="top-level code dirs (may be git repo dirs)") + argparser.add_argument("-o", "--out_dir", help="output directory") + args = argparser.parse_args() + + for in_dir in args.in_dirs: + copy_and_process(in_dir, args.out_dir) diff --git a/tools/python-semver b/tools/python-semver new file mode 160000 index 0000000000..2001c62d1a --- /dev/null +++ b/tools/python-semver @@ -0,0 +1 @@ +Subproject commit 2001c62d1a0361c44acc7076d8ce91e1d1c66141 From 644ad74ea1a33ef7112da1537e83c802b2b15202 Mon Sep 17 00:00:00 2001 From: Dan Halbert Date: Sun, 24 Dec 2017 13:49:58 -0500 Subject: [PATCH 045/135] preprocess_frozen_modules.py: make compatible with Python 3.4. --- tools/preprocess_frozen_modules.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/tools/preprocess_frozen_modules.py b/tools/preprocess_frozen_modules.py index e29b54b16f..b425ffa2d2 100755 --- a/tools/preprocess_frozen_modules.py +++ b/tools/preprocess_frozen_modules.py @@ -45,7 +45,9 @@ def copy_and_process(in_dir, out_dir): output_file_path = Path(out_dir, input_file_path.relative_to(in_dir)) if file.endswith(".py"): - output_file_path.parent.mkdir(parents=True, exist_ok=True) + # mkdir() takes an exists_ok=True, but not until Python 3.5. + if not output_file_path.parent.exists(): + output_file_path.parent.mkdir(parents=True) with input_file_path.open("r") as input, output_file_path.open("w") as output: for line in input: if line.startswith("__version__"): From 31be20744deaeb24a18205fc8099d2628531830d Mon Sep 17 00:00:00 2001 From: Dan Halbert Date: Sun, 24 Dec 2017 14:29:03 -0500 Subject: [PATCH 046/135] preprocess_frozen_modules.py: yet more Python 3.4 compatibility changes --- tools/preprocess_frozen_modules.py | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/tools/preprocess_frozen_modules.py b/tools/preprocess_frozen_modules.py index b425ffa2d2..0233fba614 100755 --- a/tools/preprocess_frozen_modules.py +++ b/tools/preprocess_frozen_modules.py @@ -6,15 +6,16 @@ from pathlib import Path import semver import subprocess +# Compatible with Python 3.4 due to travis using trusty as default. + def version_string(path=None, *, valid_semver=False): version = None - tag = subprocess.run('git describe --tags --exact-match', shell=True, - stdout=subprocess.PIPE, stderr=subprocess.PIPE, cwd=path) - if tag.returncode == 0: - version = tag.stdout.strip().decode("utf-8", "strict") - else: - describe = subprocess.run("git describe --tags", shell=True, stdout=subprocess.PIPE, cwd=path) - tag, additional_commits, commitish = describe.stdout.strip().decode("utf-8", "strict").rsplit("-", maxsplit=2) + try: + tag = subprocess.check_output('git describe --tags --exact-match', shell=True, cwd=path) + version = tag.strip().decode("utf-8", "strict") + except subprocess.CalledProcessError: + describe = subprocess.check_output("git describe --tags", shell=True, cwd=path) + tag, additional_commits, commitish = describe.strip().decode("utf-8", "strict").rsplit("-", maxsplit=2) commitish = commitish[1:] if valid_semver: version_info = semver.parse_version_info(tag) @@ -45,7 +46,6 @@ def copy_and_process(in_dir, out_dir): output_file_path = Path(out_dir, input_file_path.relative_to(in_dir)) if file.endswith(".py"): - # mkdir() takes an exists_ok=True, but not until Python 3.5. if not output_file_path.parent.exists(): output_file_path.parent.mkdir(parents=True) with input_file_path.open("r") as input, output_file_path.open("w") as output: From 9a50fa4a502359df569967c47a9b778d2660d6a5 Mon Sep 17 00:00:00 2001 From: Dan Halbert Date: Sat, 30 Dec 2017 11:22:29 -0500 Subject: [PATCH 047/135] update CPX frozen modules to latest versions --- frozen/Adafruit_CircuitPython_BusDevice | 2 +- frozen/Adafruit_CircuitPython_LIS3DH | 2 +- frozen/Adafruit_CircuitPython_NeoPixel | 2 +- frozen/Adafruit_CircuitPython_Thermistor | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/frozen/Adafruit_CircuitPython_BusDevice b/frozen/Adafruit_CircuitPython_BusDevice index be325b94a3..9a49ca04e3 160000 --- a/frozen/Adafruit_CircuitPython_BusDevice +++ b/frozen/Adafruit_CircuitPython_BusDevice @@ -1 +1 @@ -Subproject commit be325b94a3254cc1dc8deccfcab8942b3d915774 +Subproject commit 9a49ca04e3754be246524e57f8c1810c76be5948 diff --git a/frozen/Adafruit_CircuitPython_LIS3DH b/frozen/Adafruit_CircuitPython_LIS3DH index 02e57df82d..74afff3ff9 160000 --- a/frozen/Adafruit_CircuitPython_LIS3DH +++ b/frozen/Adafruit_CircuitPython_LIS3DH @@ -1 +1 @@ -Subproject commit 02e57df82dcf0594cef220f73d3dcfadc295b607 +Subproject commit 74afff3ff912c9711d207671b8b9068358eaa0d2 diff --git a/frozen/Adafruit_CircuitPython_NeoPixel b/frozen/Adafruit_CircuitPython_NeoPixel index fe8eb66b08..8e1e5bbb86 160000 --- a/frozen/Adafruit_CircuitPython_NeoPixel +++ b/frozen/Adafruit_CircuitPython_NeoPixel @@ -1 +1 @@ -Subproject commit fe8eb66b0870d8bd30d5de87f36b3cccb56b2f08 +Subproject commit 8e1e5bbb86e03d539103c6d73ccac0cb27711b77 diff --git a/frozen/Adafruit_CircuitPython_Thermistor b/frozen/Adafruit_CircuitPython_Thermistor index 0339da36f7..6c281ed26a 160000 --- a/frozen/Adafruit_CircuitPython_Thermistor +++ b/frozen/Adafruit_CircuitPython_Thermistor @@ -1 +1 @@ -Subproject commit 0339da36f78d2a598c559c26df4b60245f34a545 +Subproject commit 6c281ed26a2b38060e6a8c37c16f3bf6345cec2d From 0ff128ec0309f910bf605cde17abb2b89f409a6f Mon Sep 17 00:00:00 2001 From: Radomir Dopieralski Date: Wed, 10 Jan 2018 22:50:10 +0100 Subject: [PATCH 048/135] Fix example for gamepad The example code for the gamepad module would skip detected button presses in the code that waits for a button to be released, because it would run it even when no button is pressed. Also updated the example pin names to not use RX and TX. --- shared-bindings/gamepad/GamePad.c | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/shared-bindings/gamepad/GamePad.c b/shared-bindings/gamepad/GamePad.c index bdc3359fb6..a03b9318d8 100644 --- a/shared-bindings/gamepad/GamePad.c +++ b/shared-bindings/gamepad/GamePad.c @@ -49,8 +49,8 @@ gamepad_obj_t* gamepad_singleton = NULL; //| //| //| pad = gamepad.GamePad( -//| digitalio.DigitalInOut(board.D0), -//| digitalio.DigitalInOut(board.D1), +//| digitalio.DigitalInOut(board.D10), +//| digitalio.DigitalInOut(board.D11), //| ) //| //| y = 0 @@ -63,8 +63,9 @@ gamepad_obj_t* gamepad_singleton = NULL; //| y += 1 //| print(y) //| time.sleep(0.1) -//| while pad.get_pressed(): +//| while buttons: //| # Wait for all buttons to be released. +//| buttons = pad.get_pressed() //| time.sleep(0.1) //| From 3b946f667e0d6b160de70488d09208b6b633bc2b Mon Sep 17 00:00:00 2001 From: Tony DiCola Date: Fri, 19 Jan 2018 11:55:39 -0800 Subject: [PATCH 049/135] Add missing Feather M0 RadioFruit boards: RFM69, RFM9x. (#538) --- atmel-samd/boards/feather_m0_rfm69/board.c | 38 +++ .../boards/feather_m0_rfm69/conf_access.h | 115 +++++++++ .../boards/feather_m0_rfm69/conf_board.h | 14 ++ .../boards/feather_m0_rfm69/conf_clocks.h | 1 + atmel-samd/boards/feather_m0_rfm69/conf_usb.h | 221 ++++++++++++++++++ .../boards/feather_m0_rfm69/mpconfigboard.h | 16 ++ .../boards/feather_m0_rfm69/mpconfigboard.mk | 8 + atmel-samd/boards/feather_m0_rfm69/pins.c | 30 +++ atmel-samd/boards/feather_m0_rfm9x/board.c | 38 +++ .../boards/feather_m0_rfm9x/conf_access.h | 115 +++++++++ .../boards/feather_m0_rfm9x/conf_board.h | 14 ++ .../boards/feather_m0_rfm9x/conf_clocks.h | 1 + atmel-samd/boards/feather_m0_rfm9x/conf_usb.h | 221 ++++++++++++++++++ .../boards/feather_m0_rfm9x/mpconfigboard.h | 16 ++ .../boards/feather_m0_rfm9x/mpconfigboard.mk | 8 + atmel-samd/boards/feather_m0_rfm9x/pins.c | 30 +++ tools/build_adafruit_bins.sh | 2 +- 17 files changed, 887 insertions(+), 1 deletion(-) create mode 100644 atmel-samd/boards/feather_m0_rfm69/board.c create mode 100644 atmel-samd/boards/feather_m0_rfm69/conf_access.h create mode 100644 atmel-samd/boards/feather_m0_rfm69/conf_board.h create mode 100644 atmel-samd/boards/feather_m0_rfm69/conf_clocks.h create mode 100644 atmel-samd/boards/feather_m0_rfm69/conf_usb.h create mode 100644 atmel-samd/boards/feather_m0_rfm69/mpconfigboard.h create mode 100644 atmel-samd/boards/feather_m0_rfm69/mpconfigboard.mk create mode 100644 atmel-samd/boards/feather_m0_rfm69/pins.c create mode 100644 atmel-samd/boards/feather_m0_rfm9x/board.c create mode 100644 atmel-samd/boards/feather_m0_rfm9x/conf_access.h create mode 100644 atmel-samd/boards/feather_m0_rfm9x/conf_board.h create mode 100644 atmel-samd/boards/feather_m0_rfm9x/conf_clocks.h create mode 100644 atmel-samd/boards/feather_m0_rfm9x/conf_usb.h create mode 100644 atmel-samd/boards/feather_m0_rfm9x/mpconfigboard.h create mode 100644 atmel-samd/boards/feather_m0_rfm9x/mpconfigboard.mk create mode 100644 atmel-samd/boards/feather_m0_rfm9x/pins.c diff --git a/atmel-samd/boards/feather_m0_rfm69/board.c b/atmel-samd/boards/feather_m0_rfm69/board.c new file mode 100644 index 0000000000..c8e20206a1 --- /dev/null +++ b/atmel-samd/boards/feather_m0_rfm69/board.c @@ -0,0 +1,38 @@ +/* + * This file is part of the MicroPython project, http://micropython.org/ + * + * The MIT License (MIT) + * + * Copyright (c) 2017 Scott Shawcroft for Adafruit Industries + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +#include "boards/board.h" + +void board_init(void) +{ +} + +bool board_requests_safe_mode(void) { + return false; +} + +void reset_board(void) { +} diff --git a/atmel-samd/boards/feather_m0_rfm69/conf_access.h b/atmel-samd/boards/feather_m0_rfm69/conf_access.h new file mode 100644 index 0000000000..25109b75ca --- /dev/null +++ b/atmel-samd/boards/feather_m0_rfm69/conf_access.h @@ -0,0 +1,115 @@ +/** + * \file + * + * \brief Memory access control configuration file. + * + * Copyright (c) 2014-2015 Atmel Corporation. All rights reserved. + * + * \asf_license_start + * + * \page License + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * 3. The name of Atmel may not be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * 4. This software may only be redistributed and used in connection with an + * Atmel microcontroller product. + * + * THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE + * EXPRESSLY AND SPECIFICALLY DISCLAIMED. IN NO EVENT SHALL ATMEL BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + * \asf_license_stop + * + */ +/* + * Support and FAQ: visit Atmel Support + */ + +#ifndef _CONF_ACCESS_H_ +#define _CONF_ACCESS_H_ + +#include "compiler.h" +#include "board.h" + + +/*! \name Activation of Logical Unit Numbers + */ +//! @{ +#define LUN_0 ENABLE //!< On-Chip Virtual Memory. +#define LUN_1 DISABLE //!< AT45DBX Data Flash. +#define LUN_2 DISABLE //!< SD/MMC Card over SPI. +#define LUN_3 DISABLE //!< SD/MMC Card over MCI Slot 0. +#define LUN_4 DISABLE +#define LUN_5 DISABLE +#define LUN_6 DISABLE +#define LUN_7 DISABLE +#define LUN_USB DISABLE //!< Host Mass-Storage Memory. +//! @} + +/*! \name LUN 0 Definitions + */ +//! @{ +#define LUN_0_INCLUDE "access_vfs.h" +#define Lun_0_test_unit_ready vfs_test_unit_ready +#define Lun_0_read_capacity vfs_read_capacity +#define Lun_0_unload NULL +#define Lun_0_wr_protect vfs_wr_protect +#define Lun_0_removal vfs_removal +#define Lun_0_usb_read_10 vfs_usb_read_10 +#define Lun_0_usb_write_10 vfs_usb_write_10 +#define LUN_0_NAME "\"MicroPython VFS[0]\"" +//! @} + +#define MEM_USB LUN_USB + +/*! \name Actions Associated with Memory Accesses + * + * Write here the action to associate with each memory access. + * + * \warning Be careful not to waste time in order not to disturb the functions. + */ +//! @{ +#define memory_start_read_action(nb_sectors) +#define memory_stop_read_action() +#define memory_start_write_action(nb_sectors) +#define memory_stop_write_action() +//! @} + +/*! \name Activation of Interface Features + */ +//! @{ +#define ACCESS_USB true //!< MEM <-> USB interface. +#define ACCESS_MEM_TO_RAM false //!< MEM <-> RAM interface. +#define ACCESS_STREAM false //!< Streaming MEM <-> MEM interface. +#define ACCESS_STREAM_RECORD false //!< Streaming MEM <-> MEM interface in record mode. +#define ACCESS_MEM_TO_MEM false //!< MEM <-> MEM interface. +#define ACCESS_CODEC false //!< Codec interface. +//! @} + +/*! \name Specific Options for Access Control + */ +//! @{ +#define GLOBAL_WR_PROTECT false //!< Management of a global write protection. +//! @} + + +#endif // _CONF_ACCESS_H_ diff --git a/atmel-samd/boards/feather_m0_rfm69/conf_board.h b/atmel-samd/boards/feather_m0_rfm69/conf_board.h new file mode 100644 index 0000000000..7b88c97fc2 --- /dev/null +++ b/atmel-samd/boards/feather_m0_rfm69/conf_board.h @@ -0,0 +1,14 @@ +/** + * \file + * + * \brief User board configuration template + * + */ +/* + * Support and FAQ: visit Atmel Support + */ + +#ifndef CONF_BOARD_H +#define CONF_BOARD_H + +#endif // CONF_BOARD_H diff --git a/atmel-samd/boards/feather_m0_rfm69/conf_clocks.h b/atmel-samd/boards/feather_m0_rfm69/conf_clocks.h new file mode 100644 index 0000000000..d3f3e6496d --- /dev/null +++ b/atmel-samd/boards/feather_m0_rfm69/conf_clocks.h @@ -0,0 +1 @@ +#include "conf_clocks_external_32k.h" diff --git a/atmel-samd/boards/feather_m0_rfm69/conf_usb.h b/atmel-samd/boards/feather_m0_rfm69/conf_usb.h new file mode 100644 index 0000000000..c0c573eeef --- /dev/null +++ b/atmel-samd/boards/feather_m0_rfm69/conf_usb.h @@ -0,0 +1,221 @@ + +#include +#include + +#include "asf/common/services/usb/class/cdc/usb_protocol_cdc.h" + +#ifndef CONF_USB_H_INCLUDED +#define CONF_USB_H_INCLUDED + +#define USB_DEVICE_MAJOR_VERSION 1 +#define USB_DEVICE_MINOR_VERSION 0 +#define USB_DEVICE_POWER 100 // Consumption on Vbus line (mA) +#define USB_DEVICE_ATTR \ + (USB_CONFIG_ATTR_BUS_POWERED) +// (USB_CONFIG_ATTR_REMOTE_WAKEUP|USB_CONFIG_ATTR_SELF_POWERED) +// (USB_CONFIG_ATTR_REMOTE_WAKEUP|USB_CONFIG_ATTR_BUS_POWERED) + +//! USB Device string definitions (Optional) +#ifndef USB_DEVICE_MANUFACTURE_NAME +# define USB_DEVICE_MANUFACTURE_NAME "Adafruit Industries" +#endif + +#ifndef USB_DEVICE_PRODUCT_NAME +# define USB_DEVICE_PRODUCT_NAME "Feather M0 RFM69" +#endif + +#define USB_DEVICE_GET_SERIAL_NAME_POINTER serial_number +#define USB_DEVICE_GET_SERIAL_NAME_LENGTH 32 +extern char serial_number[USB_DEVICE_GET_SERIAL_NAME_LENGTH]; + +//! Control endpoint size +#define USB_DEVICE_EP_CTRL_SIZE 64 + +//! Two interfaces for this device (CDC COM + CDC DATA + MSC + HID mouse + HID kbd) +#define USB_DEVICE_NB_INTERFACE 5 + +// (3 | USB_EP_DIR_IN) // CDC Notify endpoint +// (4 | USB_EP_DIR_IN) // CDC TX +// (5 | USB_EP_DIR_OUT) // CDC RX +// (1 | USB_EP_DIR_IN) // MSC IN +// (2 | USB_EP_DIR_OUT) // MSC OUT +// (6 | USB_EP_DIR_IN) // HID mouse report +// (7 | USB_EP_DIR_IN) // HID keyboard report +#define USB_DEVICE_MAX_EP 7 + +#define UDI_CDC_PORT_NB 1 +#define UDI_CDC_ENABLE_EXT(port) mp_cdc_enable(port) +extern bool mp_cdc_enable(uint8_t port); +#define UDI_CDC_DISABLE_EXT(port) mp_cdc_disable(port) +extern void mp_cdc_disable(uint8_t port); +#define UDI_CDC_LOW_RATE + +#define UDI_CDC_DEFAULT_RATE 115200 +#define UDI_CDC_DEFAULT_STOPBITS CDC_STOP_BITS_1 +#define UDI_CDC_DEFAULT_PARITY CDC_PAR_NONE +#define UDI_CDC_DEFAULT_DATABITS 8 + +#define UDI_CDC_RX_NOTIFY(port) usb_rx_notify() +void usb_rx_notify(void); +#define UDI_CDC_SET_CODING_EXT(port,cfg) usb_coding_notify(port, cfg) +void usb_coding_notify(uint8_t port, usb_cdc_line_coding_t* coding); +#define UDI_CDC_SET_DTR_EXT(port,set) usb_dtr_notify(port, set) +void usb_dtr_notify(uint8_t port, bool set); +#define UDI_CDC_SET_RTS_EXT(port,set) usb_rts_notify(port, set) +void usb_rts_notify(uint8_t port, bool set); + +/** + * USB CDC low level configuration + * In standalone these configurations are defined by the CDC module. + * For composite device, these configuration must be defined here + * @{ + */ +//! Endpoint numbers definition + +#define UDI_CDC_COMM_EP_0 (3 | USB_EP_DIR_IN) // Notify endpoint +#define UDI_CDC_DATA_EP_IN_0 (4 | USB_EP_DIR_IN) // TX +#define UDI_CDC_DATA_EP_OUT_0 (5 | USB_EP_DIR_OUT) // RX + +//! Interface numbers +#define UDI_CDC_COMM_IFACE_NUMBER_0 0 +#define UDI_CDC_DATA_IFACE_NUMBER_0 1 + +/** + * Configuration of MSC interface + * @{ + */ +//! Vendor name and Product version of MSC interface +#define UDI_MSC_GLOBAL_VENDOR_ID \ + 'A', 'T', 'M', 'E', 'L', ' ', ' ', ' ' +#define UDI_MSC_GLOBAL_PRODUCT_VERSION \ + '1', '.', '0', '0' + +//! Interface callback definition +#define UDI_MSC_ENABLE_EXT() mp_msc_enable() +extern bool mp_msc_enable(void); +#define UDI_MSC_DISABLE_EXT() mp_msc_disable() +extern void mp_msc_disable(void); + +//! Enable id string of interface to add an extra USB string +#define UDI_MSC_STRING_ID 5 + +/** + * USB MSC low level configuration + * In standalone these configurations are defined by the MSC module. + * For composite device, these configuration must be defined here + * @{ + */ +//! Endpoint numbers definition +#define UDI_MSC_EP_IN (1 | USB_EP_DIR_IN) +#define UDI_MSC_EP_OUT (2 | USB_EP_DIR_OUT) + +//! Interface number +#define UDI_MSC_IFACE_NUMBER 2 + +/** + * Configuration of HID Mouse interface + * @{ + */ +//! Interface callback definition +#define UDI_HID_MOUSE_ENABLE_EXT() mp_mouse_enable() +extern bool mp_mouse_enable(void); +#define UDI_HID_MOUSE_DISABLE_EXT() mp_mouse_disable() +extern void mp_mouse_disable(void); + +//! Enable id string of interface to add an extra USB string +#define UDI_HID_MOUSE_STRING_ID 6 + +/** + * USB HID Mouse low level configuration + * In standalone these configurations are defined by the HID Mouse module. + * For composite device, these configuration must be defined here + * @{ + */ +//! Endpoint numbers definition +#define UDI_HID_MOUSE_EP_IN (6 | USB_EP_DIR_IN) + +//! Interface number +#define UDI_HID_MOUSE_IFACE_NUMBER 3 +//@} +//@} + +/** + * Configuration of HID Keyboard interface + * @{ + */ +//! Interface callback definition +#define UDI_HID_KBD_ENABLE_EXT() mp_keyboard_enable() +extern bool mp_keyboard_enable(void); +#define UDI_HID_KBD_DISABLE_EXT() mp_keyboard_disable() +extern void mp_keyboard_disable(void); +#define UDI_HID_KBD_CHANGE_LED(value) mp_keyboard_led(value) +extern void mp_keyboard_led(uint8_t); + +//! Enable id string of interface to add an extra USB string +#define UDI_HID_KBD_STRING_ID 7 + +/** + * USB HID Keyboard low level configuration + * In standalone these configurations are defined by the HID Keyboard module. + * For composite device, these configuration must be defined here + * @{ + */ +//! Endpoint numbers definition +#define UDI_HID_KBD_EP_IN (7 | USB_EP_DIR_IN) + +//! Interface number +#define UDI_HID_KBD_IFACE_NUMBER 4 + +/** + * Description of Composite Device + * @{ + */ +//! USB Interfaces descriptor structure +#define UDI_COMPOSITE_DESC_T \ + usb_iad_desc_t udi_cdc_iad; \ + udi_cdc_comm_desc_t udi_cdc_comm; \ + udi_cdc_data_desc_t udi_cdc_data; \ + udi_msc_desc_t udi_msc; \ + udi_hid_mouse_desc_t udi_hid_mouse; \ + udi_hid_kbd_desc_t udi_hid_kbd + +//! USB Interfaces descriptor value for Full Speed +#define UDI_COMPOSITE_DESC_FS \ + .udi_cdc_iad = UDI_CDC_IAD_DESC_0, \ + .udi_cdc_comm = UDI_CDC_COMM_DESC_0, \ + .udi_cdc_data = UDI_CDC_DATA_DESC_0_FS, \ + .udi_msc = UDI_MSC_DESC_FS, \ + .udi_hid_mouse = UDI_HID_MOUSE_DESC, \ + .udi_hid_kbd = UDI_HID_KBD_DESC + +//! USB Interfaces descriptor value for High Speed +#define UDI_COMPOSITE_DESC_HS \ + .udi_cdc_iad = UDI_CDC_IAD_DESC_0, \ + .udi_cdc_comm = UDI_CDC_COMM_DESC_0, \ + .udi_cdc_data = UDI_CDC_DATA_DESC_0_HS, \ + .udi_msc = UDI_MSC_DESC_HS, \ + .udi_hid_mouse = UDI_HID_MOUSE_DESC, \ + .udi_hid_kbd = UDI_HID_KBD_DESC + +//! USB Interface APIs +#define UDI_COMPOSITE_API \ + &udi_api_cdc_comm, \ + &udi_api_cdc_data, \ + &udi_api_msc, \ + &udi_api_hid_mouse, \ + &udi_api_hid_kbd +//@} + +/** + * USB Device Driver Configuration + * @{ + */ +//@} + +//! The includes of classes and other headers must be done at the end of this file to avoid compile error +#include "udi_cdc.h" +#include "udi_msc.h" +#include "udi_hid_mouse.h" +#include "udi_hid_kbd.h" + +#endif diff --git a/atmel-samd/boards/feather_m0_rfm69/mpconfigboard.h b/atmel-samd/boards/feather_m0_rfm69/mpconfigboard.h new file mode 100644 index 0000000000..56902fb9c5 --- /dev/null +++ b/atmel-samd/boards/feather_m0_rfm69/mpconfigboard.h @@ -0,0 +1,16 @@ +// LEDs +//#define MICROPY_HW_LED_MSC PIN_PA17 // red +// #define UART_REPL +#define USB_REPL + +#define MICROPY_HW_BOARD_NAME "Adafruit Feather M0 RFM69" +#define MICROPY_HW_MCU_NAME "samd21g18" + +#define MICROPY_PORT_A (PORT_PA24 | PORT_PA25) +#define MICROPY_PORT_B (0) + +#include "internal_flash.h" + +#define CIRCUITPY_INTERNAL_NVM_SIZE 0 + +#define BOARD_FLASH_SIZE (0x00040000 - 0x2000 - 0x010000) diff --git a/atmel-samd/boards/feather_m0_rfm69/mpconfigboard.mk b/atmel-samd/boards/feather_m0_rfm69/mpconfigboard.mk new file mode 100644 index 0000000000..22e4c4bfdf --- /dev/null +++ b/atmel-samd/boards/feather_m0_rfm69/mpconfigboard.mk @@ -0,0 +1,8 @@ +LD_FILE = boards/samd21x18-bootloader.ld +USB_VID = 0x239A +USB_PID = 0x8015 + +INTERNAL_FLASH_FILESYSTEM = 1 + +CHIP_VARIANT = SAMD21G18A + diff --git a/atmel-samd/boards/feather_m0_rfm69/pins.c b/atmel-samd/boards/feather_m0_rfm69/pins.c new file mode 100644 index 0000000000..eb5f531e36 --- /dev/null +++ b/atmel-samd/boards/feather_m0_rfm69/pins.c @@ -0,0 +1,30 @@ +#include "samd21_pins.h" + +STATIC const mp_rom_map_elem_t board_global_dict_table[] = { + { MP_ROM_QSTR(MP_QSTR_A0), MP_ROM_PTR(&pin_PA02) }, + { MP_ROM_QSTR(MP_QSTR_A1), MP_ROM_PTR(&pin_PB08) }, + { MP_ROM_QSTR(MP_QSTR_A2), MP_ROM_PTR(&pin_PB09) }, + { MP_ROM_QSTR(MP_QSTR_A3), MP_ROM_PTR(&pin_PA04) }, + { MP_ROM_QSTR(MP_QSTR_A4), MP_ROM_PTR(&pin_PA05) }, + { MP_ROM_QSTR(MP_QSTR_A5), MP_ROM_PTR(&pin_PB02) }, + { MP_ROM_QSTR(MP_QSTR_SCK), MP_ROM_PTR(&pin_PB11) }, + { MP_ROM_QSTR(MP_QSTR_MOSI), MP_ROM_PTR(&pin_PB10) }, + { MP_ROM_QSTR(MP_QSTR_MISO), MP_ROM_PTR(&pin_PA12) }, + { MP_ROM_QSTR(MP_QSTR_D0), MP_ROM_PTR(&pin_PA11) }, + { MP_ROM_QSTR(MP_QSTR_RX), MP_ROM_PTR(&pin_PA11) }, + { MP_ROM_QSTR(MP_QSTR_D1), MP_ROM_PTR(&pin_PA10) }, + { MP_ROM_QSTR(MP_QSTR_TX), MP_ROM_PTR(&pin_PA10) }, + { MP_ROM_QSTR(MP_QSTR_SDA), MP_ROM_PTR(&pin_PA22) }, + { MP_ROM_QSTR(MP_QSTR_SCL), MP_ROM_PTR(&pin_PA23) }, + { MP_ROM_QSTR(MP_QSTR_D5), MP_ROM_PTR(&pin_PA15) }, + { MP_ROM_QSTR(MP_QSTR_D6), MP_ROM_PTR(&pin_PA20) }, + { MP_ROM_QSTR(MP_QSTR_D9), MP_ROM_PTR(&pin_PA07) }, + { MP_ROM_QSTR(MP_QSTR_D10), MP_ROM_PTR(&pin_PA18) }, + { MP_ROM_QSTR(MP_QSTR_D11), MP_ROM_PTR(&pin_PA16) }, + { MP_ROM_QSTR(MP_QSTR_D12), MP_ROM_PTR(&pin_PA19) }, + { MP_ROM_QSTR(MP_QSTR_D13), MP_ROM_PTR(&pin_PA17) }, + { MP_ROM_QSTR(MP_QSTR_RFM69_D0), MP_ROM_PTR(&pin_PA09) }, + { MP_ROM_QSTR(MP_QSTR_RFM69_RST), MP_ROM_PTR(&pin_PA08) }, + { MP_ROM_QSTR(MP_QSTR_RFM69_CS), MP_ROM_PTR(&pin_PA06) }, +}; +MP_DEFINE_CONST_DICT(board_module_globals, board_global_dict_table); diff --git a/atmel-samd/boards/feather_m0_rfm9x/board.c b/atmel-samd/boards/feather_m0_rfm9x/board.c new file mode 100644 index 0000000000..c8e20206a1 --- /dev/null +++ b/atmel-samd/boards/feather_m0_rfm9x/board.c @@ -0,0 +1,38 @@ +/* + * This file is part of the MicroPython project, http://micropython.org/ + * + * The MIT License (MIT) + * + * Copyright (c) 2017 Scott Shawcroft for Adafruit Industries + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +#include "boards/board.h" + +void board_init(void) +{ +} + +bool board_requests_safe_mode(void) { + return false; +} + +void reset_board(void) { +} diff --git a/atmel-samd/boards/feather_m0_rfm9x/conf_access.h b/atmel-samd/boards/feather_m0_rfm9x/conf_access.h new file mode 100644 index 0000000000..25109b75ca --- /dev/null +++ b/atmel-samd/boards/feather_m0_rfm9x/conf_access.h @@ -0,0 +1,115 @@ +/** + * \file + * + * \brief Memory access control configuration file. + * + * Copyright (c) 2014-2015 Atmel Corporation. All rights reserved. + * + * \asf_license_start + * + * \page License + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * 3. The name of Atmel may not be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * 4. This software may only be redistributed and used in connection with an + * Atmel microcontroller product. + * + * THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE + * EXPRESSLY AND SPECIFICALLY DISCLAIMED. IN NO EVENT SHALL ATMEL BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + * \asf_license_stop + * + */ +/* + * Support and FAQ: visit Atmel Support + */ + +#ifndef _CONF_ACCESS_H_ +#define _CONF_ACCESS_H_ + +#include "compiler.h" +#include "board.h" + + +/*! \name Activation of Logical Unit Numbers + */ +//! @{ +#define LUN_0 ENABLE //!< On-Chip Virtual Memory. +#define LUN_1 DISABLE //!< AT45DBX Data Flash. +#define LUN_2 DISABLE //!< SD/MMC Card over SPI. +#define LUN_3 DISABLE //!< SD/MMC Card over MCI Slot 0. +#define LUN_4 DISABLE +#define LUN_5 DISABLE +#define LUN_6 DISABLE +#define LUN_7 DISABLE +#define LUN_USB DISABLE //!< Host Mass-Storage Memory. +//! @} + +/*! \name LUN 0 Definitions + */ +//! @{ +#define LUN_0_INCLUDE "access_vfs.h" +#define Lun_0_test_unit_ready vfs_test_unit_ready +#define Lun_0_read_capacity vfs_read_capacity +#define Lun_0_unload NULL +#define Lun_0_wr_protect vfs_wr_protect +#define Lun_0_removal vfs_removal +#define Lun_0_usb_read_10 vfs_usb_read_10 +#define Lun_0_usb_write_10 vfs_usb_write_10 +#define LUN_0_NAME "\"MicroPython VFS[0]\"" +//! @} + +#define MEM_USB LUN_USB + +/*! \name Actions Associated with Memory Accesses + * + * Write here the action to associate with each memory access. + * + * \warning Be careful not to waste time in order not to disturb the functions. + */ +//! @{ +#define memory_start_read_action(nb_sectors) +#define memory_stop_read_action() +#define memory_start_write_action(nb_sectors) +#define memory_stop_write_action() +//! @} + +/*! \name Activation of Interface Features + */ +//! @{ +#define ACCESS_USB true //!< MEM <-> USB interface. +#define ACCESS_MEM_TO_RAM false //!< MEM <-> RAM interface. +#define ACCESS_STREAM false //!< Streaming MEM <-> MEM interface. +#define ACCESS_STREAM_RECORD false //!< Streaming MEM <-> MEM interface in record mode. +#define ACCESS_MEM_TO_MEM false //!< MEM <-> MEM interface. +#define ACCESS_CODEC false //!< Codec interface. +//! @} + +/*! \name Specific Options for Access Control + */ +//! @{ +#define GLOBAL_WR_PROTECT false //!< Management of a global write protection. +//! @} + + +#endif // _CONF_ACCESS_H_ diff --git a/atmel-samd/boards/feather_m0_rfm9x/conf_board.h b/atmel-samd/boards/feather_m0_rfm9x/conf_board.h new file mode 100644 index 0000000000..7b88c97fc2 --- /dev/null +++ b/atmel-samd/boards/feather_m0_rfm9x/conf_board.h @@ -0,0 +1,14 @@ +/** + * \file + * + * \brief User board configuration template + * + */ +/* + * Support and FAQ: visit Atmel Support + */ + +#ifndef CONF_BOARD_H +#define CONF_BOARD_H + +#endif // CONF_BOARD_H diff --git a/atmel-samd/boards/feather_m0_rfm9x/conf_clocks.h b/atmel-samd/boards/feather_m0_rfm9x/conf_clocks.h new file mode 100644 index 0000000000..d3f3e6496d --- /dev/null +++ b/atmel-samd/boards/feather_m0_rfm9x/conf_clocks.h @@ -0,0 +1 @@ +#include "conf_clocks_external_32k.h" diff --git a/atmel-samd/boards/feather_m0_rfm9x/conf_usb.h b/atmel-samd/boards/feather_m0_rfm9x/conf_usb.h new file mode 100644 index 0000000000..d9b54871cb --- /dev/null +++ b/atmel-samd/boards/feather_m0_rfm9x/conf_usb.h @@ -0,0 +1,221 @@ + +#include +#include + +#include "asf/common/services/usb/class/cdc/usb_protocol_cdc.h" + +#ifndef CONF_USB_H_INCLUDED +#define CONF_USB_H_INCLUDED + +#define USB_DEVICE_MAJOR_VERSION 1 +#define USB_DEVICE_MINOR_VERSION 0 +#define USB_DEVICE_POWER 100 // Consumption on Vbus line (mA) +#define USB_DEVICE_ATTR \ + (USB_CONFIG_ATTR_BUS_POWERED) +// (USB_CONFIG_ATTR_REMOTE_WAKEUP|USB_CONFIG_ATTR_SELF_POWERED) +// (USB_CONFIG_ATTR_REMOTE_WAKEUP|USB_CONFIG_ATTR_BUS_POWERED) + +//! USB Device string definitions (Optional) +#ifndef USB_DEVICE_MANUFACTURE_NAME +# define USB_DEVICE_MANUFACTURE_NAME "Adafruit Industries" +#endif + +#ifndef USB_DEVICE_PRODUCT_NAME +# define USB_DEVICE_PRODUCT_NAME "Feather M0 RFM9x" +#endif + +#define USB_DEVICE_GET_SERIAL_NAME_POINTER serial_number +#define USB_DEVICE_GET_SERIAL_NAME_LENGTH 32 +extern char serial_number[USB_DEVICE_GET_SERIAL_NAME_LENGTH]; + +//! Control endpoint size +#define USB_DEVICE_EP_CTRL_SIZE 64 + +//! Two interfaces for this device (CDC COM + CDC DATA + MSC + HID mouse + HID kbd) +#define USB_DEVICE_NB_INTERFACE 5 + +// (3 | USB_EP_DIR_IN) // CDC Notify endpoint +// (4 | USB_EP_DIR_IN) // CDC TX +// (5 | USB_EP_DIR_OUT) // CDC RX +// (1 | USB_EP_DIR_IN) // MSC IN +// (2 | USB_EP_DIR_OUT) // MSC OUT +// (6 | USB_EP_DIR_IN) // HID mouse report +// (7 | USB_EP_DIR_IN) // HID keyboard report +#define USB_DEVICE_MAX_EP 7 + +#define UDI_CDC_PORT_NB 1 +#define UDI_CDC_ENABLE_EXT(port) mp_cdc_enable(port) +extern bool mp_cdc_enable(uint8_t port); +#define UDI_CDC_DISABLE_EXT(port) mp_cdc_disable(port) +extern void mp_cdc_disable(uint8_t port); +#define UDI_CDC_LOW_RATE + +#define UDI_CDC_DEFAULT_RATE 115200 +#define UDI_CDC_DEFAULT_STOPBITS CDC_STOP_BITS_1 +#define UDI_CDC_DEFAULT_PARITY CDC_PAR_NONE +#define UDI_CDC_DEFAULT_DATABITS 8 + +#define UDI_CDC_RX_NOTIFY(port) usb_rx_notify() +void usb_rx_notify(void); +#define UDI_CDC_SET_CODING_EXT(port,cfg) usb_coding_notify(port, cfg) +void usb_coding_notify(uint8_t port, usb_cdc_line_coding_t* coding); +#define UDI_CDC_SET_DTR_EXT(port,set) usb_dtr_notify(port, set) +void usb_dtr_notify(uint8_t port, bool set); +#define UDI_CDC_SET_RTS_EXT(port,set) usb_rts_notify(port, set) +void usb_rts_notify(uint8_t port, bool set); + +/** + * USB CDC low level configuration + * In standalone these configurations are defined by the CDC module. + * For composite device, these configuration must be defined here + * @{ + */ +//! Endpoint numbers definition + +#define UDI_CDC_COMM_EP_0 (3 | USB_EP_DIR_IN) // Notify endpoint +#define UDI_CDC_DATA_EP_IN_0 (4 | USB_EP_DIR_IN) // TX +#define UDI_CDC_DATA_EP_OUT_0 (5 | USB_EP_DIR_OUT) // RX + +//! Interface numbers +#define UDI_CDC_COMM_IFACE_NUMBER_0 0 +#define UDI_CDC_DATA_IFACE_NUMBER_0 1 + +/** + * Configuration of MSC interface + * @{ + */ +//! Vendor name and Product version of MSC interface +#define UDI_MSC_GLOBAL_VENDOR_ID \ + 'A', 'T', 'M', 'E', 'L', ' ', ' ', ' ' +#define UDI_MSC_GLOBAL_PRODUCT_VERSION \ + '1', '.', '0', '0' + +//! Interface callback definition +#define UDI_MSC_ENABLE_EXT() mp_msc_enable() +extern bool mp_msc_enable(void); +#define UDI_MSC_DISABLE_EXT() mp_msc_disable() +extern void mp_msc_disable(void); + +//! Enable id string of interface to add an extra USB string +#define UDI_MSC_STRING_ID 5 + +/** + * USB MSC low level configuration + * In standalone these configurations are defined by the MSC module. + * For composite device, these configuration must be defined here + * @{ + */ +//! Endpoint numbers definition +#define UDI_MSC_EP_IN (1 | USB_EP_DIR_IN) +#define UDI_MSC_EP_OUT (2 | USB_EP_DIR_OUT) + +//! Interface number +#define UDI_MSC_IFACE_NUMBER 2 + +/** + * Configuration of HID Mouse interface + * @{ + */ +//! Interface callback definition +#define UDI_HID_MOUSE_ENABLE_EXT() mp_mouse_enable() +extern bool mp_mouse_enable(void); +#define UDI_HID_MOUSE_DISABLE_EXT() mp_mouse_disable() +extern void mp_mouse_disable(void); + +//! Enable id string of interface to add an extra USB string +#define UDI_HID_MOUSE_STRING_ID 6 + +/** + * USB HID Mouse low level configuration + * In standalone these configurations are defined by the HID Mouse module. + * For composite device, these configuration must be defined here + * @{ + */ +//! Endpoint numbers definition +#define UDI_HID_MOUSE_EP_IN (6 | USB_EP_DIR_IN) + +//! Interface number +#define UDI_HID_MOUSE_IFACE_NUMBER 3 +//@} +//@} + +/** + * Configuration of HID Keyboard interface + * @{ + */ +//! Interface callback definition +#define UDI_HID_KBD_ENABLE_EXT() mp_keyboard_enable() +extern bool mp_keyboard_enable(void); +#define UDI_HID_KBD_DISABLE_EXT() mp_keyboard_disable() +extern void mp_keyboard_disable(void); +#define UDI_HID_KBD_CHANGE_LED(value) mp_keyboard_led(value) +extern void mp_keyboard_led(uint8_t); + +//! Enable id string of interface to add an extra USB string +#define UDI_HID_KBD_STRING_ID 7 + +/** + * USB HID Keyboard low level configuration + * In standalone these configurations are defined by the HID Keyboard module. + * For composite device, these configuration must be defined here + * @{ + */ +//! Endpoint numbers definition +#define UDI_HID_KBD_EP_IN (7 | USB_EP_DIR_IN) + +//! Interface number +#define UDI_HID_KBD_IFACE_NUMBER 4 + +/** + * Description of Composite Device + * @{ + */ +//! USB Interfaces descriptor structure +#define UDI_COMPOSITE_DESC_T \ + usb_iad_desc_t udi_cdc_iad; \ + udi_cdc_comm_desc_t udi_cdc_comm; \ + udi_cdc_data_desc_t udi_cdc_data; \ + udi_msc_desc_t udi_msc; \ + udi_hid_mouse_desc_t udi_hid_mouse; \ + udi_hid_kbd_desc_t udi_hid_kbd + +//! USB Interfaces descriptor value for Full Speed +#define UDI_COMPOSITE_DESC_FS \ + .udi_cdc_iad = UDI_CDC_IAD_DESC_0, \ + .udi_cdc_comm = UDI_CDC_COMM_DESC_0, \ + .udi_cdc_data = UDI_CDC_DATA_DESC_0_FS, \ + .udi_msc = UDI_MSC_DESC_FS, \ + .udi_hid_mouse = UDI_HID_MOUSE_DESC, \ + .udi_hid_kbd = UDI_HID_KBD_DESC + +//! USB Interfaces descriptor value for High Speed +#define UDI_COMPOSITE_DESC_HS \ + .udi_cdc_iad = UDI_CDC_IAD_DESC_0, \ + .udi_cdc_comm = UDI_CDC_COMM_DESC_0, \ + .udi_cdc_data = UDI_CDC_DATA_DESC_0_HS, \ + .udi_msc = UDI_MSC_DESC_HS, \ + .udi_hid_mouse = UDI_HID_MOUSE_DESC, \ + .udi_hid_kbd = UDI_HID_KBD_DESC + +//! USB Interface APIs +#define UDI_COMPOSITE_API \ + &udi_api_cdc_comm, \ + &udi_api_cdc_data, \ + &udi_api_msc, \ + &udi_api_hid_mouse, \ + &udi_api_hid_kbd +//@} + +/** + * USB Device Driver Configuration + * @{ + */ +//@} + +//! The includes of classes and other headers must be done at the end of this file to avoid compile error +#include "udi_cdc.h" +#include "udi_msc.h" +#include "udi_hid_mouse.h" +#include "udi_hid_kbd.h" + +#endif diff --git a/atmel-samd/boards/feather_m0_rfm9x/mpconfigboard.h b/atmel-samd/boards/feather_m0_rfm9x/mpconfigboard.h new file mode 100644 index 0000000000..3f6e6ee485 --- /dev/null +++ b/atmel-samd/boards/feather_m0_rfm9x/mpconfigboard.h @@ -0,0 +1,16 @@ +// LEDs +//#define MICROPY_HW_LED_MSC PIN_PA17 // red +// #define UART_REPL +#define USB_REPL + +#define MICROPY_HW_BOARD_NAME "Adafruit Feather M0 RFM9x" +#define MICROPY_HW_MCU_NAME "samd21g18" + +#define MICROPY_PORT_A (PORT_PA24 | PORT_PA25) +#define MICROPY_PORT_B (0) + +#include "internal_flash.h" + +#define CIRCUITPY_INTERNAL_NVM_SIZE 0 + +#define BOARD_FLASH_SIZE (0x00040000 - 0x2000 - 0x010000) diff --git a/atmel-samd/boards/feather_m0_rfm9x/mpconfigboard.mk b/atmel-samd/boards/feather_m0_rfm9x/mpconfigboard.mk new file mode 100644 index 0000000000..22e4c4bfdf --- /dev/null +++ b/atmel-samd/boards/feather_m0_rfm9x/mpconfigboard.mk @@ -0,0 +1,8 @@ +LD_FILE = boards/samd21x18-bootloader.ld +USB_VID = 0x239A +USB_PID = 0x8015 + +INTERNAL_FLASH_FILESYSTEM = 1 + +CHIP_VARIANT = SAMD21G18A + diff --git a/atmel-samd/boards/feather_m0_rfm9x/pins.c b/atmel-samd/boards/feather_m0_rfm9x/pins.c new file mode 100644 index 0000000000..2e5d0a8e68 --- /dev/null +++ b/atmel-samd/boards/feather_m0_rfm9x/pins.c @@ -0,0 +1,30 @@ +#include "samd21_pins.h" + +STATIC const mp_rom_map_elem_t board_global_dict_table[] = { + { MP_ROM_QSTR(MP_QSTR_A0), MP_ROM_PTR(&pin_PA02) }, + { MP_ROM_QSTR(MP_QSTR_A1), MP_ROM_PTR(&pin_PB08) }, + { MP_ROM_QSTR(MP_QSTR_A2), MP_ROM_PTR(&pin_PB09) }, + { MP_ROM_QSTR(MP_QSTR_A3), MP_ROM_PTR(&pin_PA04) }, + { MP_ROM_QSTR(MP_QSTR_A4), MP_ROM_PTR(&pin_PA05) }, + { MP_ROM_QSTR(MP_QSTR_A5), MP_ROM_PTR(&pin_PB02) }, + { MP_ROM_QSTR(MP_QSTR_SCK), MP_ROM_PTR(&pin_PB11) }, + { MP_ROM_QSTR(MP_QSTR_MOSI), MP_ROM_PTR(&pin_PB10) }, + { MP_ROM_QSTR(MP_QSTR_MISO), MP_ROM_PTR(&pin_PA12) }, + { MP_ROM_QSTR(MP_QSTR_D0), MP_ROM_PTR(&pin_PA11) }, + { MP_ROM_QSTR(MP_QSTR_RX), MP_ROM_PTR(&pin_PA11) }, + { MP_ROM_QSTR(MP_QSTR_D1), MP_ROM_PTR(&pin_PA10) }, + { MP_ROM_QSTR(MP_QSTR_TX), MP_ROM_PTR(&pin_PA10) }, + { MP_ROM_QSTR(MP_QSTR_SDA), MP_ROM_PTR(&pin_PA22) }, + { MP_ROM_QSTR(MP_QSTR_SCL), MP_ROM_PTR(&pin_PA23) }, + { MP_ROM_QSTR(MP_QSTR_D5), MP_ROM_PTR(&pin_PA15) }, + { MP_ROM_QSTR(MP_QSTR_D6), MP_ROM_PTR(&pin_PA20) }, + { MP_ROM_QSTR(MP_QSTR_D9), MP_ROM_PTR(&pin_PA07) }, + { MP_ROM_QSTR(MP_QSTR_D10), MP_ROM_PTR(&pin_PA18) }, + { MP_ROM_QSTR(MP_QSTR_D11), MP_ROM_PTR(&pin_PA16) }, + { MP_ROM_QSTR(MP_QSTR_D12), MP_ROM_PTR(&pin_PA19) }, + { MP_ROM_QSTR(MP_QSTR_D13), MP_ROM_PTR(&pin_PA17) }, + { MP_ROM_QSTR(MP_QSTR_RFM9X_D0), MP_ROM_PTR(&pin_PA09) }, + { MP_ROM_QSTR(MP_QSTR_RFM9X_RST), MP_ROM_PTR(&pin_PA08) }, + { MP_ROM_QSTR(MP_QSTR_RFM9X_CS), MP_ROM_PTR(&pin_PA06) }, +}; +MP_DEFINE_CONST_DICT(board_module_globals, board_global_dict_table); diff --git a/tools/build_adafruit_bins.sh b/tools/build_adafruit_bins.sh index f8789b9fb6..0734d356b0 100755 --- a/tools/build_adafruit_bins.sh +++ b/tools/build_adafruit_bins.sh @@ -1,7 +1,7 @@ rm -rf atmel-samd/build* rm -rf esp8266/build* -ATMEL_BOARDS="arduino_zero circuitplayground_express feather_m0_basic feather_m0_adalogger feather_m0_express metro_m0_express trinket_m0 gemma_m0 itsybitsy_m0" +ATMEL_BOARDS="arduino_zero circuitplayground_express feather_m0_basic feather_m0_adalogger feather_m0_rfm69 feather_m0_rfm9x feather_m0_express metro_m0_express trinket_m0 gemma_m0 itsybitsy_m0" ROSIE_SETUPS="rosie-ci" for board in $ATMEL_BOARDS; do From 6b66c3b7a3beffea58fcb762d8dcf4bd5d5b8a51 Mon Sep 17 00:00:00 2001 From: ladyada Date: Fri, 19 Jan 2018 22:04:40 -0500 Subject: [PATCH 050/135] Add W25Q16 USON flash support, alternative flash type support for all boards --- atmel-samd/boards/flash_GD25Q16C.h | 3 +- atmel-samd/boards/flash_S25FL064L.h | 3 +- atmel-samd/boards/flash_S25FL216K.h | 3 +- atmel-samd/boards/flash_W25Q16FW.h | 53 +++++++++++++++++++ atmel-samd/boards/flash_W25Q32BV.h | 3 +- atmel-samd/boards/flash_W25Q80DV.h | 3 +- atmel-samd/boards/itsybitsy_m0/conf_usb.h | 2 +- .../boards/itsybitsy_m0/mpconfigboard.h | 43 ++++++++++----- .../boards/itsybitsy_m0/mpconfigboard.mk | 4 ++ 9 files changed, 99 insertions(+), 18 deletions(-) create mode 100644 atmel-samd/boards/flash_W25Q16FW.h diff --git a/atmel-samd/boards/flash_GD25Q16C.h b/atmel-samd/boards/flash_GD25Q16C.h index 90ec6de5cd..e123265e29 100644 --- a/atmel-samd/boards/flash_GD25Q16C.h +++ b/atmel-samd/boards/flash_GD25Q16C.h @@ -44,11 +44,12 @@ // used to confirm we're talking to the flash we expect. #define SPI_FLASH_JEDEC_MANUFACTURER 0xc8 #define SPI_FLASH_SECTOR_PROTECTION true +#define SPI_FLASH_JEDEC_MEMORY_TYPE 0x40 #else #define SPI_FLASH_JEDEC_MANUFACTURER_2 0xc8 #define SPI_FLASH_SECTOR_PROTECTION_2 true +#define SPI_FLASH_JEDEC_MEMORY_TYPE_2 0x40 #endif -#define SPI_FLASH_JEDEC_MEMORY_TYPE 0x40 #define SPI_FLASH_JEDEC_CAPACITY 0x15 diff --git a/atmel-samd/boards/flash_S25FL064L.h b/atmel-samd/boards/flash_S25FL064L.h index 40cfa4cf0a..5a38836874 100644 --- a/atmel-samd/boards/flash_S25FL064L.h +++ b/atmel-samd/boards/flash_S25FL064L.h @@ -45,11 +45,12 @@ #ifndef SPI_FLASH_JEDEC_MANUFACTURER #define SPI_FLASH_JEDEC_MANUFACTURER 0x01 #define SPI_FLASH_SECTOR_PROTECTION false +#define SPI_FLASH_JEDEC_MEMORY_TYPE 0x60 #else #define SPI_FLASH_JEDEC_MANUFACTURER_2 0x013 #define SPI_FLASH_SECTOR_PROTECTION_2 false +#define SPI_FLASH_JEDEC_MEMORY_TYPE_2 0x60 #endif -#define SPI_FLASH_JEDEC_MEMORY_TYPE 0x60 #define SPI_FLASH_JEDEC_CAPACITY 0x17 #endif // MICROPY_INCLUDED_ATMEL_SAMD_BOARD_FLASH_S25FL216K_H diff --git a/atmel-samd/boards/flash_S25FL216K.h b/atmel-samd/boards/flash_S25FL216K.h index 61b6b75146..a6a0a12fa2 100644 --- a/atmel-samd/boards/flash_S25FL216K.h +++ b/atmel-samd/boards/flash_S25FL216K.h @@ -44,11 +44,12 @@ #ifndef SPI_FLASH_JEDEC_MANUFACTURER #define SPI_FLASH_JEDEC_MANUFACTURER 0x01 #define SPI_FLASH_SECTOR_PROTECTION false +#define SPI_FLASH_JEDEC_MEMORY_TYPE 0x40 #else #define SPI_FLASH_JEDEC_MANUFACTURER_2 0x01 #define SPI_FLASH_SECTOR_PROTECTION_2 false +#define SPI_FLASH_JEDEC_MEMORY_TYPE_2 0x40 #endif -#define SPI_FLASH_JEDEC_MEMORY_TYPE 0x40 #define SPI_FLASH_JEDEC_CAPACITY 0x15 #endif // MICROPY_INCLUDED_ATMEL_SAMD_BOARD_FLASH_S25FL216K_H diff --git a/atmel-samd/boards/flash_W25Q16FW.h b/atmel-samd/boards/flash_W25Q16FW.h new file mode 100644 index 0000000000..219a7f058f --- /dev/null +++ b/atmel-samd/boards/flash_W25Q16FW.h @@ -0,0 +1,53 @@ +/* + * This file is part of the MicroPython project, http://micropython.org/ + * + * The MIT License (MIT) + * + * Copyright (c) 2017 Scott Shawcroft for Adafruit Industries + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +#ifndef MICROPY_INCLUDED_ATMEL_SAMD_BOARD_FLASH_W25Q16FW_H +#define MICROPY_INCLUDED_ATMEL_SAMD_BOARD_FLASH_W25Q16FW_H + +// The total flash size in bytes. +#define SPI_FLASH_TOTAL_SIZE (1 << 21) // 2 MiB + +// The size of the smallest erase unit thats erased with command 0x20. +#define SPI_FLASH_ERASE_SIZE (1 << 12) // 4 KiB + +// The size of a page that is programmed with page program command 0x02. +#define SPI_FLASH_PAGE_SIZE (256) // 256 bytes + +// These are the first three response bytes to the JEDEC ID command 0x9f that is +// used to confirm we're talking to the flash we expect. +#ifndef SPI_FLASH_JEDEC_MANUFACTURER + #define SPI_FLASH_JEDEC_MANUFACTURER 0xef + #define SPI_FLASH_SECTOR_PROTECTION false + #define SPI_FLASH_JEDEC_MEMORY_TYPE 0x60 +#else + #define SPI_FLASH_JEDEC_MANUFACTURER_2 0xef + #define SPI_FLASH_SECTOR_PROTECTION_2 false + #define SPI_FLASH_JEDEC_MEMORY_TYPE_2 0x60 +#endif + +#define SPI_FLASH_JEDEC_CAPACITY 0x15 + +#endif // MICROPY_INCLUDED_ATMEL_SAMD_BOARD_FLASH_W25Q16BV_H diff --git a/atmel-samd/boards/flash_W25Q32BV.h b/atmel-samd/boards/flash_W25Q32BV.h index ae730fc6a2..d71771babc 100644 --- a/atmel-samd/boards/flash_W25Q32BV.h +++ b/atmel-samd/boards/flash_W25Q32BV.h @@ -41,11 +41,12 @@ #ifndef SPI_FLASH_JEDEC_MANUFACTURER #define SPI_FLASH_JEDEC_MANUFACTURER 0xef #define SPI_FLASH_SECTOR_PROTECTION false +#define SPI_FLASH_JEDEC_MEMORY_TYPE 0x40 #else #define SPI_FLASH_JEDEC_MANUFACTURER_2 0xef #define SPI_FLASH_SECTOR_PROTECTION_2 false +#define SPI_FLASH_JEDEC_MEMORY_TYPE_2 0x40 #endif -#define SPI_FLASH_JEDEC_MEMORY_TYPE 0x40 #define SPI_FLASH_JEDEC_CAPACITY 0x16 #endif // MICROPY_INCLUDED_ATMEL_SAMD_BOARD_FLASH_W25Q32BV_H diff --git a/atmel-samd/boards/flash_W25Q80DV.h b/atmel-samd/boards/flash_W25Q80DV.h index 1e8003867f..3fd8dc114f 100644 --- a/atmel-samd/boards/flash_W25Q80DV.h +++ b/atmel-samd/boards/flash_W25Q80DV.h @@ -41,11 +41,12 @@ #ifndef SPI_FLASH_JEDEC_MANUFACTURER #define SPI_FLASH_JEDEC_MANUFACTURER 0xef #define SPI_FLASH_SECTOR_PROTECTION false +#define SPI_FLASH_JEDEC_MEMORY_TYPE_2 0x40 #else #define SPI_FLASH_JEDEC_MANUFACTURER_2 0xef #define SPI_FLASH_SECTOR_PROTECTION_2 false +#define SPI_FLASH_JEDEC_MEMORY_TYPE_2 0x40 #endif -#define SPI_FLASH_JEDEC_MEMORY_TYPE 0x40 #define SPI_FLASH_JEDEC_CAPACITY 0x14 #endif // MICROPY_INCLUDED_ATMEL_SAMD_BOARD_FLASH_W25Q80DV_H diff --git a/atmel-samd/boards/itsybitsy_m0/conf_usb.h b/atmel-samd/boards/itsybitsy_m0/conf_usb.h index 5e8a61b884..93eacb344d 100644 --- a/atmel-samd/boards/itsybitsy_m0/conf_usb.h +++ b/atmel-samd/boards/itsybitsy_m0/conf_usb.h @@ -21,7 +21,7 @@ #endif #ifndef USB_DEVICE_PRODUCT_NAME -# define USB_DEVICE_PRODUCT_NAME "ItsyBitsy M0" +# define USB_DEVICE_PRODUCT_NAME "ItsyBitsy M0 Express" #endif // #define USB_DEVICE_SERIAL_NAME "12...EF" #define USB_DEVICE_GET_SERIAL_NAME_POINTER serial_number diff --git a/atmel-samd/boards/itsybitsy_m0/mpconfigboard.h b/atmel-samd/boards/itsybitsy_m0/mpconfigboard.h index e9fd08a5f6..5ae5eab45f 100644 --- a/atmel-samd/boards/itsybitsy_m0/mpconfigboard.h +++ b/atmel-samd/boards/itsybitsy_m0/mpconfigboard.h @@ -1,36 +1,55 @@ #define USB_REPL -#define MICROPY_HW_BOARD_NAME "Adafruit ItsyBitsy M0" +#define MICROPY_HW_BOARD_NAME "Adafruit Itsy Bitsy M0 Express" #define MICROPY_HW_MCU_NAME "samd21g18" #define CIRCUITPY_BITBANG_APA102 #define MICROPY_HW_APA102_MOSI (&pin_PA01) #define MICROPY_HW_APA102_SCK (&pin_PA00) -#define MICROPY_PORT_A (PORT_PA00 | PORT_PA01 | PORT_PA27 | PORT_PA24 | PORT_PA25) -#define MICROPY_PORT_B (PORT_PB22 | PORT_PB23 | PORT_PB03 ) - // Salae reads 12mhz which is the limit even though we set it to the safer 8mhz. #define SPI_FLASH_BAUDRATE (8000000) -#define SPI_FLASH_MUX_SETTING SPI_SIGNAL_MUX_SETTING_F -#define SPI_FLASH_PAD2_PINMUX PINMUX_PB22D_SERCOM5_PAD2 // MOSI +#define SPI_FLASH_PAD0_PINMUX PINMUX_UNUSED // CS // Use default pinmux for the chip select since we manage it ourselves. -#define SPI_FLASH_PAD3_PINMUX PINMUX_PB23D_SERCOM5_PAD3 // SCK #define SPI_FLASH_PAD1_PINMUX PINMUX_PB03D_SERCOM5_PAD1 // MISO -#define SPI_FLASH_PAD0_PINMUX PINMUX_UNUSED // -#define SPI_FLASH_SERCOM SERCOM5 +#define SPI_FLASH_MISO_PAD 1 +#define SPI_FLASH_PAD2_PINMUX PINMUX_PB22D_SERCOM5_PAD2 // MOSI +#define SPI_FLASH_MOSI_PAD 2 +#define SPI_FLASH_PAD3_PINMUX PINMUX_PB23D_SERCOM5_PAD3 // SCK +#define SPI_FLASH_SCK_PAD 3 #define SPI_FLASH_CS PIN_PA27 +#define SPI_FLASH_SERCOM SERCOM5 +#define SPI_FLASH_MOSI PIN_PB22 +#define SPI_FLASH_MISO PIN_PB03 +#define SPI_FLASH_SCK PIN_PB23 +#define SPI_FLASH_SERCOM_INDEX 5 +// Transmit Data Pinout +// <0x0=>PAD[0,1]_DO_SCK +// <0x1=>PAD[2,3]_DO_SCK +// <0x2=>PAD[3,1]_DO_SCK +// <0x3=>PAD[0,3]_DO_SCK +#define SPI_FLASH_DOPO 1 +#define SPI_FLASH_DIPO 1 // same as MISO pad +#define SPI_FLASH_MUX_SETTING SPI_SIGNAL_MUX_SETTING_F + + +// These are pins not to reset. +#define MICROPY_PORT_A (PORT_PA00 | PORT_PA01 | PORT_PA27 | PORT_PA24 | PORT_PA25) +#define MICROPY_PORT_B (PORT_PB22 | PORT_PB23 | PORT_PB03 ) +#define MICROPY_PORT_C (0) #include "spi_flash.h" // If you change this, then make sure to update the linker scripts as well to // make sure you don't overwrite code. #define CIRCUITPY_INTERNAL_NVM_SIZE 256 + #define BOARD_FLASH_SIZE (0x00040000 - 0x2000 - CIRCUITPY_INTERNAL_NVM_SIZE) -//#include "flash_S25FL216K.h" -#include "flash_W25Q80DV.h" -//#include "flash_GD25Q16C.h" +#include "flash_GD25Q16C.h" +#include "flash_W25Q16FW.h" + +#define CALIBRATE_CRYSTALLESS 1 diff --git a/atmel-samd/boards/itsybitsy_m0/mpconfigboard.mk b/atmel-samd/boards/itsybitsy_m0/mpconfigboard.mk index 167d445954..0fb0e38ed4 100644 --- a/atmel-samd/boards/itsybitsy_m0/mpconfigboard.mk +++ b/atmel-samd/boards/itsybitsy_m0/mpconfigboard.mk @@ -1,7 +1,11 @@ LD_FILE = boards/samd21x18-bootloader-external-flash-crystalless.ld USB_VID = 0x239A USB_PID = 0x8012 +USB_PRODUCT = "Itsy Bitsy M0 Express" +USB_MANUFACTURER = "Adafruit Industries LLC" SPI_FLASH_FILESYSTEM = 1 CHIP_VARIANT = SAMD21G18A +CHIP_FAMILY = samd21 + From 448d13e7b45a1edf4f290f800427db8a5890b814 Mon Sep 17 00:00:00 2001 From: ladyada Date: Tue, 30 Jan 2018 01:24:28 -0500 Subject: [PATCH 051/135] memory type for alt flash fix --- atmel-samd/spi_flash.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/atmel-samd/spi_flash.c b/atmel-samd/spi_flash.c index d74007a836..8b0030b6b7 100644 --- a/atmel-samd/spi_flash.c +++ b/atmel-samd/spi_flash.c @@ -281,7 +281,11 @@ void spi_flash_init(void) { || response[1] == SPI_FLASH_JEDEC_MANUFACTURER_2 #endif ) && - response[2] == SPI_FLASH_JEDEC_MEMORY_TYPE && + (response[2] == SPI_FLASH_JEDEC_MEMORY_TYPE + #ifdef SPI_FLASH_JEDEC_MANUFACTURER_2 + || response[2] == SPI_FLASH_JEDEC_MEMORY_TYPE_2 + #endif + ) && response[3] == SPI_FLASH_JEDEC_CAPACITY) { spi_flash_is_initialised = true; } else { From 80ff1c49a60c5325c7d43ae50f6530fe3dde262b Mon Sep 17 00:00:00 2001 From: ladyada Date: Sun, 4 Feb 2018 23:00:23 -0500 Subject: [PATCH 052/135] pIRKey tested w/ hardware - basically a trinket or gemma with only dotstar LED + IR Receiver --- atmel-samd/boards/pirkey_m0/board.c | 38 ++++ atmel-samd/boards/pirkey_m0/conf_access.h | 115 ++++++++++ atmel-samd/boards/pirkey_m0/conf_board.h | 14 ++ atmel-samd/boards/pirkey_m0/conf_clocks.h | 1 + atmel-samd/boards/pirkey_m0/conf_usb.h | 220 +++++++++++++++++++ atmel-samd/boards/pirkey_m0/mpconfigboard.h | 18 ++ atmel-samd/boards/pirkey_m0/mpconfigboard.mk | 7 + atmel-samd/boards/pirkey_m0/pins.c | 9 + 8 files changed, 422 insertions(+) create mode 100644 atmel-samd/boards/pirkey_m0/board.c create mode 100644 atmel-samd/boards/pirkey_m0/conf_access.h create mode 100644 atmel-samd/boards/pirkey_m0/conf_board.h create mode 100644 atmel-samd/boards/pirkey_m0/conf_clocks.h create mode 100644 atmel-samd/boards/pirkey_m0/conf_usb.h create mode 100644 atmel-samd/boards/pirkey_m0/mpconfigboard.h create mode 100644 atmel-samd/boards/pirkey_m0/mpconfigboard.mk create mode 100644 atmel-samd/boards/pirkey_m0/pins.c diff --git a/atmel-samd/boards/pirkey_m0/board.c b/atmel-samd/boards/pirkey_m0/board.c new file mode 100644 index 0000000000..c8e20206a1 --- /dev/null +++ b/atmel-samd/boards/pirkey_m0/board.c @@ -0,0 +1,38 @@ +/* + * This file is part of the MicroPython project, http://micropython.org/ + * + * The MIT License (MIT) + * + * Copyright (c) 2017 Scott Shawcroft for Adafruit Industries + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +#include "boards/board.h" + +void board_init(void) +{ +} + +bool board_requests_safe_mode(void) { + return false; +} + +void reset_board(void) { +} diff --git a/atmel-samd/boards/pirkey_m0/conf_access.h b/atmel-samd/boards/pirkey_m0/conf_access.h new file mode 100644 index 0000000000..25109b75ca --- /dev/null +++ b/atmel-samd/boards/pirkey_m0/conf_access.h @@ -0,0 +1,115 @@ +/** + * \file + * + * \brief Memory access control configuration file. + * + * Copyright (c) 2014-2015 Atmel Corporation. All rights reserved. + * + * \asf_license_start + * + * \page License + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * 3. The name of Atmel may not be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * 4. This software may only be redistributed and used in connection with an + * Atmel microcontroller product. + * + * THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE + * EXPRESSLY AND SPECIFICALLY DISCLAIMED. IN NO EVENT SHALL ATMEL BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + * \asf_license_stop + * + */ +/* + * Support and FAQ: visit Atmel Support + */ + +#ifndef _CONF_ACCESS_H_ +#define _CONF_ACCESS_H_ + +#include "compiler.h" +#include "board.h" + + +/*! \name Activation of Logical Unit Numbers + */ +//! @{ +#define LUN_0 ENABLE //!< On-Chip Virtual Memory. +#define LUN_1 DISABLE //!< AT45DBX Data Flash. +#define LUN_2 DISABLE //!< SD/MMC Card over SPI. +#define LUN_3 DISABLE //!< SD/MMC Card over MCI Slot 0. +#define LUN_4 DISABLE +#define LUN_5 DISABLE +#define LUN_6 DISABLE +#define LUN_7 DISABLE +#define LUN_USB DISABLE //!< Host Mass-Storage Memory. +//! @} + +/*! \name LUN 0 Definitions + */ +//! @{ +#define LUN_0_INCLUDE "access_vfs.h" +#define Lun_0_test_unit_ready vfs_test_unit_ready +#define Lun_0_read_capacity vfs_read_capacity +#define Lun_0_unload NULL +#define Lun_0_wr_protect vfs_wr_protect +#define Lun_0_removal vfs_removal +#define Lun_0_usb_read_10 vfs_usb_read_10 +#define Lun_0_usb_write_10 vfs_usb_write_10 +#define LUN_0_NAME "\"MicroPython VFS[0]\"" +//! @} + +#define MEM_USB LUN_USB + +/*! \name Actions Associated with Memory Accesses + * + * Write here the action to associate with each memory access. + * + * \warning Be careful not to waste time in order not to disturb the functions. + */ +//! @{ +#define memory_start_read_action(nb_sectors) +#define memory_stop_read_action() +#define memory_start_write_action(nb_sectors) +#define memory_stop_write_action() +//! @} + +/*! \name Activation of Interface Features + */ +//! @{ +#define ACCESS_USB true //!< MEM <-> USB interface. +#define ACCESS_MEM_TO_RAM false //!< MEM <-> RAM interface. +#define ACCESS_STREAM false //!< Streaming MEM <-> MEM interface. +#define ACCESS_STREAM_RECORD false //!< Streaming MEM <-> MEM interface in record mode. +#define ACCESS_MEM_TO_MEM false //!< MEM <-> MEM interface. +#define ACCESS_CODEC false //!< Codec interface. +//! @} + +/*! \name Specific Options for Access Control + */ +//! @{ +#define GLOBAL_WR_PROTECT false //!< Management of a global write protection. +//! @} + + +#endif // _CONF_ACCESS_H_ diff --git a/atmel-samd/boards/pirkey_m0/conf_board.h b/atmel-samd/boards/pirkey_m0/conf_board.h new file mode 100644 index 0000000000..7b88c97fc2 --- /dev/null +++ b/atmel-samd/boards/pirkey_m0/conf_board.h @@ -0,0 +1,14 @@ +/** + * \file + * + * \brief User board configuration template + * + */ +/* + * Support and FAQ: visit Atmel Support + */ + +#ifndef CONF_BOARD_H +#define CONF_BOARD_H + +#endif // CONF_BOARD_H diff --git a/atmel-samd/boards/pirkey_m0/conf_clocks.h b/atmel-samd/boards/pirkey_m0/conf_clocks.h new file mode 100644 index 0000000000..9e4f7876be --- /dev/null +++ b/atmel-samd/boards/pirkey_m0/conf_clocks.h @@ -0,0 +1 @@ +#include "conf_clocks_crystalless.h" diff --git a/atmel-samd/boards/pirkey_m0/conf_usb.h b/atmel-samd/boards/pirkey_m0/conf_usb.h new file mode 100644 index 0000000000..caa086706d --- /dev/null +++ b/atmel-samd/boards/pirkey_m0/conf_usb.h @@ -0,0 +1,220 @@ + +#include +#include + +#include "asf/common/services/usb/class/cdc/usb_protocol_cdc.h" + +#ifndef CONF_USB_H_INCLUDED +#define CONF_USB_H_INCLUDED + +#define USB_DEVICE_MAJOR_VERSION 1 +#define USB_DEVICE_MINOR_VERSION 0 +#define USB_DEVICE_POWER 100 // Consumption on Vbus line (mA) +#define USB_DEVICE_ATTR \ + (USB_CONFIG_ATTR_BUS_POWERED) +// (USB_CONFIG_ATTR_REMOTE_WAKEUP|USB_CONFIG_ATTR_SELF_POWERED) +// (USB_CONFIG_ATTR_REMOTE_WAKEUP|USB_CONFIG_ATTR_BUS_POWERED) + +//! USB Device string definitions (Optional) +#ifndef USB_DEVICE_MANUFACTURE_NAME +# define USB_DEVICE_MANUFACTURE_NAME "Adafruit Industries" +#endif + +#ifndef USB_DEVICE_PRODUCT_NAME +# define USB_DEVICE_PRODUCT_NAME "pIRKey M0" +#endif + +#define USB_DEVICE_GET_SERIAL_NAME_POINTER serial_number +#define USB_DEVICE_GET_SERIAL_NAME_LENGTH 32 +extern char serial_number[USB_DEVICE_GET_SERIAL_NAME_LENGTH]; + +//! Control endpoint size +#define USB_DEVICE_EP_CTRL_SIZE 64 + +//! Interfaces for this device (CDC COM + CDC DATA + MSC + HID mouse + HID kbd) +#define USB_DEVICE_NB_INTERFACE 5 + +// (3 | USB_EP_DIR_IN) // CDC Notify endpoint +// (4 | USB_EP_DIR_IN) // CDC TX +// (5 | USB_EP_DIR_OUT) // CDC RX +// (1 | USB_EP_DIR_IN) // MSC IN +// (2 | USB_EP_DIR_OUT) // MSC OUT +// (6 | USB_EP_DIR_IN) // HID mouse report +// (7 | USB_EP_DIR_IN) // HID keyboard report +#define USB_DEVICE_MAX_EP 7 + +#define UDI_CDC_PORT_NB 1 +#define UDI_CDC_ENABLE_EXT(port) mp_cdc_enable(port) +extern bool mp_cdc_enable(uint8_t port); +#define UDI_CDC_DISABLE_EXT(port) mp_cdc_disable(port) +extern void mp_cdc_disable(uint8_t port); +#define UDI_CDC_LOW_RATE + +#define UDI_CDC_DEFAULT_RATE 115200 +#define UDI_CDC_DEFAULT_STOPBITS CDC_STOP_BITS_1 +#define UDI_CDC_DEFAULT_PARITY CDC_PAR_NONE +#define UDI_CDC_DEFAULT_DATABITS 8 + +#define UDI_CDC_RX_NOTIFY(port) usb_rx_notify() +void usb_rx_notify(void); +#define UDI_CDC_SET_CODING_EXT(port,cfg) usb_coding_notify(port, cfg) +void usb_coding_notify(uint8_t port, usb_cdc_line_coding_t* coding); +#define UDI_CDC_SET_DTR_EXT(port,set) usb_dtr_notify(port, set) +void usb_dtr_notify(uint8_t port, bool set); +#define UDI_CDC_SET_RTS_EXT(port,set) usb_rts_notify(port, set) +void usb_rts_notify(uint8_t port, bool set); + +/** + * USB CDC low level configuration + * In standalone these configurations are defined by the CDC module. + * For composite device, these configuration must be defined here + * @{ + */ +//! Endpoint numbers definition + +#define UDI_CDC_COMM_EP_0 (3 | USB_EP_DIR_IN) // Notify endpoint +#define UDI_CDC_DATA_EP_IN_0 (4 | USB_EP_DIR_IN) // TX +#define UDI_CDC_DATA_EP_OUT_0 (5 | USB_EP_DIR_OUT) // RX + +//! Interface numbers +#define UDI_CDC_COMM_IFACE_NUMBER_0 0 +#define UDI_CDC_DATA_IFACE_NUMBER_0 1 + +/** + * Configuration of MSC interface + * @{ + */ +//! Vendor name and Product version of MSC interface +#define UDI_MSC_GLOBAL_VENDOR_ID \ + 'A', 'T', 'M', 'E', 'L', ' ', ' ', ' ' +#define UDI_MSC_GLOBAL_PRODUCT_VERSION \ + '1', '.', '0', '0' + +//! Interface callback definition +#define UDI_MSC_ENABLE_EXT() mp_msc_enable() +extern bool mp_msc_enable(void); +#define UDI_MSC_DISABLE_EXT() mp_msc_disable() +extern void mp_msc_disable(void); + +//! Enable id string of interface to add an extra USB string +#define UDI_MSC_STRING_ID 5 + +/** + * USB MSC low level configuration + * In standalone these configurations are defined by the MSC module. + * For composite device, these configuration must be defined here + * @{ + */ +//! Endpoint numbers definition +#define UDI_MSC_EP_IN (1 | USB_EP_DIR_IN) +#define UDI_MSC_EP_OUT (2 | USB_EP_DIR_OUT) + +//! Interface number +#define UDI_MSC_IFACE_NUMBER 2 +/** + * Configuration of HID Mouse interface + * @{ + */ +//! Interface callback definition +#define UDI_HID_MOUSE_ENABLE_EXT() mp_mouse_enable() +extern bool mp_mouse_enable(void); +#define UDI_HID_MOUSE_DISABLE_EXT() mp_mouse_disable() +extern void mp_mouse_disable(void); + +//! Enable id string of interface to add an extra USB string +#define UDI_HID_MOUSE_STRING_ID 6 + +/** + * USB HID Mouse low level configuration + * In standalone these configurations are defined by the HID Mouse module. + * For composite device, these configuration must be defined here + * @{ + */ +//! Endpoint numbers definition +#define UDI_HID_MOUSE_EP_IN (6 | USB_EP_DIR_IN) + +//! Interface number +#define UDI_HID_MOUSE_IFACE_NUMBER 3 +//@} +//@} + +/** + * Configuration of HID Keyboard interface + * @{ + */ +//! Interface callback definition +#define UDI_HID_KBD_ENABLE_EXT() mp_keyboard_enable() +extern bool mp_keyboard_enable(void); +#define UDI_HID_KBD_DISABLE_EXT() mp_keyboard_disable() +extern void mp_keyboard_disable(void); +#define UDI_HID_KBD_CHANGE_LED(value) mp_keyboard_led(value) +extern void mp_keyboard_led(uint8_t); + +//! Enable id string of interface to add an extra USB string +#define UDI_HID_KBD_STRING_ID 7 + +/** + * USB HID Keyboard low level configuration + * In standalone these configurations are defined by the HID Keyboard module. + * For composite device, these configuration must be defined here + * @{ + */ +//! Endpoint numbers definition +#define UDI_HID_KBD_EP_IN (7 | USB_EP_DIR_IN) + +//! Interface number +#define UDI_HID_KBD_IFACE_NUMBER 4 + +/** + * Description of Composite Device + * @{ + */ +//! USB Interfaces descriptor structure +#define UDI_COMPOSITE_DESC_T \ + usb_iad_desc_t udi_cdc_iad; \ + udi_cdc_comm_desc_t udi_cdc_comm; \ + udi_cdc_data_desc_t udi_cdc_data; \ + udi_msc_desc_t udi_msc; \ + udi_hid_mouse_desc_t udi_hid_mouse; \ + udi_hid_kbd_desc_t udi_hid_kbd + +//! USB Interfaces descriptor value for Full Speed +#define UDI_COMPOSITE_DESC_FS \ + .udi_cdc_iad = UDI_CDC_IAD_DESC_0, \ + .udi_cdc_comm = UDI_CDC_COMM_DESC_0, \ + .udi_cdc_data = UDI_CDC_DATA_DESC_0_FS, \ + .udi_msc = UDI_MSC_DESC_FS, \ + .udi_hid_mouse = UDI_HID_MOUSE_DESC, \ + .udi_hid_kbd = UDI_HID_KBD_DESC + +//! USB Interfaces descriptor value for High Speed +#define UDI_COMPOSITE_DESC_HS \ + .udi_cdc_iad = UDI_CDC_IAD_DESC_0, \ + .udi_cdc_comm = UDI_CDC_COMM_DESC_0, \ + .udi_cdc_data = UDI_CDC_DATA_DESC_0_HS, \ + .udi_msc = UDI_MSC_DESC_HS, \ + .udi_hid_mouse = UDI_HID_MOUSE_DESC, \ + .udi_hid_kbd = UDI_HID_KBD_DESC + +//! USB Interface APIs +#define UDI_COMPOSITE_API \ + &udi_api_cdc_comm, \ + &udi_api_cdc_data, \ + &udi_api_msc, \ + &udi_api_hid_mouse, \ + &udi_api_hid_kbd +//@} + +/** + * USB Device Driver Configuration + * @{ + */ +//@} + +//! The includes of classes and other headers must be done at the end of this file to avoid compile error +#include "udi_cdc.h" +#include "udi_msc.h" +#include "udi_hid_mouse.h" +#include "udi_hid_kbd.h" + +#endif diff --git a/atmel-samd/boards/pirkey_m0/mpconfigboard.h b/atmel-samd/boards/pirkey_m0/mpconfigboard.h new file mode 100644 index 0000000000..3ce4003df5 --- /dev/null +++ b/atmel-samd/boards/pirkey_m0/mpconfigboard.h @@ -0,0 +1,18 @@ +#define USB_REPL + +#define MICROPY_HW_BOARD_NAME "Adafruit pIRKey M0" +#define MICROPY_HW_MCU_NAME "samd21e18" + +#define MICROPY_HW_APA102_MOSI (&pin_PA00) +#define MICROPY_HW_APA102_SCK (&pin_PA01) + +// #define CIRCUITPY_BITBANG_APA102 + +#define MICROPY_PORT_A (PORT_PA00 | PORT_PA01 | PORT_PA24 | PORT_PA25) +#define MICROPY_PORT_B (0) + +#define CIRCUITPY_INTERNAL_NVM_SIZE 0 + +#include "internal_flash.h" + +#define BOARD_FLASH_SIZE (0x00040000 - 0x2000 - 0x010000) diff --git a/atmel-samd/boards/pirkey_m0/mpconfigboard.mk b/atmel-samd/boards/pirkey_m0/mpconfigboard.mk new file mode 100644 index 0000000000..12c1c6c923 --- /dev/null +++ b/atmel-samd/boards/pirkey_m0/mpconfigboard.mk @@ -0,0 +1,7 @@ +LD_FILE = boards/samd21x18-bootloader.ld +USB_VID = 0x239A +USB_PID = 0x8028 + +INTERNAL_FLASH_FILESYSTEM = 1 + +CHIP_VARIANT = SAMD21E18A diff --git a/atmel-samd/boards/pirkey_m0/pins.c b/atmel-samd/boards/pirkey_m0/pins.c new file mode 100644 index 0000000000..a1b7db85c8 --- /dev/null +++ b/atmel-samd/boards/pirkey_m0/pins.c @@ -0,0 +1,9 @@ +#include "samd21_pins.h" + +STATIC const mp_rom_map_elem_t board_global_dict_table[] = { + { MP_ROM_QSTR(MP_QSTR_REMOTEIN), MP_ROM_PTR(&pin_PA28) }, + + { MP_ROM_QSTR(MP_QSTR_APA102_MOSI), MP_ROM_PTR(&pin_PA00) }, + { MP_ROM_QSTR(MP_QSTR_APA102_SCK), MP_ROM_PTR(&pin_PA01) }, +}; +MP_DEFINE_CONST_DICT(board_module_globals, board_global_dict_table); From 2a3de8d1850b593875a3c1e840e065c4e0c73326 Mon Sep 17 00:00:00 2001 From: Mika Tuupola Date: Sun, 11 Feb 2018 23:15:01 +0700 Subject: [PATCH 053/135] Magnetometer values are also 3d vector of uT Unless I have misunderstood something design guide should have matching the definition with [Unified Sensor Driver](https://github.com/adafruit/Adafruit_Sensor/blob/master/Adafruit_Sensor.h#L111). --- docs/design_guide.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/design_guide.rst b/docs/design_guide.rst index 1481caad74..1c0f5dbbd7 100644 --- a/docs/design_guide.rst +++ b/docs/design_guide.rst @@ -364,7 +364,7 @@ properties. +=======================+=======================+=========================================================================+ | ``acceleration`` | (float, float, float) | x, y, z meter per second per second | +-----------------------+-----------------------+-------------------------------------------------------------------------+ -| ``magnetic`` | float | micro-Tesla (uT) | +| ``magnetic`` | (float, float, float) | micro-Tesla (uT) | +-----------------------+-----------------------+-------------------------------------------------------------------------+ | ``orientation`` | (float, float, float) | x, y, z degrees | +-----------------------+-----------------------+-------------------------------------------------------------------------+ From 4cc2cf0e8fc8584a8bd564c21f5448433a7f6a31 Mon Sep 17 00:00:00 2001 From: Scott Shawcroft Date: Mon, 12 Feb 2018 18:09:37 -0800 Subject: [PATCH 054/135] Increase the status LED brightness a bit so that newer DotStars aren't super dim. This will make status NeoPixels a bit bright but one can use samd.set_rgb_status_brightness() to dim them. --- atmel-samd/rgb_led_colors.h | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/atmel-samd/rgb_led_colors.h b/atmel-samd/rgb_led_colors.h index 12f5cc3d9d..cab7029811 100644 --- a/atmel-samd/rgb_led_colors.h +++ b/atmel-samd/rgb_led_colors.h @@ -1,12 +1,12 @@ #define BLACK 0x000000 -#define GREEN 0x001000 -#define BLUE 0x000010 -#define CYAN 0x001010 -#define RED 0x100000 -#define ORANGE 0x100800 -#define YELLOW 0x101000 -#define PURPLE 0x100010 -#define WHITE 0x101010 +#define GREEN 0x003000 +#define BLUE 0x000030 +#define CYAN 0x003030 +#define RED 0x300000 +#define ORANGE 0x302000 +#define YELLOW 0x303000 +#define PURPLE 0x300030 +#define WHITE 0x303030 #define BOOT_RUNNING BLUE #define MAIN_RUNNING GREEN From a5220010f2fd4245424ec75a093f652f63ae09ec Mon Sep 17 00:00:00 2001 From: Scott Shawcroft Date: Mon, 12 Feb 2018 18:34:59 -0800 Subject: [PATCH 055/135] Dim the neopixel status LED through the brightness control. --- atmel-samd/rgb_led_status.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/atmel-samd/rgb_led_status.c b/atmel-samd/rgb_led_status.c index 83d3f9916b..5ce74fb4fa 100644 --- a/atmel-samd/rgb_led_status.c +++ b/atmel-samd/rgb_led_status.c @@ -12,14 +12,15 @@ #include "rgb_led_status.h" #include "samd21_pins.h" -uint8_t rgb_status_brightness = 255; #ifdef MICROPY_HW_NEOPIXEL +uint8_t rgb_status_brightness = 63; static uint8_t status_neopixel_color[3]; static digitalio_digitalinout_obj_t status_neopixel; #endif #if defined(MICROPY_HW_APA102_MOSI) && defined(MICROPY_HW_APA102_SCK) +uint8_t rgb_status_brightness = 255; static uint8_t status_apa102_color[12] = {0, 0, 0, 0, 0xff, 0, 0, 0}; #ifdef CIRCUITPY_BITBANG_APA102 static bitbangio_spi_obj_t status_apa102; From 06c944519dbdaa767c3c88ec419602ea41ad16d3 Mon Sep 17 00:00:00 2001 From: Scott Shawcroft Date: Tue, 13 Feb 2018 09:39:19 -0800 Subject: [PATCH 056/135] Fix builds without status pixel. No need to track its brightness when its unavaialable. --- atmel-samd/rgb_led_status.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/atmel-samd/rgb_led_status.c b/atmel-samd/rgb_led_status.c index 5ce74fb4fa..a157385126 100644 --- a/atmel-samd/rgb_led_status.c +++ b/atmel-samd/rgb_led_status.c @@ -175,5 +175,7 @@ uint32_t color_brightness(uint32_t color, uint8_t brightness) { } void set_rgb_status_brightness(uint8_t level){ - rgb_status_brightness = level; + #if defined(MICROPY_HW_NEOPIXEL) || (defined(MICROPY_HW_APA102_MOSI) && defined(MICROPY_HW_APA102_SCK)) + rgb_status_brightness = level; + #endif } From a2bd772d5ca848b53e82410966d37897e205d018 Mon Sep 17 00:00:00 2001 From: Scott Shawcroft Date: Fri, 16 Feb 2018 09:46:34 -0800 Subject: [PATCH 057/135] Begin rework to add qspi support. --- .../boards/metro_m4_express/mpconfigboard.mk | 2 +- ports/atmel-samd/spi_flash.c | 170 ++++++++++++------ 2 files changed, 119 insertions(+), 53 deletions(-) diff --git a/ports/atmel-samd/boards/metro_m4_express/mpconfigboard.mk b/ports/atmel-samd/boards/metro_m4_express/mpconfigboard.mk index 0f96532396..1d59ed9664 100644 --- a/ports/atmel-samd/boards/metro_m4_express/mpconfigboard.mk +++ b/ports/atmel-samd/boards/metro_m4_express/mpconfigboard.mk @@ -4,7 +4,7 @@ USB_PID = 0x8021 USB_PRODUCT = "Metro M4 Express" USB_MANUFACTURER = "Adafruit Industries LLC" -SPI_FLASH_FILESYSTEM = 1 +QSPI_FLASH_FILESYSTEM = 1 CHIP_VARIANT = SAMD51J19A CHIP_FAMILY = samd51 diff --git a/ports/atmel-samd/spi_flash.c b/ports/atmel-samd/spi_flash.c index 55a00dcba3..8d6864a0c5 100644 --- a/ports/atmel-samd/spi_flash.c +++ b/ports/atmel-samd/spi_flash.c @@ -81,29 +81,84 @@ static void flash_disable(void) { gpio_set_pin_level(SPI_FLASH_CS_PIN, true); } +static void spi_flash_command(uint8_t* request, uint8_t* response, uint32_t length) { + struct spi_xfer xfer = { request, response, length }; + flash_enable(); + spi_m_sync_transfer(&spi_flash_desc, &jedec_id_xfer); + flash_disable(); +} + +static void qspi_flash_command(uint8_t* request, uint8_t* response, uint32_t length) { + +} + +static void flash_command(uint8_t* request, uint8_t* response, uint32_t length) { + #ifdef CIRCUITPY_QSPI + qspi_flash_command(request, response, length); + #else + spi_flash_command(request, response, length); + #endif +} + +static bool spi_flash_write_data(uint8_t* request, uint32_t request_length, uint8_t* data, uint32_t data_length) { + flash_enable(); + uint8_t page_program_request[4] = {CMD_PAGE_PROGRAM, 0x00, 0x00, 0x00}; + // Write the SPI flash write address into the bytes following the command byte. + address_to_bytes(address + bytes_written, page_program_request + 1); + struct spi_xfer page_program_xfer = {request, 0, request_length}; + int32_t status = spi_m_sync_transfer(&spi_flash_desc, &page_program_xfer); + if (status >= 0) { + struct spi_xfer write_data_buffer_xfer = {data, 0, data_length}; + status = spi_m_sync_transfer(&spi_flash_desc, &write_data_buffer_xfer); + } + flash_disable(); + return status >= 0; +} + +static bool qspi_flash_write_data(uint8_t* request, uint32_t request_length, uint8_t* data, uint32_t data_length) { + return true; +} + +static bool flash_write_data(uint8_t* request, uint32_t request_length, uint8_t* data, uint32_t data_length) { + #ifdef CIRCUITPY_QSPI + return qspi_flash_write_data(request, request_length, data, data_length); + #else + return spi_flash_write_data(request, request_length, data, data_length); + #endif +} + +static bool spi_flash_read_data(uint8_t* request, uint32_t request_length, uint8_t* data, uint32_t data_length) { + +} + +static bool qspi_flash_read_data(uint8_t* request, uint32_t request_length, uint8_t* data, uint32_t data_length) { + return true; +} + +static bool flash_read_data(uint8_t* request, uint32_t request_length, uint8_t* data, uint32_t data_length) { + #ifdef CIRCUITPY_QSPI + return qspi_flash_write_data(request, request_length, data, data_length); + #else + return spi_flash_write_data(request, request_length, data, data_length); + #endif +} + // Wait until both the write enable and write in progress bits have cleared. static bool wait_for_flash_ready(void) { uint8_t read_status_request[2] = {CMD_READ_STATUS, 0x00}; uint8_t read_status_response[2] = {0x00, 0x00}; - struct spi_xfer read_status_xfer = {read_status_request, read_status_response, 2}; - int32_t status; + bool ok = true; // Both the write enable and write in progress bits should be low. do { - flash_enable(); - status = spi_m_sync_transfer(&spi_flash_desc, &read_status_xfer); - flash_disable(); - } while (status >= 0 && (read_status_response[1] & 0x3) != 0); - return status >= 0; // status is number of chars read or a negative error code. + ok = flash_command(read_status_request, read_status_response, 2); + } while (ok && (read_status_response[1] & 0x3) != 0); + return ok; } // Turn on the write enable bit so we can program and erase the flash. static bool write_enable(void) { - flash_enable(); uint8_t enable_write_request[1] = {CMD_ENABLE_WRITE}; - struct spi_xfer enable_write_xfer = {enable_write_request, 0, 1}; - int32_t status = spi_m_sync_transfer(&spi_flash_desc, &enable_write_xfer); - flash_disable(); - return status >= 0; // status is number of chars read or a negative error code. + return flash_command(enable_write_request, 0, 1); } // Pack the low 24 bits of the address into a uint8_t array. @@ -123,17 +178,9 @@ static bool read_flash(uint32_t address, uint8_t* data, uint32_t data_length) { } // We can read as much as we want sequentially. uint8_t read_data_request[4] = {CMD_READ_DATA, 0x00, 0x00, 0x00}; - struct spi_xfer read_data_xfer = {read_data_request, 0, 4}; // Write the SPI flash read address into the bytes following the command byte. address_to_bytes(address, read_data_request + 1); - flash_enable(); - int32_t status = spi_m_sync_transfer(&spi_flash_desc, &read_data_xfer); - struct spi_xfer read_data_buffer_xfer = {0, data, data_length}; - if (status >= 0) { - status = spi_m_sync_transfer(&spi_flash_desc, &read_data_buffer_xfer); - } - flash_disable(); - return status >= 0; + return flash_read_data(read_data_request, 4, data, data_length); } // Writes data_length's worth of bytes starting at address from data. Assumes @@ -173,18 +220,11 @@ static bool write_flash(uint32_t address, const uint8_t* data, uint32_t data_len // flash_disable(); #endif - flash_enable(); uint8_t page_program_request[4] = {CMD_PAGE_PROGRAM, 0x00, 0x00, 0x00}; // Write the SPI flash write address into the bytes following the command byte. address_to_bytes(address + bytes_written, page_program_request + 1); - struct spi_xfer page_program_xfer = {page_program_request, 0, 4}; - status = spi_m_sync_transfer(&spi_flash_desc, &page_program_xfer); - if (status >= 0) { - struct spi_xfer write_data_buffer_xfer = {(uint8_t*) data + bytes_written, 0, SPI_FLASH_PAGE_SIZE}; - status = spi_m_sync_transfer(&spi_flash_desc, &write_data_buffer_xfer); - } - flash_disable(); - if (status < 0) { + if (!flash_write_data(page_program_request, 4, (uint8_t*) data + bytes_written, + SPI_FLASH_PAGE_SIZE)) { return false; } } @@ -230,11 +270,8 @@ static bool erase_sector(uint32_t sector_address) { uint8_t erase_request[4] = {CMD_SECTOR_ERASE, 0x00, 0x00, 0x00}; address_to_bytes(sector_address, erase_request + 1); - struct spi_xfer erase_xfer = {erase_request, 0, 4}; - flash_enable(); - int32_t status = spi_m_sync_transfer(&spi_flash_desc, &erase_xfer); - flash_disable(); - return status >= 0; + flash_command(erase_request, NULL, 4); + return true; } // Sector is really 24 bits. @@ -252,11 +289,7 @@ static bool copy_block(uint32_t src_address, uint32_t dest_address) { return true; } -void spi_flash_init(void) { - if (spi_flash_is_initialised) { - return; - } - +void init_spi_peripheral(void) { samd_peripherals_sercom_clock_init(SPI_FLASH_SERCOM, SPI_FLASH_SERCOM_INDEX); // Set up with defaults, then change. @@ -291,6 +324,47 @@ void spi_flash_init(void) { flash_disable(); spi_m_sync_enable(&spi_flash_desc); +} + +static void init_qspi_peripheral(void) { + MCLK->APBCMASK.bit.QSPI_ = true; + MCLK->AHBMASK.bit.QSPI_ = true; + MCLK->AHBMASK.bit.QSPI_2X_ = false; // Only true if we are doing DDR. + + QSPI->CTRLA.reg = QSPI_CTRLA_SWRST; + // We don't need to wait because we're running as fast as the CPU. + + QSPI->BAUD.bit.BAUD = 2; + QSPI->CTRLB.reg = QSPI_CTRLB_MODE_MEMORY | + QSPI_CTRLB_CSMODE_NORELOAD | + QSPI_CTRLB_DATALEN_8BITS | + QSPI_CTRLB_CSMODE_LASTXFER; + + QSPI->CTRLA.bit.ENABLE = 1; + + // The QSPI is only connected to one set of pins in the SAMD51 so we can hard code it. + uint32_t pins = {PIN_PA08, PIN_PA09, PIN_PA10, PIN_PA11, PIN_PB10, PIN_PB11}; + for (uint8_t i = 0; i < sizeof(pins); i++) { + gpio_set_pin_direction(SPI_FLASH_SCK_PIN, GPIO_DIRECTION_IN); + gpio_set_pin_pull_mode(SPI_FLASH_SCK_PIN, GPIO_PULL_OFF); + gpio_set_pin_function(SPI_FLASH_SCK_PIN, GPIO_PIN_FUNCTION_H); + } +} + +void init_peripherals(void) { + #ifdef CIRCUITPY_QSPI + init_qspi_peripheral(); + #else + init_spi_peripheral(); + #endif +} + +void spi_flash_init(void) { + if (spi_flash_is_initialised) { + return; + } + + init_peripherals(); // Activity LED for flash writes. #ifdef MICROPY_HW_LED_MSC @@ -302,10 +376,8 @@ void spi_flash_init(void) { uint8_t jedec_id_request[4] = {CMD_READ_JEDEC_ID, 0x00, 0x00, 0x00}; uint8_t jedec_id_response[4] = {0x00, 0x00, 0x00, 0x00}; - struct spi_xfer jedec_id_xfer = { jedec_id_request, jedec_id_response, 4 }; - flash_enable(); - spi_m_sync_transfer(&spi_flash_desc, &jedec_id_xfer); - flash_disable(); + flash_command(jedec_id_request, jedec_id_response, 4); + uint8_t manufacturer = jedec_id_response[1]; if ((jedec_id_response[1] == SPI_FLASH_JEDEC_MANUFACTURER #ifdef SPI_FLASH_JEDEC_MANUFACTURER_2 @@ -330,18 +402,12 @@ void spi_flash_init(void) { // Turn off sector protection uint8_t disable_protect_request[2] = {CMD_WRITE_STATUS_BYTE1, 0x00}; - struct spi_xfer disable_protect_xfer = { disable_protect_request, 0, 4 }; - flash_enable(); - spi_m_sync_transfer(&spi_flash_desc, &disable_protect_xfer); - flash_disable(); + flash_command(disable_protect_request, NULL, 2); } // Turn off writes in case this is a microcontroller only reset. uint8_t disable_write_request[1] = {CMD_DISABLE_WRITE}; - struct spi_xfer disable_write_xfer = { disable_write_request, 0, 1 }; - flash_enable(); - spi_m_sync_transfer(&spi_flash_desc, &disable_write_xfer); - flash_disable(); + flash_command(disable_write_request, NULL, 1); wait_for_flash_ready(); From 4710a2adba74cfaff4faf1aa8e2a490ef21a9ce5 Mon Sep 17 00:00:00 2001 From: Scott Shawcroft Date: Fri, 16 Feb 2018 14:00:26 -0800 Subject: [PATCH 058/135] Compiles for m4. Untested on m0. This introduces a new spi_flash_api.h that works for both SPI and QSPI. The previous spi_flash functions are now called external_flash to minimize confusion. --- ports/atmel-samd/Makefile | 5 +- .../circuitplayground_express/mpconfigboard.h | 2 +- .../boards/feather_m0_express/mpconfigboard.h | 2 +- .../feather_m0_supersized/mpconfigboard.h | 2 +- .../boards/itsybitsy_m0/mpconfigboard.h | 2 +- .../boards/metro_m0_express/mpconfigboard.h | 2 +- .../boards/metro_m4_express/mpconfigboard.h | 2 +- .../trinket_m0_haxpress/mpconfigboard.h | 3 +- .../atmel-samd/boards/ugame10/mpconfigboard.h | 2 +- ports/atmel-samd/external_flash.c | 663 ++++++++++++++++ .../{spi_flash.h => external_flash.h} | 26 +- ports/atmel-samd/qspi_flash.c | 74 ++ ports/atmel-samd/spi_flash.c | 741 +----------------- ports/atmel-samd/spi_flash_api.h | 40 + 14 files changed, 820 insertions(+), 746 deletions(-) create mode 100644 ports/atmel-samd/external_flash.c rename ports/atmel-samd/{spi_flash.h => external_flash.h} (69%) create mode 100644 ports/atmel-samd/qspi_flash.c create mode 100644 ports/atmel-samd/spi_flash_api.h diff --git a/ports/atmel-samd/Makefile b/ports/atmel-samd/Makefile index 041f1d1ad7..abf5bf12ef 100644 --- a/ports/atmel-samd/Makefile +++ b/ports/atmel-samd/Makefile @@ -252,7 +252,10 @@ ifeq ($(INTERNAL_FLASH_FILESYSTEM),1) SRC_C += internal_flash.c endif ifeq ($(SPI_FLASH_FILESYSTEM),1) -SRC_C += spi_flash.c +SRC_C += external_flash.c spi_flash.c +endif +ifeq ($(QSPI_FLASH_FILESYSTEM),1) +SRC_C += external_flash.c qspi_flash.c endif SRC_COMMON_HAL = \ diff --git a/ports/atmel-samd/boards/circuitplayground_express/mpconfigboard.h b/ports/atmel-samd/boards/circuitplayground_express/mpconfigboard.h index fdb96c06c3..2b8fed6b8b 100644 --- a/ports/atmel-samd/boards/circuitplayground_express/mpconfigboard.h +++ b/ports/atmel-samd/boards/circuitplayground_express/mpconfigboard.h @@ -38,7 +38,7 @@ #define SPEAKER_ENABLE_PIN (&pin_PA30) -#include "spi_flash.h" +#include "external_flash.h" // If you change this, then make sure to update the linker scripts as well to // make sure you don't overwrite code. diff --git a/ports/atmel-samd/boards/feather_m0_express/mpconfigboard.h b/ports/atmel-samd/boards/feather_m0_express/mpconfigboard.h index 448c6c52bf..d0e70d954b 100644 --- a/ports/atmel-samd/boards/feather_m0_express/mpconfigboard.h +++ b/ports/atmel-samd/boards/feather_m0_express/mpconfigboard.h @@ -31,7 +31,7 @@ #define MICROPY_PORT_B ( 0 ) #define MICROPY_PORT_C ( 0 ) -#include "spi_flash.h" +#include "external_flash.h" // If you change this, then make sure to update the linker scripts as well to // make sure you don't overwrite code. diff --git a/ports/atmel-samd/boards/feather_m0_supersized/mpconfigboard.h b/ports/atmel-samd/boards/feather_m0_supersized/mpconfigboard.h index 02ce5e1cdc..4f9b177bec 100644 --- a/ports/atmel-samd/boards/feather_m0_supersized/mpconfigboard.h +++ b/ports/atmel-samd/boards/feather_m0_supersized/mpconfigboard.h @@ -33,7 +33,7 @@ #define MICROPY_PORT_B ( 0 ) #define MICROPY_PORT_C ( 0 ) -#include "spi_flash.h" +#include "external_flash.h" // If you change this, then make sure to update the linker scripts as well to // make sure you don't overwrite code. diff --git a/ports/atmel-samd/boards/itsybitsy_m0/mpconfigboard.h b/ports/atmel-samd/boards/itsybitsy_m0/mpconfigboard.h index f41059ee4f..116775886c 100644 --- a/ports/atmel-samd/boards/itsybitsy_m0/mpconfigboard.h +++ b/ports/atmel-samd/boards/itsybitsy_m0/mpconfigboard.h @@ -33,7 +33,7 @@ #define MICROPY_PORT_B (PORT_PB22 | PORT_PB23 | PORT_PB03 ) #define MICROPY_PORT_C (0) -#include "spi_flash.h" +#include "external_flash.h" // If you change this, then make sure to update the linker scripts as well to // make sure you don't overwrite code. diff --git a/ports/atmel-samd/boards/metro_m0_express/mpconfigboard.h b/ports/atmel-samd/boards/metro_m0_express/mpconfigboard.h index 023beb6883..be1a1a57e0 100644 --- a/ports/atmel-samd/boards/metro_m0_express/mpconfigboard.h +++ b/ports/atmel-samd/boards/metro_m0_express/mpconfigboard.h @@ -34,7 +34,7 @@ #define MICROPY_PORT_B (PORT_PB03 | PORT_PB22 | PORT_PB23) #define MICROPY_PORT_C (0) -#include "spi_flash.h" +#include "external_flash.h" // If you change this, then make sure to update the linker scripts as well to // make sure you don't overwrite code. diff --git a/ports/atmel-samd/boards/metro_m4_express/mpconfigboard.h b/ports/atmel-samd/boards/metro_m4_express/mpconfigboard.h index 1af18ecbc2..fdf98625ef 100644 --- a/ports/atmel-samd/boards/metro_m4_express/mpconfigboard.h +++ b/ports/atmel-samd/boards/metro_m4_express/mpconfigboard.h @@ -40,7 +40,7 @@ #define AUTORESET_DELAY_MS 500 -#include "spi_flash.h" +#include "external_flash.h" // If you change this, then make sure to update the linker scripts as well to // make sure you don't overwrite code diff --git a/ports/atmel-samd/boards/trinket_m0_haxpress/mpconfigboard.h b/ports/atmel-samd/boards/trinket_m0_haxpress/mpconfigboard.h index 2a5792a63b..5dcea945ac 100644 --- a/ports/atmel-samd/boards/trinket_m0_haxpress/mpconfigboard.h +++ b/ports/atmel-samd/boards/trinket_m0_haxpress/mpconfigboard.h @@ -40,7 +40,7 @@ #define CALIBRATE_CRYSTALLESS 1 -#include "spi_flash.h" +#include "external_flash.h" // If you change this, then make sure to update the linker scripts as well to // make sure you don't overwrite code. @@ -49,4 +49,3 @@ #define BOARD_FLASH_SIZE (0x00040000 - 0x2000 - CIRCUITPY_INTERNAL_NVM_SIZE) #include "flash_W25Q32BV.h" - diff --git a/ports/atmel-samd/boards/ugame10/mpconfigboard.h b/ports/atmel-samd/boards/ugame10/mpconfigboard.h index 16a792f421..3bec61ff96 100644 --- a/ports/atmel-samd/boards/ugame10/mpconfigboard.h +++ b/ports/atmel-samd/boards/ugame10/mpconfigboard.h @@ -33,7 +33,7 @@ #define CALIBRATE_CRYSTALLESS 1 -#include "spi_flash.h" +#include "external_flash.h" // If you change this, then make sure to update the linker scripts as well to // make sure you don't overwrite code. diff --git a/ports/atmel-samd/external_flash.c b/ports/atmel-samd/external_flash.c new file mode 100644 index 0000000000..45406462d6 --- /dev/null +++ b/ports/atmel-samd/external_flash.c @@ -0,0 +1,663 @@ +/* + * This file is part of the MicroPython project, http://micropython.org/ + * + * The MIT License (MIT) + * + * Copyright (c) 2016, 2017 Scott Shawcroft for Adafruit Industries + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ +#include "external_flash.h" + +#include +#include + +#include "extmod/vfs.h" +#include "extmod/vfs_fat.h" +#include "py/misc.h" +#include "py/obj.h" +#include "py/runtime.h" +#include "lib/oofatfs/ff.h" +#include "peripherals.h" +#include "spi_flash_api.h" +#include "supervisor/shared/rgb_led_status.h" + +//#include "shared_dma.h" + +#include "hal_gpio.h" +#include "hal_spi_m_sync.h" + +#define SPI_FLASH_PART1_START_BLOCK (0x1) + +#define NO_SECTOR_LOADED 0xFFFFFFFF + +#define CMD_READ_JEDEC_ID 0x9f +#define CMD_READ_DATA 0x03 +#define CMD_SECTOR_ERASE 0x20 +// #define CMD_SECTOR_ERASE CMD_READ_JEDEC_ID +#define CMD_DISABLE_WRITE 0x04 +#define CMD_ENABLE_WRITE 0x06 +#define CMD_PAGE_PROGRAM 0x02 +// #define CMD_PAGE_PROGRAM CMD_READ_JEDEC_ID +#define CMD_READ_STATUS 0x05 +#define CMD_WRITE_STATUS_BYTE1 0x01 + +static bool spi_flash_is_initialised = false; + +struct spi_m_sync_descriptor spi_flash_desc; + +// The currently cached sector in the cache, ram or flash based. +static uint32_t current_sector; + +// Track which blocks (up to 32) in the current sector currently live in the +// cache. +static uint32_t dirty_mask; + +// Address of the scratch flash sector. +#define SCRATCH_SECTOR (SPI_FLASH_TOTAL_SIZE - SPI_FLASH_ERASE_SIZE) + +// Wait until both the write enable and write in progress bits have cleared. +static bool wait_for_flash_ready(void) { + uint8_t read_status_request[2] = {CMD_READ_STATUS, 0x00}; + uint8_t read_status_response[2] = {0x00, 0x00}; + bool ok = true; + // Both the write enable and write in progress bits should be low. + do { + ok = spi_flash_command(read_status_request, read_status_response, 2); + } while (ok && (read_status_response[1] & 0x3) != 0); + return ok; +} + +// Turn on the write enable bit so we can program and erase the flash. +static bool write_enable(void) { + uint8_t enable_write_request[1] = {CMD_ENABLE_WRITE}; + return spi_flash_command(enable_write_request, 0, 1); +} + +// Read data_length's worth of bytes starting at address into data. +static bool read_flash(uint32_t address, uint8_t* data, uint32_t data_length) { + if (!spi_flash_is_initialised) { + return false; + } + if (!wait_for_flash_ready()) { + return false; + } + return spi_flash_read_data(address, data, data_length); +} + +// Writes data_length's worth of bytes starting at address from data. Assumes +// that the sector that address resides in has already been erased. So make sure +// to run erase_sector. +static bool write_flash(uint32_t address, const uint8_t* data, uint32_t data_length) { + if (!spi_flash_is_initialised) { + return false; + } + // Don't bother writing if the data is all 1s. Thats equivalent to the flash + // state after an erase. + bool all_ones = true; + for (uint16_t i = 0; i < data_length; i++) { + if (data[i] != 0xff) { + all_ones = false; + break; + } + } + if (all_ones) { + return true; + } + + for (uint32_t bytes_written = 0; + bytes_written < data_length; + bytes_written += SPI_FLASH_PAGE_SIZE) { + if (!wait_for_flash_ready() || !write_enable()) { + return false; + } + + if (!spi_flash_write_data(address + bytes_written, (uint8_t*) data + bytes_written, + SPI_FLASH_PAGE_SIZE)) { + return false; + } + } + return true; +} + +static bool page_erased(uint32_t sector_address) { + // Check the first few bytes to catch the common case where there is data + // without using a bunch of memory. + uint8_t short_buffer[4]; + if (read_flash(sector_address, short_buffer, 4)) { + for (uint16_t i = 0; i < 4; i++) { + if (short_buffer[i] != 0xff) { + return false; + } + } + } else { + return false; + } + + // Now check the full length. + uint8_t full_buffer[FILESYSTEM_BLOCK_SIZE]; + if (read_flash(sector_address, full_buffer, FILESYSTEM_BLOCK_SIZE)) { + for (uint16_t i = 0; i < FILESYSTEM_BLOCK_SIZE; i++) { + if (short_buffer[i] != 0xff) { + return false; + } + } + } else { + return false; + } + return true; +} + +// Erases the given sector. Make sure you copied all of the data out of it you +// need! Also note, sector_address is really 24 bits. +static bool erase_sector(uint32_t sector_address) { + // Before we erase the sector we need to wait for any writes to finish and + // and then enable the write again. + if (!wait_for_flash_ready() || !write_enable()) { + return false; + } + + spi_flash_sector_command(CMD_SECTOR_ERASE, sector_address); + return true; +} + +// Sector is really 24 bits. +static bool copy_block(uint32_t src_address, uint32_t dest_address) { + // Copy page by page to minimize RAM buffer. + uint8_t buffer[SPI_FLASH_PAGE_SIZE]; + for (uint32_t i = 0; i < FILESYSTEM_BLOCK_SIZE / SPI_FLASH_PAGE_SIZE; i++) { + if (!read_flash(src_address + i * SPI_FLASH_PAGE_SIZE, buffer, SPI_FLASH_PAGE_SIZE)) { + return false; + } + if (!write_flash(dest_address + i * SPI_FLASH_PAGE_SIZE, buffer, SPI_FLASH_PAGE_SIZE)) { + return false; + } + } + return true; +} + +void external_flash_init(void) { + if (spi_flash_is_initialised) { + return; + } + + spi_flash_init(); + + // Activity LED for flash writes. +#ifdef MICROPY_HW_LED_MSC + gpio_set_pin_function(SPI_FLASH_CS_PIN, GPIO_PIN_FUNCTION_OFF); + gpio_set_pin_direction(MICROPY_HW_LED_MSC, GPIO_DIRECTION_OUT); + // There's already a pull-up on the board. + gpio_set_pin_level(MICROPY_HW_LED_MSC, false); +#endif + + uint8_t jedec_id_request[4] = {CMD_READ_JEDEC_ID, 0x00, 0x00, 0x00}; + uint8_t jedec_id_response[4] = {0x00, 0x00, 0x00, 0x00}; + spi_flash_command(jedec_id_request, jedec_id_response, 4); + + uint8_t manufacturer = jedec_id_response[1]; + if ((jedec_id_response[1] == SPI_FLASH_JEDEC_MANUFACTURER +#ifdef SPI_FLASH_JEDEC_MANUFACTURER_2 + || jedec_id_response[1] == SPI_FLASH_JEDEC_MANUFACTURER_2 +#endif + ) && + jedec_id_response[2] == SPI_FLASH_JEDEC_MEMORY_TYPE && + jedec_id_response[3] == SPI_FLASH_JEDEC_CAPACITY) { + spi_flash_is_initialised = true; + } else { + // Unknown flash chip! + spi_flash_is_initialised = false; + return; + } + + if ((manufacturer == SPI_FLASH_JEDEC_MANUFACTURER && SPI_FLASH_SECTOR_PROTECTION) +#ifdef SPI_FLASH_JEDEC_MANUFACTURER_2 + || (manufacturer == SPI_FLASH_JEDEC_MANUFACTURER_2 && SPI_FLASH_SECTOR_PROTECTION_2) +#endif + ) { + write_enable(); + + // Turn off sector protection + uint8_t disable_protect_request[2] = {CMD_WRITE_STATUS_BYTE1, 0x00}; + spi_flash_command(disable_protect_request, NULL, 2); + } + + // Turn off writes in case this is a microcontroller only reset. + uint8_t disable_write_request[1] = {CMD_DISABLE_WRITE}; + spi_flash_command(disable_write_request, NULL, 1); + + wait_for_flash_ready(); + + current_sector = NO_SECTOR_LOADED; + dirty_mask = 0; + MP_STATE_VM(flash_ram_cache) = NULL; + + spi_flash_is_initialised = true; +} + +// The size of each individual block. +uint32_t external_flash_get_block_size(void) { + return FILESYSTEM_BLOCK_SIZE; +} + +// The total number of available blocks. +uint32_t external_flash_get_block_count(void) { + // We subtract one erase sector size because we may use it as a staging area + // for writes. + return SPI_FLASH_PART1_START_BLOCK + (SPI_FLASH_TOTAL_SIZE - SPI_FLASH_ERASE_SIZE) / FILESYSTEM_BLOCK_SIZE; +} + +// Flush the cache that was written to the scratch portion of flash. Only used +// when ram is tight. +static bool flush_scratch_flash(void) { + // First, copy out any blocks that we haven't touched from the sector we've + // cached. + bool copy_to_scratch_ok = true; + for (uint8_t i = 0; i < SPI_FLASH_ERASE_SIZE / FILESYSTEM_BLOCK_SIZE; i++) { + if ((dirty_mask & (1 << i)) == 0) { + copy_to_scratch_ok = copy_to_scratch_ok && + copy_block(current_sector + i * FILESYSTEM_BLOCK_SIZE, + SCRATCH_SECTOR + i * FILESYSTEM_BLOCK_SIZE); + } + } + if (!copy_to_scratch_ok) { + // TODO(tannewt): Do more here. We opted to not erase and copy bad data + // in. We still risk losing the data written to the scratch sector. + return false; + } + // Second, erase the current sector. + erase_sector(current_sector); + // Finally, copy the new version into it. + for (uint8_t i = 0; i < SPI_FLASH_ERASE_SIZE / FILESYSTEM_BLOCK_SIZE; i++) { + copy_block(SCRATCH_SECTOR + i * FILESYSTEM_BLOCK_SIZE, + current_sector + i * FILESYSTEM_BLOCK_SIZE); + } + return true; +} + +// Attempts to allocate a new set of page buffers for caching a full sector in +// ram. Each page is allocated separately so that the GC doesn't need to provide +// one huge block. We can free it as we write if we want to also. +static bool allocate_ram_cache(void) { + uint8_t blocks_per_sector = SPI_FLASH_ERASE_SIZE / FILESYSTEM_BLOCK_SIZE; + uint8_t pages_per_block = FILESYSTEM_BLOCK_SIZE / SPI_FLASH_PAGE_SIZE; + MP_STATE_VM(flash_ram_cache) = m_malloc_maybe(blocks_per_sector * pages_per_block * sizeof(uint32_t), false); + if (MP_STATE_VM(flash_ram_cache) == NULL) { + return false; + } + // Declare i and j outside the loops in case we fail to allocate everything + // we need. In that case we'll give it back. + uint8_t i = 0; + uint8_t j = 0; + bool success = true; + for (i = 0; i < blocks_per_sector; i++) { + for (j = 0; j < pages_per_block; j++) { + uint8_t *page_cache = m_malloc_maybe(SPI_FLASH_PAGE_SIZE, false); + if (page_cache == NULL) { + success = false; + break; + } + MP_STATE_VM(flash_ram_cache)[i * pages_per_block + j] = page_cache; + } + if (!success) { + break; + } + } + // We couldn't allocate enough so give back what we got. + if (!success) { + // We add 1 so that we delete 0 when i is 1. Going to zero (i >= 0) + // would never stop because i is unsigned. + i++; + for (; i > 0; i--) { + for (; j > 0; j--) { + m_free(MP_STATE_VM(flash_ram_cache)[(i - 1) * pages_per_block + (j - 1)]); + } + j = pages_per_block; + } + m_free(MP_STATE_VM(flash_ram_cache)); + MP_STATE_VM(flash_ram_cache) = NULL; + } + return success; +} + +// Flush the cached sector from ram onto the flash. We'll free the cache unless +// keep_cache is true. +static bool flush_ram_cache(bool keep_cache) { + // First, copy out any blocks that we haven't touched from the sector + // we've cached. If we don't do this we'll erase the data during the sector + // erase below. + bool copy_to_ram_ok = true; + uint8_t pages_per_block = FILESYSTEM_BLOCK_SIZE / SPI_FLASH_PAGE_SIZE; + for (uint8_t i = 0; i < SPI_FLASH_ERASE_SIZE / FILESYSTEM_BLOCK_SIZE; i++) { + if ((dirty_mask & (1 << i)) == 0) { + for (uint8_t j = 0; j < pages_per_block; j++) { + copy_to_ram_ok = read_flash( + current_sector + (i * pages_per_block + j) * SPI_FLASH_PAGE_SIZE, + MP_STATE_VM(flash_ram_cache)[i * pages_per_block + j], + SPI_FLASH_PAGE_SIZE); + if (!copy_to_ram_ok) { + break; + } + } + } + if (!copy_to_ram_ok) { + break; + } + } + + if (!copy_to_ram_ok) { + return false; + } + // Second, erase the current sector. + erase_sector(current_sector); + // Lastly, write all the data in ram that we've cached. + for (uint8_t i = 0; i < SPI_FLASH_ERASE_SIZE / FILESYSTEM_BLOCK_SIZE; i++) { + for (uint8_t j = 0; j < pages_per_block; j++) { + write_flash(current_sector + (i * pages_per_block + j) * SPI_FLASH_PAGE_SIZE, + MP_STATE_VM(flash_ram_cache)[i * pages_per_block + j], + SPI_FLASH_PAGE_SIZE); + if (!keep_cache) { + m_free(MP_STATE_VM(flash_ram_cache)[i * pages_per_block + j]); + } + } + } + // We're done with the cache for now so give it back. + if (!keep_cache) { + m_free(MP_STATE_VM(flash_ram_cache)); + MP_STATE_VM(flash_ram_cache) = NULL; + } + return true; +} + +// Delegates to the correct flash flush method depending on the existing cache. +static void spi_flash_flush_keep_cache(bool keep_cache) { + if (current_sector == NO_SECTOR_LOADED) { + return; + } + #ifdef MICROPY_HW_LED_MSC + port_pin_set_output_level(MICROPY_HW_LED_MSC, true); + #endif + temp_status_color(ACTIVE_WRITE); + // If we've cached to the flash itself flush from there. + if (MP_STATE_VM(flash_ram_cache) == NULL) { + flush_scratch_flash(); + } else { + flush_ram_cache(keep_cache); + } + current_sector = NO_SECTOR_LOADED; + clear_temp_status(); + #ifdef MICROPY_HW_LED_MSC + port_pin_set_output_level(MICROPY_HW_LED_MSC, false); + #endif +} + +// External flash function used. If called externally we assume we won't need +// the cache after. +void external_flash_flush(void) { + spi_flash_flush_keep_cache(false); +} + +void flash_flush(void) { + external_flash_flush(); +} + +// Builds a partition entry for the MBR. +static void build_partition(uint8_t *buf, int boot, int type, + uint32_t start_block, uint32_t num_blocks) { + buf[0] = boot; + + if (num_blocks == 0) { + buf[1] = 0; + buf[2] = 0; + buf[3] = 0; + } else { + buf[1] = 0xff; + buf[2] = 0xff; + buf[3] = 0xff; + } + + buf[4] = type; + + if (num_blocks == 0) { + buf[5] = 0; + buf[6] = 0; + buf[7] = 0; + } else { + buf[5] = 0xff; + buf[6] = 0xff; + buf[7] = 0xff; + } + + buf[8] = start_block; + buf[9] = start_block >> 8; + buf[10] = start_block >> 16; + buf[11] = start_block >> 24; + + buf[12] = num_blocks; + buf[13] = num_blocks >> 8; + buf[14] = num_blocks >> 16; + buf[15] = num_blocks >> 24; +} + +static int32_t convert_block_to_flash_addr(uint32_t block) { + if (SPI_FLASH_PART1_START_BLOCK <= block && block < external_flash_get_block_count()) { + // a block in partition 1 + block -= SPI_FLASH_PART1_START_BLOCK; + return block * FILESYSTEM_BLOCK_SIZE; + } + // bad block + return -1; +} + +bool external_flash_read_block(uint8_t *dest, uint32_t block) { + if (block == 0) { + // Fake the MBR so we can decide on our own partition table + for (int i = 0; i < 446; i++) { + dest[i] = 0; + } + + build_partition(dest + 446, 0, 0x01 /* FAT12 */, + SPI_FLASH_PART1_START_BLOCK, + external_flash_get_block_count() - SPI_FLASH_PART1_START_BLOCK); + build_partition(dest + 462, 0, 0, 0, 0); + build_partition(dest + 478, 0, 0, 0, 0); + build_partition(dest + 494, 0, 0, 0, 0); + + dest[510] = 0x55; + dest[511] = 0xaa; + + return true; + } else if (block < SPI_FLASH_PART1_START_BLOCK) { + memset(dest, 0, FILESYSTEM_BLOCK_SIZE); + return true; + } else { + // Non-MBR block, get data from flash memory. + int32_t address = convert_block_to_flash_addr(block); + if (address == -1) { + // bad block number + return false; + } + + // Mask out the lower bits that designate the address within the sector. + uint32_t this_sector = address & (~(SPI_FLASH_ERASE_SIZE - 1)); + uint8_t block_index = (address / FILESYSTEM_BLOCK_SIZE) % (SPI_FLASH_ERASE_SIZE / FILESYSTEM_BLOCK_SIZE); + uint8_t mask = 1 << (block_index); + // We're reading from the currently cached sector. + if (current_sector == this_sector && (mask & dirty_mask) > 0) { + if (MP_STATE_VM(flash_ram_cache) != NULL) { + uint8_t pages_per_block = FILESYSTEM_BLOCK_SIZE / SPI_FLASH_PAGE_SIZE; + for (int i = 0; i < pages_per_block; i++) { + memcpy(dest + i * SPI_FLASH_PAGE_SIZE, + MP_STATE_VM(flash_ram_cache)[block_index * pages_per_block + i], + SPI_FLASH_PAGE_SIZE); + } + return true; + } else { + uint32_t scratch_address = SCRATCH_SECTOR + block_index * FILESYSTEM_BLOCK_SIZE; + return read_flash(scratch_address, dest, FILESYSTEM_BLOCK_SIZE); + } + } + return read_flash(address, dest, FILESYSTEM_BLOCK_SIZE); + } +} + +bool external_flash_write_block(const uint8_t *data, uint32_t block) { + if (block < SPI_FLASH_PART1_START_BLOCK) { + // Fake writing below the flash partition. + return true; + } else { + // Non-MBR block, copy to cache + int32_t address = convert_block_to_flash_addr(block); + if (address == -1) { + // bad block number + return false; + } + // Wait for any previous writes to finish. + wait_for_flash_ready(); + // Mask out the lower bits that designate the address within the sector. + uint32_t this_sector = address & (~(SPI_FLASH_ERASE_SIZE - 1)); + uint8_t block_index = (address / FILESYSTEM_BLOCK_SIZE) % (SPI_FLASH_ERASE_SIZE / FILESYSTEM_BLOCK_SIZE); + uint8_t mask = 1 << (block_index); + // Flush the cache if we're moving onto a sector or we're writing the + // same block again. + if (current_sector != this_sector || (mask & dirty_mask) > 0) { + // Check to see if we'd write to an erased page. In that case we + // can write directly. + if (page_erased(address)) { + return write_flash(address, data, FILESYSTEM_BLOCK_SIZE); + } + if (current_sector != NO_SECTOR_LOADED) { + spi_flash_flush_keep_cache(true); + } + if (MP_STATE_VM(flash_ram_cache) == NULL && !allocate_ram_cache()) { + erase_sector(SCRATCH_SECTOR); + wait_for_flash_ready(); + } + current_sector = this_sector; + dirty_mask = 0; + } + dirty_mask |= mask; + // Copy the block to the appropriate cache. + if (MP_STATE_VM(flash_ram_cache) != NULL) { + uint8_t pages_per_block = FILESYSTEM_BLOCK_SIZE / SPI_FLASH_PAGE_SIZE; + for (int i = 0; i < pages_per_block; i++) { + memcpy(MP_STATE_VM(flash_ram_cache)[block_index * pages_per_block + i], + data + i * SPI_FLASH_PAGE_SIZE, + SPI_FLASH_PAGE_SIZE); + } + return true; + } else { + uint32_t scratch_address = SCRATCH_SECTOR + block_index * FILESYSTEM_BLOCK_SIZE; + return write_flash(scratch_address, data, FILESYSTEM_BLOCK_SIZE); + } + } +} + +mp_uint_t external_flash_read_blocks(uint8_t *dest, uint32_t block_num, uint32_t num_blocks) { + for (size_t i = 0; i < num_blocks; i++) { + if (!external_flash_read_block(dest + i * FILESYSTEM_BLOCK_SIZE, block_num + i)) { + return 1; // error + } + } + return 0; // success +} + +mp_uint_t external_flash_write_blocks(const uint8_t *src, uint32_t block_num, uint32_t num_blocks) { + for (size_t i = 0; i < num_blocks; i++) { + if (!external_flash_write_block(src + i * FILESYSTEM_BLOCK_SIZE, block_num + i)) { + return 1; // error + } + } + return 0; // success +} + +/******************************************************************************/ +// MicroPython bindings +// +// Expose the flash as an object with the block protocol. + +// there is a singleton Flash object +STATIC const mp_obj_base_t external_flash_obj = {&external_flash_type}; + +STATIC mp_obj_t external_flash_obj_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *args) { + // check arguments + mp_arg_check_num(n_args, n_kw, 0, 0, false); + + // return singleton object + return (mp_obj_t)&external_flash_obj; +} + +STATIC mp_obj_t external_flash_obj_readblocks(mp_obj_t self, mp_obj_t block_num, mp_obj_t buf) { + mp_buffer_info_t bufinfo; + mp_get_buffer_raise(buf, &bufinfo, MP_BUFFER_WRITE); + mp_uint_t ret = external_flash_read_blocks(bufinfo.buf, mp_obj_get_int(block_num), bufinfo.len / FILESYSTEM_BLOCK_SIZE); + return MP_OBJ_NEW_SMALL_INT(ret); +} +STATIC MP_DEFINE_CONST_FUN_OBJ_3(external_flash_obj_readblocks_obj, external_flash_obj_readblocks); + +STATIC mp_obj_t external_flash_obj_writeblocks(mp_obj_t self, mp_obj_t block_num, mp_obj_t buf) { + mp_buffer_info_t bufinfo; + mp_get_buffer_raise(buf, &bufinfo, MP_BUFFER_READ); + mp_uint_t ret = external_flash_write_blocks(bufinfo.buf, mp_obj_get_int(block_num), bufinfo.len / FILESYSTEM_BLOCK_SIZE); + return MP_OBJ_NEW_SMALL_INT(ret); +} +STATIC MP_DEFINE_CONST_FUN_OBJ_3(external_flash_obj_writeblocks_obj, external_flash_obj_writeblocks); + +STATIC mp_obj_t external_flash_obj_ioctl(mp_obj_t self, mp_obj_t cmd_in, mp_obj_t arg_in) { + mp_int_t cmd = mp_obj_get_int(cmd_in); + switch (cmd) { + case BP_IOCTL_INIT: external_flash_init(); return MP_OBJ_NEW_SMALL_INT(0); + case BP_IOCTL_DEINIT: external_flash_flush(); return MP_OBJ_NEW_SMALL_INT(0); // TODO properly + case BP_IOCTL_SYNC: external_flash_flush(); return MP_OBJ_NEW_SMALL_INT(0); + case BP_IOCTL_SEC_COUNT: return MP_OBJ_NEW_SMALL_INT(external_flash_get_block_count()); + case BP_IOCTL_SEC_SIZE: return MP_OBJ_NEW_SMALL_INT(external_flash_get_block_size()); + default: return mp_const_none; + } +} +STATIC MP_DEFINE_CONST_FUN_OBJ_3(external_flash_obj_ioctl_obj, external_flash_obj_ioctl); + +STATIC const mp_rom_map_elem_t external_flash_obj_locals_dict_table[] = { + { MP_ROM_QSTR(MP_QSTR_readblocks), MP_ROM_PTR(&external_flash_obj_readblocks_obj) }, + { MP_ROM_QSTR(MP_QSTR_writeblocks), MP_ROM_PTR(&external_flash_obj_writeblocks_obj) }, + { MP_ROM_QSTR(MP_QSTR_ioctl), MP_ROM_PTR(&external_flash_obj_ioctl_obj) }, +}; + +STATIC MP_DEFINE_CONST_DICT(external_flash_obj_locals_dict, external_flash_obj_locals_dict_table); + +const mp_obj_type_t external_flash_type = { + { &mp_type_type }, + .name = MP_QSTR_SPIFlash, + .make_new = external_flash_obj_make_new, + .locals_dict = (mp_obj_t)&external_flash_obj_locals_dict, +}; + +void flash_init_vfs(fs_user_mount_t *vfs) { + vfs->base.type = &mp_fat_vfs_type; + vfs->flags |= FSUSER_NATIVE | FSUSER_HAVE_IOCTL; + vfs->fatfs.drv = vfs; + vfs->fatfs.part = 1; // flash filesystem lives on first partition + vfs->readblocks[0] = (mp_obj_t)&external_flash_obj_readblocks_obj; + vfs->readblocks[1] = (mp_obj_t)&external_flash_obj; + vfs->readblocks[2] = (mp_obj_t)external_flash_read_blocks; // native version + vfs->writeblocks[0] = (mp_obj_t)&external_flash_obj_writeblocks_obj; + vfs->writeblocks[1] = (mp_obj_t)&external_flash_obj; + vfs->writeblocks[2] = (mp_obj_t)external_flash_write_blocks; // native version + vfs->u.ioctl[0] = (mp_obj_t)&external_flash_obj_ioctl_obj; + vfs->u.ioctl[1] = (mp_obj_t)&external_flash_obj; +} diff --git a/ports/atmel-samd/spi_flash.h b/ports/atmel-samd/external_flash.h similarity index 69% rename from ports/atmel-samd/spi_flash.h rename to ports/atmel-samd/external_flash.h index e4bf8a5224..5a43b10c84 100644 --- a/ports/atmel-samd/spi_flash.h +++ b/ports/atmel-samd/external_flash.h @@ -23,8 +23,8 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ -#ifndef MICROPY_INCLUDED_ATMEL_SAMD_SPI_FLASH_H -#define MICROPY_INCLUDED_ATMEL_SAMD_SPI_FLASH_H +#ifndef MICROPY_INCLUDED_ATMEL_SAMD_EXTERNAL_FLASH_H +#define MICROPY_INCLUDED_ATMEL_SAMD_EXTERNAL_FLASH_H #include @@ -40,21 +40,21 @@ #define SPI_FLASH_SYSTICK_MASK (0x1ff) // 512ms #define SPI_FLASH_IDLE_TICK(tick) (((tick) & SPI_FLASH_SYSTICK_MASK) == 2) -void spi_flash_init(void); -uint32_t spi_flash_get_block_size(void); -uint32_t spi_flash_get_block_count(void); -void spi_flash_irq_handler(void); -void spi_flash_flush(void); -bool spi_flash_read_block(uint8_t *dest, uint32_t block); -bool spi_flash_write_block(const uint8_t *src, uint32_t block); +void external_flash_init(void); +uint32_t external_flash_get_block_size(void); +uint32_t external_flash_get_block_count(void); +void external_flash_irq_handler(void); +void external_flash_flush(void); +bool external_flash_read_block(uint8_t *dest, uint32_t block); +bool external_flash_write_block(const uint8_t *src, uint32_t block); // these return 0 on success, non-zero on error -mp_uint_t spi_flash_read_blocks(uint8_t *dest, uint32_t block_num, uint32_t num_blocks); -mp_uint_t spi_flash_write_blocks(const uint8_t *src, uint32_t block_num, uint32_t num_blocks); +mp_uint_t external_flash_read_blocks(uint8_t *dest, uint32_t block_num, uint32_t num_blocks); +mp_uint_t external_flash_write_blocks(const uint8_t *src, uint32_t block_num, uint32_t num_blocks); -extern const struct _mp_obj_type_t spi_flash_type; +extern const struct _mp_obj_type_t external_flash_type; struct _fs_user_mount_t; void flash_init_vfs(struct _fs_user_mount_t *vfs); -#endif // MICROPY_INCLUDED_ATMEL_SAMD_SPI_FLASH_H +#endif // MICROPY_INCLUDED_ATMEL_SAMD_EXTERNAL_FLASH_H diff --git a/ports/atmel-samd/qspi_flash.c b/ports/atmel-samd/qspi_flash.c new file mode 100644 index 0000000000..3fa53a8989 --- /dev/null +++ b/ports/atmel-samd/qspi_flash.c @@ -0,0 +1,74 @@ +/* + * This file is part of the MicroPython project, http://micropython.org/ + * + * The MIT License (MIT) + * + * Copyright (c) 2016, 2017 Scott Shawcroft for Adafruit Industries + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +#include "spi_flash_api.h" + +#include + +#include "atmel_start_pins.h" +#include "hal_gpio.h" + +bool spi_flash_command(uint8_t* request, uint8_t* response, uint32_t length) { + return true; +} + +bool spi_flash_sector_command(uint8_t command, uint32_t address) { + return true; +} + +bool spi_flash_write_data(uint32_t address, uint8_t* data, uint32_t data_length) { + return true; +} + +bool spi_flash_read_data(uint32_t address, uint8_t* data, uint32_t data_length) { + return true; +} + + +void spi_flash_init(void) { + MCLK->APBCMASK.bit.QSPI_ = true; + MCLK->AHBMASK.bit.QSPI_ = true; + MCLK->AHBMASK.bit.QSPI_2X_ = false; // Only true if we are doing DDR. + + QSPI->CTRLA.reg = QSPI_CTRLA_SWRST; + // We don't need to wait because we're running as fast as the CPU. + + QSPI->BAUD.bit.BAUD = 2; + QSPI->CTRLB.reg = QSPI_CTRLB_MODE_MEMORY | + QSPI_CTRLB_CSMODE_NORELOAD | + QSPI_CTRLB_DATALEN_8BITS | + QSPI_CTRLB_CSMODE_LASTXFER; + + QSPI->CTRLA.bit.ENABLE = 1; + + // The QSPI is only connected to one set of pins in the SAMD51 so we can hard code it. + uint32_t pins[6] = {PIN_PA08, PIN_PA09, PIN_PA10, PIN_PA11, PIN_PB10, PIN_PB11}; + for (uint8_t i = 0; i < 6; i++) { + gpio_set_pin_direction(pins[i], GPIO_DIRECTION_IN); + gpio_set_pin_pull_mode(pins[i], GPIO_PULL_OFF); + gpio_set_pin_function(pins[i], GPIO_PIN_FUNCTION_H); + } +} diff --git a/ports/atmel-samd/spi_flash.c b/ports/atmel-samd/spi_flash.c index 8d6864a0c5..9695067f17 100644 --- a/ports/atmel-samd/spi_flash.c +++ b/ports/atmel-samd/spi_flash.c @@ -28,49 +28,13 @@ #include #include -#include "extmod/vfs.h" -#include "extmod/vfs_fat.h" -#include "py/misc.h" -#include "py/obj.h" -#include "py/runtime.h" -#include "lib/oofatfs/ff.h" #include "peripherals.h" -#include "supervisor/shared/rgb_led_status.h" - -//#include "shared_dma.h" #include "hal_gpio.h" #include "hal_spi_m_sync.h" -#define SPI_FLASH_PART1_START_BLOCK (0x1) - -#define NO_SECTOR_LOADED 0xFFFFFFFF - -#define CMD_READ_JEDEC_ID 0x9f -#define CMD_READ_DATA 0x03 -#define CMD_SECTOR_ERASE 0x20 -// #define CMD_SECTOR_ERASE CMD_READ_JEDEC_ID -#define CMD_DISABLE_WRITE 0x04 -#define CMD_ENABLE_WRITE 0x06 -#define CMD_PAGE_PROGRAM 0x02 -// #define CMD_PAGE_PROGRAM CMD_READ_JEDEC_ID -#define CMD_READ_STATUS 0x05 -#define CMD_WRITE_STATUS_BYTE1 0x01 - -static bool spi_flash_is_initialised = false; - struct spi_m_sync_descriptor spi_flash_desc; -// The currently cached sector in the cache, ram or flash based. -static uint32_t current_sector; - -// Track which blocks (up to 32) in the current sector currently live in the -// cache. -static uint32_t dirty_mask; - -// Address of the scratch flash sector. -#define SCRATCH_SECTOR (SPI_FLASH_TOTAL_SIZE - SPI_FLASH_ERASE_SIZE) - // Enable the flash over SPI. static void flash_enable(void) { gpio_set_pin_level(SPI_FLASH_CS_PIN, false); @@ -81,30 +45,34 @@ static void flash_disable(void) { gpio_set_pin_level(SPI_FLASH_CS_PIN, true); } -static void spi_flash_command(uint8_t* request, uint8_t* response, uint32_t length) { +void spi_flash_command(uint8_t* request, uint8_t* response, uint32_t length) { struct spi_xfer xfer = { request, response, length }; flash_enable(); - spi_m_sync_transfer(&spi_flash_desc, &jedec_id_xfer); + spi_m_sync_transfer(&spi_flash_desc, &xfer); flash_disable(); } -static void qspi_flash_command(uint8_t* request, uint8_t* response, uint32_t length) { - +// Pack the low 24 bits of the address into a uint8_t array. +static void address_to_bytes(uint32_t address, uint8_t* bytes) { + bytes[0] = (address >> 16) & 0xff; + bytes[1] = (address >> 8) & 0xff; + bytes[2] = address & 0xff; } -static void flash_command(uint8_t* request, uint8_t* response, uint32_t length) { - #ifdef CIRCUITPY_QSPI - qspi_flash_command(request, response, length); - #else - spi_flash_command(request, response, length); - #endif +void spi_flash_sector_command(uint8_t command, uint32_t address) { + uint8_t request[4] = {command, 0x00, 0x00, 0x00}; + address_to_bytes(address, page_program_request + 1); + struct spi_xfer xfer = { request, NULL, 4 }; + flash_enable(); + spi_m_sync_transfer(&spi_flash_desc, &xfer); + flash_disable(); } -static bool spi_flash_write_data(uint8_t* request, uint32_t request_length, uint8_t* data, uint32_t data_length) { +bool spi_flash_write_data(uint32_t address, uint8_t* data, uint32_t data_length) { flash_enable(); uint8_t page_program_request[4] = {CMD_PAGE_PROGRAM, 0x00, 0x00, 0x00}; // Write the SPI flash write address into the bytes following the command byte. - address_to_bytes(address + bytes_written, page_program_request + 1); + address_to_bytes(address, page_program_request + 1); struct spi_xfer page_program_xfer = {request, 0, request_length}; int32_t status = spi_m_sync_transfer(&spi_flash_desc, &page_program_xfer); if (status >= 0) { @@ -115,181 +83,11 @@ static bool spi_flash_write_data(uint8_t* request, uint32_t request_length, uint return status >= 0; } -static bool qspi_flash_write_data(uint8_t* request, uint32_t request_length, uint8_t* data, uint32_t data_length) { - return true; -} - -static bool flash_write_data(uint8_t* request, uint32_t request_length, uint8_t* data, uint32_t data_length) { - #ifdef CIRCUITPY_QSPI - return qspi_flash_write_data(request, request_length, data, data_length); - #else - return spi_flash_write_data(request, request_length, data, data_length); - #endif -} - -static bool spi_flash_read_data(uint8_t* request, uint32_t request_length, uint8_t* data, uint32_t data_length) { +bool spi_flash_read_data(uint32_t address, uint8_t* data, uint32_t data_length) { } -static bool qspi_flash_read_data(uint8_t* request, uint32_t request_length, uint8_t* data, uint32_t data_length) { - return true; -} - -static bool flash_read_data(uint8_t* request, uint32_t request_length, uint8_t* data, uint32_t data_length) { - #ifdef CIRCUITPY_QSPI - return qspi_flash_write_data(request, request_length, data, data_length); - #else - return spi_flash_write_data(request, request_length, data, data_length); - #endif -} - -// Wait until both the write enable and write in progress bits have cleared. -static bool wait_for_flash_ready(void) { - uint8_t read_status_request[2] = {CMD_READ_STATUS, 0x00}; - uint8_t read_status_response[2] = {0x00, 0x00}; - bool ok = true; - // Both the write enable and write in progress bits should be low. - do { - ok = flash_command(read_status_request, read_status_response, 2); - } while (ok && (read_status_response[1] & 0x3) != 0); - return ok; -} - -// Turn on the write enable bit so we can program and erase the flash. -static bool write_enable(void) { - uint8_t enable_write_request[1] = {CMD_ENABLE_WRITE}; - return flash_command(enable_write_request, 0, 1); -} - -// Pack the low 24 bits of the address into a uint8_t array. -static void address_to_bytes(uint32_t address, uint8_t* bytes) { - bytes[0] = (address >> 16) & 0xff; - bytes[1] = (address >> 8) & 0xff; - bytes[2] = address & 0xff; -} - -// Read data_length's worth of bytes starting at address into data. -static bool read_flash(uint32_t address, uint8_t* data, uint32_t data_length) { - if (!spi_flash_is_initialised) { - return false; - } - if (!wait_for_flash_ready()) { - return false; - } - // We can read as much as we want sequentially. - uint8_t read_data_request[4] = {CMD_READ_DATA, 0x00, 0x00, 0x00}; - // Write the SPI flash read address into the bytes following the command byte. - address_to_bytes(address, read_data_request + 1); - return flash_read_data(read_data_request, 4, data, data_length); -} - -// Writes data_length's worth of bytes starting at address from data. Assumes -// that the sector that address resides in has already been erased. So make sure -// to run erase_sector. -static bool write_flash(uint32_t address, const uint8_t* data, uint32_t data_length) { - if (!spi_flash_is_initialised) { - return false; - } - // Don't bother writing if the data is all 1s. Thats equivalent to the flash - // state after an erase. - bool all_ones = true; - for (uint16_t i = 0; i < data_length; i++) { - if (data[i] != 0xff) { - all_ones = false; - break; - } - } - if (all_ones) { - return true; - } - - for (uint32_t bytes_written = 0; - bytes_written < data_length; - bytes_written += SPI_FLASH_PAGE_SIZE) { - if (!wait_for_flash_ready() || !write_enable()) { - return false; - } - int32_t status; - - #ifdef SPI_FLASH_SECTOR_PROTECTION - // Print out the protection status. - // uint8_t protect_check[5] = {0x3C, 0x00, 0x00, 0x00, 0x00}; - // address_to_bytes(address + bytes_written, protect_check + 1); - // flash_enable(); - // status = spi_write_buffer_wait(&spi_flash_desc, protect_check, 5); - // flash_disable(); - #endif - - uint8_t page_program_request[4] = {CMD_PAGE_PROGRAM, 0x00, 0x00, 0x00}; - // Write the SPI flash write address into the bytes following the command byte. - address_to_bytes(address + bytes_written, page_program_request + 1); - if (!flash_write_data(page_program_request, 4, (uint8_t*) data + bytes_written, - SPI_FLASH_PAGE_SIZE)) { - return false; - } - } - return true; -} - -static bool page_erased(uint32_t sector_address) { - // Check the first few bytes to catch the common case where there is data - // without using a bunch of memory. - uint8_t short_buffer[4]; - if (read_flash(sector_address, short_buffer, 4)) { - for (uint16_t i = 0; i < 4; i++) { - if (short_buffer[i] != 0xff) { - return false; - } - } - } else { - return false; - } - - // Now check the full length. - uint8_t full_buffer[FILESYSTEM_BLOCK_SIZE]; - if (read_flash(sector_address, full_buffer, FILESYSTEM_BLOCK_SIZE)) { - for (uint16_t i = 0; i < FILESYSTEM_BLOCK_SIZE; i++) { - if (short_buffer[i] != 0xff) { - return false; - } - } - } else { - return false; - } - return true; -} - -// Erases the given sector. Make sure you copied all of the data out of it you -// need! Also note, sector_address is really 24 bits. -static bool erase_sector(uint32_t sector_address) { - // Before we erase the sector we need to wait for any writes to finish and - // and then enable the write again. - if (!wait_for_flash_ready() || !write_enable()) { - return false; - } - - uint8_t erase_request[4] = {CMD_SECTOR_ERASE, 0x00, 0x00, 0x00}; - address_to_bytes(sector_address, erase_request + 1); - flash_command(erase_request, NULL, 4); - return true; -} - -// Sector is really 24 bits. -static bool copy_block(uint32_t src_address, uint32_t dest_address) { - // Copy page by page to minimize RAM buffer. - uint8_t buffer[SPI_FLASH_PAGE_SIZE]; - for (uint32_t i = 0; i < FILESYSTEM_BLOCK_SIZE / SPI_FLASH_PAGE_SIZE; i++) { - if (!read_flash(src_address + i * SPI_FLASH_PAGE_SIZE, buffer, SPI_FLASH_PAGE_SIZE)) { - return false; - } - if (!write_flash(dest_address + i * SPI_FLASH_PAGE_SIZE, buffer, SPI_FLASH_PAGE_SIZE)) { - return false; - } - } - return true; -} - -void init_spi_peripheral(void) { +void spi_flash_init(void) { samd_peripherals_sercom_clock_init(SPI_FLASH_SERCOM, SPI_FLASH_SERCOM_INDEX); // Set up with defaults, then change. @@ -325,506 +123,3 @@ void init_spi_peripheral(void) { spi_m_sync_enable(&spi_flash_desc); } - -static void init_qspi_peripheral(void) { - MCLK->APBCMASK.bit.QSPI_ = true; - MCLK->AHBMASK.bit.QSPI_ = true; - MCLK->AHBMASK.bit.QSPI_2X_ = false; // Only true if we are doing DDR. - - QSPI->CTRLA.reg = QSPI_CTRLA_SWRST; - // We don't need to wait because we're running as fast as the CPU. - - QSPI->BAUD.bit.BAUD = 2; - QSPI->CTRLB.reg = QSPI_CTRLB_MODE_MEMORY | - QSPI_CTRLB_CSMODE_NORELOAD | - QSPI_CTRLB_DATALEN_8BITS | - QSPI_CTRLB_CSMODE_LASTXFER; - - QSPI->CTRLA.bit.ENABLE = 1; - - // The QSPI is only connected to one set of pins in the SAMD51 so we can hard code it. - uint32_t pins = {PIN_PA08, PIN_PA09, PIN_PA10, PIN_PA11, PIN_PB10, PIN_PB11}; - for (uint8_t i = 0; i < sizeof(pins); i++) { - gpio_set_pin_direction(SPI_FLASH_SCK_PIN, GPIO_DIRECTION_IN); - gpio_set_pin_pull_mode(SPI_FLASH_SCK_PIN, GPIO_PULL_OFF); - gpio_set_pin_function(SPI_FLASH_SCK_PIN, GPIO_PIN_FUNCTION_H); - } -} - -void init_peripherals(void) { - #ifdef CIRCUITPY_QSPI - init_qspi_peripheral(); - #else - init_spi_peripheral(); - #endif -} - -void spi_flash_init(void) { - if (spi_flash_is_initialised) { - return; - } - - init_peripherals(); - - // Activity LED for flash writes. -#ifdef MICROPY_HW_LED_MSC - gpio_set_pin_function(SPI_FLASH_CS_PIN, GPIO_PIN_FUNCTION_OFF); - gpio_set_pin_direction(MICROPY_HW_LED_MSC, GPIO_DIRECTION_OUT); - // There's already a pull-up on the board. - gpio_set_pin_level(MICROPY_HW_LED_MSC, false); -#endif - - uint8_t jedec_id_request[4] = {CMD_READ_JEDEC_ID, 0x00, 0x00, 0x00}; - uint8_t jedec_id_response[4] = {0x00, 0x00, 0x00, 0x00}; - flash_command(jedec_id_request, jedec_id_response, 4); - - uint8_t manufacturer = jedec_id_response[1]; - if ((jedec_id_response[1] == SPI_FLASH_JEDEC_MANUFACTURER -#ifdef SPI_FLASH_JEDEC_MANUFACTURER_2 - || jedec_id_response[1] == SPI_FLASH_JEDEC_MANUFACTURER_2 -#endif - ) && - jedec_id_response[2] == SPI_FLASH_JEDEC_MEMORY_TYPE && - jedec_id_response[3] == SPI_FLASH_JEDEC_CAPACITY) { - spi_flash_is_initialised = true; - } else { - // Unknown flash chip! - spi_flash_is_initialised = false; - return; - } - - if ((manufacturer == SPI_FLASH_JEDEC_MANUFACTURER && SPI_FLASH_SECTOR_PROTECTION) -#ifdef SPI_FLASH_JEDEC_MANUFACTURER_2 - || (manufacturer == SPI_FLASH_JEDEC_MANUFACTURER_2 && SPI_FLASH_SECTOR_PROTECTION_2) -#endif - ) { - write_enable(); - - // Turn off sector protection - uint8_t disable_protect_request[2] = {CMD_WRITE_STATUS_BYTE1, 0x00}; - flash_command(disable_protect_request, NULL, 2); - } - - // Turn off writes in case this is a microcontroller only reset. - uint8_t disable_write_request[1] = {CMD_DISABLE_WRITE}; - flash_command(disable_write_request, NULL, 1); - - wait_for_flash_ready(); - - current_sector = NO_SECTOR_LOADED; - dirty_mask = 0; - MP_STATE_VM(flash_ram_cache) = NULL; - - spi_flash_is_initialised = true; -} - -// The size of each individual block. -uint32_t spi_flash_get_block_size(void) { - return FILESYSTEM_BLOCK_SIZE; -} - -// The total number of available blocks. -uint32_t spi_flash_get_block_count(void) { - // We subtract one erase sector size because we may use it as a staging area - // for writes. - return SPI_FLASH_PART1_START_BLOCK + (SPI_FLASH_TOTAL_SIZE - SPI_FLASH_ERASE_SIZE) / FILESYSTEM_BLOCK_SIZE; -} - -// Flush the cache that was written to the scratch portion of flash. Only used -// when ram is tight. -static bool flush_scratch_flash(void) { - // First, copy out any blocks that we haven't touched from the sector we've - // cached. - bool copy_to_scratch_ok = true; - for (uint8_t i = 0; i < SPI_FLASH_ERASE_SIZE / FILESYSTEM_BLOCK_SIZE; i++) { - if ((dirty_mask & (1 << i)) == 0) { - copy_to_scratch_ok = copy_to_scratch_ok && - copy_block(current_sector + i * FILESYSTEM_BLOCK_SIZE, - SCRATCH_SECTOR + i * FILESYSTEM_BLOCK_SIZE); - } - } - if (!copy_to_scratch_ok) { - // TODO(tannewt): Do more here. We opted to not erase and copy bad data - // in. We still risk losing the data written to the scratch sector. - return false; - } - // Second, erase the current sector. - erase_sector(current_sector); - // Finally, copy the new version into it. - for (uint8_t i = 0; i < SPI_FLASH_ERASE_SIZE / FILESYSTEM_BLOCK_SIZE; i++) { - copy_block(SCRATCH_SECTOR + i * FILESYSTEM_BLOCK_SIZE, - current_sector + i * FILESYSTEM_BLOCK_SIZE); - } - return true; -} - -// Attempts to allocate a new set of page buffers for caching a full sector in -// ram. Each page is allocated separately so that the GC doesn't need to provide -// one huge block. We can free it as we write if we want to also. -static bool allocate_ram_cache(void) { - uint8_t blocks_per_sector = SPI_FLASH_ERASE_SIZE / FILESYSTEM_BLOCK_SIZE; - uint8_t pages_per_block = FILESYSTEM_BLOCK_SIZE / SPI_FLASH_PAGE_SIZE; - MP_STATE_VM(flash_ram_cache) = m_malloc_maybe(blocks_per_sector * pages_per_block * sizeof(uint32_t), false); - if (MP_STATE_VM(flash_ram_cache) == NULL) { - return false; - } - // Declare i and j outside the loops in case we fail to allocate everything - // we need. In that case we'll give it back. - uint8_t i = 0; - uint8_t j = 0; - bool success = true; - for (i = 0; i < blocks_per_sector; i++) { - for (j = 0; j < pages_per_block; j++) { - uint8_t *page_cache = m_malloc_maybe(SPI_FLASH_PAGE_SIZE, false); - if (page_cache == NULL) { - success = false; - break; - } - MP_STATE_VM(flash_ram_cache)[i * pages_per_block + j] = page_cache; - } - if (!success) { - break; - } - } - // We couldn't allocate enough so give back what we got. - if (!success) { - // We add 1 so that we delete 0 when i is 1. Going to zero (i >= 0) - // would never stop because i is unsigned. - i++; - for (; i > 0; i--) { - for (; j > 0; j--) { - m_free(MP_STATE_VM(flash_ram_cache)[(i - 1) * pages_per_block + (j - 1)]); - } - j = pages_per_block; - } - m_free(MP_STATE_VM(flash_ram_cache)); - MP_STATE_VM(flash_ram_cache) = NULL; - } - return success; -} - -// Flush the cached sector from ram onto the flash. We'll free the cache unless -// keep_cache is true. -static bool flush_ram_cache(bool keep_cache) { - // First, copy out any blocks that we haven't touched from the sector - // we've cached. If we don't do this we'll erase the data during the sector - // erase below. - bool copy_to_ram_ok = true; - uint8_t pages_per_block = FILESYSTEM_BLOCK_SIZE / SPI_FLASH_PAGE_SIZE; - for (uint8_t i = 0; i < SPI_FLASH_ERASE_SIZE / FILESYSTEM_BLOCK_SIZE; i++) { - if ((dirty_mask & (1 << i)) == 0) { - for (uint8_t j = 0; j < pages_per_block; j++) { - copy_to_ram_ok = read_flash( - current_sector + (i * pages_per_block + j) * SPI_FLASH_PAGE_SIZE, - MP_STATE_VM(flash_ram_cache)[i * pages_per_block + j], - SPI_FLASH_PAGE_SIZE); - if (!copy_to_ram_ok) { - break; - } - } - } - if (!copy_to_ram_ok) { - break; - } - } - - if (!copy_to_ram_ok) { - return false; - } - // Second, erase the current sector. - erase_sector(current_sector); - // Lastly, write all the data in ram that we've cached. - for (uint8_t i = 0; i < SPI_FLASH_ERASE_SIZE / FILESYSTEM_BLOCK_SIZE; i++) { - for (uint8_t j = 0; j < pages_per_block; j++) { - write_flash(current_sector + (i * pages_per_block + j) * SPI_FLASH_PAGE_SIZE, - MP_STATE_VM(flash_ram_cache)[i * pages_per_block + j], - SPI_FLASH_PAGE_SIZE); - if (!keep_cache) { - m_free(MP_STATE_VM(flash_ram_cache)[i * pages_per_block + j]); - } - } - } - // We're done with the cache for now so give it back. - if (!keep_cache) { - m_free(MP_STATE_VM(flash_ram_cache)); - MP_STATE_VM(flash_ram_cache) = NULL; - } - return true; -} - -// Delegates to the correct flash flush method depending on the existing cache. -static void spi_flash_flush_keep_cache(bool keep_cache) { - if (current_sector == NO_SECTOR_LOADED) { - return; - } - #ifdef MICROPY_HW_LED_MSC - port_pin_set_output_level(MICROPY_HW_LED_MSC, true); - #endif - temp_status_color(ACTIVE_WRITE); - // If we've cached to the flash itself flush from there. - if (MP_STATE_VM(flash_ram_cache) == NULL) { - flush_scratch_flash(); - } else { - flush_ram_cache(keep_cache); - } - current_sector = NO_SECTOR_LOADED; - clear_temp_status(); - #ifdef MICROPY_HW_LED_MSC - port_pin_set_output_level(MICROPY_HW_LED_MSC, false); - #endif -} - -// External flash function used. If called externally we assume we won't need -// the cache after. -void spi_flash_flush(void) { - spi_flash_flush_keep_cache(false); -} - -void flash_flush(void) { - spi_flash_flush(); -} - -// Builds a partition entry for the MBR. -static void build_partition(uint8_t *buf, int boot, int type, - uint32_t start_block, uint32_t num_blocks) { - buf[0] = boot; - - if (num_blocks == 0) { - buf[1] = 0; - buf[2] = 0; - buf[3] = 0; - } else { - buf[1] = 0xff; - buf[2] = 0xff; - buf[3] = 0xff; - } - - buf[4] = type; - - if (num_blocks == 0) { - buf[5] = 0; - buf[6] = 0; - buf[7] = 0; - } else { - buf[5] = 0xff; - buf[6] = 0xff; - buf[7] = 0xff; - } - - buf[8] = start_block; - buf[9] = start_block >> 8; - buf[10] = start_block >> 16; - buf[11] = start_block >> 24; - - buf[12] = num_blocks; - buf[13] = num_blocks >> 8; - buf[14] = num_blocks >> 16; - buf[15] = num_blocks >> 24; -} - -static int32_t convert_block_to_flash_addr(uint32_t block) { - if (SPI_FLASH_PART1_START_BLOCK <= block && block < spi_flash_get_block_count()) { - // a block in partition 1 - block -= SPI_FLASH_PART1_START_BLOCK; - return block * FILESYSTEM_BLOCK_SIZE; - } - // bad block - return -1; -} - -bool spi_flash_read_block(uint8_t *dest, uint32_t block) { - if (block == 0) { - // Fake the MBR so we can decide on our own partition table - for (int i = 0; i < 446; i++) { - dest[i] = 0; - } - - build_partition(dest + 446, 0, 0x01 /* FAT12 */, - SPI_FLASH_PART1_START_BLOCK, - spi_flash_get_block_count() - SPI_FLASH_PART1_START_BLOCK); - build_partition(dest + 462, 0, 0, 0, 0); - build_partition(dest + 478, 0, 0, 0, 0); - build_partition(dest + 494, 0, 0, 0, 0); - - dest[510] = 0x55; - dest[511] = 0xaa; - - return true; - } else if (block < SPI_FLASH_PART1_START_BLOCK) { - memset(dest, 0, FILESYSTEM_BLOCK_SIZE); - return true; - } else { - // Non-MBR block, get data from flash memory. - int32_t address = convert_block_to_flash_addr(block); - if (address == -1) { - // bad block number - return false; - } - - // Mask out the lower bits that designate the address within the sector. - uint32_t this_sector = address & (~(SPI_FLASH_ERASE_SIZE - 1)); - uint8_t block_index = (address / FILESYSTEM_BLOCK_SIZE) % (SPI_FLASH_ERASE_SIZE / FILESYSTEM_BLOCK_SIZE); - uint8_t mask = 1 << (block_index); - // We're reading from the currently cached sector. - if (current_sector == this_sector && (mask & dirty_mask) > 0) { - if (MP_STATE_VM(flash_ram_cache) != NULL) { - uint8_t pages_per_block = FILESYSTEM_BLOCK_SIZE / SPI_FLASH_PAGE_SIZE; - for (int i = 0; i < pages_per_block; i++) { - memcpy(dest + i * SPI_FLASH_PAGE_SIZE, - MP_STATE_VM(flash_ram_cache)[block_index * pages_per_block + i], - SPI_FLASH_PAGE_SIZE); - } - return true; - } else { - uint32_t scratch_address = SCRATCH_SECTOR + block_index * FILESYSTEM_BLOCK_SIZE; - return read_flash(scratch_address, dest, FILESYSTEM_BLOCK_SIZE); - } - } - return read_flash(address, dest, FILESYSTEM_BLOCK_SIZE); - } -} - -bool spi_flash_write_block(const uint8_t *data, uint32_t block) { - if (block < SPI_FLASH_PART1_START_BLOCK) { - // Fake writing below the flash partition. - return true; - } else { - // Non-MBR block, copy to cache - int32_t address = convert_block_to_flash_addr(block); - if (address == -1) { - // bad block number - return false; - } - // Wait for any previous writes to finish. - wait_for_flash_ready(); - // Mask out the lower bits that designate the address within the sector. - uint32_t this_sector = address & (~(SPI_FLASH_ERASE_SIZE - 1)); - uint8_t block_index = (address / FILESYSTEM_BLOCK_SIZE) % (SPI_FLASH_ERASE_SIZE / FILESYSTEM_BLOCK_SIZE); - uint8_t mask = 1 << (block_index); - // Flush the cache if we're moving onto a sector or we're writing the - // same block again. - if (current_sector != this_sector || (mask & dirty_mask) > 0) { - // Check to see if we'd write to an erased page. In that case we - // can write directly. - if (page_erased(address)) { - return write_flash(address, data, FILESYSTEM_BLOCK_SIZE); - } - if (current_sector != NO_SECTOR_LOADED) { - spi_flash_flush_keep_cache(true); - } - if (MP_STATE_VM(flash_ram_cache) == NULL && !allocate_ram_cache()) { - erase_sector(SCRATCH_SECTOR); - wait_for_flash_ready(); - } - current_sector = this_sector; - dirty_mask = 0; - } - dirty_mask |= mask; - // Copy the block to the appropriate cache. - if (MP_STATE_VM(flash_ram_cache) != NULL) { - uint8_t pages_per_block = FILESYSTEM_BLOCK_SIZE / SPI_FLASH_PAGE_SIZE; - for (int i = 0; i < pages_per_block; i++) { - memcpy(MP_STATE_VM(flash_ram_cache)[block_index * pages_per_block + i], - data + i * SPI_FLASH_PAGE_SIZE, - SPI_FLASH_PAGE_SIZE); - } - return true; - } else { - uint32_t scratch_address = SCRATCH_SECTOR + block_index * FILESYSTEM_BLOCK_SIZE; - return write_flash(scratch_address, data, FILESYSTEM_BLOCK_SIZE); - } - } -} - -mp_uint_t spi_flash_read_blocks(uint8_t *dest, uint32_t block_num, uint32_t num_blocks) { - for (size_t i = 0; i < num_blocks; i++) { - if (!spi_flash_read_block(dest + i * FILESYSTEM_BLOCK_SIZE, block_num + i)) { - return 1; // error - } - } - return 0; // success -} - -mp_uint_t spi_flash_write_blocks(const uint8_t *src, uint32_t block_num, uint32_t num_blocks) { - for (size_t i = 0; i < num_blocks; i++) { - if (!spi_flash_write_block(src + i * FILESYSTEM_BLOCK_SIZE, block_num + i)) { - return 1; // error - } - } - return 0; // success -} - -/******************************************************************************/ -// MicroPython bindings -// -// Expose the flash as an object with the block protocol. - -// there is a singleton Flash object -STATIC const mp_obj_base_t spi_flash_obj = {&spi_flash_type}; - -STATIC mp_obj_t spi_flash_obj_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *args) { - // check arguments - mp_arg_check_num(n_args, n_kw, 0, 0, false); - - // return singleton object - return (mp_obj_t)&spi_flash_obj; -} - -STATIC mp_obj_t spi_flash_obj_readblocks(mp_obj_t self, mp_obj_t block_num, mp_obj_t buf) { - mp_buffer_info_t bufinfo; - mp_get_buffer_raise(buf, &bufinfo, MP_BUFFER_WRITE); - mp_uint_t ret = spi_flash_read_blocks(bufinfo.buf, mp_obj_get_int(block_num), bufinfo.len / FILESYSTEM_BLOCK_SIZE); - return MP_OBJ_NEW_SMALL_INT(ret); -} -STATIC MP_DEFINE_CONST_FUN_OBJ_3(spi_flash_obj_readblocks_obj, spi_flash_obj_readblocks); - -STATIC mp_obj_t spi_flash_obj_writeblocks(mp_obj_t self, mp_obj_t block_num, mp_obj_t buf) { - mp_buffer_info_t bufinfo; - mp_get_buffer_raise(buf, &bufinfo, MP_BUFFER_READ); - mp_uint_t ret = spi_flash_write_blocks(bufinfo.buf, mp_obj_get_int(block_num), bufinfo.len / FILESYSTEM_BLOCK_SIZE); - return MP_OBJ_NEW_SMALL_INT(ret); -} -STATIC MP_DEFINE_CONST_FUN_OBJ_3(spi_flash_obj_writeblocks_obj, spi_flash_obj_writeblocks); - -STATIC mp_obj_t spi_flash_obj_ioctl(mp_obj_t self, mp_obj_t cmd_in, mp_obj_t arg_in) { - mp_int_t cmd = mp_obj_get_int(cmd_in); - switch (cmd) { - case BP_IOCTL_INIT: spi_flash_init(); return MP_OBJ_NEW_SMALL_INT(0); - case BP_IOCTL_DEINIT: spi_flash_flush(); return MP_OBJ_NEW_SMALL_INT(0); // TODO properly - case BP_IOCTL_SYNC: spi_flash_flush(); return MP_OBJ_NEW_SMALL_INT(0); - case BP_IOCTL_SEC_COUNT: return MP_OBJ_NEW_SMALL_INT(spi_flash_get_block_count()); - case BP_IOCTL_SEC_SIZE: return MP_OBJ_NEW_SMALL_INT(spi_flash_get_block_size()); - default: return mp_const_none; - } -} -STATIC MP_DEFINE_CONST_FUN_OBJ_3(spi_flash_obj_ioctl_obj, spi_flash_obj_ioctl); - -STATIC const mp_rom_map_elem_t spi_flash_obj_locals_dict_table[] = { - { MP_ROM_QSTR(MP_QSTR_readblocks), MP_ROM_PTR(&spi_flash_obj_readblocks_obj) }, - { MP_ROM_QSTR(MP_QSTR_writeblocks), MP_ROM_PTR(&spi_flash_obj_writeblocks_obj) }, - { MP_ROM_QSTR(MP_QSTR_ioctl), MP_ROM_PTR(&spi_flash_obj_ioctl_obj) }, -}; - -STATIC MP_DEFINE_CONST_DICT(spi_flash_obj_locals_dict, spi_flash_obj_locals_dict_table); - -const mp_obj_type_t spi_flash_type = { - { &mp_type_type }, - .name = MP_QSTR_SPIFlash, - .make_new = spi_flash_obj_make_new, - .locals_dict = (mp_obj_t)&spi_flash_obj_locals_dict, -}; - -void flash_init_vfs(fs_user_mount_t *vfs) { - vfs->base.type = &mp_fat_vfs_type; - vfs->flags |= FSUSER_NATIVE | FSUSER_HAVE_IOCTL; - vfs->fatfs.drv = vfs; - vfs->fatfs.part = 1; // flash filesystem lives on first partition - vfs->readblocks[0] = (mp_obj_t)&spi_flash_obj_readblocks_obj; - vfs->readblocks[1] = (mp_obj_t)&spi_flash_obj; - vfs->readblocks[2] = (mp_obj_t)spi_flash_read_blocks; // native version - vfs->writeblocks[0] = (mp_obj_t)&spi_flash_obj_writeblocks_obj; - vfs->writeblocks[1] = (mp_obj_t)&spi_flash_obj; - vfs->writeblocks[2] = (mp_obj_t)spi_flash_write_blocks; // native version - vfs->u.ioctl[0] = (mp_obj_t)&spi_flash_obj_ioctl_obj; - vfs->u.ioctl[1] = (mp_obj_t)&spi_flash_obj; -} diff --git a/ports/atmel-samd/spi_flash_api.h b/ports/atmel-samd/spi_flash_api.h new file mode 100644 index 0000000000..d758faa774 --- /dev/null +++ b/ports/atmel-samd/spi_flash_api.h @@ -0,0 +1,40 @@ +/* + * This file is part of the MicroPython project, http://micropython.org/ + * + * The MIT License (MIT) + * + * Copyright (c) 2013, 2014 Damien P. George + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ +#ifndef MICROPY_INCLUDED_ATMEL_SAMD_SPI_FLASH_H +#define MICROPY_INCLUDED_ATMEL_SAMD_SPI_FLASH_H + +#include +#include + +// This API is implemented for both normal SPI peripherals and QSPI peripherals. + +bool spi_flash_command(uint8_t* request, uint8_t* response, uint32_t length); +bool spi_flash_sector_command(uint8_t command, uint32_t address); +bool spi_flash_write_data(uint32_t address, uint8_t* data, uint32_t data_length); +bool spi_flash_read_data(uint32_t address, uint8_t* data, uint32_t data_length); +void spi_flash_init(void); + +#endif // MICROPY_INCLUDED_ATMEL_SAMD_SPI_FLASH_H From f20d5723aab3e6b5eea316235767c5e28a2dac2d Mon Sep 17 00:00:00 2001 From: Scott Shawcroft Date: Fri, 16 Feb 2018 17:22:33 -0800 Subject: [PATCH 059/135] Reorganize things. Reading jdec works. --- ports/atmel-samd/Makefile | 4 +- .../boards/metro_m4_express/mpconfigboard.h | 6 +- .../external_flash/common_commands.h | 40 +++++ .../devices/AT25DF081A.h} | 0 .../devices/GD25Q16C.h} | 0 .../devices/S25FL064L.h} | 0 .../external_flash/devices/S25FL116K.h | 54 +++++++ .../devices/S25FL216K.h} | 0 .../devices/W25Q32BV.h} | 0 .../devices/W25Q80DV.h} | 0 .../{ => external_flash}/external_flash.c | 34 ++-- .../{ => external_flash}/external_flash.h | 0 ports/atmel-samd/external_flash/qspi_flash.c | 153 ++++++++++++++++++ .../{ => external_flash}/spi_flash.c | 0 .../{ => external_flash}/spi_flash_api.h | 4 +- ports/atmel-samd/qspi_flash.c | 74 --------- 16 files changed, 265 insertions(+), 104 deletions(-) create mode 100644 ports/atmel-samd/external_flash/common_commands.h rename ports/atmel-samd/{boards/flash_AT25DF081A.h => external_flash/devices/AT25DF081A.h} (100%) rename ports/atmel-samd/{boards/flash_GD25Q16C.h => external_flash/devices/GD25Q16C.h} (100%) rename ports/atmel-samd/{boards/flash_S25FL064L.h => external_flash/devices/S25FL064L.h} (100%) create mode 100644 ports/atmel-samd/external_flash/devices/S25FL116K.h rename ports/atmel-samd/{boards/flash_S25FL216K.h => external_flash/devices/S25FL216K.h} (100%) rename ports/atmel-samd/{boards/flash_W25Q32BV.h => external_flash/devices/W25Q32BV.h} (100%) rename ports/atmel-samd/{boards/flash_W25Q80DV.h => external_flash/devices/W25Q80DV.h} (100%) rename ports/atmel-samd/{ => external_flash}/external_flash.c (95%) rename ports/atmel-samd/{ => external_flash}/external_flash.h (100%) create mode 100644 ports/atmel-samd/external_flash/qspi_flash.c rename ports/atmel-samd/{ => external_flash}/spi_flash.c (100%) rename ports/atmel-samd/{ => external_flash}/spi_flash_api.h (89%) delete mode 100644 ports/atmel-samd/qspi_flash.c diff --git a/ports/atmel-samd/Makefile b/ports/atmel-samd/Makefile index abf5bf12ef..a5d1fd7c0e 100644 --- a/ports/atmel-samd/Makefile +++ b/ports/atmel-samd/Makefile @@ -252,10 +252,10 @@ ifeq ($(INTERNAL_FLASH_FILESYSTEM),1) SRC_C += internal_flash.c endif ifeq ($(SPI_FLASH_FILESYSTEM),1) -SRC_C += external_flash.c spi_flash.c +SRC_C += external_flash/external_flash.c external_flash/spi_flash.c endif ifeq ($(QSPI_FLASH_FILESYSTEM),1) -SRC_C += external_flash.c qspi_flash.c +SRC_C += external_flash/external_flash.c external_flash/qspi_flash.c endif SRC_COMMON_HAL = \ diff --git a/ports/atmel-samd/boards/metro_m4_express/mpconfigboard.h b/ports/atmel-samd/boards/metro_m4_express/mpconfigboard.h index fdf98625ef..6ced2ca706 100644 --- a/ports/atmel-samd/boards/metro_m4_express/mpconfigboard.h +++ b/ports/atmel-samd/boards/metro_m4_express/mpconfigboard.h @@ -40,7 +40,7 @@ #define AUTORESET_DELAY_MS 500 -#include "external_flash.h" +#include "external_flash/external_flash.h" // If you change this, then make sure to update the linker scripts as well to // make sure you don't overwrite code @@ -49,5 +49,5 @@ #define BOARD_FLASH_SIZE (FLASH_SIZE - 0x4000 - CIRCUITPY_INTERNAL_NVM_SIZE) -#include "flash_S25FL216K.h" -#include "flash_GD25Q16C.h" +#include "external_flash/devices/S25FL216K.h" +#include "external_flash/devices/GD25Q16C.h" diff --git a/ports/atmel-samd/external_flash/common_commands.h b/ports/atmel-samd/external_flash/common_commands.h new file mode 100644 index 0000000000..ca1e877823 --- /dev/null +++ b/ports/atmel-samd/external_flash/common_commands.h @@ -0,0 +1,40 @@ +/* + * This file is part of the MicroPython project, http://micropython.org/ + * + * The MIT License (MIT) + * + * Copyright (c) 2013, 2014 Damien P. George + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ +#ifndef MICROPY_INCLUDED_ATMEL_SAMD_EXTERNAL_FLASH_COMMON_COMMANDS_H +#define MICROPY_INCLUDED_ATMEL_SAMD_EXTERNAL_FLASH_COMMON_COMMANDS_H + +#define CMD_READ_JEDEC_ID 0x9f +#define CMD_READ_DATA 0x03 +#define CMD_SECTOR_ERASE 0x20 +// #define CMD_SECTOR_ERASE CMD_READ_JEDEC_ID +#define CMD_DISABLE_WRITE 0x04 +#define CMD_ENABLE_WRITE 0x06 +#define CMD_PAGE_PROGRAM 0x02 +// #define CMD_PAGE_PROGRAM CMD_READ_JEDEC_ID +#define CMD_READ_STATUS 0x05 +#define CMD_WRITE_STATUS_BYTE1 0x01 + +#endif // MICROPY_INCLUDED_ATMEL_SAMD_EXTERNAL_FLASH_COMMON_COMMANDS_H diff --git a/ports/atmel-samd/boards/flash_AT25DF081A.h b/ports/atmel-samd/external_flash/devices/AT25DF081A.h similarity index 100% rename from ports/atmel-samd/boards/flash_AT25DF081A.h rename to ports/atmel-samd/external_flash/devices/AT25DF081A.h diff --git a/ports/atmel-samd/boards/flash_GD25Q16C.h b/ports/atmel-samd/external_flash/devices/GD25Q16C.h similarity index 100% rename from ports/atmel-samd/boards/flash_GD25Q16C.h rename to ports/atmel-samd/external_flash/devices/GD25Q16C.h diff --git a/ports/atmel-samd/boards/flash_S25FL064L.h b/ports/atmel-samd/external_flash/devices/S25FL064L.h similarity index 100% rename from ports/atmel-samd/boards/flash_S25FL064L.h rename to ports/atmel-samd/external_flash/devices/S25FL064L.h diff --git a/ports/atmel-samd/external_flash/devices/S25FL116K.h b/ports/atmel-samd/external_flash/devices/S25FL116K.h new file mode 100644 index 0000000000..4928bd04e2 --- /dev/null +++ b/ports/atmel-samd/external_flash/devices/S25FL116K.h @@ -0,0 +1,54 @@ +/* + * This file is part of the MicroPython project, http://micropython.org/ + * + * The MIT License (MIT) + * + * Copyright (c) 2017 Scott Shawcroft for Adafruit Industries + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +#ifndef MICROPY_INCLUDED_ATMEL_SAMD_BOARD_FLASH_S25FL116K_H +#define MICROPY_INCLUDED_ATMEL_SAMD_BOARD_FLASH_S25FL116K_H + +// Settings for the Cypress (was Spansion) S25FL116K 2MiB SPI flash. +// Datasheet: http://www.cypress.com/file/196886/download + +// The total flash size in bytes. +#define SPI_FLASH_TOTAL_SIZE (1 << 21) // 2 MiB + +// The size of the smallest erase unit thats erased with command 0x20. +#define SPI_FLASH_ERASE_SIZE (1 << 12) // 4 KiB + +// The size of a page that is programmed with page program command 0x02. +#define SPI_FLASH_PAGE_SIZE (256) // 256 bytes + +// These are the first three response bytes to the JEDEC ID command 0x9f that is +// used to confirm we're talking to the flash we expect. +#ifndef SPI_FLASH_JEDEC_MANUFACTURER +#define SPI_FLASH_JEDEC_MANUFACTURER 0x01 +#define SPI_FLASH_SECTOR_PROTECTION false +#else +#define SPI_FLASH_JEDEC_MANUFACTURER_2 0x01 +#define SPI_FLASH_SECTOR_PROTECTION_2 false +#endif +#define SPI_FLASH_JEDEC_MEMORY_TYPE 0x40 +#define SPI_FLASH_JEDEC_CAPACITY 0x15 + +#endif // MICROPY_INCLUDED_ATMEL_SAMD_BOARD_FLASH_S25FL216K_H diff --git a/ports/atmel-samd/boards/flash_S25FL216K.h b/ports/atmel-samd/external_flash/devices/S25FL216K.h similarity index 100% rename from ports/atmel-samd/boards/flash_S25FL216K.h rename to ports/atmel-samd/external_flash/devices/S25FL216K.h diff --git a/ports/atmel-samd/boards/flash_W25Q32BV.h b/ports/atmel-samd/external_flash/devices/W25Q32BV.h similarity index 100% rename from ports/atmel-samd/boards/flash_W25Q32BV.h rename to ports/atmel-samd/external_flash/devices/W25Q32BV.h diff --git a/ports/atmel-samd/boards/flash_W25Q80DV.h b/ports/atmel-samd/external_flash/devices/W25Q80DV.h similarity index 100% rename from ports/atmel-samd/boards/flash_W25Q80DV.h rename to ports/atmel-samd/external_flash/devices/W25Q80DV.h diff --git a/ports/atmel-samd/external_flash.c b/ports/atmel-samd/external_flash/external_flash.c similarity index 95% rename from ports/atmel-samd/external_flash.c rename to ports/atmel-samd/external_flash/external_flash.c index 45406462d6..c046047e4f 100644 --- a/ports/atmel-samd/external_flash.c +++ b/ports/atmel-samd/external_flash/external_flash.c @@ -28,6 +28,8 @@ #include #include +#include "external_flash/spi_flash_api.h" +#include "external_flash/common_commands.h" #include "extmod/vfs.h" #include "extmod/vfs_fat.h" #include "py/misc.h" @@ -35,7 +37,6 @@ #include "py/runtime.h" #include "lib/oofatfs/ff.h" #include "peripherals.h" -#include "spi_flash_api.h" #include "supervisor/shared/rgb_led_status.h" //#include "shared_dma.h" @@ -47,17 +48,6 @@ #define NO_SECTOR_LOADED 0xFFFFFFFF -#define CMD_READ_JEDEC_ID 0x9f -#define CMD_READ_DATA 0x03 -#define CMD_SECTOR_ERASE 0x20 -// #define CMD_SECTOR_ERASE CMD_READ_JEDEC_ID -#define CMD_DISABLE_WRITE 0x04 -#define CMD_ENABLE_WRITE 0x06 -#define CMD_PAGE_PROGRAM 0x02 -// #define CMD_PAGE_PROGRAM CMD_READ_JEDEC_ID -#define CMD_READ_STATUS 0x05 -#define CMD_WRITE_STATUS_BYTE1 0x01 - static bool spi_flash_is_initialised = false; struct spi_m_sync_descriptor spi_flash_desc; @@ -74,20 +64,18 @@ static uint32_t dirty_mask; // Wait until both the write enable and write in progress bits have cleared. static bool wait_for_flash_ready(void) { - uint8_t read_status_request[2] = {CMD_READ_STATUS, 0x00}; - uint8_t read_status_response[2] = {0x00, 0x00}; + uint8_t read_status_response[1] = {0x00}; bool ok = true; // Both the write enable and write in progress bits should be low. do { - ok = spi_flash_command(read_status_request, read_status_response, 2); - } while (ok && (read_status_response[1] & 0x3) != 0); + ok = spi_flash_read_command(CMD_READ_STATUS, read_status_response, 1); + } while (ok && (read_status_response[0] & 0x3) != 0); return ok; } // Turn on the write enable bit so we can program and erase the flash. static bool write_enable(void) { - uint8_t enable_write_request[1] = {CMD_ENABLE_WRITE}; - return spi_flash_command(enable_write_request, 0, 1); + return spi_flash_command(CMD_ENABLE_WRITE); } // Read data_length's worth of bytes starting at address into data. @@ -207,9 +195,8 @@ void external_flash_init(void) { gpio_set_pin_level(MICROPY_HW_LED_MSC, false); #endif - uint8_t jedec_id_request[4] = {CMD_READ_JEDEC_ID, 0x00, 0x00, 0x00}; uint8_t jedec_id_response[4] = {0x00, 0x00, 0x00, 0x00}; - spi_flash_command(jedec_id_request, jedec_id_response, 4); + spi_flash_read_command(CMD_READ_JEDEC_ID, jedec_id_response, 4); uint8_t manufacturer = jedec_id_response[1]; if ((jedec_id_response[1] == SPI_FLASH_JEDEC_MANUFACTURER @@ -234,13 +221,12 @@ void external_flash_init(void) { write_enable(); // Turn off sector protection - uint8_t disable_protect_request[2] = {CMD_WRITE_STATUS_BYTE1, 0x00}; - spi_flash_command(disable_protect_request, NULL, 2); + uint8_t data[1] = {0x00}; + spi_flash_write_command(CMD_WRITE_STATUS_BYTE1, data, 1); } // Turn off writes in case this is a microcontroller only reset. - uint8_t disable_write_request[1] = {CMD_DISABLE_WRITE}; - spi_flash_command(disable_write_request, NULL, 1); + spi_flash_command(CMD_DISABLE_WRITE); wait_for_flash_ready(); diff --git a/ports/atmel-samd/external_flash.h b/ports/atmel-samd/external_flash/external_flash.h similarity index 100% rename from ports/atmel-samd/external_flash.h rename to ports/atmel-samd/external_flash/external_flash.h diff --git a/ports/atmel-samd/external_flash/qspi_flash.c b/ports/atmel-samd/external_flash/qspi_flash.c new file mode 100644 index 0000000000..42d4e5a420 --- /dev/null +++ b/ports/atmel-samd/external_flash/qspi_flash.c @@ -0,0 +1,153 @@ +/* + * This file is part of the MicroPython project, http://micropython.org/ + * + * The MIT License (MIT) + * + * Copyright (c) 2016, 2017 Scott Shawcroft for Adafruit Industries + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +#include "spi_flash_api.h" + +#include +#include + +#include "external_flash/common_commands.h" + +#include "atmel_start_pins.h" +#include "hal_gpio.h" + +bool spi_flash_command(uint8_t command) { + QSPI->INSTRCTRL.bit.INSTR = command; + + QSPI->INSTRFRAME.reg = QSPI_INSTRFRAME_WIDTH_SINGLE_BIT_SPI | + QSPI_INSTRFRAME_ADDRLEN_24BITS | + QSPI_INSTRFRAME_TFRTYPE_READ | + QSPI_INSTRFRAME_INSTREN; + + QSPI->CTRLA.reg = QSPI_CTRLA_ENABLE | QSPI_CTRLA_LASTXFER; + + while( !QSPI->INTFLAG.bit.INSTREND ); + + QSPI->INTFLAG.reg = QSPI_INTFLAG_INSTREND; + + return true; +} + +bool spi_flash_read_command(uint8_t command, uint8_t* response, uint32_t length) { + QSPI->INSTRCTRL.bit.INSTR = command; + + QSPI->INSTRFRAME.reg = QSPI_INSTRFRAME_WIDTH_SINGLE_BIT_SPI | + QSPI_INSTRFRAME_ADDRLEN_24BITS | + QSPI_INSTRFRAME_TFRTYPE_READ | + QSPI_INSTRFRAME_INSTREN | + QSPI_INSTRFRAME_DATAEN; + + memcpy(response, (uint8_t *) QSPI_AHB, length); + + QSPI->CTRLA.reg = QSPI_CTRLA_ENABLE | QSPI_CTRLA_LASTXFER; + + while( !QSPI->INTFLAG.bit.INSTREND ); + + QSPI->INTFLAG.reg = QSPI_INTFLAG_INSTREND; + + return true; +} + +bool spi_flash_write_command(uint8_t command, uint8_t* data, uint32_t length) { + QSPI->INSTRCTRL.bit.INSTR = command; + + QSPI->INSTRFRAME.reg = QSPI_INSTRFRAME_WIDTH_SINGLE_BIT_SPI | + QSPI_INSTRFRAME_ADDRLEN_24BITS | + QSPI_INSTRFRAME_TFRTYPE_WRITE | + QSPI_INSTRFRAME_INSTREN; + + if (data != NULL) { + QSPI->INSTRFRAME.bit.DATAEN = true; + + memcpy((uint8_t *) QSPI_AHB, data, length); + } + + QSPI->CTRLA.reg = QSPI_CTRLA_ENABLE | QSPI_CTRLA_LASTXFER; + + while( !QSPI->INTFLAG.bit.INSTREND ); + + QSPI->INTFLAG.reg = QSPI_INTFLAG_INSTREND; + + return true; +} + +bool spi_flash_sector_command(uint8_t command, uint32_t address) { +// QSPI->INSTRCTRL.bit.INSTR = command; +// QSPI->INSTRADDR.reg = addr; +// uint32_t iframe = QSPI->INSTRFRAME.reg; +// +// iframe = QSPI_INSTRFRAME_WIDTH(instr->ioFormat) | instr->options | +// QSPI_INSTRFRAME_OPTCODELEN(instr->opcodeLen) | (instr->addrLen << QSPI_INSTRFRAME_ADDRLEN_Pos) | +// ( instr->continuousRead << QSPI_INSTRFRAME_CRMODE_Pos) | QSPI_INSTRFRAME_TFRTYPE(instr->type) | QSPI_INSTRFRAME_DUMMYLEN(instr->dummylen); +// +// QSPI->INSTRFRAME.reg = iframe; + return true; +} + +bool spi_flash_write_data(uint32_t address, uint8_t* data, uint32_t data_length) { + return true; +} + +bool spi_flash_read_data(uint32_t address, uint8_t* data, uint32_t data_length) { + return true; +} + + +void spi_flash_init(void) { + MCLK->APBCMASK.bit.QSPI_ = true; + MCLK->AHBMASK.bit.QSPI_ = true; + MCLK->AHBMASK.bit.QSPI_2X_ = false; // Only true if we are doing DDR. + + QSPI->CTRLA.reg = QSPI_CTRLA_SWRST; + // We don't need to wait because we're running as fast as the CPU. + + QSPI->BAUD.bit.BAUD = 10; + QSPI->CTRLB.reg = QSPI_CTRLB_MODE_MEMORY | + QSPI_CTRLB_DATALEN_8BITS | + QSPI_CTRLB_CSMODE_LASTXFER; + + QSPI->CTRLA.bit.ENABLE = 1; + + // The QSPI is only connected to one set of pins in the SAMD51 so we can hard code it. + uint32_t pins[6] = {PIN_PA08, PIN_PA09, PIN_PA10, PIN_PA11, PIN_PB10, PIN_PB11}; + for (uint8_t i = 0; i < 6; i++) { + gpio_set_pin_direction(pins[i], GPIO_DIRECTION_IN); + gpio_set_pin_pull_mode(pins[i], GPIO_PULL_OFF); + gpio_set_pin_function(pins[i], GPIO_PIN_FUNCTION_H); + } + + // Verify that QSPI mode is enabled. + uint8_t status; + spi_flash_read_command(0x35, &status, 1); + + if ((status & 0x2) == 0) { + uint8_t full_status[3] = { 0, status | 0x2, 0x70}; + spi_flash_command(CMD_ENABLE_WRITE); + spi_flash_write_command(0x01, full_status, 3); + } + + asm("nop"); +} diff --git a/ports/atmel-samd/spi_flash.c b/ports/atmel-samd/external_flash/spi_flash.c similarity index 100% rename from ports/atmel-samd/spi_flash.c rename to ports/atmel-samd/external_flash/spi_flash.c diff --git a/ports/atmel-samd/spi_flash_api.h b/ports/atmel-samd/external_flash/spi_flash_api.h similarity index 89% rename from ports/atmel-samd/spi_flash_api.h rename to ports/atmel-samd/external_flash/spi_flash_api.h index d758faa774..b858ff0ea0 100644 --- a/ports/atmel-samd/spi_flash_api.h +++ b/ports/atmel-samd/external_flash/spi_flash_api.h @@ -31,7 +31,9 @@ // This API is implemented for both normal SPI peripherals and QSPI peripherals. -bool spi_flash_command(uint8_t* request, uint8_t* response, uint32_t length); +bool spi_flash_command(uint8_t command); +bool spi_flash_read_command(uint8_t command, uint8_t* response, uint32_t length); +bool spi_flash_write_command(uint8_t command, uint8_t* data, uint32_t length); bool spi_flash_sector_command(uint8_t command, uint32_t address); bool spi_flash_write_data(uint32_t address, uint8_t* data, uint32_t data_length); bool spi_flash_read_data(uint32_t address, uint8_t* data, uint32_t data_length); diff --git a/ports/atmel-samd/qspi_flash.c b/ports/atmel-samd/qspi_flash.c deleted file mode 100644 index 3fa53a8989..0000000000 --- a/ports/atmel-samd/qspi_flash.c +++ /dev/null @@ -1,74 +0,0 @@ -/* - * This file is part of the MicroPython project, http://micropython.org/ - * - * The MIT License (MIT) - * - * Copyright (c) 2016, 2017 Scott Shawcroft for Adafruit Industries - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ - -#include "spi_flash_api.h" - -#include - -#include "atmel_start_pins.h" -#include "hal_gpio.h" - -bool spi_flash_command(uint8_t* request, uint8_t* response, uint32_t length) { - return true; -} - -bool spi_flash_sector_command(uint8_t command, uint32_t address) { - return true; -} - -bool spi_flash_write_data(uint32_t address, uint8_t* data, uint32_t data_length) { - return true; -} - -bool spi_flash_read_data(uint32_t address, uint8_t* data, uint32_t data_length) { - return true; -} - - -void spi_flash_init(void) { - MCLK->APBCMASK.bit.QSPI_ = true; - MCLK->AHBMASK.bit.QSPI_ = true; - MCLK->AHBMASK.bit.QSPI_2X_ = false; // Only true if we are doing DDR. - - QSPI->CTRLA.reg = QSPI_CTRLA_SWRST; - // We don't need to wait because we're running as fast as the CPU. - - QSPI->BAUD.bit.BAUD = 2; - QSPI->CTRLB.reg = QSPI_CTRLB_MODE_MEMORY | - QSPI_CTRLB_CSMODE_NORELOAD | - QSPI_CTRLB_DATALEN_8BITS | - QSPI_CTRLB_CSMODE_LASTXFER; - - QSPI->CTRLA.bit.ENABLE = 1; - - // The QSPI is only connected to one set of pins in the SAMD51 so we can hard code it. - uint32_t pins[6] = {PIN_PA08, PIN_PA09, PIN_PA10, PIN_PA11, PIN_PB10, PIN_PB11}; - for (uint8_t i = 0; i < 6; i++) { - gpio_set_pin_direction(pins[i], GPIO_DIRECTION_IN); - gpio_set_pin_pull_mode(pins[i], GPIO_PULL_OFF); - gpio_set_pin_function(pins[i], GPIO_PIN_FUNCTION_H); - } -} From 15f626be5869a2dc5d8bc53ad44cc678bb5462d2 Mon Sep 17 00:00:00 2001 From: Scott Shawcroft Date: Sat, 17 Feb 2018 00:29:03 -0800 Subject: [PATCH 060/135] m4 qspi works. m0 compiles --- .../circuitplayground_express/mpconfigboard.h | 6 +- .../boards/feather_m0_express/mpconfigboard.h | 6 +- .../feather_m0_supersized/mpconfigboard.h | 4 +- .../boards/itsybitsy_m0/mpconfigboard.h | 8 +-- .../boards/metro_m0_express/mpconfigboard.h | 6 +- .../boards/metro_m4_express/mpconfigboard.h | 4 +- .../trinket_m0_haxpress/mpconfigboard.h | 4 +- .../atmel-samd/boards/ugame10/mpconfigboard.h | 6 +- .../external_flash/common_commands.h | 1 + .../external_flash/external_flash.c | 15 +++-- ports/atmel-samd/external_flash/qspi_flash.c | 65 +++++++++++++++---- ports/atmel-samd/external_flash/spi_flash.c | 58 ++++++++++------- 12 files changed, 121 insertions(+), 62 deletions(-) diff --git a/ports/atmel-samd/boards/circuitplayground_express/mpconfigboard.h b/ports/atmel-samd/boards/circuitplayground_express/mpconfigboard.h index 2b8fed6b8b..cc09d7f790 100644 --- a/ports/atmel-samd/boards/circuitplayground_express/mpconfigboard.h +++ b/ports/atmel-samd/boards/circuitplayground_express/mpconfigboard.h @@ -38,7 +38,7 @@ #define SPEAKER_ENABLE_PIN (&pin_PA30) -#include "external_flash.h" +#include "external_flash/external_flash.h" // If you change this, then make sure to update the linker scripts as well to // make sure you don't overwrite code. @@ -47,8 +47,8 @@ #define BOARD_FLASH_SIZE (0x00040000 - 0x2000 - CIRCUITPY_INTERNAL_NVM_SIZE) -#include "flash_S25FL216K.h" -#include "flash_GD25Q16C.h" +#include "external_flash/devices/S25FL216K.h" +#include "external_flash/devices/GD25Q16C.h" #define CALIBRATE_CRYSTALLESS 1 diff --git a/ports/atmel-samd/boards/feather_m0_express/mpconfigboard.h b/ports/atmel-samd/boards/feather_m0_express/mpconfigboard.h index d0e70d954b..378b0891ad 100644 --- a/ports/atmel-samd/boards/feather_m0_express/mpconfigboard.h +++ b/ports/atmel-samd/boards/feather_m0_express/mpconfigboard.h @@ -31,7 +31,7 @@ #define MICROPY_PORT_B ( 0 ) #define MICROPY_PORT_C ( 0 ) -#include "external_flash.h" +#include "external_flash/external_flash.h" // If you change this, then make sure to update the linker scripts as well to // make sure you don't overwrite code. @@ -40,5 +40,5 @@ #define BOARD_FLASH_SIZE (0x00040000 - 0x2000 - CIRCUITPY_INTERNAL_NVM_SIZE) -#include "flash_S25FL216K.h" -#include "flash_GD25Q16C.h" +#include "external_flash/devices/S25FL216K.h" +#include "external_flash/devices/GD25Q16C.h" diff --git a/ports/atmel-samd/boards/feather_m0_supersized/mpconfigboard.h b/ports/atmel-samd/boards/feather_m0_supersized/mpconfigboard.h index 4f9b177bec..b5ed682962 100644 --- a/ports/atmel-samd/boards/feather_m0_supersized/mpconfigboard.h +++ b/ports/atmel-samd/boards/feather_m0_supersized/mpconfigboard.h @@ -33,7 +33,7 @@ #define MICROPY_PORT_B ( 0 ) #define MICROPY_PORT_C ( 0 ) -#include "external_flash.h" +#include "external_flash/external_flash.h" // If you change this, then make sure to update the linker scripts as well to // make sure you don't overwrite code. @@ -42,4 +42,4 @@ #define BOARD_FLASH_SIZE (0x00040000 - 0x2000 - CIRCUITPY_INTERNAL_NVM_SIZE) -#include "flash_S25FL064L.h" +#include "external_flash/devices/S25FL064L.h" diff --git a/ports/atmel-samd/boards/itsybitsy_m0/mpconfigboard.h b/ports/atmel-samd/boards/itsybitsy_m0/mpconfigboard.h index 116775886c..15a9922211 100644 --- a/ports/atmel-samd/boards/itsybitsy_m0/mpconfigboard.h +++ b/ports/atmel-samd/boards/itsybitsy_m0/mpconfigboard.h @@ -33,7 +33,7 @@ #define MICROPY_PORT_B (PORT_PB22 | PORT_PB23 | PORT_PB03 ) #define MICROPY_PORT_C (0) -#include "external_flash.h" +#include "external_flash/external_flash.h" // If you change this, then make sure to update the linker scripts as well to // make sure you don't overwrite code. @@ -41,6 +41,6 @@ #define CIRCUITPY_INTERNAL_NVM_SIZE 0 #define BOARD_FLASH_SIZE (0x00040000 - 0x2000 - CIRCUITPY_INTERNAL_NVM_SIZE) -//#include "flash_S25FL216K.h" -#include "flash_W25Q80DV.h" -//#include "flash_GD25Q16C.h" +//#include "external_flash/devices/S25FL216K.h" +#include "external_flash/devices/W25Q80DV.h" +//#include "external_flash/devices/GD25Q16C.h" diff --git a/ports/atmel-samd/boards/metro_m0_express/mpconfigboard.h b/ports/atmel-samd/boards/metro_m0_express/mpconfigboard.h index be1a1a57e0..70e830620d 100644 --- a/ports/atmel-samd/boards/metro_m0_express/mpconfigboard.h +++ b/ports/atmel-samd/boards/metro_m0_express/mpconfigboard.h @@ -34,7 +34,7 @@ #define MICROPY_PORT_B (PORT_PB03 | PORT_PB22 | PORT_PB23) #define MICROPY_PORT_C (0) -#include "external_flash.h" +#include "external_flash/external_flash.h" // If you change this, then make sure to update the linker scripts as well to // make sure you don't overwrite code. @@ -43,5 +43,5 @@ #define BOARD_FLASH_SIZE (0x00040000 - 0x2000 - CIRCUITPY_INTERNAL_NVM_SIZE) -#include "flash_S25FL216K.h" -#include "flash_GD25Q16C.h" +#include "external_flash/devices/S25FL216K.h" +#include "external_flash/devices/GD25Q16C.h" diff --git a/ports/atmel-samd/boards/metro_m4_express/mpconfigboard.h b/ports/atmel-samd/boards/metro_m4_express/mpconfigboard.h index 6ced2ca706..b8f14e6253 100644 --- a/ports/atmel-samd/boards/metro_m4_express/mpconfigboard.h +++ b/ports/atmel-samd/boards/metro_m4_express/mpconfigboard.h @@ -33,8 +33,8 @@ #define SPI_FLASH_DIPO 3 // same as MISO pad // These are pins not to reset. -#define MICROPY_PORT_A (PORT_PA27) -#define MICROPY_PORT_B (PORT_PB06 | PORT_PB08 | PORT_PB09 | PORT_PB10 | PORT_PB11 | PORT_PB17) +#define MICROPY_PORT_A (PORT_PA08 | PORT_PA09 | PORT_PA10 | PORT_PA11 | PORT_PA27) +#define MICROPY_PORT_B (PORT_PB10 | PORT_PB11 | PORT_PB17) #define MICROPY_PORT_C (0) #define MICROPY_PORT_D (0) diff --git a/ports/atmel-samd/boards/trinket_m0_haxpress/mpconfigboard.h b/ports/atmel-samd/boards/trinket_m0_haxpress/mpconfigboard.h index 5dcea945ac..62bca9a413 100644 --- a/ports/atmel-samd/boards/trinket_m0_haxpress/mpconfigboard.h +++ b/ports/atmel-samd/boards/trinket_m0_haxpress/mpconfigboard.h @@ -40,7 +40,7 @@ #define CALIBRATE_CRYSTALLESS 1 -#include "external_flash.h" +#include "external_flash/external_flash.h" // If you change this, then make sure to update the linker scripts as well to // make sure you don't overwrite code. @@ -48,4 +48,4 @@ #define CIRCUITPY_INTERNAL_NVM_SIZE 0 #define BOARD_FLASH_SIZE (0x00040000 - 0x2000 - CIRCUITPY_INTERNAL_NVM_SIZE) -#include "flash_W25Q32BV.h" +#include "external_flash/devices/W25Q32BV.h" diff --git a/ports/atmel-samd/boards/ugame10/mpconfigboard.h b/ports/atmel-samd/boards/ugame10/mpconfigboard.h index 3bec61ff96..d0d9296a40 100644 --- a/ports/atmel-samd/boards/ugame10/mpconfigboard.h +++ b/ports/atmel-samd/boards/ugame10/mpconfigboard.h @@ -33,7 +33,7 @@ #define CALIBRATE_CRYSTALLESS 1 -#include "external_flash.h" +#include "external_flash/external_flash.h" // If you change this, then make sure to update the linker scripts as well to // make sure you don't overwrite code. @@ -41,5 +41,5 @@ #define CIRCUITPY_INTERNAL_NVM_SIZE 0 #define BOARD_FLASH_SIZE (0x00040000 - 0x2000 - CIRCUITPY_INTERNAL_NVM_SIZE) -//#include "flash_W25Q32BV.h" -#include "flash_S25FL216K.h" +//#include "external_flash/devices/W25Q32BV.h" +#include "external_flash/devices/S25FL216K.h" diff --git a/ports/atmel-samd/external_flash/common_commands.h b/ports/atmel-samd/external_flash/common_commands.h index ca1e877823..fc05e70de7 100644 --- a/ports/atmel-samd/external_flash/common_commands.h +++ b/ports/atmel-samd/external_flash/common_commands.h @@ -36,5 +36,6 @@ // #define CMD_PAGE_PROGRAM CMD_READ_JEDEC_ID #define CMD_READ_STATUS 0x05 #define CMD_WRITE_STATUS_BYTE1 0x01 +#define CMD_QUAD_READ 0x6b #endif // MICROPY_INCLUDED_ATMEL_SAMD_EXTERNAL_FLASH_COMMON_COMMANDS_H diff --git a/ports/atmel-samd/external_flash/external_flash.c b/ports/atmel-samd/external_flash/external_flash.c index c046047e4f..48872adda7 100644 --- a/ports/atmel-samd/external_flash/external_flash.c +++ b/ports/atmel-samd/external_flash/external_flash.c @@ -195,19 +195,20 @@ void external_flash_init(void) { gpio_set_pin_level(MICROPY_HW_LED_MSC, false); #endif - uint8_t jedec_id_response[4] = {0x00, 0x00, 0x00, 0x00}; - spi_flash_read_command(CMD_READ_JEDEC_ID, jedec_id_response, 4); + uint8_t jedec_id_response[3] = {0x00, 0x00, 0x00}; + spi_flash_read_command(CMD_READ_JEDEC_ID, jedec_id_response, 3); - uint8_t manufacturer = jedec_id_response[1]; - if ((jedec_id_response[1] == SPI_FLASH_JEDEC_MANUFACTURER + uint8_t manufacturer = jedec_id_response[0]; + if ((jedec_id_response[0] == SPI_FLASH_JEDEC_MANUFACTURER #ifdef SPI_FLASH_JEDEC_MANUFACTURER_2 - || jedec_id_response[1] == SPI_FLASH_JEDEC_MANUFACTURER_2 + || jedec_id_response[0] == SPI_FLASH_JEDEC_MANUFACTURER_2 #endif ) && - jedec_id_response[2] == SPI_FLASH_JEDEC_MEMORY_TYPE && - jedec_id_response[3] == SPI_FLASH_JEDEC_CAPACITY) { + jedec_id_response[1] == SPI_FLASH_JEDEC_MEMORY_TYPE && + jedec_id_response[2] == SPI_FLASH_JEDEC_CAPACITY) { spi_flash_is_initialised = true; } else { + asm("bkpt"); // Unknown flash chip! spi_flash_is_initialised = false; return; diff --git a/ports/atmel-samd/external_flash/qspi_flash.c b/ports/atmel-samd/external_flash/qspi_flash.c index 42d4e5a420..d9dc3bf01e 100644 --- a/ports/atmel-samd/external_flash/qspi_flash.c +++ b/ports/atmel-samd/external_flash/qspi_flash.c @@ -95,23 +95,66 @@ bool spi_flash_write_command(uint8_t command, uint8_t* data, uint32_t length) { } bool spi_flash_sector_command(uint8_t command, uint32_t address) { -// QSPI->INSTRCTRL.bit.INSTR = command; -// QSPI->INSTRADDR.reg = addr; -// uint32_t iframe = QSPI->INSTRFRAME.reg; -// -// iframe = QSPI_INSTRFRAME_WIDTH(instr->ioFormat) | instr->options | -// QSPI_INSTRFRAME_OPTCODELEN(instr->opcodeLen) | (instr->addrLen << QSPI_INSTRFRAME_ADDRLEN_Pos) | -// ( instr->continuousRead << QSPI_INSTRFRAME_CRMODE_Pos) | QSPI_INSTRFRAME_TFRTYPE(instr->type) | QSPI_INSTRFRAME_DUMMYLEN(instr->dummylen); -// -// QSPI->INSTRFRAME.reg = iframe; + QSPI->INSTRCTRL.bit.INSTR = command; + QSPI->INSTRADDR.bit.ADDR = address; + + QSPI->INSTRFRAME.reg = QSPI_INSTRFRAME_WIDTH_SINGLE_BIT_SPI | + QSPI_INSTRFRAME_ADDRLEN_24BITS | + QSPI_INSTRFRAME_TFRTYPE_WRITE | + QSPI_INSTRFRAME_INSTREN | + QSPI_INSTRFRAME_ADDREN; + + QSPI->CTRLA.reg = QSPI_CTRLA_ENABLE | QSPI_CTRLA_LASTXFER; + + while( !QSPI->INTFLAG.bit.INSTREND ); + + QSPI->INTFLAG.reg = QSPI_INTFLAG_INSTREND; + return true; } -bool spi_flash_write_data(uint32_t address, uint8_t* data, uint32_t data_length) { +bool spi_flash_write_data(uint32_t address, uint8_t* data, uint32_t length) { + QSPI->INSTRCTRL.bit.INSTR = CMD_PAGE_PROGRAM; + uint32_t mode = QSPI_INSTRFRAME_WIDTH_SINGLE_BIT_SPI; + + QSPI->INSTRFRAME.reg = mode | + QSPI_INSTRFRAME_ADDRLEN_24BITS | + QSPI_INSTRFRAME_TFRTYPE_WRITEMEMORY | + QSPI_INSTRFRAME_INSTREN | + QSPI_INSTRFRAME_ADDREN | + QSPI_INSTRFRAME_DATAEN; + + memcpy(((uint8_t *) QSPI_AHB) + address, data, length); + + QSPI->CTRLA.reg = QSPI_CTRLA_ENABLE | QSPI_CTRLA_LASTXFER; + + while( !QSPI->INTFLAG.bit.INSTREND ); + + QSPI->INTFLAG.reg = QSPI_INTFLAG_INSTREND; + return true; } -bool spi_flash_read_data(uint32_t address, uint8_t* data, uint32_t data_length) { +bool spi_flash_read_data(uint32_t address, uint8_t* data, uint32_t length) { + QSPI->INSTRCTRL.bit.INSTR = CMD_QUAD_READ; + uint32_t mode = QSPI_INSTRFRAME_WIDTH_QUAD_OUTPUT; + + QSPI->INSTRFRAME.reg = mode | + QSPI_INSTRFRAME_ADDRLEN_24BITS | + QSPI_INSTRFRAME_TFRTYPE_READMEMORY | + QSPI_INSTRFRAME_INSTREN | + QSPI_INSTRFRAME_ADDREN | + QSPI_INSTRFRAME_DATAEN | + QSPI_INSTRFRAME_DUMMYLEN(8); + + memcpy(data, ((uint8_t *) QSPI_AHB) + address, length); + + QSPI->CTRLA.reg = QSPI_CTRLA_ENABLE | QSPI_CTRLA_LASTXFER; + + while( !QSPI->INTFLAG.bit.INSTREND ); + + QSPI->INTFLAG.reg = QSPI_INTFLAG_INSTREND; + return true; } diff --git a/ports/atmel-samd/external_flash/spi_flash.c b/ports/atmel-samd/external_flash/spi_flash.c index 9695067f17..4b63132eea 100644 --- a/ports/atmel-samd/external_flash/spi_flash.c +++ b/ports/atmel-samd/external_flash/spi_flash.c @@ -23,11 +23,12 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ -#include "spi_flash.h" +#include "spi_flash_api.h" #include #include +#include "external_flash/common_commands.h" #include "peripherals.h" #include "hal_gpio.h" @@ -45,11 +46,32 @@ static void flash_disable(void) { gpio_set_pin_level(SPI_FLASH_CS_PIN, true); } -void spi_flash_command(uint8_t* request, uint8_t* response, uint32_t length) { - struct spi_xfer xfer = { request, response, length }; +static bool transfer(uint8_t* command, uint32_t command_length, uint8_t* data_in, uint8_t* data_out, uint32_t data_length) { + struct spi_xfer xfer = { command, NULL, command_length }; flash_enable(); - spi_m_sync_transfer(&spi_flash_desc, &xfer); + int32_t status = spi_m_sync_transfer(&spi_flash_desc, &xfer); + if (status >= 0 && !(data_in == NULL && data_out == NULL)) { + struct spi_xfer data_xfer = {data_in, data_out, data_length}; + status = spi_m_sync_transfer(&spi_flash_desc, &data_xfer); + } flash_disable(); + return status >= 0; +} + +static bool transfer_command(uint8_t command, uint8_t* data_in, uint8_t* data_out, uint32_t data_length) { + return transfer(&command, 1, data_in, data_out, data_length); +} + +bool spi_flash_command(uint8_t command) { + return transfer_command(command, NULL, NULL, 0); +} + +bool spi_flash_read_command(uint8_t command, uint8_t* data, uint32_t data_length) { + return transfer_command(command, NULL, data, data_length); +} + +bool spi_flash_write_command(uint8_t command, uint8_t* data, uint32_t data_length) { + return transfer_command(command, data, NULL, data_length); } // Pack the low 24 bits of the address into a uint8_t array. @@ -59,32 +81,24 @@ static void address_to_bytes(uint32_t address, uint8_t* bytes) { bytes[2] = address & 0xff; } -void spi_flash_sector_command(uint8_t command, uint32_t address) { +bool spi_flash_sector_command(uint8_t command, uint32_t address) { uint8_t request[4] = {command, 0x00, 0x00, 0x00}; - address_to_bytes(address, page_program_request + 1); - struct spi_xfer xfer = { request, NULL, 4 }; - flash_enable(); - spi_m_sync_transfer(&spi_flash_desc, &xfer); - flash_disable(); + address_to_bytes(address, request + 1); + return transfer(request, 4, NULL, NULL, 0); } bool spi_flash_write_data(uint32_t address, uint8_t* data, uint32_t data_length) { - flash_enable(); - uint8_t page_program_request[4] = {CMD_PAGE_PROGRAM, 0x00, 0x00, 0x00}; + uint8_t request[4] = {CMD_PAGE_PROGRAM, 0x00, 0x00, 0x00}; // Write the SPI flash write address into the bytes following the command byte. - address_to_bytes(address, page_program_request + 1); - struct spi_xfer page_program_xfer = {request, 0, request_length}; - int32_t status = spi_m_sync_transfer(&spi_flash_desc, &page_program_xfer); - if (status >= 0) { - struct spi_xfer write_data_buffer_xfer = {data, 0, data_length}; - status = spi_m_sync_transfer(&spi_flash_desc, &write_data_buffer_xfer); - } - flash_disable(); - return status >= 0; + address_to_bytes(address, request + 1); + return transfer(request, 4, data, NULL, data_length); } bool spi_flash_read_data(uint32_t address, uint8_t* data, uint32_t data_length) { - + uint8_t request[4] = {CMD_READ_DATA, 0x00, 0x00, 0x00}; + // Write the SPI flash write address into the bytes following the command byte. + address_to_bytes(address, request + 1); + return transfer(request, 4, NULL, data, data_length); } void spi_flash_init(void) { From 653fc8877df4814a66aa4979bbc09be00d151c91 Mon Sep 17 00:00:00 2001 From: Scott Shawcroft Date: Mon, 19 Feb 2018 21:38:14 -0800 Subject: [PATCH 061/135] Remove breakpoint instruction used for debugging. --- ports/atmel-samd/external_flash/external_flash.c | 1 - 1 file changed, 1 deletion(-) diff --git a/ports/atmel-samd/external_flash/external_flash.c b/ports/atmel-samd/external_flash/external_flash.c index 48872adda7..d3a2b4bae6 100644 --- a/ports/atmel-samd/external_flash/external_flash.c +++ b/ports/atmel-samd/external_flash/external_flash.c @@ -208,7 +208,6 @@ void external_flash_init(void) { jedec_id_response[2] == SPI_FLASH_JEDEC_CAPACITY) { spi_flash_is_initialised = true; } else { - asm("bkpt"); // Unknown flash chip! spi_flash_is_initialised = false; return; From d02251f8cd0726d9a25f414af1f2f66fd6709bd5 Mon Sep 17 00:00:00 2001 From: Scott Shawcroft Date: Tue, 20 Feb 2018 12:34:07 -0800 Subject: [PATCH 062/135] Add a new board for Metro M4 Express Rev B. This is the board send to community members for testing. Also tweaked and commented reset pin list for main Metro M4 Express which is currently unreleased and is Rev D. --- .../boards/metro_m4_express/mpconfigboard.h | 38 +++--------- .../atmel-samd/boards/metro_m4_express/pins.c | 10 ++-- .../boards/metro_m4_express_revb/board.c | 46 +++++++++++++++ .../metro_m4_express_revb/mpconfigboard.h | 58 +++++++++++++++++++ .../metro_m4_express_revb/mpconfigboard.mk | 10 ++++ .../boards/metro_m4_express_revb/pins.c | 42 ++++++++++++++ 6 files changed, 170 insertions(+), 34 deletions(-) create mode 100644 ports/atmel-samd/boards/metro_m4_express_revb/board.c create mode 100644 ports/atmel-samd/boards/metro_m4_express_revb/mpconfigboard.h create mode 100644 ports/atmel-samd/boards/metro_m4_express_revb/mpconfigboard.mk create mode 100644 ports/atmel-samd/boards/metro_m4_express_revb/pins.c diff --git a/ports/atmel-samd/boards/metro_m4_express/mpconfigboard.h b/ports/atmel-samd/boards/metro_m4_express/mpconfigboard.h index b8f14e6253..18d65df2b2 100644 --- a/ports/atmel-samd/boards/metro_m4_express/mpconfigboard.h +++ b/ports/atmel-samd/boards/metro_m4_express/mpconfigboard.h @@ -3,40 +3,20 @@ #define CIRCUITPY_MCU_FAMILY samd51 +// This is for Rev D which is light blue + #define MICROPY_HW_LED_TX PIN_PA27 #define MICROPY_HW_LED_RX PIN_PB06 #define MICROPY_HW_NEOPIXEL (&pin_PB17) -#define SPI_FLASH_BAUDRATE (8000000) - -// Rev B: single channel SPI -// Rev C will be QSPI -#define SPI_FLASH_MOSI_PIN PIN_PB08 -#define SPI_FLASH_MISO_PIN PIN_PB11 -#define SPI_FLASH_SCK_PIN PIN_PB09 -#define SPI_FLASH_CS_PIN PIN_PB10 -#define SPI_FLASH_MOSI_PIN_FUNCTION PINMUX_PB08D_SERCOM4_PAD0 -#define SPI_FLASH_MISO_PIN_FUNCTION PINMUX_PB11D_SERCOM4_PAD3 -#define SPI_FLASH_SCK_PIN_FUNCTION PINMUX_PB09D_SERCOM4_PAD1 -#define SPI_FLASH_SERCOM SERCOM4 -#define SPI_FLASH_SERCOM_INDEX 4 -#define SPI_FLASH_MOSI_PAD 0 -#define SPI_FLASH_MISO_PAD 3 -#define SPI_FLASH_SCK_PAD 1 -// Transmit Data Pinout -// <0x0=>PAD[0,1]_DO_SCK -// <0x1=>PAD[2,3]_DO_SCK -// <0x2=>PAD[3,1]_DO_SCK -// <0x3=>PAD[0,3]_DO_SCK -#define SPI_FLASH_DOPO 0 -#define SPI_FLASH_DIPO 3 // same as MISO pad - // These are pins not to reset. -#define MICROPY_PORT_A (PORT_PA08 | PORT_PA09 | PORT_PA10 | PORT_PA11 | PORT_PA27) -#define MICROPY_PORT_B (PORT_PB10 | PORT_PB11 | PORT_PB17) -#define MICROPY_PORT_C (0) -#define MICROPY_PORT_D (0) +// QSPI Data pins and TX LED +#define MICROPY_PORT_A (PORT_PA08 | PORT_PA09 | PORT_PA10 | PORT_PA11 | PORT_PA27) +// RX LED, QSPI CS, QSPI SCK and NeoPixel pin +#define MICROPY_PORT_B ( PORT_PB06 | PORT_PB10 | PORT_PB11 | PORT_PB17) +#define MICROPY_PORT_C (0) +#define MICROPY_PORT_D (0) #define AUTORESET_DELAY_MS 500 @@ -49,5 +29,5 @@ #define BOARD_FLASH_SIZE (FLASH_SIZE - 0x4000 - CIRCUITPY_INTERNAL_NVM_SIZE) -#include "external_flash/devices/S25FL216K.h" +#include "external_flash/devices/S25FL116K.h" #include "external_flash/devices/GD25Q16C.h" diff --git a/ports/atmel-samd/boards/metro_m4_express/pins.c b/ports/atmel-samd/boards/metro_m4_express/pins.c index f6ad05f2da..5889c6c685 100644 --- a/ports/atmel-samd/boards/metro_m4_express/pins.c +++ b/ports/atmel-samd/boards/metro_m4_express/pins.c @@ -7,16 +7,16 @@ STATIC const mp_map_elem_t board_global_dict_table[] = { { MP_OBJ_NEW_QSTR(MP_QSTR_A0), (mp_obj_t)&pin_PA02 }, { MP_OBJ_NEW_QSTR(MP_QSTR_A1), (mp_obj_t)&pin_PA05 }, { MP_OBJ_NEW_QSTR(MP_QSTR_A2), (mp_obj_t)&pin_PA06 }, - { MP_OBJ_NEW_QSTR(MP_QSTR_A3), (mp_obj_t)&pin_PA04 }, - { MP_OBJ_NEW_QSTR(MP_QSTR_A4), (mp_obj_t)&pin_PA11 }, + { MP_OBJ_NEW_QSTR(MP_QSTR_A3), (mp_obj_t)&pin_PB09 }, + { MP_OBJ_NEW_QSTR(MP_QSTR_A4), (mp_obj_t)&pin_PB08 }, { MP_OBJ_NEW_QSTR(MP_QSTR_A5), (mp_obj_t)&pin_PA07 }, { MP_OBJ_NEW_QSTR(MP_QSTR_D0), (mp_obj_t)&pin_PA23 }, { MP_OBJ_NEW_QSTR(MP_QSTR_D1), (mp_obj_t)&pin_PA22 }, - { MP_OBJ_NEW_QSTR(MP_QSTR_D2), (mp_obj_t)&pin_PA08 }, - { MP_OBJ_NEW_QSTR(MP_QSTR_D3), (mp_obj_t)&pin_PA10 }, - { MP_OBJ_NEW_QSTR(MP_QSTR_D4), (mp_obj_t)&pin_PB12 }, + { MP_OBJ_NEW_QSTR(MP_QSTR_D2), (mp_obj_t)&pin_PA04 }, + { MP_OBJ_NEW_QSTR(MP_QSTR_D3), (mp_obj_t)&pin_PB16 }, + { MP_OBJ_NEW_QSTR(MP_QSTR_D4), (mp_obj_t)&pin_PB13 }, { MP_OBJ_NEW_QSTR(MP_QSTR_D5), (mp_obj_t)&pin_PB14 }, { MP_OBJ_NEW_QSTR(MP_QSTR_D6), (mp_obj_t)&pin_PB15 }, { MP_OBJ_NEW_QSTR(MP_QSTR_D7), (mp_obj_t)&pin_PA14 }, diff --git a/ports/atmel-samd/boards/metro_m4_express_revb/board.c b/ports/atmel-samd/boards/metro_m4_express_revb/board.c new file mode 100644 index 0000000000..a98385d295 --- /dev/null +++ b/ports/atmel-samd/boards/metro_m4_express_revb/board.c @@ -0,0 +1,46 @@ +/* + * This file is part of the MicroPython project, http://micropython.org/ + * + * The MIT License (MIT) + * + * Copyright (c) 2017 Scott Shawcroft for Adafruit Industries + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +#include "boards/board.h" +#include "mpconfigboard.h" +#include "hal/include/hal_gpio.h" + +void board_init(void) { + gpio_set_pin_function(MICROPY_HW_LED_TX, GPIO_PIN_FUNCTION_OFF); + gpio_set_pin_direction(MICROPY_HW_LED_TX, GPIO_DIRECTION_OUT); + gpio_set_pin_level(MICROPY_HW_LED_TX, true); + + gpio_set_pin_function(MICROPY_HW_LED_RX, GPIO_PIN_FUNCTION_OFF); + gpio_set_pin_direction(MICROPY_HW_LED_RX, GPIO_DIRECTION_OUT); + gpio_set_pin_level(MICROPY_HW_LED_RX, true); +} + +bool board_requests_safe_mode(void) { + return false; +} + +void reset_board(void) { +} diff --git a/ports/atmel-samd/boards/metro_m4_express_revb/mpconfigboard.h b/ports/atmel-samd/boards/metro_m4_express_revb/mpconfigboard.h new file mode 100644 index 0000000000..7c51bae870 --- /dev/null +++ b/ports/atmel-samd/boards/metro_m4_express_revb/mpconfigboard.h @@ -0,0 +1,58 @@ +// This is for Rev B which a larger run was done and sent to Adafruit community +// members. + +#define MICROPY_HW_BOARD_NAME "Metro M4 Express Rev B (Black)" +#define MICROPY_HW_MCU_NAME "samd51j19" + +#define CIRCUITPY_MCU_FAMILY samd51 + +#define MICROPY_HW_LED_TX PIN_PA27 +#define MICROPY_HW_LED_RX PIN_PB06 + +#define MICROPY_HW_NEOPIXEL (&pin_PB17) + +#define SPI_FLASH_BAUDRATE (8000000) + +// Rev B: single channel SPI +// Rev C will be QSPI +#define SPI_FLASH_MOSI_PIN PIN_PB08 +#define SPI_FLASH_MISO_PIN PIN_PB11 +#define SPI_FLASH_SCK_PIN PIN_PB09 +#define SPI_FLASH_CS_PIN PIN_PB10 +#define SPI_FLASH_MOSI_PIN_FUNCTION PINMUX_PB08D_SERCOM4_PAD0 +#define SPI_FLASH_MISO_PIN_FUNCTION PINMUX_PB11D_SERCOM4_PAD3 +#define SPI_FLASH_SCK_PIN_FUNCTION PINMUX_PB09D_SERCOM4_PAD1 +#define SPI_FLASH_SERCOM SERCOM4 +#define SPI_FLASH_SERCOM_INDEX 4 +#define SPI_FLASH_MOSI_PAD 0 +#define SPI_FLASH_MISO_PAD 3 +#define SPI_FLASH_SCK_PAD 1 +// Transmit Data Pinout +// <0x0=>PAD[0,1]_DO_SCK +// <0x1=>PAD[2,3]_DO_SCK +// <0x2=>PAD[3,1]_DO_SCK +// <0x3=>PAD[0,3]_DO_SCK +#define SPI_FLASH_DOPO 0 +#define SPI_FLASH_DIPO 3 // same as MISO pad + +// These are pins not to reset. +// Pin for TX LED +#define MICROPY_PORT_A (PORT_PA27) +// Pins for RX LED, SPI flash and neopixel +#define MICROPY_PORT_B (PORT_PB06 | PORT_PB08 | PORT_PB09 | PORT_PB10 | PORT_PB11 | PORT_PB17) +#define MICROPY_PORT_C (0) +#define MICROPY_PORT_D (0) + +#define AUTORESET_DELAY_MS 500 + +#include "external_flash/external_flash.h" + +// If you change this, then make sure to update the linker scripts as well to +// make sure you don't overwrite code +// #define CIRCUITPY_INTERNAL_NVM_SIZE 256 +#define CIRCUITPY_INTERNAL_NVM_SIZE 0 + +#define BOARD_FLASH_SIZE (FLASH_SIZE - 0x4000 - CIRCUITPY_INTERNAL_NVM_SIZE) + +#include "external_flash/devices/S25FL216K.h" +#include "external_flash/devices/GD25Q16C.h" diff --git a/ports/atmel-samd/boards/metro_m4_express_revb/mpconfigboard.mk b/ports/atmel-samd/boards/metro_m4_express_revb/mpconfigboard.mk new file mode 100644 index 0000000000..a3d6e25221 --- /dev/null +++ b/ports/atmel-samd/boards/metro_m4_express_revb/mpconfigboard.mk @@ -0,0 +1,10 @@ +LD_FILE = boards/samd51x19-bootloader-external-flash.ld +USB_VID = 0x239A +USB_PID = 0x8021 +USB_PRODUCT = "Metro M4 Express Rev B (Black)" +USB_MANUFACTURER = "Adafruit Industries LLC" + +SPI_FLASH_FILESYSTEM = 1 + +CHIP_VARIANT = SAMD51J19A +CHIP_FAMILY = samd51 diff --git a/ports/atmel-samd/boards/metro_m4_express_revb/pins.c b/ports/atmel-samd/boards/metro_m4_express_revb/pins.c new file mode 100644 index 0000000000..f6ad05f2da --- /dev/null +++ b/ports/atmel-samd/boards/metro_m4_express_revb/pins.c @@ -0,0 +1,42 @@ +#include "samd51_pins.h" + +// This mapping only includes functional names because pins broken +// out on connectors are labeled with their MCU name available from +// microcontroller.pin. +STATIC const mp_map_elem_t board_global_dict_table[] = { + { MP_OBJ_NEW_QSTR(MP_QSTR_A0), (mp_obj_t)&pin_PA02 }, + { MP_OBJ_NEW_QSTR(MP_QSTR_A1), (mp_obj_t)&pin_PA05 }, + { MP_OBJ_NEW_QSTR(MP_QSTR_A2), (mp_obj_t)&pin_PA06 }, + { MP_OBJ_NEW_QSTR(MP_QSTR_A3), (mp_obj_t)&pin_PA04 }, + { MP_OBJ_NEW_QSTR(MP_QSTR_A4), (mp_obj_t)&pin_PA11 }, + { MP_OBJ_NEW_QSTR(MP_QSTR_A5), (mp_obj_t)&pin_PA07 }, + + + { MP_OBJ_NEW_QSTR(MP_QSTR_D0), (mp_obj_t)&pin_PA23 }, + { MP_OBJ_NEW_QSTR(MP_QSTR_D1), (mp_obj_t)&pin_PA22 }, + { MP_OBJ_NEW_QSTR(MP_QSTR_D2), (mp_obj_t)&pin_PA08 }, + { MP_OBJ_NEW_QSTR(MP_QSTR_D3), (mp_obj_t)&pin_PA10 }, + { MP_OBJ_NEW_QSTR(MP_QSTR_D4), (mp_obj_t)&pin_PB12 }, + { MP_OBJ_NEW_QSTR(MP_QSTR_D5), (mp_obj_t)&pin_PB14 }, + { MP_OBJ_NEW_QSTR(MP_QSTR_D6), (mp_obj_t)&pin_PB15 }, + { MP_OBJ_NEW_QSTR(MP_QSTR_D7), (mp_obj_t)&pin_PA14 }, + { MP_OBJ_NEW_QSTR(MP_QSTR_D8), (mp_obj_t)&pin_PA16 }, + { MP_OBJ_NEW_QSTR(MP_QSTR_D9), (mp_obj_t)&pin_PA17 }, + { MP_OBJ_NEW_QSTR(MP_QSTR_D10), (mp_obj_t)&pin_PA18 }, + { MP_OBJ_NEW_QSTR(MP_QSTR_D11), (mp_obj_t)&pin_PA19 }, + { MP_OBJ_NEW_QSTR(MP_QSTR_D12), (mp_obj_t)&pin_PA20 }, + { MP_OBJ_NEW_QSTR(MP_QSTR_D13), (mp_obj_t)&pin_PA21 }, + + { MP_OBJ_NEW_QSTR(MP_QSTR_SDA), (mp_obj_t)&pin_PB02 }, + { MP_OBJ_NEW_QSTR(MP_QSTR_SCL), (mp_obj_t)&pin_PB03 }, + + { MP_OBJ_NEW_QSTR(MP_QSTR_NEOPIXEL), (mp_obj_t)&pin_PB17 }, + + { MP_OBJ_NEW_QSTR(MP_QSTR_SCK), (mp_obj_t)&pin_PA13 }, + { MP_OBJ_NEW_QSTR(MP_QSTR_MOSI), (mp_obj_t)&pin_PA12 }, + { MP_OBJ_NEW_QSTR(MP_QSTR_MISO), (mp_obj_t)&pin_PA15 }, + + { MP_OBJ_NEW_QSTR(MP_QSTR_LED_RX), (mp_obj_t)&pin_PB06 }, + { MP_OBJ_NEW_QSTR(MP_QSTR_LED_TX), (mp_obj_t)&pin_PA27 }, +}; +MP_DEFINE_CONST_DICT(board_module_globals, board_global_dict_table); From 20dd3b1e434f57a0609fd5306f47863396d1022e Mon Sep 17 00:00:00 2001 From: Scott Shawcroft Date: Tue, 20 Feb 2018 17:34:59 -0800 Subject: [PATCH 063/135] Delete a bunch of docs, drivers and examples not relevant to CircuitPython. This fixes #345 and fixes #215. --- CODECONVENTIONS.md | 210 -- README.md | 213 -- README.rst | 253 ++ atmel-samd/README.rst | 68 +- conf.py | 19 +- docs/design_guide.rst | 9 +- docs/differences/index_template.txt | 10 - docs/esp8266/general.rst | 147 -- .../img/adafruit_products_pinoutstop.jpg | Bin 79455 -> 0 bytes docs/esp8266/index.rst | 8 - docs/esp8266/quickref.rst | 364 --- docs/esp8266/tutorial/adc.rst | 19 - docs/esp8266/tutorial/dht.rst | 65 - docs/esp8266/tutorial/filesystem.rst | 69 - docs/esp8266/tutorial/index.rst | 33 - docs/esp8266/tutorial/intro.rst | 202 -- docs/esp8266/tutorial/neopixel.rst | 70 - docs/esp8266/tutorial/network_basics.rst | 81 - docs/esp8266/tutorial/network_tcp.rst | 122 - docs/esp8266/tutorial/nextsteps.rst | 12 - docs/esp8266/tutorial/onewire.rst | 37 - docs/esp8266/tutorial/pins.rst | 75 - docs/esp8266/tutorial/powerctrl.rst | 61 - docs/esp8266/tutorial/pwm.rst | 87 - docs/esp8266/tutorial/repl.rst | 212 -- docs/esp8266_index.rst | 12 - docs/index.rst | 53 + docs/library/array.rst | 4 +- docs/library/btree.rst | 4 +- docs/library/builtins.rst | 14 +- docs/library/cmath.rst | 63 - docs/library/esp.rst | 2 + docs/library/framebuf.rst | 2 + docs/library/gc.rst | 4 +- docs/library/index.rst | 210 +- docs/library/lcd160cr.rst | 394 ---- docs/library/machine.ADC.rst | 74 - docs/library/machine.I2C.rst | 172 -- docs/library/machine.Pin.rst | 248 -- docs/library/machine.RTC.rst | 69 - docs/library/machine.SD.rst | 42 - docs/library/machine.SPI.rst | 97 - docs/library/machine.Signal.rst | 96 - docs/library/machine.Timer.rst | 160 -- docs/library/machine.UART.rst | 142 -- docs/library/machine.WDT.rst | 36 - docs/library/machine.rst | 170 -- docs/library/math.rst | 4 +- docs/library/micropython.rst | 2 + docs/library/network.rst | 504 +--- docs/library/pyb.ADC.rst | 143 -- docs/library/pyb.Accel.rst | 56 - docs/library/pyb.CAN.rst | 222 -- docs/library/pyb.DAC.rst | 109 - docs/library/pyb.ExtInt.rst | 114 - docs/library/pyb.I2C.rst | 175 -- docs/library/pyb.LCD.rst | 96 - docs/library/pyb.LED.rst | 46 - docs/library/pyb.Pin.rst | 280 --- docs/library/pyb.RTC.rst | 83 - docs/library/pyb.SPI.rst | 132 -- docs/library/pyb.Servo.rst | 80 - docs/library/pyb.Switch.rst | 45 - docs/library/pyb.Timer.rst | 286 --- docs/library/pyb.UART.rst | 245 -- docs/library/pyb.USB_HID.rst | 39 - docs/library/pyb.USB_VCP.rst | 102 - docs/library/pyb.rst | 321 --- docs/library/sys.rst | 7 +- docs/library/ubinascii.rst | 4 +- docs/library/ucollections.rst | 4 +- docs/library/uctypes.rst | 4 +- docs/library/uerrno.rst | 12 +- docs/library/uhashlib.rst | 4 +- docs/library/uheapq.rst | 4 +- docs/library/uio.rst | 6 +- docs/library/ujson.rst | 4 +- docs/library/uos.rst | 96 - docs/library/ure.rst | 4 +- docs/library/uselect.rst | 4 +- docs/library/usocket.rst | 21 +- docs/library/ussl.rst | 8 +- docs/library/ustruct.rst | 4 +- docs/library/utime.rst | 229 -- docs/library/uzlib.rst | 4 +- docs/library/wipy.rst | 17 - docs/pyboard/general.rst | 80 - docs/pyboard/hardware/index.rst | 30 - docs/pyboard/index.rst | 9 - docs/pyboard/quickref.rst | 169 -- docs/pyboard/tutorial/accel.rst | 92 - docs/pyboard/tutorial/amp_skin.rst | 98 - docs/pyboard/tutorial/assembler.rst | 131 -- docs/pyboard/tutorial/debounce.rst | 37 - docs/pyboard/tutorial/fading_led.rst | 89 - .../img/fading_leds_breadboard_fritzing.png | Bin 61821 -> 0 bytes docs/pyboard/tutorial/img/pyboard_servo.jpg | Bin 70642 -> 0 bytes .../tutorial/img/pyboard_usb_micro.jpg | Bin 86846 -> 0 bytes docs/pyboard/tutorial/img/skin_amp_1.jpg | Bin 83408 -> 0 bytes docs/pyboard/tutorial/img/skin_amp_2.jpg | Bin 75075 -> 0 bytes docs/pyboard/tutorial/img/skin_lcd_1.jpg | Bin 99320 -> 0 bytes docs/pyboard/tutorial/img/skin_lcd_2.jpg | Bin 69460 -> 0 bytes docs/pyboard/tutorial/index.rst | 48 - docs/pyboard/tutorial/intro.rst | 54 - docs/pyboard/tutorial/lcd160cr_skin.rst | 134 -- docs/pyboard/tutorial/lcd_skin.rst | 86 - docs/pyboard/tutorial/leds.rst | 75 - docs/pyboard/tutorial/pass_through.rst | 18 - docs/pyboard/tutorial/power_ctrl.rst | 13 - docs/pyboard/tutorial/repl.rst | 110 - docs/pyboard/tutorial/reset.rst | 60 - docs/pyboard/tutorial/script.rst | 105 - docs/pyboard/tutorial/servo.rst | 146 -- docs/pyboard/tutorial/switch.rst | 113 - docs/pyboard/tutorial/timer.rst | 114 - docs/pyboard/tutorial/usb_mouse.rst | 131 -- docs/pyboard_index.rst | 12 - docs/reference/asm_thumb2_arith.rst | 50 - docs/reference/asm_thumb2_compare.rst | 90 - docs/reference/asm_thumb2_directives.rst | 36 - docs/reference/asm_thumb2_float.rst | 77 - docs/reference/asm_thumb2_hints_tips.rst | 244 -- docs/reference/asm_thumb2_index.rst | 73 - docs/reference/asm_thumb2_label_branch.rst | 85 - docs/reference/asm_thumb2_ldr.rst | 23 - docs/reference/asm_thumb2_logical_bit.rst | 53 - docs/reference/asm_thumb2_misc.rst | 13 - docs/reference/asm_thumb2_mov.rst | 27 - docs/reference/asm_thumb2_stack.rst | 20 - docs/reference/asm_thumb2_str.rst | 21 - docs/reference/constrained.rst | 456 ---- docs/reference/glossary.rst | 105 - docs/reference/index.rst | 33 - docs/reference/isr_rules.rst | 332 --- docs/reference/repl.rst | 211 -- docs/reference/speed_python.rst | 342 --- docs/sphinx_selective_exclude/LICENSE | 25 - docs/sphinx_selective_exclude/README.md | 138 -- docs/sphinx_selective_exclude/__init__.py | 0 docs/sphinx_selective_exclude/eager_only.py | 45 - .../modindex_exclude.py | 75 - .../search_auto_exclude.py | 34 - docs/supported_ports.rst | 6 +- docs/templates/layout.html | 6 - docs/templates/replace.inc | 6 +- docs/templates/topindex.html | 112 - .../unsupported_in_circuitpython.inc | 5 + docs/templates/versions.html | 37 - docs/troubleshooting.rst | 4 +- docs/unix_index.rst | 9 - docs/unsupported_ports.rst | 14 - docs/wipy/general.rst | 385 --- docs/wipy/index.rst | 8 - docs/wipy/quickref.rst | 218 -- docs/wipy/tutorial/blynk.rst | 19 - docs/wipy/tutorial/index.rst | 18 - docs/wipy/tutorial/intro.rst | 64 - docs/wipy/tutorial/repl.rst | 130 - docs/wipy/tutorial/reset.rst | 54 - docs/wipy/tutorial/timer.rst | 70 - docs/wipy/tutorial/wlan.rst | 71 - docs/wipy_index.rst | 12 - drivers/README.md | 2 - drivers/cc3000/inc/cc3000_common.h | 365 --- drivers/cc3000/inc/ccspi.h | 84 - drivers/cc3000/inc/data_types.h | 107 - drivers/cc3000/inc/evnt_handler.h | 166 -- drivers/cc3000/inc/hci.h | 330 --- drivers/cc3000/inc/host_driver_version.h | 40 - drivers/cc3000/inc/inet_ntop.h | 4 - drivers/cc3000/inc/inet_pton.h | 4 - drivers/cc3000/inc/netapp.h | 343 --- drivers/cc3000/inc/nvmem.h | 248 -- drivers/cc3000/inc/patch_prog.h | 11 - drivers/cc3000/inc/security.h | 130 - drivers/cc3000/inc/socket.h | 676 ------ drivers/cc3000/inc/wlan.h | 518 ---- drivers/cc3000/src/cc3000_common.c | 164 -- drivers/cc3000/src/ccspi.c | 456 ---- drivers/cc3000/src/evnt_handler.c | 849 ------- drivers/cc3000/src/hci.c | 225 -- drivers/cc3000/src/inet_ntop.c | 200 -- drivers/cc3000/src/inet_pton.c | 216 -- drivers/cc3000/src/netapp.c | 459 ---- drivers/cc3000/src/nvmem.c | 334 --- drivers/cc3000/src/patch.c | 117 - drivers/cc3000/src/patch_prog.c | 414 ---- drivers/cc3000/src/security.c | 530 ----- drivers/cc3000/src/socket.c | 1182 ---------- drivers/cc3000/src/wlan.c | 1252 ---------- drivers/cc3100/inc/device.h | 656 ------ drivers/cc3100/inc/driver.h | 247 -- drivers/cc3100/inc/flowcont.h | 61 - drivers/cc3100/inc/fs.h | 382 --- drivers/cc3100/inc/netapp.h | 884 ------- drivers/cc3100/inc/netcfg.h | 283 --- drivers/cc3100/inc/nonos.h | 325 --- drivers/cc3100/inc/objInclusion.h | 322 --- drivers/cc3100/inc/protocol.h | 1182 ---------- drivers/cc3100/inc/simplelink.h | 948 -------- drivers/cc3100/inc/socket.h | 1573 ------------- drivers/cc3100/inc/spawn.h | 63 - drivers/cc3100/inc/trace.h | 173 -- drivers/cc3100/inc/wlan.h | 1308 ----------- drivers/cc3100/inc/wlan_rx_filters.h | 932 -------- drivers/cc3100/src/device.c | 557 ----- drivers/cc3100/src/driver.c | 1843 --------------- drivers/cc3100/src/flowcont.c | 71 - drivers/cc3100/src/fs.c | 424 ---- drivers/cc3100/src/netapp.c | 1304 ---------- drivers/cc3100/src/netcfg.c | 150 -- drivers/cc3100/src/nonos.c | 171 -- drivers/cc3100/src/socket.c | 1150 --------- drivers/cc3100/src/spawn.c | 197 -- drivers/cc3100/src/wlan.c | 1006 -------- drivers/dht/dht.c | 89 - drivers/dht/dht.h | 8 - drivers/display/lcd160cr.py | 474 ---- drivers/display/lcd160cr_test.py | 171 -- drivers/display/ssd1306.py | 161 -- drivers/memory/spiflash.c | 200 -- drivers/memory/spiflash.h | 41 - drivers/nrf24l01/nrf24l01.py | 252 -- drivers/nrf24l01/nrf24l01test.py | 100 - drivers/onewire/ds18x20.py | 51 - drivers/onewire/onewire.py | 91 - drivers/sdcard/sdcard.py | 272 --- drivers/sdcard/sdtest.py | 57 - drivers/wiznet5k/README.md | 6 - drivers/wiznet5k/ethernet/socket.c | 723 ------ drivers/wiznet5k/ethernet/socket.h | 472 ---- drivers/wiznet5k/ethernet/w5200/w5200.c | 206 -- drivers/wiznet5k/ethernet/w5200/w5200.h | 2092 ----------------- drivers/wiznet5k/ethernet/w5500/w5500.c | 237 -- drivers/wiznet5k/ethernet/w5500/w5500.h | 2058 ---------------- drivers/wiznet5k/ethernet/wizchip_conf.c | 662 ------ drivers/wiznet5k/ethernet/wizchip_conf.h | 552 ----- drivers/wiznet5k/internet/dhcp/dhcp.c | 978 -------- drivers/wiznet5k/internet/dhcp/dhcp.h | 150 -- drivers/wiznet5k/internet/dns/dns.c | 566 ----- drivers/wiznet5k/internet/dns/dns.h | 96 - examples/SDdatalogger/README.md | 4 - examples/SDdatalogger/boot.py | 25 - examples/SDdatalogger/cardreader.py | 2 - examples/SDdatalogger/datalogger.py | 33 - examples/accel_i2c.py | 34 - examples/accellog.py | 17 - examples/asmled.py | 85 - examples/asmsum.py | 57 - examples/conwaylife.py | 46 - examples/embedding/Makefile | 8 - examples/embedding/Makefile.upylib | 199 -- examples/embedding/README.md | 67 - examples/embedding/hello-embed.c | 74 - examples/embedding/mpconfigport.h | 1 - examples/embedding/mpconfigport_minimal.h | 134 -- examples/hwapi/README.md | 126 - examples/hwapi/button_led.py | 9 - examples/hwapi/button_reaction.py | 19 - examples/hwapi/hwconfig_console.py | 13 - examples/hwapi/hwconfig_dragonboard410c.py | 22 - examples/hwapi/hwconfig_esp8266_esp12.py | 5 - examples/hwapi/hwconfig_pyboard.py | 13 - examples/hwapi/hwconfig_z_96b_carbon.py | 9 - examples/hwapi/hwconfig_z_frdm_k64f.py | 5 - examples/hwapi/soft_pwm.py | 38 - examples/hwapi/soft_pwm2_uasyncio.py | 31 - examples/hwapi/soft_pwm_uasyncio.py | 28 - examples/ledangle.py | 25 - examples/mandel.py | 27 - examples/micropython.py | 8 - examples/network/http_client.py | 30 - examples/network/http_client_ssl.py | 38 - examples/network/http_server.py | 64 - examples/network/http_server_simplistic.py | 40 - .../http_server_simplistic_commented.py | 76 - examples/network/http_server_ssl.py | 64 - examples/pins.py | 58 - examples/pyb.py | 49 - examples/switch.py | 45 - examples/unix/ffi_example.py | 38 - examples/unix/machine_bios.py | 9 - index.rst | 92 - shared-bindings/_stage/__init__.c | 21 +- shared-bindings/audiobusio/PDMIn.c | 6 +- shared-bindings/audiobusio/__init__.c | 2 +- shared-bindings/help.c | 9 + shared-bindings/microcontroller/Processor.c | 2 +- shared-bindings/microcontroller/__init__.c | 5 +- shared-bindings/random/__init__.c | 4 +- shared-bindings/storage/__init__.c | 4 +- 291 files changed, 621 insertions(+), 51446 deletions(-) delete mode 100644 CODECONVENTIONS.md delete mode 100644 README.md create mode 100644 README.rst delete mode 100644 docs/differences/index_template.txt delete mode 100644 docs/esp8266/general.rst delete mode 100644 docs/esp8266/img/adafruit_products_pinoutstop.jpg delete mode 100644 docs/esp8266/index.rst delete mode 100644 docs/esp8266/quickref.rst delete mode 100644 docs/esp8266/tutorial/adc.rst delete mode 100644 docs/esp8266/tutorial/dht.rst delete mode 100644 docs/esp8266/tutorial/filesystem.rst delete mode 100644 docs/esp8266/tutorial/index.rst delete mode 100644 docs/esp8266/tutorial/intro.rst delete mode 100644 docs/esp8266/tutorial/neopixel.rst delete mode 100644 docs/esp8266/tutorial/network_basics.rst delete mode 100644 docs/esp8266/tutorial/network_tcp.rst delete mode 100644 docs/esp8266/tutorial/nextsteps.rst delete mode 100644 docs/esp8266/tutorial/onewire.rst delete mode 100644 docs/esp8266/tutorial/pins.rst delete mode 100644 docs/esp8266/tutorial/powerctrl.rst delete mode 100644 docs/esp8266/tutorial/pwm.rst delete mode 100644 docs/esp8266/tutorial/repl.rst delete mode 100644 docs/esp8266_index.rst create mode 100644 docs/index.rst delete mode 100644 docs/library/cmath.rst delete mode 100644 docs/library/lcd160cr.rst delete mode 100644 docs/library/machine.ADC.rst delete mode 100644 docs/library/machine.I2C.rst delete mode 100644 docs/library/machine.Pin.rst delete mode 100644 docs/library/machine.RTC.rst delete mode 100644 docs/library/machine.SD.rst delete mode 100644 docs/library/machine.SPI.rst delete mode 100644 docs/library/machine.Signal.rst delete mode 100644 docs/library/machine.Timer.rst delete mode 100644 docs/library/machine.UART.rst delete mode 100644 docs/library/machine.WDT.rst delete mode 100644 docs/library/machine.rst delete mode 100644 docs/library/pyb.ADC.rst delete mode 100644 docs/library/pyb.Accel.rst delete mode 100644 docs/library/pyb.CAN.rst delete mode 100644 docs/library/pyb.DAC.rst delete mode 100644 docs/library/pyb.ExtInt.rst delete mode 100644 docs/library/pyb.I2C.rst delete mode 100644 docs/library/pyb.LCD.rst delete mode 100644 docs/library/pyb.LED.rst delete mode 100644 docs/library/pyb.Pin.rst delete mode 100644 docs/library/pyb.RTC.rst delete mode 100644 docs/library/pyb.SPI.rst delete mode 100644 docs/library/pyb.Servo.rst delete mode 100644 docs/library/pyb.Switch.rst delete mode 100644 docs/library/pyb.Timer.rst delete mode 100644 docs/library/pyb.UART.rst delete mode 100644 docs/library/pyb.USB_HID.rst delete mode 100644 docs/library/pyb.USB_VCP.rst delete mode 100644 docs/library/pyb.rst delete mode 100644 docs/library/uos.rst delete mode 100644 docs/library/utime.rst delete mode 100644 docs/library/wipy.rst delete mode 100644 docs/pyboard/general.rst delete mode 100644 docs/pyboard/hardware/index.rst delete mode 100644 docs/pyboard/index.rst delete mode 100644 docs/pyboard/quickref.rst delete mode 100644 docs/pyboard/tutorial/accel.rst delete mode 100644 docs/pyboard/tutorial/amp_skin.rst delete mode 100644 docs/pyboard/tutorial/assembler.rst delete mode 100644 docs/pyboard/tutorial/debounce.rst delete mode 100644 docs/pyboard/tutorial/fading_led.rst delete mode 100644 docs/pyboard/tutorial/img/fading_leds_breadboard_fritzing.png delete mode 100644 docs/pyboard/tutorial/img/pyboard_servo.jpg delete mode 100644 docs/pyboard/tutorial/img/pyboard_usb_micro.jpg delete mode 100644 docs/pyboard/tutorial/img/skin_amp_1.jpg delete mode 100644 docs/pyboard/tutorial/img/skin_amp_2.jpg delete mode 100644 docs/pyboard/tutorial/img/skin_lcd_1.jpg delete mode 100644 docs/pyboard/tutorial/img/skin_lcd_2.jpg delete mode 100644 docs/pyboard/tutorial/index.rst delete mode 100644 docs/pyboard/tutorial/intro.rst delete mode 100644 docs/pyboard/tutorial/lcd160cr_skin.rst delete mode 100644 docs/pyboard/tutorial/lcd_skin.rst delete mode 100644 docs/pyboard/tutorial/leds.rst delete mode 100644 docs/pyboard/tutorial/pass_through.rst delete mode 100644 docs/pyboard/tutorial/power_ctrl.rst delete mode 100644 docs/pyboard/tutorial/repl.rst delete mode 100644 docs/pyboard/tutorial/reset.rst delete mode 100644 docs/pyboard/tutorial/script.rst delete mode 100644 docs/pyboard/tutorial/servo.rst delete mode 100644 docs/pyboard/tutorial/switch.rst delete mode 100644 docs/pyboard/tutorial/timer.rst delete mode 100644 docs/pyboard/tutorial/usb_mouse.rst delete mode 100644 docs/pyboard_index.rst delete mode 100644 docs/reference/asm_thumb2_arith.rst delete mode 100644 docs/reference/asm_thumb2_compare.rst delete mode 100644 docs/reference/asm_thumb2_directives.rst delete mode 100644 docs/reference/asm_thumb2_float.rst delete mode 100644 docs/reference/asm_thumb2_hints_tips.rst delete mode 100644 docs/reference/asm_thumb2_index.rst delete mode 100644 docs/reference/asm_thumb2_label_branch.rst delete mode 100644 docs/reference/asm_thumb2_ldr.rst delete mode 100644 docs/reference/asm_thumb2_logical_bit.rst delete mode 100644 docs/reference/asm_thumb2_misc.rst delete mode 100644 docs/reference/asm_thumb2_mov.rst delete mode 100644 docs/reference/asm_thumb2_stack.rst delete mode 100644 docs/reference/asm_thumb2_str.rst delete mode 100644 docs/reference/constrained.rst delete mode 100644 docs/reference/glossary.rst delete mode 100644 docs/reference/index.rst delete mode 100644 docs/reference/isr_rules.rst delete mode 100644 docs/reference/repl.rst delete mode 100644 docs/reference/speed_python.rst delete mode 100644 docs/sphinx_selective_exclude/LICENSE delete mode 100644 docs/sphinx_selective_exclude/README.md delete mode 100644 docs/sphinx_selective_exclude/__init__.py delete mode 100644 docs/sphinx_selective_exclude/eager_only.py delete mode 100644 docs/sphinx_selective_exclude/modindex_exclude.py delete mode 100644 docs/sphinx_selective_exclude/search_auto_exclude.py delete mode 100644 docs/templates/layout.html delete mode 100644 docs/templates/topindex.html create mode 100644 docs/templates/unsupported_in_circuitpython.inc delete mode 100644 docs/templates/versions.html delete mode 100644 docs/unix_index.rst delete mode 100644 docs/unsupported_ports.rst delete mode 100644 docs/wipy/general.rst delete mode 100644 docs/wipy/index.rst delete mode 100644 docs/wipy/quickref.rst delete mode 100644 docs/wipy/tutorial/blynk.rst delete mode 100644 docs/wipy/tutorial/index.rst delete mode 100644 docs/wipy/tutorial/intro.rst delete mode 100644 docs/wipy/tutorial/repl.rst delete mode 100644 docs/wipy/tutorial/reset.rst delete mode 100644 docs/wipy/tutorial/timer.rst delete mode 100644 docs/wipy/tutorial/wlan.rst delete mode 100644 docs/wipy_index.rst delete mode 100644 drivers/README.md delete mode 100644 drivers/cc3000/inc/cc3000_common.h delete mode 100644 drivers/cc3000/inc/ccspi.h delete mode 100644 drivers/cc3000/inc/data_types.h delete mode 100644 drivers/cc3000/inc/evnt_handler.h delete mode 100644 drivers/cc3000/inc/hci.h delete mode 100644 drivers/cc3000/inc/host_driver_version.h delete mode 100644 drivers/cc3000/inc/inet_ntop.h delete mode 100644 drivers/cc3000/inc/inet_pton.h delete mode 100644 drivers/cc3000/inc/netapp.h delete mode 100644 drivers/cc3000/inc/nvmem.h delete mode 100644 drivers/cc3000/inc/patch_prog.h delete mode 100644 drivers/cc3000/inc/security.h delete mode 100644 drivers/cc3000/inc/socket.h delete mode 100644 drivers/cc3000/inc/wlan.h delete mode 100644 drivers/cc3000/src/cc3000_common.c delete mode 100644 drivers/cc3000/src/ccspi.c delete mode 100644 drivers/cc3000/src/evnt_handler.c delete mode 100644 drivers/cc3000/src/hci.c delete mode 100644 drivers/cc3000/src/inet_ntop.c delete mode 100644 drivers/cc3000/src/inet_pton.c delete mode 100644 drivers/cc3000/src/netapp.c delete mode 100644 drivers/cc3000/src/nvmem.c delete mode 100644 drivers/cc3000/src/patch.c delete mode 100644 drivers/cc3000/src/patch_prog.c delete mode 100644 drivers/cc3000/src/security.c delete mode 100644 drivers/cc3000/src/socket.c delete mode 100644 drivers/cc3000/src/wlan.c delete mode 100644 drivers/cc3100/inc/device.h delete mode 100644 drivers/cc3100/inc/driver.h delete mode 100644 drivers/cc3100/inc/flowcont.h delete mode 100644 drivers/cc3100/inc/fs.h delete mode 100644 drivers/cc3100/inc/netapp.h delete mode 100644 drivers/cc3100/inc/netcfg.h delete mode 100644 drivers/cc3100/inc/nonos.h delete mode 100644 drivers/cc3100/inc/objInclusion.h delete mode 100644 drivers/cc3100/inc/protocol.h delete mode 100644 drivers/cc3100/inc/simplelink.h delete mode 100644 drivers/cc3100/inc/socket.h delete mode 100644 drivers/cc3100/inc/spawn.h delete mode 100644 drivers/cc3100/inc/trace.h delete mode 100644 drivers/cc3100/inc/wlan.h delete mode 100644 drivers/cc3100/inc/wlan_rx_filters.h delete mode 100644 drivers/cc3100/src/device.c delete mode 100644 drivers/cc3100/src/driver.c delete mode 100644 drivers/cc3100/src/flowcont.c delete mode 100644 drivers/cc3100/src/fs.c delete mode 100644 drivers/cc3100/src/netapp.c delete mode 100644 drivers/cc3100/src/netcfg.c delete mode 100644 drivers/cc3100/src/nonos.c delete mode 100644 drivers/cc3100/src/socket.c delete mode 100644 drivers/cc3100/src/spawn.c delete mode 100644 drivers/cc3100/src/wlan.c delete mode 100644 drivers/dht/dht.c delete mode 100644 drivers/dht/dht.h delete mode 100644 drivers/display/lcd160cr.py delete mode 100644 drivers/display/lcd160cr_test.py delete mode 100644 drivers/display/ssd1306.py delete mode 100644 drivers/memory/spiflash.c delete mode 100644 drivers/memory/spiflash.h delete mode 100644 drivers/nrf24l01/nrf24l01.py delete mode 100644 drivers/nrf24l01/nrf24l01test.py delete mode 100644 drivers/onewire/ds18x20.py delete mode 100644 drivers/onewire/onewire.py delete mode 100644 drivers/sdcard/sdcard.py delete mode 100644 drivers/sdcard/sdtest.py delete mode 100644 drivers/wiznet5k/README.md delete mode 100644 drivers/wiznet5k/ethernet/socket.c delete mode 100644 drivers/wiznet5k/ethernet/socket.h delete mode 100644 drivers/wiznet5k/ethernet/w5200/w5200.c delete mode 100644 drivers/wiznet5k/ethernet/w5200/w5200.h delete mode 100644 drivers/wiznet5k/ethernet/w5500/w5500.c delete mode 100644 drivers/wiznet5k/ethernet/w5500/w5500.h delete mode 100644 drivers/wiznet5k/ethernet/wizchip_conf.c delete mode 100644 drivers/wiznet5k/ethernet/wizchip_conf.h delete mode 100644 drivers/wiznet5k/internet/dhcp/dhcp.c delete mode 100644 drivers/wiznet5k/internet/dhcp/dhcp.h delete mode 100644 drivers/wiznet5k/internet/dns/dns.c delete mode 100644 drivers/wiznet5k/internet/dns/dns.h delete mode 100644 examples/SDdatalogger/README.md delete mode 100644 examples/SDdatalogger/boot.py delete mode 100644 examples/SDdatalogger/cardreader.py delete mode 100644 examples/SDdatalogger/datalogger.py delete mode 100644 examples/accel_i2c.py delete mode 100644 examples/accellog.py delete mode 100644 examples/asmled.py delete mode 100644 examples/asmsum.py delete mode 100644 examples/conwaylife.py delete mode 100644 examples/embedding/Makefile delete mode 100644 examples/embedding/Makefile.upylib delete mode 100644 examples/embedding/README.md delete mode 100644 examples/embedding/hello-embed.c delete mode 120000 examples/embedding/mpconfigport.h delete mode 100644 examples/embedding/mpconfigport_minimal.h delete mode 100644 examples/hwapi/README.md delete mode 100644 examples/hwapi/button_led.py delete mode 100644 examples/hwapi/button_reaction.py delete mode 100644 examples/hwapi/hwconfig_console.py delete mode 100644 examples/hwapi/hwconfig_dragonboard410c.py delete mode 100644 examples/hwapi/hwconfig_esp8266_esp12.py delete mode 100644 examples/hwapi/hwconfig_pyboard.py delete mode 100644 examples/hwapi/hwconfig_z_96b_carbon.py delete mode 100644 examples/hwapi/hwconfig_z_frdm_k64f.py delete mode 100644 examples/hwapi/soft_pwm.py delete mode 100644 examples/hwapi/soft_pwm2_uasyncio.py delete mode 100644 examples/hwapi/soft_pwm_uasyncio.py delete mode 100644 examples/ledangle.py delete mode 100644 examples/mandel.py delete mode 100644 examples/micropython.py delete mode 100644 examples/network/http_client.py delete mode 100644 examples/network/http_client_ssl.py delete mode 100644 examples/network/http_server.py delete mode 100644 examples/network/http_server_simplistic.py delete mode 100644 examples/network/http_server_simplistic_commented.py delete mode 100644 examples/network/http_server_ssl.py delete mode 100644 examples/pins.py delete mode 100644 examples/pyb.py delete mode 100644 examples/switch.py delete mode 100644 examples/unix/ffi_example.py delete mode 100644 examples/unix/machine_bios.py delete mode 100644 index.rst diff --git a/CODECONVENTIONS.md b/CODECONVENTIONS.md deleted file mode 100644 index a80d5ec92e..0000000000 --- a/CODECONVENTIONS.md +++ /dev/null @@ -1,210 +0,0 @@ -Git commit conventions -====================== - -Each commit message should start with a directory or full file path -prefix, so it was clear which part of codebase a commit affects. If -a change affects one file, it's better to use path to a file. If it -affects few files in a subdirectory, using subdirectory as a prefix -is ok. For longish paths, it's acceptable to drop intermediate -components, which still should provide good context of a change. -It's also ok to drop file extensions. - -Besides prefix, first line of a commit message should describe a -change clearly and to the point, and be a grammatical sentence with -final full stop. First line should fit within 78 characters. Examples -of good first line of commit messages: - - py/objstr: Add splitlines() method. - py: Rename FOO to BAR. - docs/machine: Fix typo in reset() description. - ports: Switch to use lib/foo instead of duplicated code. - -After the first line, add an empty line and in following lines describe -a change in a detail, if needed. Any change beyond 5 lines would likely -require such detailed description. - -To get good practical examples of good commits and their messages, browse -the `git log` of the project. - -MicroPython doesn't require explicit sign-off for patches ("Signed-off-by" -lines and similar). Instead, the commit message, and your name and email -address on it construes your sign-off of the following: - -* That you wrote the change yourself, or took it from a project with - a compatible license (in the latter case the commit message, and possibly - source code should provide reference where the implementation was taken - from and give credit to the original author, as required by the license). -* That you are allowed to release these changes to an open-source project - (for example, changes done during paid work for a third party may require - explicit approval from that third party). -* That you (or your employer) agree to release the changes under - MicroPython's license, which is the MIT license. Note that you retain - copyright for your changes (for smaller changes, the commit message - conveys your copyright; if you make significant changes to a particular - source module, you're welcome to add your name to the file header). -* Your signature for all of the above, which is the 'Author' line in - the commit message, and which should include your full real name and - a valid and active email address by which you can be contacted in the - foreseeable future. - -Python code conventions -======================= - -Python code follows [PEP 8](http://legacy.python.org/dev/peps/pep-0008/). - -Naming conventions: -- Module names are short and all lowercase; eg pyb, stm. -- Class names are CamelCase, with abbreviations all uppercase; eg I2C, not - I2c. -- Function and method names are all lowercase with words separated by - a single underscore as necessary to improve readability; eg mem_read. -- Constants are all uppercase with words separated by a single underscore; - eg GPIO_IDR. - -C code conventions -================== - -When writing new C code, please adhere to the following conventions. - -White space: -- Expand tabs to 4 spaces. -- Don't leave trailing whitespace at the end of a line. -- For control blocks (if, for, while), put 1 space between the - keyword and the opening parenthesis. -- Put 1 space after a comma, and 1 space around operators. - -Braces: -- Use braces for all blocks, even no-line and single-line pieces of - code. -- Put opening braces on the end of the line it belongs to, not on - a new line. -- For else-statements, put the else on the same line as the previous - closing brace. - -Header files: -- Header files should be protected from multiple inclusion with #if - directives. See an existing header for naming convention. - -Names: -- Use underscore_case, not camelCase for all names. -- Use CAPS_WITH_UNDERSCORE for enums and macros. -- When defining a type use underscore_case and put '_t' after it. - -Integer types: MicroPython runs on 16, 32, and 64 bit machines, so it's -important to use the correctly-sized (and signed) integer types. The -general guidelines are: -- For most cases use mp_int_t for signed and mp_uint_t for unsigned - integer values. These are guaranteed to be machine-word sized and - therefore big enough to hold the value from a MicroPython small-int - object. -- Use size_t for things that count bytes / sizes of objects. -- You can use int/uint, but remember that they may be 16-bits wide. -- If in doubt, use mp_int_t/mp_uint_t. - -Comments: -- Be concise and only write comments for things that are not obvious. -- Use `// ` prefix, NOT `/* ... */`. No extra fluff. - -Memory allocation: -- Use m_new, m_renew, m_del (and friends) to allocate and free heap memory. - These macros are defined in py/misc.h. - -Examples --------- - -Braces, spaces, names and comments: - - #define TO_ADD (123) - - // This function will always recurse indefinitely and is only used to show - // coding style - int foo_function(int x, int some_value) { - if (x < some_value) { - foo(some_value, x); - } else { - foo(x + TO_ADD, some_value - 1); - } - - for (int my_counter = 0; my_counter < x; my_counter++) { - } - } - -Type declarations: - - typedef struct _my_struct_t { - int member; - void *data; - } my_struct_t; - -Documentation conventions -========================= - -MicroPython generally follows CPython in documentation process and -conventions. reStructuredText syntax is used for the documention. - -Specific conventions/suggestions: - -* Use `*` markup to refer to arguments of a function, e.g.: - -``` -.. method:: poll.unregister(obj) - - Unregister *obj* from polling. -``` - -* Use following syntax for cross-references/cross-links: - -``` -:func:`foo` - function foo in current module -:func:`module1.foo` - function foo in module "module1" - (similarly for other referent types) -:class:`Foo` - class Foo -:meth:`Class.method1` - method1 in Class -:meth:`~Class.method1` - method1 in Class, but rendered just as "method1()", - not "Class.method1()" -:meth:`title ` - reference method1, but render as "title" (use only - if really needed) -:mod:`module1` - module module1 - -`symbol` - generic xref syntax which can replace any of the above in case - the xref is unambiguous. If there's ambiguity, there will be a warning - during docs generation, which need to be fixed using one of the syntaxes - above -``` - -* Cross-referencing arbitrary locations -~~~ -.. _xref_target: - -Normal non-indented text. - -This is :ref:`reference `. - -(If xref target is followed by section title, can be just -:ref:`xref_target`). -~~~ - -* Linking to external URL: -``` -`link text `_ -``` - -* Referencing builtin singleton objects: -``` -``None``, ``True``, ``False`` -``` - -* Use following syntax to create common description for more than one element: -~~~ -.. function:: foo(x) - bar(y) - - Description common to foo() and bar(). -~~~ - - -More detailed guides and quickrefs: - -* http://www.sphinx-doc.org/en/stable/rest.html -* http://www.sphinx-doc.org/en/stable/markup/inline.html -* http://docutils.sourceforge.net/docs/user/rst/quickref.html diff --git a/README.md b/README.md deleted file mode 100644 index dedafb96b6..0000000000 --- a/README.md +++ /dev/null @@ -1,213 +0,0 @@ -# Adafruit CircuitPython - -[![Build Status](https://travis-ci.org/adafruit/circuitpython.svg?branch=master)](https://travis-ci.org/adafruit/circuitpython) -[![Doc Status](https://readthedocs.org/projects/circuitpython/badge/?version=latest)](http://circuitpython.readthedocs.io/) -[![Gitter](https://badges.gitter.im/adafruit/circuitpython.svg)](https://gitter.im/adafruit/circuitpython?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge) -[![Discord](https://img.shields.io/discord/327254708534116352.svg)](https://discord.gg/nBQh6qu) - -**[Status](#status)** | -**[Supported Boards](#supported-boards)** | -**[Download](#download)** | -**[Documentation](#documentation)** | -**[Contributing](#contributing)** | -**[Differences from Micropython](#differences-from-micropython)** | -**[Project Structure](#project-structure)** - -**Adafruit CircuitPython** is an open source derivative of -[MicroPython](http://www.micropython.org) for use on educational -development boards designed and sold by [Adafruit](https://www.adafruit.com). - -**CircuitPython**, a MicroPython derivative, implements Python 3.x on -microcontrollers such as the SAMD21 and ESP8266. - -## Status - -This project is in beta. Most APIs should be stable going forward. - -## Supported Boards - -### Designed for CircuitPython - -* [Adafruit CircuitPlayground Express][] -* [Adafruit Feather M0 Express][] -* [Adafruit Metro M0 Express][] -* [Adafruit Gemma M0][] - -### Other - -* [Adafruit Feather HUZZAH][] -* [Adafruit Feather M0 Basic][] -* [Adafruit Feather M0 Bluefruit LE][] (uses M0 Basic binaries) -* [Adafruit Feather M0 Adalogger][] (MicroSD card supported using the [Adafruit CircuitPython SD library](https://github.com/adafruit/Adafruit_CircuitPython_SD)) -* [Arduino Zero][] - -## Download - -Official binaries are available through the -[latest GitHub releases](https://github.com/adafruit/circuitpython/releases). -Continuous (one per commit) builds are available -[here](https://adafruit-circuit-python.s3.amazonaws.com/index.html?prefix=bin) -and includes experimental hardware support. - -## Documentation - -Guides and videos are available through the [Adafruit Learning System](https://learn.adafruit.com/) -under the [CircuitPython category](https://learn.adafruit.com/category/circuitpython) -and [MicroPython category](https://learn.adafruit.com/category/micropython). -An API reference is also available on [Read the Docs](http://circuitpython.readthedocs.io/en/latest/?). - -## Contributing - -See [CONTRIBUTING.md](https://github.com/adafruit/circuitpython/blob/master/CONTRIBUTING.md) -for full guidelines but please be aware that by contributing to this -project you are agreeing to the [Code of Conduct][]. Contributors who -follow the [Code of Conduct][] are welcome to submit pull requests and -they will be promptly reviewed by project admins. Please join the -[Gitter chat](https://gitter.im/adafruit/circuitpython) or -[Discord](https://discord.gg/nBQh6qu) too. - ---- - -## Differences from [MicroPython][] - -CircuitPython: - -* includes a port for Atmel SAMD21 (Commonly known as M0 - in Adafruit product names.) -* supports only Atmel SAMD21 and ESP8266 ports. -* tracks MicroPython's releases (not master). - -### Behavior - -* The order that files are run and the state that is shared between them. - CircuitPython's goal is to clarify the role of each file and make each - file independent from each other. - * `boot.py` (or `settings.py`) runs only once on start up before - USB is initialized. This lays the ground work for configuring USB - at startup rather than it being fixed. Since serial is not - available, output is written to `boot_out.txt`. - * `code.py` (or `main.py`) is run after every reload until it - finishes or is interrupted. After it is done running, the vm and hardware is - reinitialized. **This means you cannot read state from `code.py` - in the REPL anymore.** CircuitPython's goal for this change includes - reduce confusion about pins and memory being used. - * After `code.py` the REPL can be entered by pressing any key. It no - longer shares state with `code.py` so it is a fresh vm. - * Autoreload state will be maintained across reload. -* Adds a safe mode that does not run user code after a hard crash or - brown out. The hope is that this will make it easier to fix code that - causes nasty crashes by making it available through mass storage after - the crash. A reset (the button) is needed after its fixed to get back - into normal mode. - -### API - -* Unified hardware APIs: - [`audioio`](https://circuitpython.readthedocs.io/en/latest/shared-bindings/audioio/__init__.html), - [`analogio`](https://circuitpython.readthedocs.io/en/latest/shared-bindings/analogio/__init__.html), - [`busio`](https://circuitpython.readthedocs.io/en/latest/shared-bindings/busio/__init__.html), - [`digitalio`](https://circuitpython.readthedocs.io/en/latest/shared-bindings/digitalio/__init__.html), - [`pulseio`](https://circuitpython.readthedocs.io/en/latest/shared-bindings/pulseio/__init__.html), - [`touchio`](https://circuitpython.readthedocs.io/en/latest/shared-bindings/touchio/__init__.html), - [`microcontroller`](https://circuitpython.readthedocs.io/en/latest/shared-bindings/microcontroller/__init__.html), - [`board`](https://circuitpython.readthedocs.io/en/latest/shared-bindings/board/__init__.html), - [`bitbangio`](https://circuitpython.readthedocs.io/en/latest/shared-bindings/bitbangio/__init__.html) (Only available on atmel-samd21 and ESP8266 currently.) -* No `machine` API on Atmel SAMD21 port. - -### Modules - -* No module aliasing. (`uos` and `utime` are not available as `os` and - `time` respectively.) Instead `os`, `time`, and `random` are CPython - compatible. -* New `storage` module which manages file system mounts. (Functionality - from `uos` in MicroPython.) -* Modules with a CPython counterpart, such as `time`, `os` and `random`, - are strict [subsets](https://circuitpython.readthedocs.io/en/latest/shared-bindings/time/__init__.html) - of their [CPython version](https://docs.python.org/3.4/library/time.html?highlight=time#module-time). - Therefore, code from CircuitPython is runnable on CPython but not - necessarily the reverse. -* tick count is available as [`time.monotonic()`](https://circuitpython.readthedocs.io/en/latest/shared-bindings/time/__init__.html#time.monotonic) - -### atmel-samd21 features - -* RGB status LED -* Auto-reload after file write over mass storage. (Disable with - `samd.disable_autoreload()`) -* Wait state after boot and main run, before REPL. -* Main is one of these: `code.txt`, `code.py`, `main.py`, `main.txt` -* Boot is one of these: `settings.txt`, `settings.py`, `boot.py`, - `boot.txt` - ---- - -## Project Structure - -Here is an overview of the top-level source code directories. - -### Core - -The core code of [MicroPython][] is shared amongst ports including -CircuitPython: - -* `docs` High level user documentation in Sphinx reStructuredText - format. -* `drivers` External device drivers written in Python. -* `examples` A few example Python scripts. -* `extmod` Shared C code used in multiple ports' modules. -* `lib` Shared core C code including externally developed libraries such - as FATFS. -* `logo` The MicroPython logo. -* `mpy-cross` A cross compiler that converts Python files to byte code - prior to being run in MicroPython. Useful for reducing library size. -* `py` Core Python implementation, including compiler, runtime, and - core library. -* `shared-bindings` Shared definition of Python modules, their docs and - backing C APIs. Ports must implement the C API to support the - corresponding module. -* `shared-module` Shared implementation of Python modules that may be - based on `common-hal`. -* `tests` Test framework and test scripts. -* `tools` Various tools, including the pyboard.py module. - -### Ports - -Ports include the code unique to a microcontroller line and also -variations based on the board. - -* `atmel-samd` Support for SAMD21 based boards such as [Arduino Zero][], - [Adafruit Feather M0 Basic][], and [Adafruit Feather M0 Bluefruit LE][]. -* `bare-arm` A bare minimum version of MicroPython for ARM MCUs. -* `cc3200` Support for boards based [CC3200](http://www.ti.com/product/CC3200) - from TI such as the [WiPy 1.0](https://www.pycom.io/solutions/py-boards/wipy1/). -* `esp8266` Support for boards based on ESP8266 WiFi modules such as the - [Adafruit Feather HUZZAH][]. -* `minimal` A minimal MicroPython port. Start with this if you want - to port MicroPython to another microcontroller. -* `pic16bit` Support for 16-bit PIC microcontrollers. -* `qemu-arm` Support for ARM emulation through [QEMU](https://qemu.org). -* `stmhal` Support for boards based on STM32 microcontrollers including - the MicroPython flagship [PyBoard](https://store.micropython.org/store/#/products/PYBv1_1). -* `teensy` Support for the Teensy line of boards such as the - [Teensy 3.1](https://www.pjrc.com/teensy/teensy31.html). -* `unix` Support for UNIX. -* `windows` Support for [Windows](https://www.microsoft.com/en-us/windows/). -* `zephyr` Support for [Zephyr](https://www.zephyrproject.org/), a - real-time operating system by the Linux Foundation. - -CircuitPython only maintains the `atmel-samd` and `esp8266` ports. The -rest are here to maintain compatibility with the -[MicroPython][] parent project. - -**[⬆ back to top](#adafruit-circuitpython)** - -[Adafruit CircuitPlayground Express]: https://www.adafruit.com/product/3333 -[Adafruit Feather M0 Express]: https://www.adafruit.com/product/3403 -[Adafruit Metro M0 Express]: https://www.adafruit.com/product/3505 -[Adafruit Gemma M0]: https://www.adafruit.com/product/3501 -[Adafruit Feather HUZZAH]: https://www.adafruit.com/products/2821 -[Adafruit Feather M0 Basic]: https://www.adafruit.com/products/2772 -[Adafruit Feather M0 Bluefruit LE]: https://www.adafruit.com/products/2995 -[Adafruit Feather M0 Adalogger]: https://www.adafruit.com/product/2796 -[Arduino Zero]: https://www.arduino.cc/en/Main/ArduinoBoardZero -[MicroPython]: https://github.com/micropython/micropython -[Code of Conduct]: https://github.com/adafruit/circuitpython/blob/master/CODE_OF_CONDUCT.md \ No newline at end of file diff --git a/README.rst b/README.rst new file mode 100644 index 0000000000..b2de4decab --- /dev/null +++ b/README.rst @@ -0,0 +1,253 @@ +Adafruit CircuitPython +====================== + +|Build Status| |Doc Status| |Discord| + +**`Status <#status>`__** \| **`Supported Boards <#supported-boards>`__** +\| **`Download <#download>`__** \| +**`Documentation <#documentation>`__** \| +**`Contributing <#contributing>`__** \| **`Differences from +Micropython <#differences-from-micropython>`__** \| **`Project +Structure <#project-structure>`__** + +**CircuitPython** is an *education friendly* open source derivative of +``MicroPython ``\ *. CircuitPython supports use +on educational development boards designed and sold by +``Adafruit ``*. Adafruit CircuitPython features +unified Python core APIs and a growing list of Adafruit libraries and +drivers of that work with it. + +Status +------ + +This project is stable. Most APIs should be stable going forward. Those +that change will change on major version numbers such as 2.0.0 and +3.0.0. + +Supported Boards +---------------- + +Designed for CircuitPython +~~~~~~~~~~~~~~~~~~~~~~~~~~ + +- `Adafruit CircuitPlayground + Express `__ +- `Adafruit Feather M0 + Express `__ +- `Adafruit Metro M0 Express `__ +- `Adafruit Gemma M0 `__ + +Other +~~~~~ + +- `Adafruit Feather HUZZAH `__ +- `Adafruit Feather M0 + Basic `__ +- `Adafruit Feather M0 Bluefruit + LE `__ (uses M0 Basic + binaries) +- `Adafruit Feather M0 + Adalogger `__ (MicroSD card + supported using the `Adafruit CircuitPython SD + library `__) +- `Arduino Zero `__ + +Download +-------- + +Official binaries are available through the `latest GitHub +releases `__. +Continuous (one per commit) builds are available +`here `__ +and includes experimental hardware support. + +Documentation +------------- + +Guides and videos are available through the `Adafruit Learning +System `__ under the `CircuitPython +category `__ and +`MicroPython +category `__. An API +reference is also available on `Read the +Docs `__. + +Contributing +------------ + +See +`CONTRIBUTING.md `__ +for full guidelines but please be aware that by contributing to this +project you are agreeing to the `Code of +Conduct `__. +Contributors who follow the `Code of +Conduct `__ +are welcome to submit pull requests and they will be promptly reviewed +by project admins. Please join the `Gitter +chat `__ or +`Discord `__ too. + +-------------- + +Differences from `MicroPython `__ +----------------------------------------------------------------------------- + +CircuitPython: + +- includes a port for Atmel SAMD21 (Commonly known as M0 in Adafruit + product names.) +- supports only Atmel SAMD21 and ESP8266 ports. +- tracks MicroPython's releases (not master). + +Behavior +~~~~~~~~ + +- The order that files are run and the state that is shared between + them. CircuitPython's goal is to clarify the role of each file and + make each file independent from each other. +- ``boot.py`` (or ``settings.py``) runs only once on start up before + USB is initialized. This lays the ground work for configuring USB at + startup rather than it being fixed. Since serial is not available, + output is written to ``boot_out.txt``. +- ``code.py`` (or ``main.py``) is run after every reload until it + finishes or is interrupted. After it is done running, the vm and + hardware is reinitialized. **This means you cannot read state from + ``code.py`` in the REPL anymore.** CircuitPython's goal for this + change includes reduce confusion about pins and memory being used. +- After ``code.py`` the REPL can be entered by pressing any key. It no + longer shares state with ``code.py`` so it is a fresh vm. +- Autoreload state will be maintained across reload. +- Adds a safe mode that does not run user code after a hard crash or + brown out. The hope is that this will make it easier to fix code that + causes nasty crashes by making it available through mass storage + after the crash. A reset (the button) is needed after its fixed to + get back into normal mode. + +API +~~~ + +- Unified hardware APIs: + ```audioio`` `__, + ```analogio`` `__, + ```busio`` `__, + ```digitalio`` `__, + ```pulseio`` `__, + ```touchio`` `__, + ```microcontroller`` `__, + ```board`` `__, + ```bitbangio`` `__ + (Only available on atmel-samd21 and ESP8266 currently.) +- No ``machine`` API on Atmel SAMD21 port. + +Modules +~~~~~~~ + +- No module aliasing. (``uos`` and ``utime`` are not available as + ``os`` and ``time`` respectively.) Instead ``os``, ``time``, and + ``random`` are CPython compatible. +- New ``storage`` module which manages file system mounts. + (Functionality from ``uos`` in MicroPython.) +- Modules with a CPython counterpart, such as ``time``, ``os`` and + ``random``, are strict + `subsets `__ + of their `CPython + version `__. + Therefore, code from CircuitPython is runnable on CPython but not + necessarily the reverse. +- tick count is available as + ```time.monotonic()`` `__ + +atmel-samd21 features +~~~~~~~~~~~~~~~~~~~~~ + +- RGB status LED +- Auto-reload after file write over mass storage. (Disable with + ``samd.disable_autoreload()``) +- Wait state after boot and main run, before REPL. +- Main is one of these: ``code.txt``, ``code.py``, ``main.py``, + ``main.txt`` +- Boot is one of these: ``settings.txt``, ``settings.py``, ``boot.py``, + ``boot.txt`` + +-------------- + +Project Structure +----------------- + +Here is an overview of the top-level source code directories. + +Core +~~~~ + +The core code of +`MicroPython `__ is shared +amongst ports including CircuitPython: + +- ``docs`` High level user documentation in Sphinx reStructuredText + format. +- ``drivers`` External device drivers written in Python. +- ``examples`` A few example Python scripts. +- ``extmod`` Shared C code used in multiple ports' modules. +- ``lib`` Shared core C code including externally developed libraries + such as FATFS. +- ``logo`` The MicroPython logo. +- ``mpy-cross`` A cross compiler that converts Python files to byte + code prior to being run in MicroPython. Useful for reducing library + size. +- ``py`` Core Python implementation, including compiler, runtime, and + core library. +- ``shared-bindings`` Shared definition of Python modules, their docs + and backing C APIs. Ports must implement the C API to support the + corresponding module. +- ``shared-module`` Shared implementation of Python modules that may be + based on ``common-hal``. +- ``tests`` Test framework and test scripts. +- ``tools`` Various tools, including the pyboard.py module. + +Ports +~~~~~ + +Ports include the code unique to a microcontroller line and also +variations based on the board. + +- ``atmel-samd`` Support for SAMD21 based boards such as `Arduino + Zero `__, `Adafruit + Feather M0 Basic `__, and + `Adafruit Feather M0 Bluefruit + LE `__. +- ``bare-arm`` A bare minimum version of MicroPython for ARM MCUs. +- ``cc3200`` Support for boards based + `CC3200 `__ from TI such as the + `WiPy 1.0 `__. +- ``esp8266`` Support for boards based on ESP8266 WiFi modules such as + the `Adafruit Feather + HUZZAH `__. +- ``minimal`` A minimal MicroPython port. Start with this if you want + to port MicroPython to another microcontroller. +- ``pic16bit`` Support for 16-bit PIC microcontrollers. +- ``qemu-arm`` Support for ARM emulation through + `QEMU `__. +- ``stmhal`` Support for boards based on STM32 microcontrollers + including the MicroPython flagship + `PyBoard `__. +- ``teensy`` Support for the Teensy line of boards such as the `Teensy + 3.1 `__. +- ``unix`` Support for UNIX. +- ``windows`` Support for + `Windows `__. +- ``zephyr`` Support for `Zephyr `__, a + real-time operating system by the Linux Foundation. + +CircuitPython only maintains the ``atmel-samd`` and ``esp8266`` ports. +The rest are here to maintain compatibility with the +`MicroPython `__ parent +project. + +**`⬆ back to top <#adafruit-circuitpython>`__** + +.. |Build Status| image:: https://travis-ci.org/adafruit/circuitpython.svg?branch=master + :target: https://travis-ci.org/adafruit/circuitpython +.. |Doc Status| image:: https://readthedocs.org/projects/circuitpython/badge/?version=latest + :target: http://circuitpython.readthedocs.io/ +.. |Discord| image:: https://img.shields.io/discord/327254708534116352.svg + :target: https://discord.gg/nBQh6qu diff --git a/atmel-samd/README.rst b/atmel-samd/README.rst index 5c314c53f6..4260ea4b81 100644 --- a/atmel-samd/README.rst +++ b/atmel-samd/README.rst @@ -15,39 +15,39 @@ different names. The table below matches the pin order in and omits the pins only available on the largest package because all supported boards use smaller version. -===================== =============== =========================== ==================== ================ ================== ========================= ================ ================ +===================== =============== =========================== ====================== ================ ================== ========================= ================ ================ `microcontroller.pin` `board` ---------------------- ----------------------------------------------------------------------------------------------------------------------------------------------------------------------- -Datasheet arduino_zero circuitplayground_express feather_m0_adalogger feather_m0_basic feather_m0_express gemma_m0 metro_m0_express trinket_m0 -===================== =============== =========================== ==================== ================ ================== ========================= ================ ================ -PA00 ``ACCELEROMETER_SDA`` ``APA102_MOSI`` ``APA102_MOSI`` -PA01 ``ACCELEROMETER_SCL`` ``APA102_SCK`` ``APA102_SCK`` -PA02 ``A0`` ``A0`` / ``SPEAKER`` ``A0`` ``A0`` ``A0`` ``A0`` / ``D1`` ``A0`` ``D1`` / ``A0`` +--------------------- ------------------------------------------------------------------------------------------------------------------------------------------------------------------------- +Datasheet arduino_zero circuitplayground_express feather_m0_adalogger feather_m0_basic feather_m0_express gemma_m0 metro_m0_express trinket_m0 +===================== =============== =========================== ====================== ================ ================== ========================= ================ ================ +PA00 ``ACCELEROMETER_SDA`` ``APA102_MOSI`` ``APA102_MOSI`` +PA01 ``ACCELEROMETER_SCL`` ``APA102_SCK`` ``APA102_SCK`` +PA02 ``A0`` ``A0`` / ``SPEAKER`` ``A0`` ``A0`` ``A0`` ``A0`` / ``D1`` ``A0`` ``D1`` / ``A0`` PA03 -PB08 ``A1`` ``A7`` / ``TX`` ``A1`` ``A1`` ``A1`` ``A1`` -PB09 ``A2`` ``A6`` / ``RX`` ``A2`` ``A2`` ``A2`` ``A2`` -PA04 ``A3`` ``IR_PROXIMITY`` ``A3`` ``A3`` ``A3`` ``D0`` / ``TX`` / ``SDA`` ``A3`` -PA05 ``A4`` ``A1`` ``A4`` ``A4`` ``A4`` ``D2`` / ``RX`` / ``SCL`` ``A4`` -PA06 ``D8`` ``A2`` ``D8`` / ``GREEN_LED`` ``NEOPIXEL`` ``D8`` ``D4`` / ``TX`` -PA07 ``D9`` ``A3`` ``D9`` ``D9`` ``D9`` ``D9`` ``D3`` / ``RX`` -PA08 ``D4`` ``MICROPHONE_DO`` ``D4`` / ``SD_CS`` ``D4`` ``D0`` / ``SDA`` -PA09 ``D3`` ``TEMPERATURE`` / ``A9`` ``D3`` ``D2`` / ``SCL`` -PA10 ``D1`` / ``TX`` ``MICROPHONE_SCK`` ``D1`` / ``TX`` ``D1`` / ``TX`` ``D1`` / ``TX`` ``D1`` / ``TX`` ``D13`` -PA11 ``D0`` / ``RX`` ``LIGHT`` / ``A8`` ``D0`` / ``RX`` ``D0`` / ``RX`` ``D0`` / ``RX`` ``D0`` / ``RX`` -PB10 ``MOSI`` ``MOSI`` ``MOSI`` ``MOSI`` ``MOSI`` -PB11 ``SCK`` ``SCK`` ``SCK`` ``SCK`` ``SCK`` -PA12 ``MISO`` ``REMOTEIN`` / ``IR_RX`` ``MISO`` ``MISO`` ``MISO`` ``MISO`` -PA13 ``ACCELEROMETER_INTERRUPT`` ``FLASH_CS`` -PA14 ``D2`` ``BUTTON_B`` / ``D5`` ``D2`` -PA15 ``D5`` ``SLIDE_SWITCH`` / ``D7`` ``D5`` ``D5`` ``D5`` ``D5`` -PA16 ``D11`` ``MISO`` ``D11`` ``D11`` ``D11`` ``D11`` -PA17 ``D13`` ``D13`` ``D13`` / ``RED_LED`` ``D13`` ``D13`` ``D13`` -PA18 ``D10`` ``D10`` ``D10`` ``D10`` ``D10`` -PA19 ``D12`` ``D12`` ``D12`` ``D12`` ``D12`` -PA20 ``D6`` ``MOSI`` ``D6`` ``D6`` ``D6`` ``D6`` -PA21 ``D7`` ``SCK`` ``D7`` / ``SD_CD`` ``D7`` -PA22 ``SDA`` ``SDA`` ``SDA`` ``SDA`` ``SDA`` -PA23 ``SCL`` ``REMOTEOUT`` / ``IR_TX`` ``SCL`` ``SCL`` ``SCL`` ``L`` / ``D13`` ``SCL`` +PB08 ``A1`` ``A7`` / ``TX`` ``A1`` ``A1`` ``A1`` ``A1`` +PB09 ``A2`` ``A6`` / ``RX`` ``A2`` ``A2`` ``A2`` ``A2`` +PA04 ``A3`` ``IR_PROXIMITY`` ``A3`` ``A3`` ``A3`` ``D0`` / ``TX`` / ``SDA`` ``A3`` +PA05 ``A4`` ``A1`` ``A4`` ``A4`` ``A4`` ``D2`` / ``RX`` / ``SCL`` ``A4`` +PA06 ``D8`` ``A2`` ``D8`` / ``GREEN_LED`` ``NEOPIXEL`` ``D8`` ``D4`` / ``TX`` +PA07 ``D9`` ``A3`` ``D9`` ``D9`` ``D9`` ``D9`` ``D3`` / ``RX`` +PA08 ``D4`` ``MICROPHONE_DO`` ``D4`` / ``SD_CS`` ``D4`` ``D0`` / ``SDA`` +PA09 ``D3`` ``TEMPERATURE`` / ``A9`` ``D3`` ``D2`` / ``SCL`` +PA10 ``D1`` / ``TX`` ``MICROPHONE_SCK`` ``D1`` / ``TX`` ``D1`` / ``TX`` ``D1`` / ``TX`` ``D1`` / ``TX`` ``D13`` +PA11 ``D0`` / ``RX`` ``LIGHT`` / ``A8`` ``D0`` / ``RX`` ``D0`` / ``RX`` ``D0`` / ``RX`` ``D0`` / ``RX`` +PB10 ``MOSI`` ``MOSI`` ``MOSI`` ``MOSI`` ``MOSI`` +PB11 ``SCK`` ``SCK`` ``SCK`` ``SCK`` ``SCK`` +PA12 ``MISO`` ``REMOTEIN`` / ``IR_RX`` ``MISO`` ``MISO`` ``MISO`` ``MISO`` +PA13 ``ACCELEROMETER_INTERRUPT`` ``FLASH_CS`` +PA14 ``D2`` ``BUTTON_B`` / ``D5`` ``D2`` +PA15 ``D5`` ``SLIDE_SWITCH`` / ``D7`` ``D5`` ``D5`` ``D5`` ``D5`` +PA16 ``D11`` ``MISO`` ``D11`` ``D11`` ``D11`` ``D11`` +PA17 ``D13`` ``D13`` ``D13`` / ``RED_LED`` ``D13`` ``D13`` ``D13`` +PA18 ``D10`` ``D10`` ``D10`` ``D10`` ``D10`` +PA19 ``D12`` ``D12`` ``D12`` ``D12`` ``D12`` +PA20 ``D6`` ``MOSI`` ``D6`` ``D6`` ``D6`` ``D6`` +PA21 ``D7`` ``SCK`` ``D7`` / ``SD_CD`` ``D7`` +PA22 ``SDA`` ``SDA`` ``SDA`` ``SDA`` ``SDA`` +PA23 ``SCL`` ``REMOTEOUT`` / ``IR_TX`` ``SCL`` ``SCL`` ``SCL`` ``L`` / ``D13`` ``SCL`` PA24 PA25 PB22 ``FLASH_CS`` @@ -55,11 +55,11 @@ PB23 ``NEOPIXEL`` / ``D8`` PA27 PA28 ``BUTTON_A`` / ``D4`` PA29 -PA30 ``SPEAKER_ENABLE`` ``NEOPIXEL`` +PA30 ``SPEAKER_ENABLE`` ``NEOPIXEL`` PA31 -PB02 ``A5`` ``A5`` / ``SDA`` ``A5`` ``A5`` ``A5`` ``A5`` +PB02 ``A5`` ``A5`` / ``SDA`` ``A5`` ``A5`` ``A5`` ``A5`` PB03 ``A4`` / ``SCL`` -===================== =============== =========================== ==================== ================ ================== ========================= ================ ================ +===================== =============== =========================== ====================== ================ ================== ========================= ================ ================ Here is a table about which pins can do what in CircuitPython terms. However, just because something is listed, doesn't mean it will always work. Existing use diff --git a/conf.py b/conf.py index 42536368f4..cb46b13a5d 100644 --- a/conf.py +++ b/conf.py @@ -23,9 +23,7 @@ from recommonmark.parser import CommonMarkParser # documentation root, use os.path.abspath to make it absolute, like shown here. sys.path.insert(0, os.path.abspath('.')) - -# Specify a custom master document based on the port name -master_doc = 'index' +master_doc = 'docs/index' # -- General configuration ------------------------------------------------ @@ -60,7 +58,7 @@ source_parsers = {'.md': CommonMarkParser, # General information about the project. project = 'Adafruit CircuitPython' -copyright = '2014-2017, MicroPython & CircuitPython contributors (https://github.com/adafruit/circuitpython/graphs/contributors)' +copyright = '2014-2018, MicroPython & CircuitPython contributors (https://github.com/adafruit/circuitpython/graphs/contributors)' # These are overwritten on ReadTheDocs. # The version info for the project you're documenting, acts as replacement for @@ -83,21 +81,27 @@ version = release = '0.0.0' # List of patterns, relative to source directory, that match files and # directories to ignore when looking for source files. -exclude_patterns = ["*/build-*", +exclude_patterns = ["*/build*", ".venv", "atmel-samd/asf", "atmel-samd/asf_conf", "atmel-samd/common-hal", "atmel-samd/boards", "atmel-samd/QTouch", + "atmel-samd/freetouch", "atmel-samd/*.c", "atmel-samd/*.h", "bare-arm", "cc3200", "cc3200/FreeRTOS", "cc3200/hal", + "docs/README.md", "drivers", - "esp8266", + "esp8266/boards", + "esp8266/common-hal", + "esp8266/modules", + "esp8266/*.c", + "esp8266/*.h", "examples", "extmod", "frozen", @@ -107,6 +111,7 @@ exclude_patterns = ["*/build-*", "pic16bit", "py", "qemu-arm", + "shared-bindings/util.*", "shared-module", "stmhal", "stmhal/hal", @@ -148,7 +153,7 @@ pygments_style = 'sphinx' # of rst_prolog, so we follow. Absolute paths below mean "from the base # of the doctree". rst_epilog = """ -.. include:: /templates/replace.inc +.. include:: /docs/templates/replace.inc """ # -- Options for HTML output ---------------------------------------------- diff --git a/docs/design_guide.rst b/docs/design_guide.rst index 1c0f5dbbd7..1a4a08a52f 100644 --- a/docs/design_guide.rst +++ b/docs/design_guide.rst @@ -305,10 +305,11 @@ For example, if you are writing a driver for an I2C device, then take in an I2C object instead of the pins themselves. This allows the calling code to provide any object with the appropriate methods such as an I2C expansion board. -Another example is to expect a `DigitalInOut` for a pin to toggle instead of a -`microcontroller.Pin` from `board`. Taking in the `~microcontroller.Pin` object -alone would limit the driver to pins on the actual microcontroller instead of pins -provided by another driver such as an IO expander. +Another example is to expect a :py:class:`~digitalio.DigitalInOut` for a pin to +toggle instead of a :py:class:`~microcontroller.Pin` from `board`. Taking in the +:py:class:`~microcontroller.Pin` object alone would limit the driver to pins on +the actual microcontroller instead of pins provided by another driver such as an +IO expander. Lots of small modules -------------------------------------------------------------------------------- diff --git a/docs/differences/index_template.txt b/docs/differences/index_template.txt deleted file mode 100644 index eb8b3ba640..0000000000 --- a/docs/differences/index_template.txt +++ /dev/null @@ -1,10 +0,0 @@ -.. _cpython_diffs: - -MicroPython differences from CPython -==================================== - -The operations listed in this section produce conflicting results in MicroPython when compared to standard Python. - -.. toctree:: - :maxdepth: 2 - diff --git a/docs/esp8266/general.rst b/docs/esp8266/general.rst deleted file mode 100644 index e23acb469b..0000000000 --- a/docs/esp8266/general.rst +++ /dev/null @@ -1,147 +0,0 @@ -General information about the ESP8266 port -========================================== - -ESP8266 is a popular WiFi-enabled System-on-Chip (SoC) by Espressif Systems. - -Multitude of boards -------------------- - -There are a multitude of modules and boards from different sources which carry -the ESP8266 chip. MicroPython tries to provide a generic port which would run on -as many boards/modules as possible, but there may be limitations. Adafruit -Feather HUZZAH board is taken as a reference board for the port (for example, -testing is performed on it). If you have another board, please make sure you -have datasheet, schematics and other reference materials for your board -handy to look up various aspects of your board functioning. - -To make a generic ESP8266 port and support as many boards as possible, -following design and implementation decision were made: - -* GPIO pin numbering is based on ESP8266 chip numbering, not some "logical" - numbering of a particular board. Please have the manual/pin diagram of your board - at hand to find correspondence between your board pins and actual ESP8266 pins. - We also encourage users of various boards to share this mapping via MicroPython - forum, with the idea to collect community-maintained reference materials - eventually. -* All pins which make sense to support, are supported by MicroPython - (for example, pins which are used to connect SPI flash - are not exposed, as they're unlikely useful for anything else, and - operating on them will lead to board lock-up). However, any particular - board may expose only subset of pins. Consult your board reference manual. -* Some boards may lack external pins/internal connectivity to support - ESP8266 deepsleep mode. - - -Technical specifications and SoC datasheets -------------------------------------------- - -The datasheets and other reference material for ESP8266 chip are available -from the vendor site: http://bbs.espressif.com/viewtopic.php?f=67&t=225 . -They are the primary reference for the chip technical specifications, capabilities, -operating modes, internal functioning, etc. - -For your convenience, some of technical specifications are provided below: - -* Architecture: Xtensa lx106 -* CPU frequency: 80MHz overclockable to 160MHz -* Total RAM available: 96KB (part of it reserved for system) -* BootROM: 64KB -* Internal FlashROM: None -* External FlashROM: code and data, via SPI Flash. Normal sizes 512KB-4MB. -* GPIO: 16 + 1 (GPIOs are multiplexed with other functions, including - external FlashROM, UART, deep sleep wake-up, etc.) -* UART: One RX/TX UART (no hardware handshaking), one TX-only UART. -* SPI: 2 SPI interfaces (one used for FlashROM). -* I2C: No native external I2C (bitbang implementation available on any pins). -* I2S: 1. -* Programming: using BootROM bootloader from UART. Due to external FlashROM - and always-available BootROM bootloader, ESP8266 is not brickable. - - -Scarcity of runtime resources ------------------------------ - -ESP8266 has very modest resources (first of all, RAM memory). So, please -avoid allocating too big container objects (lists, dictionaries) and -buffers. There is also no full-fledged OS to keep track of resources -and automatically clean them up, so that's the task of a user/user -application: please be sure to close open files, sockets, etc. as soon -as possible after use. - - -Boot process ------------- - -On boot, MicroPython EPS8266 port executes ``_boot.py`` script from internal -frozen modules. It mounts filesystem in FlashROM, or if it's not available, -performs first-time setup of the module and creates the filesystem. This -part of the boot process is considered fixed, and not available for customization -for end users (even if you build from source, please refrain from changes to -it; customization of early boot process is available only to advanced users -and developers, who can diagnose themselves any issues arising from -modifying the standard process). - -Once the filesystem is mounted, ``boot.py`` is executed from it. The standard -version of this file is created during first-time module set up and has -commands to start a WebREPL daemon (disabled by default, configurable -with ``webrepl_setup`` module), etc. This -file is customizable by end users (for example, you may want to set some -parameters or add other services which should be run on -a module start-up). But keep in mind that incorrect modifications to boot.py -may still lead to boot loops or lock ups, requiring to reflash a module -from scratch. (In particular, it's recommended that you use either -``webrepl_setup`` module or manual editing to configure WebREPL, but not -both). - -As a final step of boot procedure, ``main.py`` is executed from filesystem, -if exists. This file is a hook to start up a user application each time -on boot (instead of going to REPL). For small test applications, you may -name them directly as ``main.py``, and upload to module, but instead it's -recommended to keep your application(s) in separate files, and have just -the following in ``main.py``:: - - import my_app - my_app.main() - -This will allow to keep the structure of your application clear, as well as -allow to install multiple applications on a board, and switch among them. - - -Known Issues ------------- - -Real-time clock -~~~~~~~~~~~~~~~ - -RTC in ESP8266 has very bad accuracy, drift may be seconds per minute. As -a workaround, to measure short enough intervals you can use -``utime.time()``, etc. functions, and for wall clock time, synchronize from -the net using included ``ntptime.py`` module. - -Due to limitations of the ESP8266 chip the internal real-time clock (RTC) -will overflow every 7:45h. If a long-term working RTC time is required then -``time()`` or ``localtime()`` must be called at least once within 7 hours. -MicroPython will then handle the overflow. - -Sockets and WiFi buffers overflow -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -Socket instances remain active until they are explicitly closed. This has two -consequences. Firstly they occupy RAM, so an application which opens sockets -without closing them may eventually run out of memory. Secondly not properly -closed socket can cause the low-level part of the vendor WiFi stack to emit -``Lmac`` errors. This occurs if data comes in for a socket and is not -processed in a timely manner. This can overflow the WiFi stack input queue -and lead to a deadlock. The only recovery is by a hard reset. - -The above may also happen after an application terminates and quits to the REPL -for any reason including an exception. Subsequent arrival of data provokes the -failure with the above error message repeatedly issued. So, sockets should be -closed in any case, regardless whether an application terminates successfully -or by an exeption, for example using try/finally:: - - sock = socket(...) - try: - # Use sock - finally: - sock.close() diff --git a/docs/esp8266/img/adafruit_products_pinoutstop.jpg b/docs/esp8266/img/adafruit_products_pinoutstop.jpg deleted file mode 100644 index 655e27aee3104b7d8a0abce7e8f0fa5750de7ec3..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 79455 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
{H;Du9-dX(`yD<{eQ8>rn^$#q^zr!| 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 z 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 r!9hp@5j0B{3ypEh_v!`PNt)ePp`lzj^=JbkvIv diff --git a/docs/esp8266/index.rst b/docs/esp8266/index.rst deleted file mode 100644 index 63cf65c614..0000000000 --- a/docs/esp8266/index.rst +++ /dev/null @@ -1,8 +0,0 @@ -ESP8266 -======================================== - -.. toctree:: - - quickref.rst - general.rst - tutorial/index.rst diff --git a/docs/esp8266/quickref.rst b/docs/esp8266/quickref.rst deleted file mode 100644 index ccf6365c83..0000000000 --- a/docs/esp8266/quickref.rst +++ /dev/null @@ -1,364 +0,0 @@ -.. _quickref: - -Quick reference for the ESP8266 -=============================== - -.. image:: img/adafruit_products_pinoutstop.jpg - :alt: Adafruit Feather HUZZAH board - :width: 640px - -The Adafruit Feather HUZZAH board (image attribution: Adafruit). - -Installing MicroPython ----------------------- - -See the corresponding section of tutorial: :ref:`intro`. It also includes -a troubleshooting subsection. - -General board control ---------------------- - -The MicroPython REPL is on UART0 (GPIO1=TX, GPIO3=RX) at baudrate 115200. -Tab-completion is useful to find out what methods an object has. -Paste mode (ctrl-E) is useful to paste a large slab of Python code into -the REPL. - -The :mod:`machine` module:: - - import machine - - machine.freq() # get the current frequency of the CPU - machine.freq(160000000) # set the CPU frequency to 160 MHz - -The :mod:`esp` module:: - - import esp - - esp.osdebug(None) # turn off vendor O/S debugging messages - esp.osdebug(0) # redirect vendor O/S debugging messages to UART(0) - -Networking ----------- - -The :mod:`network` module:: - - import network - - wlan = network.WLAN(network.STA_IF) # create station interface - wlan.active(True) # activate the interface - wlan.scan() # scan for access points - wlan.isconnected() # check if the station is connected to an AP - wlan.connect('essid', 'password') # connect to an AP - wlan.config('mac') # get the interface's MAC adddress - wlan.ifconfig() # get the interface's IP/netmask/gw/DNS addresses - - ap = network.WLAN(network.AP_IF) # create access-point interface - ap.active(True) # activate the interface - ap.config(essid='ESP-AP') # set the ESSID of the access point - -A useful function for connecting to your local WiFi network is:: - - def do_connect(): - import network - wlan = network.WLAN(network.STA_IF) - wlan.active(True) - if not wlan.isconnected(): - print('connecting to network...') - wlan.connect('essid', 'password') - while not wlan.isconnected(): - pass - print('network config:', wlan.ifconfig()) - -Once the network is established the :mod:`socket ` module can be used -to create and use TCP/UDP sockets as usual. - -Delay and timing ----------------- - -Use the :mod:`time ` module:: - - import time - - time.sleep(1) # sleep for 1 second - time.sleep_ms(500) # sleep for 500 milliseconds - time.sleep_us(10) # sleep for 10 microseconds - start = time.ticks_ms() # get millisecond counter - delta = time.ticks_diff(time.ticks_ms(), start) # compute time difference - -Timers ------- - -Virtual (RTOS-based) timers are supported. Use the :ref:`machine.Timer ` class -with timer ID of -1:: - - from machine import Timer - - tim = Timer(-1) - tim.init(period=5000, mode=Timer.ONE_SHOT, callback=lambda t:print(1)) - tim.init(period=2000, mode=Timer.PERIODIC, callback=lambda t:print(2)) - -The period is in milliseconds. - -Pins and GPIO -------------- - -Use the :ref:`machine.Pin ` class:: - - from machine import Pin - - p0 = Pin(0, Pin.OUT) # create output pin on GPIO0 - p0.on() # set pin to "on" (high) level - p0.off() # set pin to "off" (low) level - p0.value(1) # set pin to on/high - - p2 = Pin(2, Pin.IN) # create input pin on GPIO2 - print(p2.value()) # get value, 0 or 1 - - p4 = Pin(4, Pin.IN, Pin.PULL_UP) # enable internal pull-up resistor - p5 = Pin(5, Pin.OUT, value=1) # set pin high on creation - -Available pins are: 0, 1, 2, 3, 4, 5, 12, 13, 14, 15, 16, which correspond -to the actual GPIO pin numbers of ESP8266 chip. Note that many end-user -boards use their own adhoc pin numbering (marked e.g. D0, D1, ...). As -MicroPython supports different boards and modules, physical pin numbering -was chosen as the lowest common denominator. For mapping between board -logical pins and physical chip pins, consult your board documentation. - -Note that Pin(1) and Pin(3) are REPL UART TX and RX respectively. -Also note that Pin(16) is a special pin (used for wakeup from deepsleep -mode) and may be not available for use with higher-level classes like -``Neopixel``. - -PWM (pulse width modulation) ----------------------------- - -PWM can be enabled on all pins except Pin(16). There is a single frequency -for all channels, with range between 1 and 1000 (measured in Hz). The duty -cycle is between 0 and 1023 inclusive. - -Use the ``machine.PWM`` class:: - - from machine import Pin, PWM - - pwm0 = PWM(Pin(0)) # create PWM object from a pin - pwm0.freq() # get current frequency - pwm0.freq(1000) # set frequency - pwm0.duty() # get current duty cycle - pwm0.duty(200) # set duty cycle - pwm0.deinit() # turn off PWM on the pin - - pwm2 = PWM(Pin(2), freq=500, duty=512) # create and configure in one go - -ADC (analog to digital conversion) ----------------------------------- - -ADC is available on a dedicated pin. -Note that input voltages on the ADC pin must be between 0v and 1.0v. - -Use the :ref:`machine.ADC ` class:: - - from machine import ADC - - adc = ADC(0) # create ADC object on ADC pin - adc.read() # read value, 0-1024 - -Software SPI bus ----------------- - -There are two SPI drivers. One is implemented in software (bit-banging) -and works on all pins, and is accessed via the :ref:`machine.SPI ` -class:: - - from machine import Pin, SPI - - # construct an SPI bus on the given pins - # polarity is the idle state of SCK - # phase=0 means sample on the first edge of SCK, phase=1 means the second - spi = SPI(-1, baudrate=100000, polarity=1, phase=0, sck=Pin(0), mosi=Pin(2), miso=Pin(4)) - - spi.init(baudrate=200000) # set the baudrate - - spi.read(10) # read 10 bytes on MISO - spi.read(10, 0xff) # read 10 bytes while outputing 0xff on MOSI - - buf = bytearray(50) # create a buffer - spi.readinto(buf) # read into the given buffer (reads 50 bytes in this case) - spi.readinto(buf, 0xff) # read into the given buffer and output 0xff on MOSI - - spi.write(b'12345') # write 5 bytes on MOSI - - buf = bytearray(4) # create a buffer - spi.write_readinto(b'1234', buf) # write to MOSI and read from MISO into the buffer - spi.write_readinto(buf, buf) # write buf to MOSI and read MISO back into buf - - -Hardware SPI bus ----------------- - -The hardware SPI is faster (up to 80Mhz), but only works on following pins: -``MISO`` is GPIO12, ``MOSI`` is GPIO13, and ``SCK`` is GPIO14. It has the same -methods as the bitbanging SPI class above, except for the pin parameters for the -constructor and init (as those are fixed):: - - from machine import Pin, SPI - - hspi = SPI(1, baudrate=80000000, polarity=0, phase=0) - -(``SPI(0)`` is used for FlashROM and not available to users.) - -I2C bus -------- - -The I2C driver is implemented in software and works on all pins, -and is accessed via the :ref:`machine.I2C ` class:: - - from machine import Pin, I2C - - # construct an I2C bus - i2c = I2C(scl=Pin(5), sda=Pin(4), freq=100000) - - i2c.readfrom(0x3a, 4) # read 4 bytes from slave device with address 0x3a - i2c.writeto(0x3a, '12') # write '12' to slave device with address 0x3a - - buf = bytearray(10) # create a buffer with 10 bytes - i2c.writeto(0x3a, buf) # write the given buffer to the slave - -Deep-sleep mode ---------------- - -Connect GPIO16 to the reset pin (RST on HUZZAH). Then the following code -can be used to sleep, wake and check the reset cause:: - - import machine - - # configure RTC.ALARM0 to be able to wake the device - rtc = machine.RTC() - rtc.irq(trigger=rtc.ALARM0, wake=machine.DEEPSLEEP) - - # check if the device woke from a deep sleep - if machine.reset_cause() == machine.DEEPSLEEP_RESET: - print('woke from a deep sleep') - - # set RTC.ALARM0 to fire after 10 seconds (waking the device) - rtc.alarm(rtc.ALARM0, 10000) - - # put the device to sleep - machine.deepsleep() - -OneWire driver --------------- - -The OneWire driver is implemented in software and works on all pins:: - - from machine import Pin - import onewire - - ow = onewire.OneWire(Pin(12)) # create a OneWire bus on GPIO12 - ow.scan() # return a list of devices on the bus - ow.reset() # reset the bus - ow.readbyte() # read a byte - ow.writebyte(0x12) # write a byte on the bus - ow.write('123') # write bytes on the bus - ow.select_rom(b'12345678') # select a specific device by its ROM code - -There is a specific driver for DS18S20 and DS18B20 devices:: - - import time, ds18x20 - ds = ds18x20.DS18X20(ow) - roms = ds.scan() - ds.convert_temp() - time.sleep_ms(750) - for rom in roms: - print(ds.read_temp(rom)) - -Be sure to put a 4.7k pull-up resistor on the data line. Note that -the ``convert_temp()`` method must be called each time you want to -sample the temperature. - -NeoPixel driver ---------------- - -Use the ``neopixel`` module:: - - from machine import Pin - from neopixel import NeoPixel - - pin = Pin(0, Pin.OUT) # set GPIO0 to output to drive NeoPixels - np = NeoPixel(pin, 8) # create NeoPixel driver on GPIO0 for 8 pixels - np[0] = (255, 255, 255) # set the first pixel to white - np.write() # write data to all pixels - r, g, b = np[0] # get first pixel colour - -For low-level driving of a NeoPixel:: - - import esp - esp.neopixel_write(pin, grb_buf, is800khz) - -APA102 driver -------------- - -Use the ``apa102`` module:: - - from machine import Pin - from apa102 import APA102 - - clock = Pin(14, Pin.OUT) # set GPIO14 to output to drive the clock - data = Pin(13, Pin.OUT) # set GPIO13 to output to drive the data - apa = APA102(clock, data, 8) # create APA102 driver on the clock and the data pin for 8 pixels - apa[0] = (255, 255, 255, 31) # set the first pixel to white with a maximum brightness of 31 - apa.write() # write data to all pixels - r, g, b, brightness = apa[0] # get first pixel colour - -For low-level driving of an APA102:: - - import esp - esp.apa102_write(clock_pin, data_pin, rgbi_buf) - -DHT driver ----------- - -The DHT driver is implemented in software and works on all pins:: - - import dht - import machine - - d = dht.DHT11(machine.Pin(4)) - d.measure() - d.temperature() # eg. 23 (°C) - d.humidity() # eg. 41 (% RH) - - d = dht.DHT22(machine.Pin(4)) - d.measure() - d.temperature() # eg. 23.6 (°C) - d.humidity() # eg. 41.3 (% RH) - -WebREPL (web browser interactive prompt) ----------------------------------------- - -WebREPL (REPL over WebSockets, accessible via a web browser) is an -experimental feature available in ESP8266 port. Download web client -from https://github.com/micropython/webrepl (hosted version available -at http://micropython.org/webrepl), and configure it by executing:: - - import webrepl_setup - -and following on-screen instructions. After reboot, it will be available -for connection. If you disabled automatic start-up on boot, you may -run configured daemon on demand using:: - - import webrepl - webrepl.start() - -The supported way to use WebREPL is by connecting to ESP8266 access point, -but the daemon is also started on STA interface if it is active, so if your -router is set up and works correctly, you may also use WebREPL while connected -to your normal Internet access point (use the ESP8266 AP connection method -if you face any issues). - -Besides terminal/command prompt access, WebREPL also has provision for file -transfer (both upload and download). Web client has buttons for the -corresponding functions, or you can use command-line client ``webrepl_cli.py`` -from the repository above. - -See the MicroPython forum for other community-supported alternatives -to transfer files to ESP8266. diff --git a/docs/esp8266/tutorial/adc.rst b/docs/esp8266/tutorial/adc.rst deleted file mode 100644 index fa6fdaba73..0000000000 --- a/docs/esp8266/tutorial/adc.rst +++ /dev/null @@ -1,19 +0,0 @@ -Analog to Digital Conversion -============================ - -The ESP8266 has a single pin (separate to the GPIO pins) which can be used to -read analog voltages and convert them to a digital value. You can construct -such an ADC pin object using:: - - >>> import machine - >>> adc = machine.ADC(0) - -Then read its value with:: - - >>> adc.read() - 58 - -The values returned from the ``read()`` function are between 0 (for 0.0 volts) -and 1024 (for 1.0 volts). Please note that this input can only tolerate a -maximum of 1.0 volts and you must use a voltage divider circuit to measure -larger voltages. diff --git a/docs/esp8266/tutorial/dht.rst b/docs/esp8266/tutorial/dht.rst deleted file mode 100644 index 1602e8a337..0000000000 --- a/docs/esp8266/tutorial/dht.rst +++ /dev/null @@ -1,65 +0,0 @@ -Temperature and Humidity -======================== - -DHT (Digital Humidity & Temperature) sensors are low cost digital sensors with -capacitive humidity sensors and thermistors to measure the surrounding air. -They feature a chip that handles analog to digital conversion and provide a -1-wire interface. Newer sensors additionally provide an I2C interface. - -The DHT11 (blue) and DHT22 (white) sensors provide the same 1-wire interface, -however, the DHT22 requires a separate object as it has more complex -calculation. DHT22 have 1 decimal place resolution for both humidity and -temperature readings. DHT11 have whole number for both. - -A custom 1-wire protocol, which is different to Dallas 1-wire, is used to get -the measurements from the sensor. The payload consists of a humidity value, -a temperature value and a checksum. - -To use the 1-wire interface, construct the objects referring to their data pin:: - - >>> import dht - >>> import machine - >>> d = dht.DHT11(machine.Pin(4)) - - >>> import dht - >>> import machine - >>> d = dht.DHT22(machine.Pin(4)) - -Then measure and read their values with:: - - >>> d.measure() - >>> d.temperature() - >>> d.humidity() - -Values returned from ``temperature()`` are in degrees Celsius and values -returned from ``humidity()`` are a percentage of relative humidity. - -The DHT11 can be called no more than once per second and the DHT22 once every -two seconds for most accurate results. Sensor accuracy will degrade over time. -Each sensor supports a different operating range. Refer to the product -datasheets for specifics. - -In 1-wire mode, only three of the four pins are used and in I2C mode, all four -pins are used. Older sensors may still have 4 pins even though they do not -support I2C. The 3rd pin is simply not connected. - -Pin configurations: - -Sensor without I2C in 1-wire mode (eg. DHT11, DHT22, AM2301, AM2302): - - 1=VDD, 2=Data, 3=NC, 4=GND - -Sensor with I2C in 1-wire mode (eg. DHT12, AM2320, AM2321, AM2322): - - 1=VDD, 2=Data, 3=GND, 4=GND - -Sensor with I2C in I2C mode (eg. DHT12, AM2320, AM2321, AM2322): - - 1=VDD, 2=SDA, 3=GND, 4=SCL - -You should use pull-up resistors for the Data, SDA and SCL pins. - -To make newer I2C sensors work in backwards compatible 1-wire mode, you must -connect both pins 3 and 4 to GND. This disables the I2C interface. - -DHT22 sensors are now sold under the name AM2302 and are otherwise identical. diff --git a/docs/esp8266/tutorial/filesystem.rst b/docs/esp8266/tutorial/filesystem.rst deleted file mode 100644 index 27b0d2608c..0000000000 --- a/docs/esp8266/tutorial/filesystem.rst +++ /dev/null @@ -1,69 +0,0 @@ -The internal filesystem -======================= - -If your devices has 1Mbyte or more of storage then it will be set up (upon first -boot) to contain a filesystem. This filesystem uses the FAT format and is -stored in the flash after the MicroPython firmware. - -Creating and reading files --------------------------- - -MicroPython on the ESP8266 supports the standard way of accessing files in -Python, using the built-in ``open()`` function. - -To create a file try:: - - >>> f = open('data.txt', 'w') - >>> f.write('some data') - 9 - >>> f.close() - -The "9" is the number of bytes that were written with the ``write()`` method. -Then you can read back the contents of this new file using:: - - >>> f = open('data.txt') - >>> f.read() - 'some data' - >>> f.close() - -Note that the default mode when opening a file is to open it in read-only mode, -and as a text file. Specify ``'wb'`` as the second argument to ``open()`` to -open for writing in binary mode, and ``'rb'`` to open for reading in binary -mode. - -Listing file and more ---------------------- - -The os module can be used for further control over the filesystem. First -import the module:: - - >>> import os - -Then try listing the contents of the filesystem:: - - >>> os.listdir() - ['boot.py', 'port_config.py', 'data.txt'] - -You can make directories:: - - >>> os.mkdir('dir') - -And remove entries:: - - >>> os.remove('data.txt') - -Start up scripts ----------------- - -There are two files that are treated specially by the ESP8266 when it starts up: -boot.py and main.py. The boot.py script is executed first (if it exists) and -then once it completes the main.py script is executed. You can create these -files yourself and populate them with the code that you want to run when the -device starts up. - -Accessing the filesystem via WebREPL ------------------------------------- - -You can access the filesystem over WebREPL using the web client in a browser -or via the command-line tool. Please refer to Quick Reference and Tutorial -sections for more information about WebREPL. diff --git a/docs/esp8266/tutorial/index.rst b/docs/esp8266/tutorial/index.rst deleted file mode 100644 index 39b4592600..0000000000 --- a/docs/esp8266/tutorial/index.rst +++ /dev/null @@ -1,33 +0,0 @@ -.. _tutorial-index: - -MicroPython tutorial for ESP8266 -================================ - -This tutorial is intended to get you started using MicroPython on the ESP8266 -system-on-a-chip. If it is your first time it is recommended to follow the -tutorial through in the order below. Otherwise the sections are mostly self -contained, so feel free to skip to those that interest you. - -The tutorial does not assume that you know Python, but it also does not attempt -to explain any of the details of the Python language. Instead it provides you -with commands that are ready to run, and hopes that you will gain a bit of -Python knowledge along the way. To learn more about Python itself please refer -to ``__. - -.. toctree:: - :maxdepth: 1 - :numbered: - - intro.rst - repl.rst - filesystem.rst - network_basics.rst - network_tcp.rst - pins.rst - pwm.rst - adc.rst - powerctrl.rst - onewire.rst - neopixel.rst - dht.rst - nextsteps.rst diff --git a/docs/esp8266/tutorial/intro.rst b/docs/esp8266/tutorial/intro.rst deleted file mode 100644 index 711db3fceb..0000000000 --- a/docs/esp8266/tutorial/intro.rst +++ /dev/null @@ -1,202 +0,0 @@ -.. _intro: - -Getting started with MicroPython on the ESP8266 -=============================================== - -Using MicroPython is a great way to get the most of your ESP8266 board. And -vice versa, the ESP8266 chip is a great platform for using MicroPython. This -tutorial will guide you through setting up MicroPython, getting a prompt, using -WebREPL, connecting to the network and communicating with the Internet, using -the hardware peripherals, and controlling some external components. - -Let's get started! - -Requirements ------------- - -The first thing you need is a board with an ESP8266 chip. The MicroPython -software supports the ESP8266 chip itself and any board should work. The main -characteristic of a board is how much flash it has, how the GPIO pins are -connected to the outside world, and whether it includes a built-in USB-serial -convertor to make the UART available to your PC. - -The minimum requirement for flash size is 1Mbyte. There is also a special -build for boards with 512KB, but it is highly limited comparing to the -normal build: there is no support for filesystem, and thus features which -depend on it won't work (WebREPL, upip, etc.). As such, 512KB build will -be more interesting for users who build from source and fine-tune parameters -for their particular application. - -Names of pins will be given in this tutorial using the chip names (eg GPIO0) -and it should be straightforward to find which pin this corresponds to on your -particular board. - -Powering the board ------------------- - -If your board has a USB connector on it then most likely it is powered through -this when connected to your PC. Otherwise you will need to power it directly. -Please refer to the documentation for your board for further details. - -Getting the firmware --------------------- - -The first thing you need to do is download the most recent MicroPython firmware -.bin file to load onto your ESP8266 device. You can download it from the -`MicroPython downloads page `_. -From here, you have 3 main choices - -* Stable firmware builds for 1024kb modules and above. -* Daily firmware builds for 1024kb modules and above. -* Daily firmware builds for 512kb modules. - -If you are just starting with MicroPython, the best bet is to go for the Stable -firmware builds. If you are an advanced, experienced MicroPython ESP8266 user -who would like to follow development closely and help with testing new -features, there are daily builds (note: you actually may need some -development experience, e.g. being ready to follow git history to know -what new changes and features were introduced). - -Support for 512kb modules is provided on a feature preview basis. For end -users, it's recommended to use modules with flash of 1024kb or more. As -such, only daily builds for 512kb modules are provided. - -Deploying the firmware ----------------------- - -Once you have the MicroPython firmware (compiled code), you need to load it onto -your ESP8266 device. There are two main steps to do this: first you -need to put your device in boot-loader mode, and second you need to copy across -the firmware. The exact procedure for these steps is highly dependent on the -particular board and you will need to refer to its documentation for details. - -If you have a board that has a USB connector, a USB-serial convertor, and has -the DTR and RTS pins wired in a special way then deploying the firmware should -be easy as all steps can be done automatically. Boards that have such features -include the Adafruit Feather HUZZAH and NodeMCU boards. - -For best results it is recommended to first erase the entire flash of your -device before putting on new MicroPython firmware. - -Currently we only support esptool.py to copy across the firmware. You can find -this tool here: ``__, or install it -using pip:: - - pip install esptool - -Versions starting with 1.3 support both Python 2.7 and Python 3.4 (or newer). -An older version (at least 1.2.1 is needed) works fine but will require Python -2.7. - -Any other flashing program should work, so feel free to try them out or refer -to the documentation for your board to see its recommendations. - -Using esptool.py you can erase the flash with the command:: - - esptool.py --port /dev/ttyUSB0 erase_flash - -And then deploy the new firmware using:: - - esptool.py --port /dev/ttyUSB0 --baud 460800 write_flash --flash_size=detect 0 esp8266-20170108-v1.8.7.bin - -You might need to change the "port" setting to something else relevant for your -PC. You may also need to reduce the baudrate if you get errors when flashing -(eg down to 115200). The filename of the firmware should also match the file -that you have. - -For some boards with a particular FlashROM configuration (e.g. some variants of -a NodeMCU board) you may need to use the following command to deploy -the firmware (note the ``-fm dio`` option):: - - esptool.py --port /dev/ttyUSB0 --baud 460800 write_flash --flash_size=detect -fm dio 0 esp8266-20170108-v1.8.7.bin - -If the above commands run without error then MicroPython should be installed on -your board! - -Serial prompt -------------- - -Once you have the firmware on the device you can access the REPL (Python prompt) -over UART0 (GPIO1=TX, GPIO3=RX), which might be connected to a USB-serial -convertor, depending on your board. The baudrate is 115200. The next part of -the tutorial will discuss the prompt in more detail. - -WiFi ----- - -After a fresh install and boot the device configures itself as a WiFi access -point (AP) that you can connect to. The ESSID is of the form MicroPython-xxxxxx -where the x's are replaced with part of the MAC address of your device (so will -be the same everytime, and most likely different for all ESP8266 chips). The -password for the WiFi is micropythoN (note the upper-case N). Its IP address -will be 192.168.4.1 once you connect to its network. WiFi configuration will -be discussed in more detail later in the tutorial. - -Troubleshooting installation problems -------------------------------------- - -If you experience problems during flashing or with running firmware immediately -after it, here are troubleshooting recommendations: - -* Be aware of and try to exclude hardware problems. There are 2 common problems: - bad power source quality and worn-out/defective FlashROM. Speaking of power - source, not just raw amperage is important, but also low ripple and noise/EMI - in general. If you experience issues with self-made or wall-wart style power - supply, try USB power from a computer. Unearthed power supplies are also known - to cause problems as they source of increased EMI (electromagnetic interference) - - at the very least, and may lead to electrical devices breakdown. So, you are - advised to avoid using unearthed power connections when working with ESP8266 - and other boards. In regard to FlashROM hardware problems, there are independent - (not related to MicroPython in any way) reports - `(e.g.) `_ - that on some ESP8266 modules, FlashROM can be programmed as little as 20 times - before programming errors occur. This is *much* less than 100,000 programming - cycles cited for FlashROM chips of a type used with ESP8266 by reputable - vendors, which points to either production rejects, or second-hand worn-out - flash chips to be used on some (apparently cheap) modules/boards. You may want - to use your best judgement about source, price, documentation, warranty, - post-sales support for the modules/boards you purchase. - -* The flashing instructions above use flashing speed of 460800 baud, which is - good compromise between speed and stability. However, depending on your - module/board, USB-UART convertor, cables, host OS, etc., the above baud - rate may be too high and lead to errors. Try a more common 115200 baud - rate instead in such cases. - -* If lower baud rate didn't help, you may want to try older version of - esptool.py, which had a different programming algorithm:: - - pip install esptool==1.0.1 - - This version doesn't support ``--flash_size=detect`` option, so you will - need to specify FlashROM size explicitly (in megabits). It also requires - Python 2.7, so you may need to use ``pip2`` instead of ``pip`` in the - command above. - -* The ``--flash_size`` option in the commands above is mandatory. Omitting - it will lead to a corrupted firmware. - -* To catch incorrect flash content (e.g. from a defective sector on a chip), - add ``--verify`` switch to the commands above. - -* Additionally, you can check the firmware integrity from a MicroPython REPL - prompt (assuming you were able to flash it and ``--verify`` option doesn't - report errors):: - - import esp - esp.check_fw() - - If the last output value is True, the firmware is OK. Otherwise, it's - corrupted and need to be reflashed correctly. - -* If you experience any issues with another flashing application (not - esptool.py), try esptool.py, it is a generally accepted flashing - application in the ESP8266 community. - -* If you still experience problems with even flashing the firmware, please - refer to esptool.py project page, https://github.com/espressif/esptool - for additional documentation and bug tracker where you can report problems. - -* If you are able to flash firmware, but ``--verify`` option or - ``esp.check_fw()`` return errors even after multiple retries, you - may have a defective FlashROM chip, as explained above. diff --git a/docs/esp8266/tutorial/neopixel.rst b/docs/esp8266/tutorial/neopixel.rst deleted file mode 100644 index 245aed6d46..0000000000 --- a/docs/esp8266/tutorial/neopixel.rst +++ /dev/null @@ -1,70 +0,0 @@ -Controlling NeoPixels -===================== - -NeoPixels, also known as WS2812 LEDs, are full-colour LEDs that are connected in -serial, are individually addressable, and can have their red, green and blue -components set between 0 and 255. They require precise timing to control them -and there is a special neopixel module to do just this. - -To create a NeoPixel object do the following:: - - >>> import machine, neopixel - >>> np = neopixel.NeoPixel(machine.Pin(4), 8) - -This configures a NeoPixel strip on GPIO4 with 8 pixels. You can adjust the -"4" (pin number) and the "8" (number of pixel) to suit your set up. - -To set the colour of pixels use:: - - >>> np[0] = (255, 0, 0) # set to red, full brightness - >>> np[1] = (0, 128, 0) # set to green, half brightness - >>> np[2] = (0, 0, 64) # set to blue, quarter brightness - -Then use the ``write()`` method to output the colours to the LEDs:: - - >>> np.write() - -The following demo function makes a fancy show on the LEDs:: - - import time - - def demo(np): - n = np.n - - # cycle - for i in range(4 * n): - for j in range(n): - np[j] = (0, 0, 0) - np[i % n] = (255, 255, 255) - np.write() - time.sleep_ms(25) - - # bounce - for i in range(4 * n): - for j in range(n): - np[j] = (0, 0, 128) - if (i // n) % 2 == 0: - np[i % n] = (0, 0, 0) - else: - np[n - 1 - (i % n)] = (0, 0, 0) - np.write() - time.sleep_ms(60) - - # fade in/out - for i in range(0, 4 * 256, 8): - for j in range(n): - if (i // 256) % 2 == 0: - val = i & 0xff - else: - val = 255 - (i & 0xff) - np[j] = (val, 0, 0) - np.write() - - # clear - for i in range(n): - np[i] = (0, 0, 0) - np.write() - -Execute it using:: - - >>> demo(np) diff --git a/docs/esp8266/tutorial/network_basics.rst b/docs/esp8266/tutorial/network_basics.rst deleted file mode 100644 index 95d8cba4f9..0000000000 --- a/docs/esp8266/tutorial/network_basics.rst +++ /dev/null @@ -1,81 +0,0 @@ -Network basics -============== - -The network module is used to configure the WiFi connection. There are two WiFi -interfaces, one for the station (when the ESP8266 connects to a router) and one -for the access point (for other devices to connect to the ESP8266). Create -instances of these objects using:: - - >>> import network - >>> sta_if = network.WLAN(network.STA_IF) - >>> ap_if = network.WLAN(network.AP_IF) - -You can check if the interfaces are active by:: - - >>> sta_if.active() - False - >>> ap_if.active() - True - -You can also check the network settings of the interface by:: - - >>> ap_if.ifconfig() - ('192.168.4.1', '255.255.255.0', '192.168.4.1', '8.8.8.8') - -The returned values are: IP address, netmask, gateway, DNS. - -Configuration of the WiFi -------------------------- - -Upon a fresh install the ESP8266 is configured in access point mode, so the -AP_IF interface is active and the STA_IF interface is inactive. You can -configure the module to connect to your own network using the STA_IF interface. - -First activate the station interface:: - - >>> sta_if.active(True) - -Then connect to your WiFi network:: - - >>> sta_if.connect('', '') - -To check if the connection is established use:: - - >>> sta_if.isconnected() - -Once established you can check the IP address:: - - >>> sta_if.ifconfig() - ('192.168.0.2', '255.255.255.0', '192.168.0.1', '8.8.8.8') - -You can then disable the access-point interface if you no longer need it:: - - >>> ap_if.active(False) - -Here is a function you can run (or put in your boot.py file) to automatically -connect to your WiFi network:: - - def do_connect(): - import network - sta_if = network.WLAN(network.STA_IF) - if not sta_if.isconnected(): - print('connecting to network...') - sta_if.active(True) - sta_if.connect('', '') - while not sta_if.isconnected(): - pass - print('network config:', sta_if.ifconfig()) - -Sockets -------- - -Once the WiFi is set up the way to access the network is by using sockets. -A socket represents an endpoint on a network device, and when two sockets are -connected together communication can proceed. -Internet protocols are built on top of sockets, such as email (SMTP), the web -(HTTP), telnet, ssh, among many others. Each of these protocols is assigned -a specific port, which is just an integer. Given an IP address and a port -number you can connect to a remote device and start talking with it. - -The next part of the tutorial discusses how to use sockets to do some common -and useful network tasks. diff --git a/docs/esp8266/tutorial/network_tcp.rst b/docs/esp8266/tutorial/network_tcp.rst deleted file mode 100644 index 26a2f469ce..0000000000 --- a/docs/esp8266/tutorial/network_tcp.rst +++ /dev/null @@ -1,122 +0,0 @@ -Network - TCP sockets -===================== - -The building block of most of the internet is the TCP socket. These sockets -provide a reliable stream of bytes between the connected network devices. -This part of the tutorial will show how to use TCP sockets in a few different -cases. - -Star Wars Asciimation ---------------------- - -The simplest thing to do is to download data from the internet. In this case -we will use the Star Wars Asciimation service provided by the blinkenlights.nl -website. It uses the telnet protocol on port 23 to stream data to anyone that -connects. It's very simple to use because it doesn't require you to -authenticate (give a username or password), you can just start downloading data -straight away. - -The first thing to do is make sure we have the socket module available:: - - >>> import socket - -Then get the IP address of the server:: - - >>> addr_info = socket.getaddrinfo("towel.blinkenlights.nl", 23) - -The ``getaddrinfo`` function actually returns a list of addresses, and each -address has more information than we need. We want to get just the first valid -address, and then just the IP address and port of the server. To do this use:: - - >>> addr = addr_info[0][-1] - -If you type ``addr_info`` and ``addr`` at the prompt you will see exactly what -information they hold. - -Using the IP address we can make a socket and connect to the server:: - - >>> s = socket.socket() - >>> s.connect(addr) - -Now that we are connected we can download and display the data:: - - >>> while True: - ... data = s.recv(500) - ... print(str(data, 'utf8'), end='') - ... - -When this loop executes it should start showing the animation (use ctrl-C to -interrupt it). - -You should also be able to run this same code on your PC using normal Python if -you want to try it out there. - -HTTP GET request ----------------- - -The next example shows how to download a webpage. HTTP uses port 80 and you -first need to send a "GET" request before you can download anything. As part -of the request you need to specify the page to retrieve. - -Let's define a function that can download and print a URL:: - - def http_get(url): - _, _, host, path = url.split('/', 3) - addr = socket.getaddrinfo(host, 80)[0][-1] - s = socket.socket() - s.connect(addr) - s.send(bytes('GET /%s HTTP/1.0\r\nHost: %s\r\n\r\n' % (path, host), 'utf8')) - while True: - data = s.recv(100) - if data: - print(str(data, 'utf8'), end='') - else: - break - s.close() - -Make sure that you import the socket module before running this function. Then -you can try:: - - >>> http_get('http://micropython.org/ks/test.html') - -This should retrieve the webpage and print the HTML to the console. - -Simple HTTP server ------------------- - -The following code creates an simple HTTP server which serves a single webpage -that contains a table with the state of all the GPIO pins:: - - import machine - pins = [machine.Pin(i, machine.Pin.IN) for i in (0, 2, 4, 5, 12, 13, 14, 15)] - - html = """ - - ESP8266 Pins -

ESP8266 Pins

- %s
PinValue
- - - """ - - import socket - addr = socket.getaddrinfo('0.0.0.0', 80)[0][-1] - - s = socket.socket() - s.bind(addr) - s.listen(1) - - print('listening on', addr) - - while True: - cl, addr = s.accept() - print('client connected from', addr) - cl_file = cl.makefile('rwb', 0) - while True: - line = cl_file.readline() - if not line or line == b'\r\n': - break - rows = ['%s%d' % (str(p), p.value()) for p in pins] - response = html % '\n'.join(rows) - cl.send(response) - cl.close() diff --git a/docs/esp8266/tutorial/nextsteps.rst b/docs/esp8266/tutorial/nextsteps.rst deleted file mode 100644 index 318bd7ddf8..0000000000 --- a/docs/esp8266/tutorial/nextsteps.rst +++ /dev/null @@ -1,12 +0,0 @@ -Next steps -========== - -That brings us to the end of the tutorial! Hopefully by now you have a good -feel for the capabilities of MicroPython on the ESP8266 and understand how to -control both the WiFi and IO aspects of the chip. - -There are many features that were not covered in this tutorial. The best way -to learn about them is to read the full documentation of the modules, and to -experiment! - -Good luck creating your Internet of Things devices! diff --git a/docs/esp8266/tutorial/onewire.rst b/docs/esp8266/tutorial/onewire.rst deleted file mode 100644 index c2cede9e38..0000000000 --- a/docs/esp8266/tutorial/onewire.rst +++ /dev/null @@ -1,37 +0,0 @@ -Controlling 1-wire devices -========================== - -The 1-wire bus is a serial bus that uses just a single wire for communication -(in addition to wires for ground and power). The DS18B20 temperature sensor -is a very popular 1-wire device, and here we show how to use the onewire module -to read from such a device. - -For the following code to work you need to have at least one DS18S20 or DS18B20 temperature -sensor with its data line connected to GPIO12. You must also power the sensors -and connect a 4.7k Ohm resistor between the data pin and the power pin. :: - - import time - import machine - import onewire, ds18x20 - - # the device is on GPIO12 - dat = machine.Pin(12) - - # create the onewire object - ds = ds18x20.DS18X20(onewire.OneWire(dat)) - - # scan for devices on the bus - roms = ds.scan() - print('found devices:', roms) - - # loop 10 times and print all temperatures - for i in range(10): - print('temperatures:', end=' ') - ds.convert_temp() - time.sleep_ms(750) - for rom in roms: - print(ds.read_temp(rom), end=' ') - print() - -Note that you must execute the ``convert_temp()`` function to initiate a -temperature reading, then wait at least 750ms before reading the value. diff --git a/docs/esp8266/tutorial/pins.rst b/docs/esp8266/tutorial/pins.rst deleted file mode 100644 index cd45c83cd3..0000000000 --- a/docs/esp8266/tutorial/pins.rst +++ /dev/null @@ -1,75 +0,0 @@ -GPIO Pins -========= - -The way to connect your board to the external world, and control other -components, is through the GPIO pins. Not all pins are available to use, -in most cases only pins 0, 2, 4, 5, 12, 13, 14, 15, and 16 can be used. - -The pins are available in the machine module, so make sure you import that -first. Then you can create a pin using:: - - >>> pin = machine.Pin(0) - -Here, the "0" is the pin that you want to access. Usually you want to -configure the pin to be input or output, and you do this when constructing -it. To make an input pin use:: - - >>> pin = machine.Pin(0, machine.Pin.IN, machine.Pin.PULL_UP) - -You can either use PULL_UP or None for the input pull-mode. If it's -not specified then it defaults to None, which is no pull resistor. -You can read the value on the pin using:: - - >>> pin.value() - 0 - -The pin on your board may return 0 or 1 here, depending on what it's connected -to. To make an output pin use:: - - >>> pin = machine.Pin(0, machine.Pin.OUT) - -Then set its value using:: - - >>> pin.value(0) - >>> pin.value(1) - -Or:: - - >>> pin.off() - >>> pin.on() - -External interrupts -------------------- - -All pins except number 16 can be configured to trigger a hard interrupt if their -input changes. You can set code (a callback function) to be executed on the -trigger. - -Let's first define a callback function, which must take a single argument, -being the pin that triggered the function. We will make the function just print -the pin:: - - >>> def callback(p): - ... print('pin change', p) - -Next we will create two pins and configure them as inputs:: - - >>> from machine import Pin - >>> p0 = Pin(0, Pin.IN) - >>> p2 = Pin(2, Pin.IN) - -An finally we need to tell the pins when to trigger, and the function to call -when they detect an event:: - - >>> p0.irq(trigger=Pin.IRQ_FALLING, handler=callback) - >>> p2.irq(trigger=Pin.IRQ_RISING | Pin.IRQ_FALLING, handler=callback) - -We set pin 0 to trigger only on a falling edge of the input (when it goes from -high to low), and set pin 2 to trigger on both a rising and falling edge. After -entering this code you can apply high and low voltages to pins 0 and 2 to see -the interrupt being executed. - -A hard interrupt will trigger as soon as the event occurs and will interrupt any -running code, including Python code. As such your callback functions are -limited in what they can do (they cannot allocate memory, for example) and -should be as short and simple as possible. diff --git a/docs/esp8266/tutorial/powerctrl.rst b/docs/esp8266/tutorial/powerctrl.rst deleted file mode 100644 index 3502624ab5..0000000000 --- a/docs/esp8266/tutorial/powerctrl.rst +++ /dev/null @@ -1,61 +0,0 @@ -Power control -============= - -The ESP8266 provides the ability to change the CPU frequency on the fly, and -enter a deep-sleep state. Both can be used to manage power consumption. - -Changing the CPU frequency --------------------------- - -The machine module has a function to get and set the CPU frequency. To get the -current frequency use:: - - >>> import machine - >>> machine.freq() - 80000000 - -By default the CPU runs at 80MHz. It can be change to 160MHz if you need more -processing power, at the expense of current consumption:: - - >>> machine.freq(160000000) - >>> machine.freq() - 160000000 - -You can change to the higher frequency just while your code does the heavy -processing and then change back when it's finished. - -Deep-sleep mode ---------------- - -The deep-sleep mode will shut down the ESP8266 and all its peripherals, -including the WiFi (but not including the real-time-clock, which is used to wake -the chip). This drastically reduces current consumption and is a good way to -make devices that can run for a while on a battery. - -To be able to use the deep-sleep feature you must connect GPIO16 to the reset -pin (RST on the Adafruit Feather HUZZAH board). Then the following code can be -used to sleep and wake the device:: - - import machine - - # configure RTC.ALARM0 to be able to wake the device - rtc = machine.RTC() - rtc.irq(trigger=rtc.ALARM0, wake=machine.DEEPSLEEP) - - # set RTC.ALARM0 to fire after 10 seconds (waking the device) - rtc.alarm(rtc.ALARM0, 10000) - - # put the device to sleep - machine.deepsleep() - -Note that when the chip wakes from a deep-sleep it is completely reset, -including all of the memory. The boot scripts will run as usual and you can -put code in them to check the reset cause to perhaps do something different if -the device just woke from a deep-sleep. For example, to print the reset cause -you can use:: - - if machine.reset_cause() == machine.DEEPSLEEP_RESET: - print('woke from a deep sleep') - else: - print('power on or hard reset') - diff --git a/docs/esp8266/tutorial/pwm.rst b/docs/esp8266/tutorial/pwm.rst deleted file mode 100644 index 8de509427c..0000000000 --- a/docs/esp8266/tutorial/pwm.rst +++ /dev/null @@ -1,87 +0,0 @@ -Pulse Width Modulation -====================== - -Pulse width modulation (PWM) is a way to get an artificial analog output on a -digital pin. It achieves this by rapidly toggling the pin from low to high. -There are two parameters associated with this: the frequency of the toggling, -and the duty cycle. The duty cycle is defined to be how long the pin is high -compared with the length of a single period (low plus high time). Maximum -duty cycle is when the pin is high all of the time, and minimum is when it is -low all of the time. - -On the ESP8266 the pins 0, 2, 4, 5, 12, 13, 14 and 15 all support PWM. The -limitation is that they must all be at the same frequency, and the frequency -must be between 1Hz and 1kHz. - -To use PWM on a pin you must first create the pin object, for example:: - - >>> import machine - >>> p12 = machine.Pin(12) - -Then create the PWM object using:: - - >>> pwm12 = machine.PWM(p12) - -You can set the frequency and duty cycle using:: - - >>> pwm12.freq(500) - >>> pwm12.duty(512) - -Note that the duty cycle is between 0 (all off) and 1023 (all on), with 512 -being a 50% duty. If you print the PWM object then it will tell you its current -configuration:: - - >>> pwm12 - PWM(12, freq=500, duty=512) - -You can also call the ``freq()`` and ``duty()`` methods with no arguments to -get their current values. - -The pin will continue to be in PWM mode until you deinitialise it using:: - - >>> pwm12.deinit() - -Fading an LED -------------- - -Let's use the PWM feature to fade an LED. Assuming your board has an LED -connected to pin 2 (ESP-12 modules do) we can create an LED-PWM object using:: - - >>> led = machine.PWM(machine.Pin(2), freq=1000) - -Notice that we can set the frequency in the PWM constructor. - -For the next part we will use timing and some math, so import these modules:: - - >>> import time, math - -Then create a function to pulse the LED:: - - >>> def pulse(l, t): - ... for i in range(20): - ... l.duty(int(math.sin(i / 10 * math.pi) * 500 + 500)) - ... time.sleep_ms(t) - -You can try this function out using:: - - >>> pulse(led, 50) - -For a nice effect you can pulse many times in a row:: - - >>> for i in range(10): - ... pulse(led, 20) - -Remember you can use ctrl-C to interrupt the code. - -Control a hobby servo ---------------------- - -Hobby servo motors can be controlled using PWM. They require a frequency of -50Hz and then a duty between about 40 and 115, with 77 being the centre value. -If you connect a servo to the power and ground pins, and then the signal line -to pin 12 (other pins will work just as well), you can control the motor using:: - - >>> servo = machine.PWM(machine.Pin(12), freq=50) - >>> servo.duty(40) - >>> servo.duty(115) - >>> servo.duty(77) diff --git a/docs/esp8266/tutorial/repl.rst b/docs/esp8266/tutorial/repl.rst deleted file mode 100644 index ba64fcccbe..0000000000 --- a/docs/esp8266/tutorial/repl.rst +++ /dev/null @@ -1,212 +0,0 @@ -Getting a MicroPython REPL prompt -================================= - -REPL stands for Read Evaluate Print Loop, and is the name given to the -interactive MicroPython prompt that you can access on the ESP8266. Using the -REPL is by far the easiest way to test out your code and run commands. - -There are two ways to access the REPL: either via a wired connection through the -UART serial port, or via WiFi. - -REPL over the serial port -------------------------- - -The REPL is always available on the UART0 serial peripheral, which is connected -to the pins GPIO1 for TX and GPIO3 for RX. The baudrate of the REPL is 115200. -If your board has a USB-serial convertor on it then you should be able to access -the REPL directly from your PC. Otherwise you will need to have a way of -communicating with the UART. - -To access the prompt over USB-serial you need to use a terminal emulator program. -On Windows TeraTerm is a good choice, on Mac you can use the built-in screen -program, and Linux has picocom and minicom. Of course, there are many other -terminal programs that will work, so pick your favourite! - -For example, on Linux you can try running:: - - picocom /dev/ttyUSB0 -b115200 - -Once you have made the connection over the serial port you can test if it is -working by hitting enter a few times. You should see the Python REPL prompt, -indicated by ``>>>``. - -WebREPL - a prompt over WiFi ----------------------------- - -WebREPL allows you to use the Python prompt over WiFi, connecting through a -browser. The latest versions of Firefox and Chrome are supported. - -For your convenience, WebREPL client is hosted at -``__ . Alternatively, you can install it -locally from the the GitHub repository -``__ . - -Before connecting to WebREPL, you should set a password and enable it via -a normal serial connection. Initial versions of MicroPython for ESP8266 -came with WebREPL automatically enabled on the boot and with the -ability to set a password via WiFi on the first connection, but as WebREPL -was becoming more widely known and popular, the initial setup has switched -to a wired connection for improved security:: - - import webrepl_setup - -Follow the on-screen instructions and prompts. To make any changes active, -you will need to reboot your device. - -To use WebREPL connect your computer to the ESP8266's access point -(MicroPython-xxxxxx, see the previous section about this). If you have -already reconfigured your ESP8266 to connect to a router then you can -skip this part. - -Once you are on the same network as the ESP8266 you click the "Connect" button -(if you are connecting via a router then you may need to change the IP address, -by default the IP address is correct when connected to the ESP8266's access -point). If the connection succeeds then you should see a password prompt. - -Once you type the password configured at the setup step above, press Enter once -more and you should get a prompt looking like ``>>>``. You can now start -typing Python commands! - -Using the REPL --------------- - -Once you have a prompt you can start experimenting! Anything you type at the -prompt will be executed after you press the Enter key. MicroPython will run -the code that you enter and print the result (if there is one). If there is an -error with the text that you enter then an error message is printed. - -Try typing the following at the prompt:: - - >>> print('hello esp8266!') - hello esp8266! - -Note that you shouldn't type the ``>>>`` arrows, they are there to indicate that -you should type the text after it at the prompt. And then the line following is -what the device should respond with. In the end, once you have entered the text -``print("hello esp8266!")`` and pressed the Enter key, the output on your screen -should look exactly like it does above. - -If you already know some python you can now try some basic commands here. For -example:: - - >>> 1 + 2 - 3 - >>> 1 / 2 - 0.5 - >>> 12**34 - 4922235242952026704037113243122008064 - -If your board has an LED attached to GPIO2 (the ESP-12 modules do) then you can -turn it on and off using the following code:: - - >>> import machine - >>> pin = machine.Pin(2, machine.Pin.OUT) - >>> pin.on() - >>> pin.off() - -Note that ``on`` method of a Pin might turn the LED off and ``off`` might -turn it on (or vice versa), depending on how the LED is wired on your board. -To resolve this, machine.Signal class is provided. - -Line editing -~~~~~~~~~~~~ - -You can edit the current line that you are entering using the left and right -arrow keys to move the cursor, as well as the delete and backspace keys. Also, -pressing Home or ctrl-A moves the cursor to the start of the line, and pressing -End or ctrl-E moves to the end of the line. - -Input history -~~~~~~~~~~~~~ - -The REPL remembers a certain number of previous lines of text that you entered -(up to 8 on the ESP8266). To recall previous lines use the up and down arrow -keys. - -Tab completion -~~~~~~~~~~~~~~ - -Pressing the Tab key will do an auto-completion of the current word that you are -entering. This can be very useful to find out functions and methods that a -module or object has. Try it out by typing "ma" and then pressing Tab. It -should complete to "machine" (assuming you imported machine in the above -example). Then type "." and press Tab again to see a list of all the functions -that the machine module has. - -Line continuation and auto-indent -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -Certain things that you type will need "continuing", that is, will need more -lines of text to make a proper Python statement. In this case the prompt will -change to ``...`` and the cursor will auto-indent the correct amount so you can -start typing the next line straight away. Try this by defining the following -function:: - - >>> def toggle(p): - ... p.value(not p.value()) - ... - ... - ... - >>> - -In the above, you needed to press the Enter key three times in a row to finish -the compound statement (that's the three lines with just dots on them). The -other way to finish a compound statement is to press backspace to get to the -start of the line, then press the Enter key. (If you did something wrong and -want to escape the continuation mode then press ctrl-C; all lines will be -ignored.) - -The function you just defined allows you to toggle a pin. The pin object you -created earlier should still exist (recreate it if it doesn't) and you can -toggle the LED using:: - - >>> toggle(pin) - -Let's now toggle the LED in a loop (if you don't have an LED then you can just -print some text instead of calling toggle, to see the effect):: - - >>> import time - >>> while True: - ... toggle(pin) - ... time.sleep_ms(500) - ... - ... - ... - >>> - -This will toggle the LED at 1Hz (half a second on, half a second off). To stop -the toggling press ctrl-C, which will raise a KeyboardInterrupt exception and -break out of the loop. - -The time module provides some useful functions for making delays and doing -timing. Use tab completion to find out what they are and play around with them! - -Paste mode -~~~~~~~~~~ - -Pressing ctrl-E will enter a special paste mode. This allows you to copy and -paste a chunk of text into the REPL. If you press ctrl-E you will see the -paste-mode prompt:: - - paste mode; Ctrl-C to cancel, Ctrl-D to finish - === - -You can then paste (or type) your text in. Note that none of the special keys -or commands work in paste mode (eg Tab or backspace), they are just accepted -as-is. Press ctrl-D to finish entering the text and execute it. - -Other control commands -~~~~~~~~~~~~~~~~~~~~~~ - -There are four other control commands: - -* Ctrl-A on a blank line will enter raw REPL mode. This is like a permanent - paste mode, except that characters are not echoed back. - -* Ctrl-B on a blank like goes to normal REPL mode. - -* Ctrl-C cancels any input, or interrupts the currently running code. - -* Ctrl-D on a blank line will do a soft reset. - -Note that ctrl-A and ctrl-D do not work with WebREPL. diff --git a/docs/esp8266_index.rst b/docs/esp8266_index.rst deleted file mode 100644 index 519acecda5..0000000000 --- a/docs/esp8266_index.rst +++ /dev/null @@ -1,12 +0,0 @@ -MicroPython documentation and references -======================================== - -.. toctree:: - - esp8266/quickref.rst - esp8266/general.rst - esp8266/tutorial/index.rst - library/index.rst - reference/index.rst - genrst/index.rst - license.rst diff --git a/docs/index.rst b/docs/index.rst new file mode 100644 index 0000000000..17badba394 --- /dev/null +++ b/docs/index.rst @@ -0,0 +1,53 @@ +Adafruit CircuitPython API Reference +==================================== + +Welcome to the API reference documentation for Adafruit CircuitPython. +This contains low-level API reference docs which may link out to separate +*"getting started"* guides. `Adafruit `_ has many +excellent tutorials available through the +`Adafruit Learning System `_. + +.. include:: ../README.rst + +.. _contents: + +Full Table of Contents +---------------------- + +.. toctree:: + :maxdepth: 3 + :caption: API and Usage + + ../shared-bindings/index.rst + supported_ports.rst + troubleshooting.rst + drivers.rst + +.. toctree:: + :maxdepth: 1 + :caption: Design and porting reference + + design_guide + common_hal + +.. toctree:: + :maxdepth: 2 + :caption: MicroPython specific + + library/index.rst + +.. toctree:: + :maxdepth: 1 + :caption: About the project + + ../README + ../CONTRIBUTING + ../CODE_OF_CONDUCT + ../license.rst + +Indices and tables +================== + +* :ref:`genindex` +* :ref:`modindex` +* :ref:`search` diff --git a/docs/library/array.rst b/docs/library/array.rst index d096c6ec48..dfaef0ff6c 100644 --- a/docs/library/array.rst +++ b/docs/library/array.rst @@ -1,10 +1,12 @@ :mod:`array` -- arrays of numeric data ====================================== +.. include:: ../templates/unsupported_in_circuitpython.inc + .. module:: array :synopsis: efficient arrays of numeric data -|see_cpython_module| :mod:`python:array`. +|see_cpython_module| :mod:`cpython:array`. Supported format codes: ``b``, ``B``, ``h``, ``H``, ``i``, ``I``, ``l``, ``L``, ``q``, ``Q``, ``f``, ``d`` (the latter 2 depending on the diff --git a/docs/library/btree.rst b/docs/library/btree.rst index 9322d32e6a..cdc4b42cff 100644 --- a/docs/library/btree.rst +++ b/docs/library/btree.rst @@ -1,6 +1,8 @@ :mod:`btree` -- simple BTree database ===================================== +.. include:: ../templates/unsupported_in_circuitpython.inc + .. module:: btree :synopsis: simple BTree database @@ -78,7 +80,7 @@ Functions .. function:: open(stream, \*, flags=0, cachesize=0, pagesize=0, minkeypage=0) - Open a database from a random-access `stream` (like an open file). All + Open a database from a random-access ``stream`` (like an open file). All other parameters are optional and keyword-only, and allow to tweak advanced parameters of the database operation (most users will not need them): diff --git a/docs/library/builtins.rst b/docs/library/builtins.rst index 365248dc76..b45b6fe380 100644 --- a/docs/library/builtins.rst +++ b/docs/library/builtins.rst @@ -1,6 +1,12 @@ Builtin functions and exceptions ================================ +.. warning:: + + These builtins are inherited from MicroPython and may not work in CircuitPython + as documented or at all! If work differently from CPython, then their behavior + may change. + All builtin functions and exceptions are described here. They are also available via ``builtins`` module. @@ -21,7 +27,7 @@ Functions and types .. class:: bytes() - |see_cpython| `python:bytes`. + |see_cpython| `bytes`. .. function:: callable() @@ -176,7 +182,7 @@ Exceptions .. exception:: OSError - |see_cpython| `python:OSError`. MicroPython doesn't implement ``errno`` + |see_cpython| `OSError`. MicroPython doesn't implement ``errno`` attribute, instead use the standard way to access exception arguments: ``exc.args[0]``. @@ -188,11 +194,11 @@ Exceptions .. exception:: SystemExit - |see_cpython| `python:SystemExit`. + |see_cpython| :py:class:`python:SystemExit`. .. exception:: TypeError - |see_cpython| `python:TypeError`. + |see_cpython| :py:class:`python:TypeError`. .. exception:: ValueError diff --git a/docs/library/cmath.rst b/docs/library/cmath.rst deleted file mode 100644 index 59e4ec1722..0000000000 --- a/docs/library/cmath.rst +++ /dev/null @@ -1,63 +0,0 @@ -:mod:`cmath` -- mathematical functions for complex numbers -========================================================== - -.. module:: cmath - :synopsis: mathematical functions for complex numbers - -|see_cpython_module| :mod:`python:cmath`. - -The ``cmath`` module provides some basic mathematical functions for -working with complex numbers. - -Availability: not available on WiPy and ESP8266. Floating point support -required for this module. - -Functions ---------- - -.. function:: cos(z) - - Return the cosine of ``z``. - -.. function:: exp(z) - - Return the exponential of ``z``. - -.. function:: log(z) - - Return the natural logarithm of ``z``. The branch cut is along the negative real axis. - -.. function:: log10(z) - - Return the base-10 logarithm of ``z``. The branch cut is along the negative real axis. - -.. function:: phase(z) - - Returns the phase of the number ``z``, in the range (-pi, +pi]. - -.. function:: polar(z) - - Returns, as a tuple, the polar form of ``z``. - -.. function:: rect(r, phi) - - Returns the complex number with modulus ``r`` and phase ``phi``. - -.. function:: sin(z) - - Return the sine of ``z``. - -.. function:: sqrt(z) - - Return the square-root of ``z``. - -Constants ---------- - -.. data:: e - - base of the natural logarithm - -.. data:: pi - - the ratio of a circle's circumference to its diameter diff --git a/docs/library/esp.rst b/docs/library/esp.rst index 121a80d42e..125aaa890f 100644 --- a/docs/library/esp.rst +++ b/docs/library/esp.rst @@ -1,6 +1,8 @@ :mod:`esp` --- functions related to the ESP8266 =============================================== +.. include:: ../templates/unsupported_in_circuitpython.inc + .. module:: esp :synopsis: functions related to the ESP8266 diff --git a/docs/library/framebuf.rst b/docs/library/framebuf.rst index b92bd08eff..10ae405148 100644 --- a/docs/library/framebuf.rst +++ b/docs/library/framebuf.rst @@ -1,6 +1,8 @@ :mod:`framebuf` --- Frame buffer manipulation ============================================= +.. include:: ../templates/unsupported_in_circuitpython.inc + .. module:: framebuf :synopsis: Frame buffer manipulation diff --git a/docs/library/gc.rst b/docs/library/gc.rst index c823aed3e6..01bd925e99 100644 --- a/docs/library/gc.rst +++ b/docs/library/gc.rst @@ -1,10 +1,12 @@ :mod:`gc` -- control the garbage collector ========================================== +.. include:: ../templates/unsupported_in_circuitpython.inc + .. module:: gc :synopsis: control the garbage collector -|see_cpython_module| :mod:`python:gc`. +|see_cpython_module| :mod:`cpython:gc`. Functions --------- diff --git a/docs/library/index.rst b/docs/library/index.rst index bf72c5ffa8..9bdf8b1ed8 100644 --- a/docs/library/index.rst +++ b/docs/library/index.rst @@ -5,159 +5,35 @@ MicroPython libraries .. warning:: - Important summary of this section + These modules are inherited from MicroPython and may not work in CircuitPython + as documented or at all! If they do work, they may change at any time. - * MicroPython implements a subset of Python functionality for each module. - * To ease extensibility, MicroPython versions of standard Python modules - usually have ``u`` (micro) prefix. - * Any particular MicroPython variant or port may miss any feature/function - described in this general documentation, due to resource constraints. - - -This chapter describes modules (function and class libraries) which are built -into MicroPython and CircuitPython. There are a few categories of modules: - -* Modules which implement a subset of standard Python functionality and are not - intended to be extended by the user. -* Modules which implement a subset of Python functionality, with a provision - for extension by the user (via Python code). -* Modules which implement MicroPython extensions to the Python standard libraries. -* Modules specific to a particular port and thus not portable. - -Note about the availability of modules and their contents: This documentation -in general aspires to describe all modules and functions/classes which are -implemented in MicroPython. However, MicroPython is highly configurable, and -each port to a particular board/embedded system makes available only a subset -of MicroPython libraries. For officially supported ports, there is an effort -to either filter out non-applicable items, or mark individual descriptions -with "Availability:" clauses describing which ports provide a given feature. -With that in mind, please still be warned that some functions/classes -in a module (or even the entire module) described in this documentation may be -unavailable in a particular build of MicroPython on a particular board. The -best place to find general information of the availability/non-availability -of a particular feature is the "General Information" section which contains -information pertaining to a specific port. - -Beyond the built-in libraries described in this documentation, many more -modules from the Python standard library, as well as further MicroPython -extensions to it, can be found in `micropython-lib`. Python standard libraries and micro-libraries --------------------------------------------- -The following standard Python libraries have been "micro-ified" to fit in with -the philosophy of MicroPython. They provide the core functionality of that -module and are intended to be a drop-in replacement for the standard Python -library. Some modules below use a standard Python name, but prefixed with "u", -e.g. ``ujson`` instead of ``json``. This is to signify that such a module is -micro-library, i.e. implements only a subset of CPython module functionality. -By naming them differently, a user has a choice to write a Python-level module -to extend functionality for better compatibility with CPython (indeed, this is -what done by the `micropython-lib` project mentioned above). -On some embedded platforms, where it may be cumbersome to add Python-level -wrapper modules to achieve naming compatibility with CPython, micro-modules -are available both by their u-name, and also by their non-u-name. The -non-u-name can be overridden by a file of that name in your package path. -For example, ``import json`` will first search for a file ``json.py`` or -directory ``json`` and load that package if it is found. If nothing is found, -it will fallback to loading the built-in ``ujson`` module. +.. toctree:: + :maxdepth: 1 -.. only:: port_unix - - .. toctree:: - :maxdepth: 1 - - builtins.rst - array.rst - cmath.rst - gc.rst - math.rst - sys.rst - ubinascii.rst - ucollections.rst - uerrno.rst - uhashlib.rst - uheapq.rst - uio.rst - ujson.rst - uos.rst - ure.rst - uselect.rst - usocket.rst - ustruct.rst - utime.rst - uzlib.rst - -.. only:: port_pyboard - - .. toctree:: - :maxdepth: 1 - - builtins.rst - array.rst - cmath.rst - gc.rst - math.rst - sys.rst - ubinascii.rst - ucollections.rst - uerrno.rst - uhashlib.rst - uheapq.rst - uio.rst - ujson.rst - uos.rst - ure.rst - uselect.rst - usocket.rst - ustruct.rst - utime.rst - uzlib.rst - -.. only:: port_wipy - - .. toctree:: - :maxdepth: 1 - - builtins.rst - array.rst - gc.rst - sys.rst - ubinascii.rst - ujson.rst - uos.rst - ure.rst - uselect.rst - usocket.rst - ussl.rst - utime.rst - -.. only:: port_esp8266 - - .. toctree:: - :maxdepth: 1 - - builtins.rst - array.rst - gc.rst - math.rst - sys.rst - ubinascii.rst - ucollections.rst - uerrno.rst - uhashlib.rst - uheapq.rst - uio.rst - ujson.rst - uos.rst - ure.rst - uselect.rst - usocket.rst - ussl.rst - ustruct.rst - utime.rst - uzlib.rst + builtins.rst + array.rst + gc.rst + math.rst + sys.rst + ubinascii.rst + ucollections.rst + uerrno.rst + uhashlib.rst + uheapq.rst + uio.rst + ujson.rst + ure.rst + uselect.rst + usocket.rst + ussl.rst + ustruct.rst + uzlib.rst MicroPython-specific libraries @@ -171,46 +47,16 @@ the following libraries. btree.rst framebuf.rst - machine.rst micropython.rst network.rst uctypes.rst +Libraries specific to the ESP8266 +--------------------------------- -.. only:: port_pyboard +The following libraries are specific to the ESP8266. - Libraries specific to the pyboard - --------------------------------- +.. toctree:: + :maxdepth: 2 - The following libraries are specific to the pyboard. - - .. toctree:: - :maxdepth: 2 - - pyb.rst - lcd160cr.rst - -.. only:: port_wipy - - Libraries specific to the WiPy - --------------------------------- - - The following libraries are specific to the WiPy. - - .. toctree:: - :maxdepth: 2 - - wipy.rst - - -.. only:: port_esp8266 - - Libraries specific to the ESP8266 - --------------------------------- - - The following libraries are specific to the ESP8266. - - .. toctree:: - :maxdepth: 2 - - esp.rst + esp.rst diff --git a/docs/library/lcd160cr.rst b/docs/library/lcd160cr.rst deleted file mode 100644 index 567994640b..0000000000 --- a/docs/library/lcd160cr.rst +++ /dev/null @@ -1,394 +0,0 @@ -:mod:`lcd160cr` --- control of LCD160CR display -=============================================== - -.. module:: lcd160cr - :synopsis: control of LCD160CR display - -This module provides control of the MicroPython LCD160CR display. - -.. image:: http://micropython.org/resources/LCD160CRv10-persp.jpg - :alt: LCD160CRv1.0 picture - :width: 640px - -Further resources are available via the following links: - -* `LCD160CRv1.0 reference manual `_ (100KiB PDF) -* `LCD160CRv1.0 schematics `_ (1.6MiB PDF) - -class LCD160CR --------------- - -The LCD160CR class provides an interface to the display. Create an -instance of this class and use its methods to draw to the LCD and get -the status of the touch panel. - -For example:: - - import lcd160cr - - lcd = lcd160cr.LCD160CR('X') - lcd.set_orient(lcd160cr.PORTRAIT) - lcd.set_pos(0, 0) - lcd.set_text_color(lcd.rgb(255, 0, 0), lcd.rgb(0, 0, 0)) - lcd.set_font(1) - lcd.write('Hello MicroPython!') - print('touch:', lcd.get_touch()) - -Constructors ------------- - -.. class:: LCD160CR(connect=None, \*, pwr=None, i2c=None, spi=None, i2c_addr=98) - - Construct an LCD160CR object. The parameters are: - - - *connect* is a string specifying the physical connection of the LCD - display to the board; valid values are "X", "Y", "XY", "YX". - Use "X" when the display is connected to a pyboard in the X-skin - position, and "Y" when connected in the Y-skin position. "XY" - and "YX" are used when the display is connected to the right or - left side of the pyboard, respectively. - - *pwr* is a Pin object connected to the LCD's power/enabled pin. - - *i2c* is an I2C object connected to the LCD's I2C interface. - - *spi* is an SPI object connected to the LCD's SPI interface. - - *i2c_addr* is the I2C address of the display. - - One must specify either a valid *connect* or all of *pwr*, *i2c* and *spi*. - If a valid *connect* is given then any of *pwr*, *i2c* or *spi* which are - not passed as parameters (i.e. they are ``None``) will be created based on the - value of *connect*. This allows to override the default interface to the - display if needed. - - The default values are: - - - "X" is for the X-skin and uses: - ``pwr=Pin("X4")``, ``i2c=I2C("X")``, ``spi=SPI("X")`` - - "Y" is for the Y-skin and uses: - ``pwr=Pin("Y4")``, ``i2c=I2C("Y")``, ``spi=SPI("Y")`` - - "XY" is for the right-side and uses: - ``pwr=Pin("X4")``, ``i2c=I2C("Y")``, ``spi=SPI("X")`` - - "YX" is for the left-side and uses: - ``pwr=Pin("Y4")``, ``i2c=I2C("X")``, ``spi=SPI("Y")`` - - See `this image `_ - for how the display can be connected to the pyboard. - -Static methods --------------- - -.. staticmethod:: LCD160CR.rgb(r, g, b) - - Return a 16-bit integer representing the given rgb color values. The - 16-bit value can be used to set the font color (see - :meth:`LCD160CR.set_text_color`) pen color (see :meth:`LCD160CR.set_pen`) - and draw individual pixels. - -.. staticmethod:: LCD160CR.clip_line(data, w, h): - - Clip the given line data. This is for internal use. - -Instance members ----------------- - -The following instance members are publicly accessible. - -.. data:: LCD160CR.w -.. data:: LCD160CR.h - - The width and height of the display, respectively, in pixels. These - members are updated when calling :meth:`LCD160CR.set_orient` and should - be considered read-only. - -Setup commands --------------- - -.. method:: LCD160CR.set_power(on) - - Turn the display on or off, depending on the given value of *on*: 0 or ``False`` - will turn the display off, and 1 or ``True`` will turn it on. - -.. method:: LCD160CR.set_orient(orient) - - Set the orientation of the display. The *orient* parameter can be one - of `PORTRAIT`, `LANDSCAPE`, `PORTRAIT_UPSIDEDOWN`, `LANDSCAPE_UPSIDEDOWN`. - -.. method:: LCD160CR.set_brightness(value) - - Set the brightness of the display, between 0 and 31. - -.. method:: LCD160CR.set_i2c_addr(addr) - - Set the I2C address of the display. The *addr* value must have the - lower 2 bits cleared. - -.. method:: LCD160CR.set_uart_baudrate(baudrate) - - Set the baudrate of the UART interface. - -.. method:: LCD160CR.set_startup_deco(value) - - Set the start-up decoration of the display. The *value* parameter can be a - logical or of `STARTUP_DECO_NONE`, `STARTUP_DECO_MLOGO`, `STARTUP_DECO_INFO`. - -.. method:: LCD160CR.save_to_flash() - - Save the following parameters to flash so they persist on restart and power up: - initial decoration, orientation, brightness, UART baud rate, I2C address. - -Pixel access methods --------------------- - -The following methods manipulate individual pixels on the display. - -.. method:: LCD160CR.set_pixel(x, y, c) - - Set the specified pixel to the given color. The color should be a 16-bit - integer and can be created by :meth:`LCD160CR.rgb`. - -.. method:: LCD160CR.get_pixel(x, y) - - Get the 16-bit value of the specified pixel. - -.. method:: LCD160CR.get_line(x, y, buf) - - Low-level method to get a line of pixels into the given buffer. - To read *n* pixels *buf* should be *2*n+1* bytes in length. The first byte - is a dummy byte and should be ignored, and subsequent bytes represent the - pixels in the line starting at coordinate *(x, y)*. - -.. method:: LCD160CR.screen_dump(buf, x=0, y=0, w=None, h=None) - - Dump the contents of the screen to the given buffer. The parameters *x* and *y* - specify the starting coordinate, and *w* and *h* the size of the region. If *w* - or *h* are ``None`` then they will take on their maximum values, set by the size - of the screen minus the given *x* and *y* values. *buf* should be large enough - to hold ``2*w*h`` bytes. If it's smaller then only the initial horizontal lines - will be stored. - -.. method:: LCD160CR.screen_load(buf) - - Load the entire screen from the given buffer. - -Drawing text ------------- - -To draw text one sets the position, color and font, and then uses -`write` to draw the text. - -.. method:: LCD160CR.set_pos(x, y) - - Set the position for text output using :meth:`LCD160CR.write`. The position - is the upper-left corner of the text. - -.. method:: LCD160CR.set_text_color(fg, bg) - - Set the foreground and background color of the text. - -.. method:: LCD160CR.set_font(font, scale=0, bold=0, trans=0, scroll=0) - - Set the font for the text. Subsequent calls to `write` will use the newly - configured font. The parameters are: - - - *font* is the font family to use, valid values are 0, 1, 2, 3. - - *scale* is a scaling value for each character pixel, where the pixels - are drawn as a square with side length equal to *scale + 1*. The value - can be between 0 and 63. - - *bold* controls the number of pixels to overdraw each character pixel, - making a bold effect. The lower 2 bits of *bold* are the number of - pixels to overdraw in the horizontal direction, and the next 2 bits are - for the vertical direction. For example, a *bold* value of 5 will - overdraw 1 pixel in both the horizontal and vertical directions. - - *trans* can be either 0 or 1 and if set to 1 the characters will be - drawn with a transparent background. - - *scroll* can be either 0 or 1 and if set to 1 the display will do a - soft scroll if the text moves to the next line. - -.. method:: LCD160CR.write(s) - - Write text to the display, using the current position, color and font. - As text is written the position is automatically incremented. The - display supports basic VT100 control codes such as newline and backspace. - -Drawing primitive shapes ------------------------- - -Primitive drawing commands use a foreground and background color set by the -`set_pen` method. - -.. method:: LCD160CR.set_pen(line, fill) - - Set the line and fill color for primitive shapes. - -.. method:: LCD160CR.erase() - - Erase the entire display to the pen fill color. - -.. method:: LCD160CR.dot(x, y) - - Draw a single pixel at the given location using the pen line color. - -.. method:: LCD160CR.rect(x, y, w, h) -.. method:: LCD160CR.rect_outline(x, y, w, h) -.. method:: LCD160CR.rect_interior(x, y, w, h) - - Draw a rectangle at the given location and size using the pen line - color for the outline, and the pen fill color for the interior. - The `rect` method draws the outline and interior, while the other methods - just draw one or the other. - -.. method:: LCD160CR.line(x1, y1, x2, y2) - - Draw a line between the given coordinates using the pen line color. - -.. method:: LCD160CR.dot_no_clip(x, y) -.. method:: LCD160CR.rect_no_clip(x, y, w, h) -.. method:: LCD160CR.rect_outline_no_clip(x, y, w, h) -.. method:: LCD160CR.rect_interior_no_clip(x, y, w, h) -.. method:: LCD160CR.line_no_clip(x1, y1, x2, y2) - - These methods are as above but don't do any clipping on the input - coordinates. They are faster than the clipping versions and can be - used when you know that the coordinates are within the display. - -.. method:: LCD160CR.poly_dot(data) - - Draw a sequence of dots using the pen line color. - The *data* should be a buffer of bytes, with each successive pair of - bytes corresponding to coordinate pairs (x, y). - -.. method:: LCD160CR.poly_line(data) - - Similar to :meth:`LCD160CR.poly_dot` but draws lines between the dots. - -Touch screen methods --------------------- - -.. method:: LCD160CR.touch_config(calib=False, save=False, irq=None) - - Configure the touch panel: - - - If *calib* is ``True`` then the call will trigger a touch calibration of - the resistive touch sensor. This requires the user to touch various - parts of the screen. - - If *save* is ``True`` then the touch parameters will be saved to NVRAM - to persist across reset/power up. - - If *irq* is ``True`` then the display will be configured to pull the IRQ - line low when a touch force is detected. If *irq* is ``False`` then this - feature is disabled. If *irq* is ``None`` (the default value) then no - change is made to this setting. - -.. method:: LCD160CR.is_touched() - - Returns a boolean: ``True`` if there is currently a touch force on the screen, - `False` otherwise. - -.. method:: LCD160CR.get_touch() - - Returns a 3-tuple of: *(active, x, y)*. If there is currently a touch force - on the screen then *active* is 1, otherwise it is 0. The *x* and *y* values - indicate the position of the current or most recent touch. - -Advanced commands ------------------ - -.. method:: LCD160CR.set_spi_win(x, y, w, h) - - Set the window that SPI data is written to. - -.. method:: LCD160CR.fast_spi(flush=True) - - Ready the display to accept RGB pixel data on the SPI bus, resetting the location - of the first byte to go to the top-left corner of the window set by - :meth:`LCD160CR.set_spi_win`. - The method returns an SPI object which can be used to write the pixel data. - - Pixels should be sent as 16-bit RGB values in the 5-6-5 format. The destination - counter will increase as data is sent, and data can be sent in arbitrary sized - chunks. Once the destination counter reaches the end of the window specified by - :meth:`LCD160CR.set_spi_win` it will wrap around to the top-left corner of that window. - -.. method:: LCD160CR.show_framebuf(buf) - - Show the given buffer on the display. *buf* should be an array of bytes containing - the 16-bit RGB values for the pixels, and they will be written to the area - specified by :meth:`LCD160CR.set_spi_win`, starting from the top-left corner. - - The `framebuf `_ module can be used to construct frame buffers - and provides drawing primitives. Using a frame buffer will improve - performance of animations when compared to drawing directly to the screen. - -.. method:: LCD160CR.set_scroll(on) - - Turn scrolling on or off. This controls globally whether any window regions will - scroll. - -.. method:: LCD160CR.set_scroll_win(win, x=-1, y=0, w=0, h=0, vec=0, pat=0, fill=0x07e0, color=0) - - Configure a window region for scrolling: - - - *win* is the window id to configure. There are 0..7 standard windows for - general purpose use. Window 8 is the text scroll window (the ticker). - - *x*, *y*, *w*, *h* specify the location of the window in the display. - - *vec* specifies the direction and speed of scroll: it is a 16-bit value - of the form ``0bF.ddSSSSSSSSSSSS``. *dd* is 0, 1, 2, 3 for +x, +y, -x, - -y scrolling. *F* sets the speed format, with 0 meaning that the window - is shifted *S % 256* pixel every frame, and 1 meaning that the window - is shifted 1 pixel every *S* frames. - - *pat* is a 16-bit pattern mask for the background. - - *fill* is the fill color. - - *color* is the extra color, either of the text or pattern foreground. - -.. method:: LCD160CR.set_scroll_win_param(win, param, value) - - Set a single parameter of a scrolling window region: - - - *win* is the window id, 0..8. - - *param* is the parameter number to configure, 0..7, and corresponds - to the parameters in the `set_scroll_win` method. - - *value* is the value to set. - -.. method:: LCD160CR.set_scroll_buf(s) - - Set the string for scrolling in window 8. The parameter *s* must be a string - with length 32 or less. - -.. method:: LCD160CR.jpeg(buf) - - Display a JPEG. *buf* should contain the entire JPEG data. JPEG data should - not include EXIF information. The following encodings are supported: Baseline - DCT, Huffman coding, 8 bits per sample, 3 color components, YCbCr4:2:2. - The origin of the JPEG is set by :meth:`LCD160CR.set_pos`. - -.. method:: LCD160CR.jpeg_start(total_len) -.. method:: LCD160CR.jpeg_data(buf) - - Display a JPEG with the data split across multiple buffers. There must be - a single call to `jpeg_start` to begin with, specifying the total number of - bytes in the JPEG. Then this number of bytes must be transferred to the - display using one or more calls to the `jpeg_data` command. - -.. method:: LCD160CR.feed_wdt() - - The first call to this method will start the display's internal watchdog - timer. Subsequent calls will feed the watchdog. The timeout is roughly 30 - seconds. - -.. method:: LCD160CR.reset() - - Reset the display. - -Constants ---------- - -.. data:: lcd160cr.PORTRAIT - lcd160cr.LANDSCAPE - lcd160cr.PORTRAIT_UPSIDEDOWN - lcd160cr.LANDSCAPE_UPSIDEDOWN - - Orientations of the display, used by :meth:`LCD160CR.set_orient`. - -.. data:: lcd160cr.STARTUP_DECO_NONE - lcd160cr.STARTUP_DECO_MLOGO - lcd160cr.STARTUP_DECO_INFO - - Types of start-up decoration, can be OR'ed together, used by - :meth:`LCD160CR.set_startup_deco`. diff --git a/docs/library/machine.ADC.rst b/docs/library/machine.ADC.rst deleted file mode 100644 index 4c7a04d74f..0000000000 --- a/docs/library/machine.ADC.rst +++ /dev/null @@ -1,74 +0,0 @@ -.. currentmodule:: machine -.. _machine.ADC: - -class ADC -- analog to digital conversion -========================================= - -Usage:: - - import machine - - adc = machine.ADC() # create an ADC object - apin = adc.channel(pin='GP3') # create an analog pin on GP3 - val = apin() # read an analog value - -Constructors ------------- - -.. class:: ADC(id=0, \*, bits=12) - - Create an ADC object associated with the given pin. - This allows you to then read analog values on that pin. - For more info check the `pinout and alternate functions - table. `_ - - .. warning:: - - ADC pin input range is 0-1.4V (being 1.8V the absolute maximum that it - can withstand). When GP2, GP3, GP4 or GP5 are remapped to the - ADC block, 1.8 V is the maximum. If these pins are used in digital mode, - then the maximum allowed input is 3.6V. - -Methods -------- - -.. method:: ADC.channel(id, \*, pin) - - Create an analog pin. If only channel ID is given, the correct pin will - be selected. Alternatively, only the pin can be passed and the correct - channel will be selected. Examples:: - - # all of these are equivalent and enable ADC channel 1 on GP3 - apin = adc.channel(1) - apin = adc.channel(pin='GP3') - apin = adc.channel(id=1, pin='GP3') - -.. method:: ADC.init() - - Enable the ADC block. - -.. method:: ADC.deinit() - - Disable the ADC block. - -class ADCChannel --- read analog values from internal or external sources -========================================================================= - -ADC channels can be connected to internal points of the MCU or to GPIO pins. -ADC channels are created using the ADC.channel method. - -.. method:: adcchannel() - - Fast method to read the channel value. - -.. method:: adcchannel.value() - - Read the channel value. - -.. method:: adcchannel.init() - - Re-init (and effectively enable) the ADC channel. - -.. method:: adcchannel.deinit() - - Disable the ADC channel. diff --git a/docs/library/machine.I2C.rst b/docs/library/machine.I2C.rst deleted file mode 100644 index a69c58999f..0000000000 --- a/docs/library/machine.I2C.rst +++ /dev/null @@ -1,172 +0,0 @@ -.. currentmodule:: machine -.. _machine.I2C: - -class I2C -- a two-wire serial protocol -======================================= - -I2C is a two-wire protocol for communicating between devices. At the physical -level it consists of 2 wires: SCL and SDA, the clock and data lines respectively. - -I2C objects are created attached to a specific bus. They can be initialised -when created, or initialised later on. - -Printing the I2C object gives you information about its configuration. - -Example usage:: - - from machine import I2C - - i2c = I2C(freq=400000) # create I2C peripheral at frequency of 400kHz - # depending on the port, extra parameters may be required - # to select the peripheral and/or pins to use - - i2c.scan() # scan for slaves, returning a list of 7-bit addresses - - i2c.writeto(42, b'123') # write 3 bytes to slave with 7-bit address 42 - i2c.readfrom(42, 4) # read 4 bytes from slave with 7-bit address 42 - - i2c.readfrom_mem(42, 8, 3) # read 3 bytes from memory of slave 42, - # starting at memory-address 8 in the slave - i2c.writeto_mem(42, 2, b'\x10') # write 1 byte to memory of slave 42 - # starting at address 2 in the slave - -Constructors ------------- - -.. class:: I2C(id=-1, \*, scl, sda, freq=400000) - - Construct and return a new I2C object using the following parameters: - - - *id* identifies a particular I2C peripheral. The default - value of -1 selects a software implementation of I2C which can - work (in most cases) with arbitrary pins for SCL and SDA. - If *id* is -1 then *scl* and *sda* must be specified. Other - allowed values for *id* depend on the particular port/board, - and specifying *scl* and *sda* may or may not be required or - allowed in this case. - - *scl* should be a pin object specifying the pin to use for SCL. - - *sda* should be a pin object specifying the pin to use for SDA. - - *freq* should be an integer which sets the maximum frequency - for SCL. - -General Methods ---------------- - -.. method:: I2C.init(scl, sda, \*, freq=400000) - - Initialise the I2C bus with the given arguments: - - - *scl* is a pin object for the SCL line - - *sda* is a pin object for the SDA line - - *freq* is the SCL clock rate - -.. method:: I2C.deinit() - - Turn off the I2C bus. - - Availability: WiPy. - -.. method:: I2C.scan() - - Scan all I2C addresses between 0x08 and 0x77 inclusive and return a list of - those that respond. A device responds if it pulls the SDA line low after - its address (including a write bit) is sent on the bus. - -Primitive I2C operations ------------------------- - -The following methods implement the primitive I2C master bus operations and can -be combined to make any I2C transaction. They are provided if you need more -control over the bus, otherwise the standard methods (see below) can be used. - -.. method:: I2C.start() - - Generate a START condition on the bus (SDA transitions to low while SCL is high). - - Availability: ESP8266. - -.. method:: I2C.stop() - - Generate a STOP condition on the bus (SDA transitions to high while SCL is high). - - Availability: ESP8266. - -.. method:: I2C.readinto(buf, nack=True) - - Reads bytes from the bus and stores them into *buf*. The number of bytes - read is the length of *buf*. An ACK will be sent on the bus after - receiving all but the last byte. After the last byte is received, if *nack* - is true then a NACK will be sent, otherwise an ACK will be sent (and in this - case the slave assumes more bytes are going to be read in a later call). - - Availability: ESP8266. - -.. method:: I2C.write(buf) - - Write the bytes from *buf* to the bus. Checks that an ACK is received - after each byte and stops transmitting the remaining bytes if a NACK is - received. The function returns the number of ACKs that were received. - - Availability: ESP8266. - -Standard bus operations ------------------------ - -The following methods implement the standard I2C master read and write -operations that target a given slave device. - -.. method:: I2C.readfrom(addr, nbytes, stop=True) - - Read *nbytes* from the slave specified by *addr*. - If *stop* is true then a STOP condition is generated at the end of the transfer. - Returns a `bytes` object with the data read. - -.. method:: I2C.readfrom_into(addr, buf, stop=True) - - Read into *buf* from the slave specified by *addr*. - The number of bytes read will be the length of *buf*. - If *stop* is true then a STOP condition is generated at the end of the transfer. - - The method returns ``None``. - -.. method:: I2C.writeto(addr, buf, stop=True) - - Write the bytes from *buf* to the slave specified by *addr*. If a - NACK is received following the write of a byte from *buf* then the - remaining bytes are not sent. If *stop* is true then a STOP condition is - generated at the end of the transfer, even if a NACK is received. - The function returns the number of ACKs that were received. - -Memory operations ------------------ - -Some I2C devices act as a memory device (or set of registers) that can be read -from and written to. In this case there are two addresses associated with an -I2C transaction: the slave address and the memory address. The following -methods are convenience functions to communicate with such devices. - -.. method:: I2C.readfrom_mem(addr, memaddr, nbytes, \*, addrsize=8) - - Read *nbytes* from the slave specified by *addr* starting from the memory - address specified by *memaddr*. - The argument *addrsize* specifies the address size in bits. - Returns a `bytes` object with the data read. - -.. method:: I2C.readfrom_mem_into(addr, memaddr, buf, \*, addrsize=8) - - Read into *buf* from the slave specified by *addr* starting from the - memory address specified by *memaddr*. The number of bytes read is the - length of *buf*. - The argument *addrsize* specifies the address size in bits (on ESP8266 - this argument is not recognised and the address size is always 8 bits). - - The method returns ``None``. - -.. method:: I2C.writeto_mem(addr, memaddr, buf, \*, addrsize=8) - - Write *buf* to the slave specified by *addr* starting from the - memory address specified by *memaddr*. - The argument *addrsize* specifies the address size in bits (on ESP8266 - this argument is not recognised and the address size is always 8 bits). - - The method returns ``None``. diff --git a/docs/library/machine.Pin.rst b/docs/library/machine.Pin.rst deleted file mode 100644 index 05ceb4ad33..0000000000 --- a/docs/library/machine.Pin.rst +++ /dev/null @@ -1,248 +0,0 @@ -.. currentmodule:: machine -.. _machine.Pin: - -class Pin -- control I/O pins -============================= - -A pin object is used to control I/O pins (also known as GPIO - general-purpose -input/output). Pin objects are commonly associated with a physical pin that can -drive an output voltage and read input voltages. The pin class has methods to set the mode of -the pin (IN, OUT, etc) and methods to get and set the digital logic level. -For analog control of a pin, see the :class:`ADC` class. - -A pin object is constructed by using an identifier which unambiguously -specifies a certain I/O pin. The allowed forms of the identifier and the -physical pin that the identifier maps to are port-specific. Possibilities -for the identifier are an integer, a string or a tuple with port and pin -number. - -Usage Model:: - - from machine import Pin - - # create an output pin on pin #0 - p0 = Pin(0, Pin.OUT) - - # set the value low then high - p0.value(0) - p0.value(1) - - # create an input pin on pin #2, with a pull up resistor - p2 = Pin(2, Pin.IN, Pin.PULL_UP) - - # read and print the pin value - print(p2.value()) - - # reconfigure pin #0 in input mode - p0.mode(p0.IN) - - # configure an irq callback - p0.irq(lambda p:print(p)) - -Constructors ------------- - -.. class:: Pin(id, mode=-1, pull=-1, \*, value, drive, alt) - - Access the pin peripheral (GPIO pin) associated with the given ``id``. If - additional arguments are given in the constructor then they are used to initialise - the pin. Any settings that are not specified will remain in their previous state. - - The arguments are: - - - ``id`` is mandatory and can be an arbitrary object. Among possible value - types are: int (an internal Pin identifier), str (a Pin name), and tuple - (pair of [port, pin]). - - - ``mode`` specifies the pin mode, which can be one of: - - - ``Pin.IN`` - Pin is configured for input. If viewed as an output the pin - is in high-impedance state. - - - ``Pin.OUT`` - Pin is configured for (normal) output. - - - ``Pin.OPEN_DRAIN`` - Pin is configured for open-drain output. Open-drain - output works in the following way: if the output value is set to 0 the pin - is active at a low level; if the output value is 1 the pin is in a high-impedance - state. Not all ports implement this mode, or some might only on certain pins. - - - ``Pin.ALT`` - Pin is configured to perform an alternative function, which is - port specific. For a pin configured in such a way any other Pin methods - (except :meth:`Pin.init`) are not applicable (calling them will lead to undefined, - or a hardware-specific, result). Not all ports implement this mode. - - - ``Pin.ALT_OPEN_DRAIN`` - The Same as ``Pin.ALT``, but the pin is configured as - open-drain. Not all ports implement this mode. - - - ``pull`` specifies if the pin has a (weak) pull resistor attached, and can be - one of: - - - ``None`` - No pull up or down resistor. - - ``Pin.PULL_UP`` - Pull up resistor enabled. - - ``Pin.PULL_DOWN`` - Pull down resistor enabled. - - - ``value`` is valid only for Pin.OUT and Pin.OPEN_DRAIN modes and specifies initial - output pin value if given, otherwise the state of the pin peripheral remains - unchanged. - - - ``drive`` specifies the output power of the pin and can be one of: ``Pin.LOW_POWER``, - ``Pin.MED_POWER`` or ``Pin.HIGH_POWER``. The actual current driving capabilities - are port dependent. Not all ports implement this argument. - - - ``alt`` specifies an alternate function for the pin and the values it can take are - port dependent. This argument is valid only for ``Pin.ALT`` and ``Pin.ALT_OPEN_DRAIN`` - modes. It may be used when a pin supports more than one alternate function. If only - one pin alternate function is supported the this argument is not required. Not all - ports implement this argument. - - As specified above, the Pin class allows to set an alternate function for a particular - pin, but it does not specify any further operations on such a pin. Pins configured in - alternate-function mode are usually not used as GPIO but are instead driven by other - hardware peripherals. The only operation supported on such a pin is re-initialising, - by calling the constructor or :meth:`Pin.init` method. If a pin that is configured in - alternate-function mode is re-initialised with ``Pin.IN``, ``Pin.OUT``, or - ``Pin.OPEN_DRAIN``, the alternate function will be removed from the pin. - -Methods -------- - -.. method:: Pin.init(mode=-1, pull=-1, \*, value, drive, alt) - - Re-initialise the pin using the given parameters. Only those arguments that - are specified will be set. The rest of the pin peripheral state will remain - unchanged. See the constructor documentation for details of the arguments. - - Returns ``None``. - -.. method:: Pin.value([x]) - - This method allows to set and get the value of the pin, depending on whether - the argument ``x`` is supplied or not. - - If the argument is omitted then this method gets the digital logic level of - the pin, returning 0 or 1 corresponding to low and high voltage signals - respectively. The behaviour of this method depends on the mode of the pin: - - - ``Pin.IN`` - The method returns the actual input value currently present - on the pin. - - ``Pin.OUT`` - The behaviour and return value of the method is undefined. - - ``Pin.OPEN_DRAIN`` - If the pin is in state '0' then the behaviour and - return value of the method is undefined. Otherwise, if the pin is in - state '1', the method returns the actual input value currently present - on the pin. - - If the argument is supplied then this method sets the digital logic level of - the pin. The argument ``x`` can be anything that converts to a boolean. - If it converts to ``True``, the pin is set to state '1', otherwise it is set - to state '0'. The behaviour of this method depends on the mode of the pin: - - - ``Pin.IN`` - The value is stored in the output buffer for the pin. The - pin state does not change, it remains in the high-impedance state. The - stored value will become active on the pin as soon as it is changed to - ``Pin.OUT`` or ``Pin.OPEN_DRAIN`` mode. - - ``Pin.OUT`` - The output buffer is set to the given value immediately. - - ``Pin.OPEN_DRAIN`` - If the value is '0' the pin is set to a low voltage - state. Otherwise the pin is set to high-impedance state. - - When setting the value this method returns ``None``. - -.. method:: Pin.__call__([x]) - - Pin objects are callable. The call method provides a (fast) shortcut to set - and get the value of the pin. It is equivalent to Pin.value([x]). - See :meth:`Pin.value` for more details. - -.. method:: Pin.on() - - Set pin to "1" output level. - -.. method:: Pin.off() - - Set pin to "0" output level. - -.. method:: Pin.mode([mode]) - - Get or set the pin mode. - See the constructor documentation for details of the ``mode`` argument. - -.. method:: Pin.pull([pull]) - - Get or set the pin pull state. - See the constructor documentation for details of the ``pull`` argument. - -.. method:: Pin.drive([drive]) - - Get or set the pin drive strength. - See the constructor documentation for details of the ``drive`` argument. - - Not all ports implement this method. - - Availability: WiPy. - -.. method:: Pin.irq(handler=None, trigger=(Pin.IRQ_FALLING | Pin.IRQ_RISING), \*, priority=1, wake=None) - - Configure an interrupt handler to be called when the trigger source of the - pin is active. If the pin mode is ``Pin.IN`` then the trigger source is - the external value on the pin. If the pin mode is ``Pin.OUT`` then the - trigger source is the output buffer of the pin. Otherwise, if the pin mode - is ``Pin.OPEN_DRAIN`` then the trigger source is the output buffer for - state '0' and the external pin value for state '1'. - - The arguments are: - - - ``handler`` is an optional function to be called when the interrupt - triggers. - - - ``trigger`` configures the event which can generate an interrupt. - Possible values are: - - - ``Pin.IRQ_FALLING`` interrupt on falling edge. - - ``Pin.IRQ_RISING`` interrupt on rising edge. - - ``Pin.IRQ_LOW_LEVEL`` interrupt on low level. - - ``Pin.IRQ_HIGH_LEVEL`` interrupt on high level. - - These values can be OR'ed together to trigger on multiple events. - - - ``priority`` sets the priority level of the interrupt. The values it - can take are port-specific, but higher values always represent higher - priorities. - - - ``wake`` selects the power mode in which this interrupt can wake up the - system. It can be ``machine.IDLE``, ``machine.SLEEP`` or ``machine.DEEPSLEEP``. - These values can also be OR'ed together to make a pin generate interrupts in - more than one power mode. - - This method returns a callback object. - -Constants ---------- - -The following constants are used to configure the pin objects. Note that -not all constants are available on all ports. - -.. data:: Pin.IN - Pin.OUT - Pin.OPEN_DRAIN - Pin.ALT - Pin.ALT_OPEN_DRAIN - - Selects the pin mode. - -.. data:: Pin.PULL_UP - Pin.PULL_DOWN - - Selects whether there is a pull up/down resistor. Use the value - ``None`` for no pull. - -.. data:: Pin.LOW_POWER - Pin.MED_POWER - Pin.HIGH_POWER - - Selects the pin drive strength. - -.. data:: Pin.IRQ_FALLING - Pin.IRQ_RISING - Pin.IRQ_LOW_LEVEL - Pin.IRQ_HIGH_LEVEL - - Selects the IRQ trigger type. diff --git a/docs/library/machine.RTC.rst b/docs/library/machine.RTC.rst deleted file mode 100644 index 95fa2b4ce6..0000000000 --- a/docs/library/machine.RTC.rst +++ /dev/null @@ -1,69 +0,0 @@ -.. currentmodule:: machine -.. _machine.RTC: - -class RTC -- real time clock -============================ - -The RTC is and independent clock that keeps track of the date -and time. - -Example usage:: - - rtc = machine.RTC() - rtc.init((2014, 5, 1, 4, 13, 0, 0, 0)) - print(rtc.now()) - - -Constructors ------------- - -.. class:: RTC(id=0, ...) - - Create an RTC object. See init for parameters of initialization. - -Methods -------- - -.. method:: RTC.init(datetime) - - Initialise the RTC. Datetime is a tuple of the form: - - ``(year, month, day[, hour[, minute[, second[, microsecond[, tzinfo]]]]])`` - -.. method:: RTC.now() - - Get get the current datetime tuple. - -.. method:: RTC.deinit() - - Resets the RTC to the time of January 1, 2015 and starts running it again. - -.. method:: RTC.alarm(id, time, \*, repeat=False) - - Set the RTC alarm. Time might be either a millisecond value to program the alarm to - current time + time_in_ms in the future, or a datetimetuple. If the time passed is in - milliseconds, repeat can be set to ``True`` to make the alarm periodic. - -.. method:: RTC.alarm_left(alarm_id=0) - - Get the number of milliseconds left before the alarm expires. - -.. method:: RTC.cancel(alarm_id=0) - - Cancel a running alarm. - -.. method:: RTC.irq(\*, trigger, handler=None, wake=machine.IDLE) - - Create an irq object triggered by a real time clock alarm. - - - ``trigger`` must be ``RTC.ALARM0`` - - ``handler`` is the function to be called when the callback is triggered. - - ``wake`` specifies the sleep mode from where this interrupt can wake - up the system. - -Constants ---------- - -.. data:: RTC.ALARM0 - - irq trigger source diff --git a/docs/library/machine.SD.rst b/docs/library/machine.SD.rst deleted file mode 100644 index 608e958317..0000000000 --- a/docs/library/machine.SD.rst +++ /dev/null @@ -1,42 +0,0 @@ -.. currentmodule:: machine -.. _machine.SD: - -class SD -- secure digital memory card -====================================== - -The SD card class allows to configure and enable the memory card -module of the WiPy and automatically mount it as ``/sd`` as part -of the file system. There are several pin combinations that can be -used to wire the SD card socket to the WiPy and the pins used can -be specified in the constructor. Please check the `pinout and alternate functions -table. `_ for -more info regarding the pins which can be remapped to be used with a SD card. - -Example usage:: - - from machine import SD - import os - # clk cmd and dat0 pins must be passed along with - # their respective alternate functions - sd = machine.SD(pins=('GP10', 'GP11', 'GP15')) - os.mount(sd, '/sd') - # do normal file operations - -Constructors ------------- - -.. class:: SD(id,... ) - - Create a SD card object. See ``init()`` for parameters if initialization. - -Methods -------- - -.. method:: SD.init(id=0, pins=('GP10', 'GP11', 'GP15')) - - Enable the SD card. In order to initialize the card, give it a 3-tuple: - ``(clk_pin, cmd_pin, dat0_pin)``. - -.. method:: SD.deinit() - - Disable the SD card. diff --git a/docs/library/machine.SPI.rst b/docs/library/machine.SPI.rst deleted file mode 100644 index 080f6fdfb2..0000000000 --- a/docs/library/machine.SPI.rst +++ /dev/null @@ -1,97 +0,0 @@ -.. currentmodule:: machine -.. _machine.SPI: - -class SPI -- a Serial Peripheral Interface bus protocol (master side) -===================================================================== - -SPI is a synchronous serial protocol that is driven by a master. At the -physical level, a bus consists of 3 lines: SCK, MOSI, MISO. Multiple devices -can share the same bus. Each device should have a separate, 4th signal, -SS (Slave Select), to select a particular device on a bus with which -communication takes place. Management of an SS signal should happen in -user code (via machine.Pin class). - -Constructors ------------- - -.. class:: SPI(id, ...) - - Construct an SPI object on the given bus, ``id``. Values of ``id`` depend - on a particular port and its hardware. Values 0, 1, etc. are commonly used - to select hardware SPI block #0, #1, etc. Value -1 can be used for - bitbanging (software) implementation of SPI (if supported by a port). - - With no additional parameters, the SPI object is created but not - initialised (it has the settings from the last initialisation of - the bus, if any). If extra arguments are given, the bus is initialised. - See ``init`` for parameters of initialisation. - -Methods -------- - -.. method:: SPI.init(baudrate=1000000, \*, polarity=0, phase=0, bits=8, firstbit=SPI.MSB, sck=None, mosi=None, miso=None, pins=(SCK, MOSI, MISO)) - - Initialise the SPI bus with the given parameters: - - - ``baudrate`` is the SCK clock rate. - - ``polarity`` can be 0 or 1, and is the level the idle clock line sits at. - - ``phase`` can be 0 or 1 to sample data on the first or second clock edge - respectively. - - ``bits`` is the width in bits of each transfer. Only 8 is guaranteed to be supported by all hardware. - - ``firstbit`` can be ``SPI.MSB`` or ``SPI.LSB``. - - ``sck``, ``mosi``, ``miso`` are pins (machine.Pin) objects to use for bus signals. For most - hardware SPI blocks (as selected by ``id`` parameter to the constructor), pins are fixed - and cannot be changed. In some cases, hardware blocks allow 2-3 alternative pin sets for - a hardware SPI block. Arbitrary pin assignments are possible only for a bitbanging SPI driver - (``id`` = -1). - - ``pins`` - WiPy port doesn't ``sck``, ``mosi``, ``miso`` arguments, and instead allows to - specify them as a tuple of ``pins`` parameter. - -.. method:: SPI.deinit() - - Turn off the SPI bus. - -.. method:: SPI.read(nbytes, write=0x00) - - Read a number of bytes specified by ``nbytes`` while continuously writing - the single byte given by ``write``. - Returns a ``bytes`` object with the data that was read. - -.. method:: SPI.readinto(buf, write=0x00) - - Read into the buffer specified by ``buf`` while continuously writing the - single byte given by ``write``. - Returns ``None``. - - Note: on WiPy this function returns the number of bytes read. - -.. method:: SPI.write(buf) - - Write the bytes contained in ``buf``. - Returns ``None``. - - Note: on WiPy this function returns the number of bytes written. - -.. method:: SPI.write_readinto(write_buf, read_buf) - - Write the bytes from ``write_buf`` while reading into ``read_buf``. The - buffers can be the same or different, but both buffers must have the - same length. - Returns ``None``. - - Note: on WiPy this function returns the number of bytes written. - -Constants ---------- - -.. data:: SPI.MASTER - - for initialising the SPI bus to master; this is only used for the WiPy - -.. data:: SPI.MSB - - set the first bit to be the most significant bit - -.. data:: SPI.LSB - - set the first bit to be the least significant bit diff --git a/docs/library/machine.Signal.rst b/docs/library/machine.Signal.rst deleted file mode 100644 index 4869086274..0000000000 --- a/docs/library/machine.Signal.rst +++ /dev/null @@ -1,96 +0,0 @@ -.. currentmodule:: machine -.. _machine.Signal: - -class Signal -- control and sense external I/O devices -====================================================== - -The Signal class is a simple extension of Pin class. Unlike Pin, which -can be only in "absolute" 0 and 1 states, a Signal can be in "asserted" -(on) or "deasserted" (off) states, while being inverted (active-low) or -not. Summing up, it adds logical inversion support to Pin functionality. -While this may seem a simple addition, it is exactly what is needed to -support wide array of simple digital devices in a way portable across -different boards, which is one of the major MicroPython goals. Regardless -whether different users have an active-high or active-low LED, a normally -open or normally closed relay - you can develop single, nicely looking -application which works with each of them, and capture hardware -configuration differences in few lines on the config file of your app. - -Following is the guide when Signal vs Pin should be used: - -* Use Signal: If you want to control a simple on/off (including software - PWM!) devices like LEDs, multi-segment indicators, relays, buzzers, or - read simple binary sensors, like normally open or normally closed buttons, - pulled high or low, Reed switches, moisture/flame detectors, etc. etc. - Summing up, if you have a real physical device/sensor requiring GPIO - access, you likely should use a Signal. - -* Use Pin: If you implement a higher-level protocol or bus to communicate - with more complex devices. - -The split between Pin and Signal come from the usecases above and the -architecture of MicroPython: Pin offers the lowest overhead, which may -be important when bit-banging protocols. But Signal adds additional -flexibility on top of Pin, at the cost of minor overhead (much smaller -than if you implemented active-high vs active-low device differences in -Python manually!). Also, Pin is low-level object which needs to be -implemented for each support board, while Signal is a high-level object -which comes for free once Pin is implemented. - -If in doubt, give the Signal a try! Once again, it is developed to save -developers from the need to handle unexciting differences like active-low -vs active-high signals, and allow other users to share and enjoy your -application, instead of being frustrated by the fact that it doesn't -work for them simply because their LEDs or relays are wired in a slightly -different way. - -Constructors ------------- - -.. class:: Signal(pin_obj, invert=False) - Signal(pin_arguments..., \*, invert=False) - - Create a Signal object. There're two ways to create it: - - * By wrapping existing Pin object - universal method which works for - any board. - * By passing required Pin parameters directly to Signal constructor, - skipping the need to create intermediate Pin object. Available on - many, but not all boards. - - The arguments are: - - - ``pin_obj`` is existing Pin object. - - - ``pin_arguments`` are the same arguments as can be passed to Pin constructor. - - - ``invert`` - if True, the signal will be inverted (active low). - -Methods -------- - -.. method:: Signal.value([x]) - - This method allows to set and get the value of the signal, depending on whether - the argument ``x`` is supplied or not. - - If the argument is omitted then this method gets the signal level, 1 meaning - signal is asserted (active) and 0 - signal inactive. - - If the argument is supplied then this method sets the signal level. The - argument ``x`` can be anything that converts to a boolean. If it converts - to ``True``, the signal is active, otherwise it is inactive. - - Correspondence between signal being active and actual logic level on the - underlying pin depends on whether signal is inverted (active-low) or not. - For non-inverted signal, active status corresponds to logical 1, inactive - - to logical 0. For inverted/active-low signal, active status corresponds - to logical 0, while inactive - to logical 1. - -.. method:: Signal.on() - - Activate signal. - -.. method:: Signal.off() - - Deactivate signal. diff --git a/docs/library/machine.Timer.rst b/docs/library/machine.Timer.rst deleted file mode 100644 index ef46f9dd7c..0000000000 --- a/docs/library/machine.Timer.rst +++ /dev/null @@ -1,160 +0,0 @@ -.. currentmodule:: machine -.. _machine.Timer: - -class Timer -- control hardware timers -====================================== - -Hardware timers deal with timing of periods and events. Timers are perhaps -the most flexible and heterogeneous kind of hardware in MCUs and SoCs, -differently greatly from a model to a model. MicroPython's Timer class -defines a baseline operation of executing a callback with a given period -(or once after some delay), and allow specific boards to define more -non-standard behavior (which thus won't be portable to other boards). - -See discussion of :ref:`important constraints ` on -Timer callbacks. - -.. note:: - - Memory can't be allocated inside irq handlers (an interrupt) and so - exceptions raised within a handler don't give much information. See - :func:`micropython.alloc_emergency_exception_buf` for how to get around this - limitation. - -Constructors ------------- - -.. class:: Timer(id, ...) - - Construct a new timer object of the given id. Id of -1 constructs a - virtual timer (if supported by a board). - -Methods -------- - -.. only:: port_wipy - - .. method:: Timer.init(mode, \*, width=16) - - Initialise the timer. Example:: - - tim.init(Timer.PERIODIC) # periodic 16-bit timer - tim.init(Timer.ONE_SHOT, width=32) # one shot 32-bit timer - - Keyword arguments: - - - ``mode`` can be one of: - - - ``Timer.ONE_SHOT`` - The timer runs once until the configured - period of the channel expires. - - ``Timer.PERIODIC`` - The timer runs periodically at the configured - frequency of the channel. - - ``Timer.PWM`` - Output a PWM signal on a pin. - - - ``width`` must be either 16 or 32 (bits). For really low frequencies < 5Hz - (or large periods), 32-bit timers should be used. 32-bit mode is only available - for ``ONE_SHOT`` AND ``PERIODIC`` modes. - -.. method:: Timer.deinit() - - Deinitialises the timer. Stops the timer, and disables the timer peripheral. - -.. only:: port_wipy - - .. method:: Timer.channel(channel, \**, freq, period, polarity=Timer.POSITIVE, duty_cycle=0) - - If only a channel identifier passed, then a previously initialized channel - object is returned (or ``None`` if there is no previous channel). - - Otherwise, a TimerChannel object is initialized and returned. - - The operating mode is is the one configured to the Timer object that was used to - create the channel. - - - ``channel`` if the width of the timer is 16-bit, then must be either ``TIMER.A``, ``TIMER.B``. - If the width is 32-bit then it **must be** ``TIMER.A | TIMER.B``. - - Keyword only arguments: - - - ``freq`` sets the frequency in Hz. - - ``period`` sets the period in microseconds. - - .. note:: - - Either ``freq`` or ``period`` must be given, never both. - - - ``polarity`` this is applicable for ``PWM``, and defines the polarity of the duty cycle - - ``duty_cycle`` only applicable to ``PWM``. It's a percentage (0.00-100.00). Since the WiPy - doesn't support floating point numbers the duty cycle must be specified in the range 0-10000, - where 10000 would represent 100.00, 5050 represents 50.50, and so on. - - .. note:: - - When the channel is in PWM mode, the corresponding pin is assigned automatically, therefore - there's no need to assign the alternate function of the pin via the ``Pin`` class. The pins which - support PWM functionality are the following: - - - ``GP24`` on Timer 0 channel A. - - ``GP25`` on Timer 1 channel A. - - ``GP9`` on Timer 2 channel B. - - ``GP10`` on Timer 3 channel A. - - ``GP11`` on Timer 3 channel B. - -.. only:: port_wipy - - class TimerChannel --- setup a channel for a timer - ================================================== - - Timer channels are used to generate/capture a signal using a timer. - - TimerChannel objects are created using the Timer.channel() method. - - Methods - ------- - - .. method:: timerchannel.irq(\*, trigger, priority=1, handler=None) - - The behavior of this callback is heavily dependent on the operating - mode of the timer channel: - - - If mode is ``Timer.PERIODIC`` the callback is executed periodically - with the configured frequency or period. - - If mode is ``Timer.ONE_SHOT`` the callback is executed once when - the configured timer expires. - - If mode is ``Timer.PWM`` the callback is executed when reaching the duty - cycle value. - - The accepted params are: - - - ``priority`` level of the interrupt. Can take values in the range 1-7. - Higher values represent higher priorities. - - ``handler`` is an optional function to be called when the interrupt is triggered. - - ``trigger`` must be ``Timer.TIMEOUT`` when the operating mode is either ``Timer.PERIODIC`` or - ``Timer.ONE_SHOT``. In the case that mode is ``Timer.PWM`` then trigger must be equal to - ``Timer.MATCH``. - - Returns a callback object. - -.. only:: port_wipy - - .. method:: timerchannel.freq([value]) - - Get or set the timer channel frequency (in Hz). - - .. method:: timerchannel.period([value]) - - Get or set the timer channel period (in microseconds). - - .. method:: timerchannel.duty_cycle([value]) - - Get or set the duty cycle of the PWM signal. It's a percentage (0.00-100.00). Since the WiPy - doesn't support floating point numbers the duty cycle must be specified in the range 0-10000, - where 10000 would represent 100.00, 5050 represents 50.50, and so on. - -Constants ---------- - -.. data:: Timer.ONE_SHOT -.. data:: Timer.PERIODIC - - Timer operating mode. diff --git a/docs/library/machine.UART.rst b/docs/library/machine.UART.rst deleted file mode 100644 index 983ef0a947..0000000000 --- a/docs/library/machine.UART.rst +++ /dev/null @@ -1,142 +0,0 @@ -.. currentmodule:: machine -.. _machine.UART: - -class UART -- duplex serial communication bus -============================================= - -UART implements the standard UART/USART duplex serial communications protocol. At -the physical level it consists of 2 lines: RX and TX. The unit of communication -is a character (not to be confused with a string character) which can be 8 or 9 -bits wide. - -UART objects can be created and initialised using:: - - from machine import UART - - uart = UART(1, 9600) # init with given baudrate - uart.init(9600, bits=8, parity=None, stop=1) # init with given parameters - -Supported parameters differ on a board: - -Pyboard: Bits can be 7, 8 or 9. Stop can be 1 or 2. With *parity=None*, -only 8 and 9 bits are supported. With parity enabled, only 7 and 8 bits -are supported. - -WiPy/CC3200: Bits can be 5, 6, 7, 8. Stop can be 1 or 2. - -A UART object acts like a stream object and reading and writing is done -using the standard stream methods:: - - uart.read(10) # read 10 characters, returns a bytes object - uart.read() # read all available characters - uart.readline() # read a line - uart.readinto(buf) # read and store into the given buffer - uart.write('abc') # write the 3 characters - -Constructors ------------- - -.. class:: UART(id, ...) - - Construct a UART object of the given id. - -Methods -------- - -.. only:: port_wipy - - .. method:: UART.init(baudrate=9600, bits=8, parity=None, stop=1, \*, pins=(TX, RX, RTS, CTS)) - - Initialise the UART bus with the given parameters: - - - ``baudrate`` is the clock rate. - - ``bits`` is the number of bits per character, 7, 8 or 9. - - ``parity`` is the parity, ``None``, 0 (even) or 1 (odd). - - ``stop`` is the number of stop bits, 1 or 2. - - ``pins`` is a 4 or 2 item list indicating the TX, RX, RTS and CTS pins (in that order). - Any of the pins can be None if one wants the UART to operate with limited functionality. - If the RTS pin is given the the RX pin must be given as well. The same applies to CTS. - When no pins are given, then the default set of TX and RX pins is taken, and hardware - flow control will be disabled. If pins=None, no pin assignment will be made. - -.. method:: UART.deinit() - - Turn off the UART bus. - -.. method:: UART.any() - - Returns an integer counting the number of characters that can be read without - blocking. It will return 0 if there are no characters available and a positive - number if there are characters. The method may return 1 even if there is more - than one character available for reading. - - For more sophisticated querying of available characters use select.poll:: - - poll = select.poll() - poll.register(uart, select.POLLIN) - poll.poll(timeout) - -.. method:: UART.read([nbytes]) - - Read characters. If ``nbytes`` is specified then read at most that many bytes, - otherwise read as much data as possible. - - Return value: a bytes object containing the bytes read in. Returns ``None`` - on timeout. - -.. method:: UART.readinto(buf[, nbytes]) - - Read bytes into the ``buf``. If ``nbytes`` is specified then read at most - that many bytes. Otherwise, read at most ``len(buf)`` bytes. - - Return value: number of bytes read and stored into ``buf`` or ``None`` on - timeout. - -.. method:: UART.readline() - - Read a line, ending in a newline character. - - Return value: the line read or ``None`` on timeout. - -.. method:: UART.write(buf) - - Write the buffer of bytes to the bus. - - Return value: number of bytes written or ``None`` on timeout. - -.. method:: UART.sendbreak() - - Send a break condition on the bus. This drives the bus low for a duration - longer than required for a normal transmission of a character. - -.. only:: port_wipy - - .. method:: UART.irq(trigger, priority=1, handler=None, wake=machine.IDLE) - - Create a callback to be triggered when data is received on the UART. - - - ``trigger`` can only be ``UART.RX_ANY`` - - ``priority`` level of the interrupt. Can take values in the range 1-7. - Higher values represent higher priorities. - - ``handler`` an optional function to be called when new characters arrive. - - ``wake`` can only be ``machine.IDLE``. - - .. note:: - - The handler will be called whenever any of the following two conditions are met: - - - 8 new characters have been received. - - At least 1 new character is waiting in the Rx buffer and the Rx line has been - silent for the duration of 1 complete frame. - - This means that when the handler function is called there will be between 1 to 8 - characters waiting. - - Returns an irq object. - - Constants - --------- - - .. data:: UART.RX_ANY - - IRQ trigger sources diff --git a/docs/library/machine.WDT.rst b/docs/library/machine.WDT.rst deleted file mode 100644 index 5ca6dce45d..0000000000 --- a/docs/library/machine.WDT.rst +++ /dev/null @@ -1,36 +0,0 @@ -.. currentmodule:: machine -.. _machine.WDT: - -class WDT -- watchdog timer -=========================== - -The WDT is used to restart the system when the application crashes and ends -up into a non recoverable state. Once started it cannot be stopped or -reconfigured in any way. After enabling, the application must "feed" the -watchdog periodically to prevent it from expiring and resetting the system. - -Example usage:: - - from machine import WDT - wdt = WDT(timeout=2000) # enable it with a timeout of 2s - wdt.feed() - -Availability of this class: pyboard, WiPy. - -Constructors ------------- - -.. class:: WDT(id=0, timeout=5000) - - Create a WDT object and start it. The timeout must be given in seconds and - the minimum value that is accepted is 1 second. Once it is running the timeout - cannot be changed and the WDT cannot be stopped either. - -Methods -------- - -.. method:: wdt.feed() - - Feed the WDT to prevent it from resetting the system. The application - should place this call in a sensible place ensuring that the WDT is - only fed after verifying that everything is functioning correctly. diff --git a/docs/library/machine.rst b/docs/library/machine.rst deleted file mode 100644 index 087f19cc6c..0000000000 --- a/docs/library/machine.rst +++ /dev/null @@ -1,170 +0,0 @@ -:mod:`machine` --- functions related to the hardware -==================================================== - -.. module:: machine - :synopsis: functions related to the hardware - -The ``machine`` module contains specific functions related to the hardware -on a particular board. Most functions in this module allow to achieve direct -and unrestricted access to and control of hardware blocks on a system -(like CPU, timers, buses, etc.). Used incorrectly, this can lead to -malfunction, lockups, crashes of your board, and in extreme cases, hardware -damage. - -.. _machine_callbacks: - -A note of callbacks used by functions and class methods of :mod:`machine` module: -all these callbacks should be considered as executing in an interrupt context. -This is true for both physical devices with IDs >= 0 and "virtual" devices -with negative IDs like -1 (these "virtual" devices are still thin shims on -top of real hardware and real hardware interrupts). See :ref:`isr_rules`. - -Reset related functions ------------------------ - -.. function:: reset() - - Resets the device in a manner similar to pushing the external RESET - button. - -.. function:: reset_cause() - - Get the reset cause. See :ref:`constants ` for the possible return values. - -Interrupt related functions ---------------------------- - -.. function:: disable_irq() - - Disable interrupt requests. - Returns the previous IRQ state which should be considered an opaque value. - This return value should be passed to the `enable_irq()` function to restore - interrupts to their original state, before `disable_irq()` was called. - -.. function:: enable_irq(state) - - Re-enable interrupt requests. - The *state* parameter should be the value that was returned from the most - recent call to the `disable_irq()` function. - -Power related functions ------------------------ - -.. function:: freq() - - Returns CPU frequency in hertz. - -.. function:: idle() - - Gates the clock to the CPU, useful to reduce power consumption at any time during - short or long periods. Peripherals continue working and execution resumes as soon - as any interrupt is triggered (on many ports this includes system timer - interrupt occurring at regular intervals on the order of millisecond). - -.. function:: sleep() - - Stops the CPU and disables all peripherals except for WLAN. Execution is resumed from - the point where the sleep was requested. For wake up to actually happen, wake sources - should be configured first. - -.. function:: deepsleep() - - Stops the CPU and all peripherals (including networking interfaces, if any). Execution - is resumed from the main script, just as with a reset. The reset cause can be checked - to know that we are coming from `machine.DEEPSLEEP`. For wake up to actually happen, - wake sources should be configured first, like `Pin` change or `RTC` timeout. - -.. only:: port_wipy - - .. function:: wake_reason() - - Get the wake reason. See :ref:`constants ` for the possible return values. - -Miscellaneous functions ------------------------ - -.. only:: port_wipy - - .. function:: rng() - - Return a 24-bit software generated random number. - -.. function:: unique_id() - - Returns a byte string with a unique identifier of a board/SoC. It will vary - from a board/SoC instance to another, if underlying hardware allows. Length - varies by hardware (so use substring of a full value if you expect a short - ID). In some MicroPython ports, ID corresponds to the network MAC address. - -.. function:: time_pulse_us(pin, pulse_level, timeout_us=1000000) - - Time a pulse on the given *pin*, and return the duration of the pulse in - microseconds. The *pulse_level* argument should be 0 to time a low pulse - or 1 to time a high pulse. - - If the current input value of the pin is different to *pulse_level*, - the function first (*) waits until the pin input becomes equal to *pulse_level*, - then (**) times the duration that the pin is equal to *pulse_level*. - If the pin is already equal to *pulse_level* then timing starts straight away. - - The function will return -2 if there was timeout waiting for condition marked - (*) above, and -1 if there was timeout during the main measurement, marked (**) - above. The timeout is the same for both cases and given by *timeout_us* (which - is in microseconds). - -.. _machine_constants: - -Constants ---------- - -.. data:: machine.IDLE - machine.SLEEP - machine.DEEPSLEEP - - IRQ wake values. - -.. data:: machine.PWRON_RESET - machine.HARD_RESET - machine.WDT_RESET - machine.DEEPSLEEP_RESET - machine.SOFT_RESET - - Reset causes. - -.. data:: machine.WLAN_WAKE - machine.PIN_WAKE - machine.RTC_WAKE - - Wake-up reasons. - -Classes -------- - -.. only:: not port_wipy - - .. toctree:: - :maxdepth: 1 - - machine.Pin.rst - machine.Signal.rst - machine.UART.rst - machine.SPI.rst - machine.I2C.rst - machine.RTC.rst - machine.Timer.rst - machine.WDT.rst - -.. only:: port_wipy - - .. toctree:: - :maxdepth: 1 - - machine.Pin.rst - machine.UART.rst - machine.SPI.rst - machine.I2C.rst - machine.RTC.rst - machine.Timer.rst - machine.WDT.rst - machine.ADC.rst - machine.SD.rst diff --git a/docs/library/math.rst b/docs/library/math.rst index a6f13d48c1..811d514bae 100644 --- a/docs/library/math.rst +++ b/docs/library/math.rst @@ -1,10 +1,12 @@ :mod:`math` -- mathematical functions ===================================== +.. include:: ../templates/unsupported_in_circuitpython.inc + .. module:: math :synopsis: mathematical functions -|see_cpython_module| :mod:`python:math`. +|see_cpython_module| :mod:`cpython:math`. The ``math`` module provides some basic mathematical functions for working with floating-point numbers. diff --git a/docs/library/micropython.rst b/docs/library/micropython.rst index 4ff0b0c159..8f8af6b379 100644 --- a/docs/library/micropython.rst +++ b/docs/library/micropython.rst @@ -1,6 +1,8 @@ :mod:`micropython` -- access and control MicroPython internals ============================================================== +.. include:: ../templates/unsupported_in_circuitpython.inc + .. module:: micropython :synopsis: access and control MicroPython internals diff --git a/docs/library/network.rst b/docs/library/network.rst index de93c0e01d..4674fe6769 100644 --- a/docs/library/network.rst +++ b/docs/library/network.rst @@ -2,6 +2,8 @@ :mod:`network` --- network configuration **************************************** +.. include:: ../templates/unsupported_in_circuitpython.inc + .. module:: network :synopsis: network configuration @@ -132,450 +134,142 @@ parameter should be `id`. # Extended status information also available this way print(sta.config('rssi')) -.. only:: port_pyboard - - class CC3K - ========== - - This class provides a driver for CC3000 WiFi modules. Example usage:: - - import network - nic = network.CC3K(pyb.SPI(2), pyb.Pin.board.Y5, pyb.Pin.board.Y4, pyb.Pin.board.Y3) - nic.connect('your-ssid', 'your-password') - while not nic.isconnected(): - pyb.delay(50) - print(nic.ifconfig()) - - # now use socket as usual - ... - - For this example to work the CC3000 module must have the following connections: - - - MOSI connected to Y8 - - MISO connected to Y7 - - CLK connected to Y6 - - CS connected to Y5 - - VBEN connected to Y4 - - IRQ connected to Y3 - - It is possible to use other SPI busses and other pins for CS, VBEN and IRQ. - - Constructors - ------------ - - .. class:: CC3K(spi, pin_cs, pin_en, pin_irq) - - Create a CC3K driver object, initialise the CC3000 module using the given SPI bus - and pins, and return the CC3K object. - - Arguments are: - - - *spi* is an :ref:`SPI object ` which is the SPI bus that the CC3000 is - connected to (the MOSI, MISO and CLK pins). - - *pin_cs* is a :ref:`Pin object ` which is connected to the CC3000 CS pin. - - *pin_en* is a :ref:`Pin object ` which is connected to the CC3000 VBEN pin. - - *pin_irq* is a :ref:`Pin object ` which is connected to the CC3000 IRQ pin. - - All of these objects will be initialised by the driver, so there is no need to - initialise them yourself. For example, you can use:: - - nic = network.CC3K(pyb.SPI(2), pyb.Pin.board.Y5, pyb.Pin.board.Y4, pyb.Pin.board.Y3) - - Methods - ------- - - .. method:: cc3k.connect(ssid, key=None, \*, security=WPA2, bssid=None) - - Connect to a WiFi access point using the given SSID, and other security - parameters. - - .. method:: cc3k.disconnect() - - Disconnect from the WiFi access point. - - .. method:: cc3k.isconnected() - - Returns True if connected to a WiFi access point and has a valid IP address, - False otherwise. - - .. method:: cc3k.ifconfig() - - Returns a 7-tuple with (ip, subnet mask, gateway, DNS server, DHCP server, - MAC address, SSID). - - .. method:: cc3k.patch_version() - - Return the version of the patch program (firmware) on the CC3000. - - .. method:: cc3k.patch_program('pgm') - - Upload the current firmware to the CC3000. You must pass 'pgm' as the first - argument in order for the upload to proceed. - - Constants - --------- - - .. data:: CC3K.WEP - .. data:: CC3K.WPA - .. data:: CC3K.WPA2 - - security type to use - - class WIZNET5K - ============== - - This class allows you to control WIZnet5x00 Ethernet adaptors based on - the W5200 and W5500 chipsets (only W5200 tested). - - Example usage:: - - import network - nic = network.WIZNET5K(pyb.SPI(1), pyb.Pin.board.X5, pyb.Pin.board.X4) - print(nic.ifconfig()) - - # now use socket as usual - ... - - For this example to work the WIZnet5x00 module must have the following connections: - - - MOSI connected to X8 - - MISO connected to X7 - - SCLK connected to X6 - - nSS connected to X5 - - nRESET connected to X4 - - It is possible to use other SPI busses and other pins for nSS and nRESET. - - Constructors - ------------ - - .. class:: WIZNET5K(spi, pin_cs, pin_rst) - - Create a WIZNET5K driver object, initialise the WIZnet5x00 module using the given - SPI bus and pins, and return the WIZNET5K object. - - Arguments are: - - - *spi* is an :ref:`SPI object ` which is the SPI bus that the WIZnet5x00 is - connected to (the MOSI, MISO and SCLK pins). - - *pin_cs* is a :ref:`Pin object ` which is connected to the WIZnet5x00 nSS pin. - - *pin_rst* is a :ref:`Pin object ` which is connected to the WIZnet5x00 nRESET pin. - - All of these objects will be initialised by the driver, so there is no need to - initialise them yourself. For example, you can use:: - - nic = network.WIZNET5K(pyb.SPI(1), pyb.Pin.board.X5, pyb.Pin.board.X4) - - Methods - ------- - - .. method:: wiznet5k.ifconfig([(ip, subnet, gateway, dns)]) - - Get/set IP address, subnet mask, gateway and DNS. - - When called with no arguments, this method returns a 4-tuple with the above information. - - To set the above values, pass a 4-tuple with the required information. For example:: - - nic.ifconfig(('192.168.0.4', '255.255.255.0', '192.168.0.1', '8.8.8.8')) - - .. method:: wiznet5k.regs() - - Dump the WIZnet5x00 registers. Useful for debugging. - .. _network.WLAN: -.. only:: port_esp8266 - Functions - ========= +Functions +========= - .. function:: phy_mode([mode]) +.. function:: phy_mode([mode]) - Get or set the PHY mode. + Get or set the PHY mode. - If the *mode* parameter is provided, sets the mode to its value. If - the function is called without parameters, returns the current mode. + If the *mode* parameter is provided, sets the mode to its value. If + the function is called without parameters, returns the current mode. - The possible modes are defined as constants: - * ``MODE_11B`` -- IEEE 802.11b, - * ``MODE_11G`` -- IEEE 802.11g, - * ``MODE_11N`` -- IEEE 802.11n. + The possible modes are defined as constants: + * ``MODE_11B`` -- IEEE 802.11b, + * ``MODE_11G`` -- IEEE 802.11g, + * ``MODE_11N`` -- IEEE 802.11n. - class WLAN - ========== +class WLAN +========== - This class provides a driver for WiFi network processor in the ESP8266. Example usage:: +This class provides a driver for WiFi network processor in the ESP8266. Example usage:: - import network - # enable station interface and connect to WiFi access point - nic = network.WLAN(network.STA_IF) - nic.active(True) - nic.connect('your-ssid', 'your-password') - # now use sockets as usual + import network + # enable station interface and connect to WiFi access point + nic = network.WLAN(network.STA_IF) + nic.active(True) + nic.connect('your-ssid', 'your-password') + # now use sockets as usual - Constructors - ------------ - .. class:: WLAN(interface_id) +Constructors +------------ +.. class:: WLAN(interface_id) - Create a WLAN network interface object. Supported interfaces are - ``network.STA_IF`` (station aka client, connects to upstream WiFi access - points) and ``network.AP_IF`` (access point, allows other WiFi clients to - connect). Availability of the methods below depends on interface type. - For example, only STA interface may `connect()` to an access point. +Create a WLAN network interface object. Supported interfaces are +``network.STA_IF`` (station aka client, connects to upstream WiFi access +points) and ``network.AP_IF`` (access point, allows other WiFi clients to +connect). Availability of the methods below depends on interface type. +For example, only STA interface may `connect()` to an access point. - Methods - ------- +Methods +------- - .. method:: wlan.active([is_active]) +.. method:: wlan.active([is_active]) - Activate ("up") or deactivate ("down") network interface, if boolean - argument is passed. Otherwise, query current state if no argument is - provided. Most other methods require active interface. + Activate ("up") or deactivate ("down") network interface, if boolean + argument is passed. Otherwise, query current state if no argument is + provided. Most other methods require active interface. - .. method:: wlan.connect(ssid, password) +.. method:: wlan.connect(ssid, password) - Connect to the specified wireless network, using the specified password. + Connect to the specified wireless network, using the specified password. - .. method:: wlan.disconnect() +.. method:: wlan.disconnect() - Disconnect from the currently connected wireless network. + Disconnect from the currently connected wireless network. - .. method:: wlan.scan() +.. method:: wlan.scan() - Scan for the available wireless networks. + Scan for the available wireless networks. - Scanning is only possible on STA interface. Returns list of tuples with - the information about WiFi access points: + Scanning is only possible on STA interface. Returns list of tuples with + the information about WiFi access points: - (ssid, bssid, channel, RSSI, authmode, hidden) + (ssid, bssid, channel, RSSI, authmode, hidden) - *bssid* is hardware address of an access point, in binary form, returned as - bytes object. You can use `ubinascii.hexlify()` to convert it to ASCII form. + *bssid* is hardware address of an access point, in binary form, returned as + bytes object. You can use `ubinascii.hexlify()` to convert it to ASCII form. - There are five values for authmode: + There are five values for authmode: - * 0 -- open - * 1 -- WEP - * 2 -- WPA-PSK - * 3 -- WPA2-PSK - * 4 -- WPA/WPA2-PSK + * 0 -- open + * 1 -- WEP + * 2 -- WPA-PSK + * 3 -- WPA2-PSK + * 4 -- WPA/WPA2-PSK - and two for hidden: + and two for hidden: - * 0 -- visible - * 1 -- hidden + * 0 -- visible + * 1 -- hidden - .. method:: wlan.status() +.. method:: wlan.status() - Return the current status of the wireless connection. + Return the current status of the wireless connection. - The possible statuses are defined as constants: + The possible statuses are defined as constants: - * ``STAT_IDLE`` -- no connection and no activity, - * ``STAT_CONNECTING`` -- connecting in progress, - * ``STAT_WRONG_PASSWORD`` -- failed due to incorrect password, - * ``STAT_NO_AP_FOUND`` -- failed because no access point replied, - * ``STAT_CONNECT_FAIL`` -- failed due to other problems, - * ``STAT_GOT_IP`` -- connection successful. + * ``STAT_IDLE`` -- no connection and no activity, + * ``STAT_CONNECTING`` -- connecting in progress, + * ``STAT_WRONG_PASSWORD`` -- failed due to incorrect password, + * ``STAT_NO_AP_FOUND`` -- failed because no access point replied, + * ``STAT_CONNECT_FAIL`` -- failed due to other problems, + * ``STAT_GOT_IP`` -- connection successful. - .. method:: wlan.isconnected() +.. method:: wlan.isconnected() - In case of STA mode, returns ``True`` if connected to a WiFi access - point and has a valid IP address. In AP mode returns ``True`` when a - station is connected. Returns ``False`` otherwise. + In case of STA mode, returns ``True`` if connected to a WiFi access + point and has a valid IP address. In AP mode returns ``True`` when a + station is connected. Returns ``False`` otherwise. - .. method:: wlan.ifconfig([(ip, subnet, gateway, dns)]) +.. method:: wlan.ifconfig([(ip, subnet, gateway, dns)]) - Get/set IP-level network interface parameters: IP address, subnet mask, - gateway and DNS server. When called with no arguments, this method returns - a 4-tuple with the above information. To set the above values, pass a - 4-tuple with the required information. For example:: + Get/set IP-level network interface parameters: IP address, subnet mask, + gateway and DNS server. When called with no arguments, this method returns + a 4-tuple with the above information. To set the above values, pass a + 4-tuple with the required information. For example:: - nic.ifconfig(('192.168.0.4', '255.255.255.0', '192.168.0.1', '8.8.8.8')) + nic.ifconfig(('192.168.0.4', '255.255.255.0', '192.168.0.1', '8.8.8.8')) - .. method:: wlan.config('param') - .. method:: wlan.config(param=value, ...) +.. method:: wlan.config('param') +.. method:: wlan.config(param=value, ...) - Get or set general network interface parameters. These methods allow to work - with additional parameters beyond standard IP configuration (as dealt with by - `wlan.ifconfig()`). These include network-specific and hardware-specific - parameters. For setting parameters, keyword argument syntax should be used, - multiple parameters can be set at once. For querying, parameters name should - be quoted as a string, and only one parameter can be queries at time:: + Get or set general network interface parameters. These methods allow to work + with additional parameters beyond standard IP configuration (as dealt with by + `wlan.ifconfig()`). These include network-specific and hardware-specific + parameters. For setting parameters, keyword argument syntax should be used, + multiple parameters can be set at once. For querying, parameters name should + be quoted as a string, and only one parameter can be queries at time:: - # Set WiFi access point name (formally known as ESSID) and WiFi channel - ap.config(essid='My AP', channel=11) - # Query params one by one - print(ap.config('essid')) - print(ap.config('channel')) + # Set WiFi access point name (formally known as ESSID) and WiFi channel + ap.config(essid='My AP', channel=11) + # Query params one by one + print(ap.config('essid')) + print(ap.config('channel')) - Following are commonly supported parameters (availability of a specific parameter - depends on network technology type, driver, and MicroPython port). + Following are commonly supported parameters (availability of a specific parameter + depends on network technology type, driver, and MicroPython port). - ========= =========== - Parameter Description - ========= =========== - mac MAC address (bytes) - essid WiFi access point name (string) - channel WiFi channel (integer) - hidden Whether ESSID is hidden (boolean) - authmode Authentication mode supported (enumeration, see module constants) - password Access password (string) - ========= =========== - - - -.. only:: port_wipy - - class WLAN - ========== - - This class provides a driver for the WiFi network processor in the WiPy. Example usage:: - - import network - import time - # setup as a station - wlan = network.WLAN(mode=WLAN.STA) - wlan.connect('your-ssid', auth=(WLAN.WPA2, 'your-key')) - while not wlan.isconnected(): - time.sleep_ms(50) - print(wlan.ifconfig()) - - # now use socket as usual - ... - - Constructors - ------------ - - .. class:: WLAN(id=0, ...) - - Create a WLAN object, and optionally configure it. See `init()` for params of configuration. - - .. note:: - - The ``WLAN`` constructor is special in the sense that if no arguments besides the id are given, - it will return the already existing ``WLAN`` instance without re-configuring it. This is - because ``WLAN`` is a system feature of the WiPy. If the already existing instance is not - initialized it will do the same as the other constructors an will initialize it with default - values. - - Methods - ------- - - .. method:: wlan.init(mode, \*, ssid, auth, channel, antenna) - - Set or get the WiFi network processor configuration. - - Arguments are: - - - *mode* can be either ``WLAN.STA`` or ``WLAN.AP``. - - *ssid* is a string with the ssid name. Only needed when mode is ``WLAN.AP``. - - *auth* is a tuple with (sec, key). Security can be ``None``, ``WLAN.WEP``, - ``WLAN.WPA`` or ``WLAN.WPA2``. The key is a string with the network password. - If ``sec`` is ``WLAN.WEP`` the key must be a string representing hexadecimal - values (e.g. 'ABC1DE45BF'). Only needed when mode is ``WLAN.AP``. - - *channel* a number in the range 1-11. Only needed when mode is ``WLAN.AP``. - - *antenna* selects between the internal and the external antenna. Can be either - ``WLAN.INT_ANT`` or ``WLAN.EXT_ANT``. - - For example, you can do:: - - # create and configure as an access point - wlan.init(mode=WLAN.AP, ssid='wipy-wlan', auth=(WLAN.WPA2,'www.wipy.io'), channel=7, antenna=WLAN.INT_ANT) - - or:: - - # configure as an station - wlan.init(mode=WLAN.STA) - - .. method:: wlan.connect(ssid, \*, auth=None, bssid=None, timeout=None) - - Connect to a WiFi access point using the given SSID, and other security - parameters. - - - *auth* is a tuple with (sec, key). Security can be ``None``, ``WLAN.WEP``, - ``WLAN.WPA`` or ``WLAN.WPA2``. The key is a string with the network password. - If ``sec`` is ``WLAN.WEP`` the key must be a string representing hexadecimal - values (e.g. 'ABC1DE45BF'). - - *bssid* is the MAC address of the AP to connect to. Useful when there are several - APs with the same ssid. - - *timeout* is the maximum time in milliseconds to wait for the connection to succeed. - - .. method:: wlan.scan() - - Performs a network scan and returns a list of named tuples with (ssid, bssid, sec, channel, rssi). - Note that channel is always ``None`` since this info is not provided by the WiPy. - - .. method:: wlan.disconnect() - - Disconnect from the WiFi access point. - - .. method:: wlan.isconnected() - - In case of STA mode, returns ``True`` if connected to a WiFi access point and has a valid IP address. - In AP mode returns ``True`` when a station is connected, ``False`` otherwise. - - .. method:: wlan.ifconfig(if_id=0, config=['dhcp' or configtuple]) - - With no parameters given returns a 4-tuple of *(ip, subnet_mask, gateway, DNS_server)*. - - if ``'dhcp'`` is passed as a parameter then the DHCP client is enabled and the IP params - are negotiated with the AP. - - If the 4-tuple config is given then a static IP is configured. For instance:: - - wlan.ifconfig(config=('192.168.0.4', '255.255.255.0', '192.168.0.1', '8.8.8.8')) - - .. method:: wlan.mode([mode]) - - Get or set the WLAN mode. - - .. method:: wlan.ssid([ssid]) - - Get or set the SSID when in AP mode. - - .. method:: wlan.auth([auth]) - - Get or set the authentication type when in AP mode. - - .. method:: wlan.channel([channel]) - - Get or set the channel (only applicable in AP mode). - - .. method:: wlan.antenna([antenna]) - - Get or set the antenna type (external or internal). - - .. method:: wlan.mac([mac_addr]) - - Get or set a 6-byte long bytes object with the MAC address. - - .. method:: wlan.irq(\*, handler, wake) - - Create a callback to be triggered when a WLAN event occurs during ``machine.SLEEP`` - mode. Events are triggered by socket activity or by WLAN connection/disconnection. - - - *handler* is the function that gets called when the IRQ is triggered. - - *wake* must be ``machine.SLEEP``. - - Returns an IRQ object. - - Constants - --------- - - .. data:: WLAN.STA - .. data:: WLAN.AP - - selects the WLAN mode - - .. data:: WLAN.WEP - .. data:: WLAN.WPA - .. data:: WLAN.WPA2 - - selects the network security - - .. data:: WLAN.INT_ANT - .. data:: WLAN.EXT_ANT - - selects the antenna type + ========= =========== + Parameter Description + ========= =========== + mac MAC address (bytes) + essid WiFi access point name (string) + channel WiFi channel (integer) + hidden Whether ESSID is hidden (boolean) + authmode Authentication mode supported (enumeration, see module constants) + password Access password (string) + ========= =========== diff --git a/docs/library/pyb.ADC.rst b/docs/library/pyb.ADC.rst deleted file mode 100644 index 51021fdc1a..0000000000 --- a/docs/library/pyb.ADC.rst +++ /dev/null @@ -1,143 +0,0 @@ -.. currentmodule:: pyb -.. _pyb.ADC: - -class ADC -- analog to digital conversion -========================================= - -.. only:: port_pyboard - - Usage:: - - import pyb - - adc = pyb.ADC(pin) # create an analog object from a pin - val = adc.read() # read an analog value - - adc = pyb.ADCAll(resolution) # create an ADCAll object - val = adc.read_channel(channel) # read the given channel - val = adc.read_core_temp() # read MCU temperature - val = adc.read_core_vbat() # read MCU VBAT - val = adc.read_core_vref() # read MCU VREF - - -Constructors ------------- - - -.. only:: port_pyboard - - .. class:: pyb.ADC(pin) - - Create an ADC object associated with the given pin. - This allows you to then read analog values on that pin. - -Methods -------- - -.. only:: port_pyboard - - .. method:: ADC.read() - - Read the value on the analog pin and return it. The returned value - will be between 0 and 4095. - - .. method:: ADC.read_timed(buf, timer) - - Read analog values into ``buf`` at a rate set by the ``timer`` object. - - ``buf`` can be bytearray or array.array for example. The ADC values have - 12-bit resolution and are stored directly into ``buf`` if its element size is - 16 bits or greater. If ``buf`` has only 8-bit elements (eg a bytearray) then - the sample resolution will be reduced to 8 bits. - - ``timer`` should be a Timer object, and a sample is read each time the timer - triggers. The timer must already be initialised and running at the desired - sampling frequency. - - To support previous behaviour of this function, ``timer`` can also be an - integer which specifies the frequency (in Hz) to sample at. In this case - Timer(6) will be automatically configured to run at the given frequency. - - Example using a Timer object (preferred way):: - - adc = pyb.ADC(pyb.Pin.board.X19) # create an ADC on pin X19 - tim = pyb.Timer(6, freq=10) # create a timer running at 10Hz - buf = bytearray(100) # creat a buffer to store the samples - adc.read_timed(buf, tim) # sample 100 values, taking 10s - - Example using an integer for the frequency:: - - adc = pyb.ADC(pyb.Pin.board.X19) # create an ADC on pin X19 - buf = bytearray(100) # create a buffer of 100 bytes - adc.read_timed(buf, 10) # read analog values into buf at 10Hz - # this will take 10 seconds to finish - for val in buf: # loop over all values - print(val) # print the value out - - This function does not allocate any memory. - -The ADCAll Object ------------------ - -.. only:: port_pyboard - - Instantiating this changes all ADC pins to analog inputs. The raw MCU temperature, - VREF and VBAT data can be accessed on ADC channels 16, 17 and 18 respectively. - Appropriate scaling will need to be applied. The temperature sensor on the chip - has poor absolute accuracy and is suitable only for detecting temperature changes. - - The ``ADCAll`` ``read_core_vbat()`` and ``read_core_vref()`` methods read - the backup battery voltage and the (1.21V nominal) reference voltage using the - 3.3V supply as a reference. Assuming the ``ADCAll`` object has been Instantiated with - ``adc = pyb.ADCAll(12)`` the 3.3V supply voltage may be calculated: - - ``v33 = 3.3 * 1.21 / adc.read_core_vref()`` - - If the 3.3V supply is correct the value of ``adc.read_core_vbat()`` will be - valid. If the supply voltage can drop below 3.3V, for example in in battery - powered systems with a discharging battery, the regulator will fail to preserve - the 3.3V supply resulting in an incorrect reading. To produce a value which will - remain valid under these circumstances use the following: - - ``vback = adc.read_core_vbat() * 1.21 / adc.read_core_vref()`` - - It is possible to access these values without incurring the side effects of ``ADCAll``:: - - def adcread(chan): # 16 temp 17 vbat 18 vref - assert chan >= 16 and chan <= 18, 'Invalid ADC channel' - start = pyb.millis() - timeout = 100 - stm.mem32[stm.RCC + stm.RCC_APB2ENR] |= 0x100 # enable ADC1 clock.0x4100 - stm.mem32[stm.ADC1 + stm.ADC_CR2] = 1 # Turn on ADC - stm.mem32[stm.ADC1 + stm.ADC_CR1] = 0 # 12 bit - if chan == 17: - stm.mem32[stm.ADC1 + stm.ADC_SMPR1] = 0x200000 # 15 cycles - stm.mem32[stm.ADC + 4] = 1 << 23 - elif chan == 18: - stm.mem32[stm.ADC1 + stm.ADC_SMPR1] = 0x1000000 - stm.mem32[stm.ADC + 4] = 0xc00000 - else: - stm.mem32[stm.ADC1 + stm.ADC_SMPR1] = 0x40000 - stm.mem32[stm.ADC + 4] = 1 << 23 - stm.mem32[stm.ADC1 + stm.ADC_SQR3] = chan - stm.mem32[stm.ADC1 + stm.ADC_CR2] = 1 | (1 << 30) | (1 << 10) # start conversion - while not stm.mem32[stm.ADC1 + stm.ADC_SR] & 2: # wait for EOC - if pyb.elapsed_millis(start) > timeout: - raise OSError('ADC timout') - data = stm.mem32[stm.ADC1 + stm.ADC_DR] # clear down EOC - stm.mem32[stm.ADC1 + stm.ADC_CR2] = 0 # Turn off ADC - return data - - def v33(): - return 4096 * 1.21 / adcread(17) - - def vbat(): - return 1.21 * 2 * adcread(18) / adcread(17) # 2:1 divider on Vbat channel - - def vref(): - return 3.3 * adcread(17) / 4096 - - def temperature(): - return 25 + 400 * (3.3 * adcread(16) / 4096 - 0.76) - - \ No newline at end of file diff --git a/docs/library/pyb.Accel.rst b/docs/library/pyb.Accel.rst deleted file mode 100644 index 061996485f..0000000000 --- a/docs/library/pyb.Accel.rst +++ /dev/null @@ -1,56 +0,0 @@ -.. currentmodule:: pyb - -class Accel -- accelerometer control -==================================== - -Accel is an object that controls the accelerometer. Example usage:: - - accel = pyb.Accel() - for i in range(10): - print(accel.x(), accel.y(), accel.z()) - -Raw values are between -32 and 31. - - -Constructors ------------- - -.. class:: pyb.Accel() - - Create and return an accelerometer object. - -Methods -------- - -.. method:: Accel.filtered_xyz() - - Get a 3-tuple of filtered x, y and z values. - - Implementation note: this method is currently implemented as taking the - sum of 4 samples, sampled from the 3 previous calls to this function along - with the sample from the current call. Returned values are therefore 4 - times the size of what they would be from the raw x(), y() and z() calls. - -.. method:: Accel.tilt() - - Get the tilt register. - -.. method:: Accel.x() - - Get the x-axis value. - -.. method:: Accel.y() - - Get the y-axis value. - -.. method:: Accel.z() - - Get the z-axis value. - -Hardware Note -------------- - -The accelerometer uses I2C bus 1 to communicate with the processor. Consequently -when readings are being taken pins X9 and X10 should be unused (other than for -I2C). Other devices using those pins, and which therefore cannot be used -concurrently, are UART 1 and Timer 4 channels 1 and 2. diff --git a/docs/library/pyb.CAN.rst b/docs/library/pyb.CAN.rst deleted file mode 100644 index 9e71f12b06..0000000000 --- a/docs/library/pyb.CAN.rst +++ /dev/null @@ -1,222 +0,0 @@ -.. currentmodule:: pyb - -class CAN -- controller area network communication bus -====================================================== - -CAN implements the standard CAN communications protocol. At -the physical level it consists of 2 lines: RX and TX. Note that -to connect the pyboard to a CAN bus you must use a CAN transceiver -to convert the CAN logic signals from the pyboard to the correct -voltage levels on the bus. - -Example usage (works without anything connected):: - - from pyb import CAN - can = CAN(1, CAN.LOOPBACK) - can.setfilter(0, CAN.LIST16, 0, (123, 124, 125, 126)) # set a filter to receive messages with id=123, 124, 125 and 126 - can.send('message!', 123) # send a message with id 123 - can.recv(0) # receive message on FIFO 0 - - -Constructors ------------- - -.. class:: pyb.CAN(bus, ...) - - Construct a CAN object on the given bus. ``bus`` can be 1-2, or 'YA' or 'YB'. - With no additional parameters, the CAN object is created but not - initialised (it has the settings from the last initialisation of - the bus, if any). If extra arguments are given, the bus is initialised. - See ``init`` for parameters of initialisation. - - The physical pins of the CAN busses are: - - - ``CAN(1)`` is on ``YA``: ``(RX, TX) = (Y3, Y4) = (PB8, PB9)`` - - ``CAN(2)`` is on ``YB``: ``(RX, TX) = (Y5, Y6) = (PB12, PB13)`` - -Class Methods -------------- -.. classmethod:: CAN.initfilterbanks(nr) - - Reset and disable all filter banks and assign how many banks should be available for CAN(1). - - STM32F405 has 28 filter banks that are shared between the two available CAN bus controllers. - This function configures how many filter banks should be assigned to each. ``nr`` is the number of banks - that will be assigned to CAN(1), the rest of the 28 are assigned to CAN(2). - At boot, 14 banks are assigned to each controller. - -Methods -------- - -.. method:: CAN.init(mode, extframe=False, prescaler=100, \*, sjw=1, bs1=6, bs2=8) - - Initialise the CAN bus with the given parameters: - - - ``mode`` is one of: NORMAL, LOOPBACK, SILENT, SILENT_LOOPBACK - - if ``extframe`` is True then the bus uses extended identifiers in the frames - (29 bits); otherwise it uses standard 11 bit identifiers - - ``prescaler`` is used to set the duration of 1 time quanta; the time quanta - will be the input clock (PCLK1, see :meth:`pyb.freq()`) divided by the prescaler - - ``sjw`` is the resynchronisation jump width in units of the time quanta; - it can be 1, 2, 3, 4 - - ``bs1`` defines the location of the sample point in units of the time quanta; - it can be between 1 and 1024 inclusive - - ``bs2`` defines the location of the transmit point in units of the time quanta; - it can be between 1 and 16 inclusive - - The time quanta tq is the basic unit of time for the CAN bus. tq is the CAN - prescaler value divided by PCLK1 (the frequency of internal peripheral bus 1); - see :meth:`pyb.freq()` to determine PCLK1. - - A single bit is made up of the synchronisation segment, which is always 1 tq. - Then follows bit segment 1, then bit segment 2. The sample point is after bit - segment 1 finishes. The transmit point is after bit segment 2 finishes. - The baud rate will be 1/bittime, where the bittime is 1 + BS1 + BS2 multiplied - by the time quanta tq. - - For example, with PCLK1=42MHz, prescaler=100, sjw=1, bs1=6, bs2=8, the value of - tq is 2.38 microseconds. The bittime is 35.7 microseconds, and the baudrate - is 28kHz. - - See page 680 of the STM32F405 datasheet for more details. - -.. method:: CAN.deinit() - - Turn off the CAN bus. - -.. method:: CAN.setfilter(bank, mode, fifo, params, \*, rtr) - - Configure a filter bank: - - - ``bank`` is the filter bank that is to be configured. - - ``mode`` is the mode the filter should operate in. - - ``fifo`` is which fifo (0 or 1) a message should be stored in, if it is accepted by this filter. - - ``params`` is an array of values the defines the filter. The contents of the array depends on the ``mode`` argument. - - +-----------+---------------------------------------------------------+ - |``mode`` |contents of parameter array | - +===========+=========================================================+ - |CAN.LIST16 |Four 16 bit ids that will be accepted | - +-----------+---------------------------------------------------------+ - |CAN.LIST32 |Two 32 bit ids that will be accepted | - +-----------+---------------------------------------------------------+ - |CAN.MASK16 |Two 16 bit id/mask pairs. E.g. (1, 3, 4, 4) | - | | | The first pair, 1 and 3 will accept all ids | - | | | that have bit 0 = 1 and bit 1 = 0. | - | | | The second pair, 4 and 4, will accept all ids | - | | | that have bit 2 = 1. | - +-----------+---------------------------------------------------------+ - |CAN.MASK32 |As with CAN.MASK16 but with only one 32 bit id/mask pair.| - +-----------+---------------------------------------------------------+ - - - ``rtr`` is an array of booleans that states if a filter should accept a - remote transmission request message. If this argument is not given - then it defaults to False for all entries. The length of the array - depends on the ``mode`` argument. - - +-----------+----------------------+ - |``mode`` |length of rtr array | - +===========+======================+ - |CAN.LIST16 |4 | - +-----------+----------------------+ - |CAN.LIST32 |2 | - +-----------+----------------------+ - |CAN.MASK16 |2 | - +-----------+----------------------+ - |CAN.MASK32 |1 | - +-----------+----------------------+ - -.. method:: CAN.clearfilter(bank) - - Clear and disables a filter bank: - - - ``bank`` is the filter bank that is to be cleared. - -.. method:: CAN.any(fifo) - - Return ``True`` if any message waiting on the FIFO, else ``False``. - -.. method:: CAN.recv(fifo, \*, timeout=5000) - - Receive data on the bus: - - - ``fifo`` is an integer, which is the FIFO to receive on - - ``timeout`` is the timeout in milliseconds to wait for the receive. - - Return value: A tuple containing four values. - - - The id of the message. - - A boolean that indicates if the message is an RTR message. - - The FMI (Filter Match Index) value. - - An array containing the data. - -.. method:: CAN.send(data, id, \*, timeout=0, rtr=False) - - Send a message on the bus: - - - ``data`` is the data to send (an integer to send, or a buffer object). - - ``id`` is the id of the message to be sent. - - ``timeout`` is the timeout in milliseconds to wait for the send. - - ``rtr`` is a boolean that specifies if the message shall be sent as - a remote transmission request. If ``rtr`` is True then only the length - of ``data`` is used to fill in the DLC slot of the frame; the actual - bytes in ``data`` are unused. - - If timeout is 0 the message is placed in a buffer in one of three hardware - buffers and the method returns immediately. If all three buffers are in use - an exception is thrown. If timeout is not 0, the method waits until the - message is transmitted. If the message can't be transmitted within the - specified time an exception is thrown. - - Return value: ``None``. - -.. method:: CAN.rxcallback(fifo, fun) - - Register a function to be called when a message is accepted into a empty fifo: - - - ``fifo`` is the receiving fifo. - - ``fun`` is the function to be called when the fifo becomes non empty. - - The callback function takes two arguments the first is the can object it self the second is - a integer that indicates the reason for the callback. - - +--------+------------------------------------------------+ - | Reason | | - +========+================================================+ - | 0 | A message has been accepted into a empty FIFO. | - +--------+------------------------------------------------+ - | 1 | The FIFO is full | - +--------+------------------------------------------------+ - | 2 | A message has been lost due to a full FIFO | - +--------+------------------------------------------------+ - - Example use of rxcallback:: - - def cb0(bus, reason): - print('cb0') - if reason == 0: - print('pending') - if reason == 1: - print('full') - if reason == 2: - print('overflow') - - can = CAN(1, CAN.LOOPBACK) - can.rxcallback(0, cb0) - -Constants ---------- - -.. data:: CAN.NORMAL -.. data:: CAN.LOOPBACK -.. data:: CAN.SILENT -.. data:: CAN.SILENT_LOOPBACK - - the mode of the CAN bus - -.. data:: CAN.LIST16 -.. data:: CAN.MASK16 -.. data:: CAN.LIST32 -.. data:: CAN.MASK32 - - the operation mode of a filter diff --git a/docs/library/pyb.DAC.rst b/docs/library/pyb.DAC.rst deleted file mode 100644 index fd786b63b6..0000000000 --- a/docs/library/pyb.DAC.rst +++ /dev/null @@ -1,109 +0,0 @@ -.. currentmodule:: pyb -.. _pyb.DAC: - -class DAC -- digital to analog conversion -========================================= - -The DAC is used to output analog values (a specific voltage) on pin X5 or pin X6. -The voltage will be between 0 and 3.3V. - -*This module will undergo changes to the API.* - -Example usage:: - - from pyb import DAC - - dac = DAC(1) # create DAC 1 on pin X5 - dac.write(128) # write a value to the DAC (makes X5 1.65V) - - dac = DAC(1, bits=12) # use 12 bit resolution - dac.write(4095) # output maximum value, 3.3V - -To output a continuous sine-wave:: - - import math - from pyb import DAC - - # create a buffer containing a sine-wave - buf = bytearray(100) - for i in range(len(buf)): - buf[i] = 128 + int(127 * math.sin(2 * math.pi * i / len(buf))) - - # output the sine-wave at 400Hz - dac = DAC(1) - dac.write_timed(buf, 400 * len(buf), mode=DAC.CIRCULAR) - -To output a continuous sine-wave at 12-bit resolution:: - - import math - from array import array - from pyb import DAC - - # create a buffer containing a sine-wave, using half-word samples - buf = array('H', 2048 + int(2047 * math.sin(2 * math.pi * i / 128)) for i in range(128)) - - # output the sine-wave at 400Hz - dac = DAC(1, bits=12) - dac.write_timed(buf, 400 * len(buf), mode=DAC.CIRCULAR) - -Constructors ------------- - -.. class:: pyb.DAC(port, bits=8) - - Construct a new DAC object. - - ``port`` can be a pin object, or an integer (1 or 2). - DAC(1) is on pin X5 and DAC(2) is on pin X6. - - ``bits`` is an integer specifying the resolution, and can be 8 or 12. - The maximum value for the write and write_timed methods will be - 2\*\*``bits``-1. - -Methods -------- - -.. method:: DAC.init(bits=8) - - Reinitialise the DAC. ``bits`` can be 8 or 12. - -.. method:: DAC.deinit() - - De-initialise the DAC making its pin available for other uses. - -.. method:: DAC.noise(freq) - - Generate a pseudo-random noise signal. A new random sample is written - to the DAC output at the given frequency. - -.. method:: DAC.triangle(freq) - - Generate a triangle wave. The value on the DAC output changes at - the given frequency, and the frequency of the repeating triangle wave - itself is 2048 times smaller. - -.. method:: DAC.write(value) - - Direct access to the DAC output. The minimum value is 0. The maximum - value is 2\*\*``bits``-1, where ``bits`` is set when creating the DAC - object or by using the ``init`` method. - -.. method:: DAC.write_timed(data, freq, \*, mode=DAC.NORMAL) - - Initiates a burst of RAM to DAC using a DMA transfer. - The input data is treated as an array of bytes in 8-bit mode, and - an array of unsigned half-words (array typecode 'H') in 12-bit mode. - - ``freq`` can be an integer specifying the frequency to write the DAC - samples at, using Timer(6). Or it can be an already-initialised - Timer object which is used to trigger the DAC sample. Valid timers - are 2, 4, 5, 6, 7 and 8. - - ``mode`` can be ``DAC.NORMAL`` or ``DAC.CIRCULAR``. - - Example using both DACs at the same time:: - - dac1 = DAC(1) - dac2 = DAC(2) - dac1.write_timed(buf1, pyb.Timer(6, freq=100), mode=DAC.CIRCULAR) - dac2.write_timed(buf2, pyb.Timer(7, freq=200), mode=DAC.CIRCULAR) diff --git a/docs/library/pyb.ExtInt.rst b/docs/library/pyb.ExtInt.rst deleted file mode 100644 index 814217cef0..0000000000 --- a/docs/library/pyb.ExtInt.rst +++ /dev/null @@ -1,114 +0,0 @@ -.. currentmodule:: pyb -.. _pyb.ExtInt: - -class ExtInt -- configure I/O pins to interrupt on external events -================================================================== - -There are a total of 22 interrupt lines. 16 of these can come from GPIO pins -and the remaining 6 are from internal sources. - -For lines 0 through 15, a given line can map to the corresponding line from an -arbitrary port. So line 0 can map to Px0 where x is A, B, C, ... and -line 1 can map to Px1 where x is A, B, C, ... :: - - def callback(line): - print("line =", line) - -Note: ExtInt will automatically configure the gpio line as an input. :: - - extint = pyb.ExtInt(pin, pyb.ExtInt.IRQ_FALLING, pyb.Pin.PULL_UP, callback) - -Now every time a falling edge is seen on the X1 pin, the callback will be -called. Caution: mechanical pushbuttons have "bounce" and pushing or -releasing a switch will often generate multiple edges. -See: http://www.eng.utah.edu/~cs5780/debouncing.pdf for a detailed -explanation, along with various techniques for debouncing. - -Trying to register 2 callbacks onto the same pin will throw an exception. - -If pin is passed as an integer, then it is assumed to map to one of the -internal interrupt sources, and must be in the range 16 through 22. - -All other pin objects go through the pin mapper to come up with one of the -gpio pins. :: - - extint = pyb.ExtInt(pin, mode, pull, callback) - -Valid modes are pyb.ExtInt.IRQ_RISING, pyb.ExtInt.IRQ_FALLING, -pyb.ExtInt.IRQ_RISING_FALLING, pyb.ExtInt.EVT_RISING, -pyb.ExtInt.EVT_FALLING, and pyb.ExtInt.EVT_RISING_FALLING. - -Only the IRQ_xxx modes have been tested. The EVT_xxx modes have -something to do with sleep mode and the WFE instruction. - -Valid pull values are pyb.Pin.PULL_UP, pyb.Pin.PULL_DOWN, pyb.Pin.PULL_NONE. - -There is also a C API, so that drivers which require EXTI interrupt lines -can also use this code. See extint.h for the available functions and -usrsw.h for an example of using this. - - -Constructors ------------- - -.. class:: pyb.ExtInt(pin, mode, pull, callback) - - Create an ExtInt object: - - - ``pin`` is the pin on which to enable the interrupt (can be a pin object or any valid pin name). - - ``mode`` can be one of: - - ``ExtInt.IRQ_RISING`` - trigger on a rising edge; - - ``ExtInt.IRQ_FALLING`` - trigger on a falling edge; - - ``ExtInt.IRQ_RISING_FALLING`` - trigger on a rising or falling edge. - - ``pull`` can be one of: - - ``pyb.Pin.PULL_NONE`` - no pull up or down resistors; - - ``pyb.Pin.PULL_UP`` - enable the pull-up resistor; - - ``pyb.Pin.PULL_DOWN`` - enable the pull-down resistor. - - ``callback`` is the function to call when the interrupt triggers. The - callback function must accept exactly 1 argument, which is the line that - triggered the interrupt. - - -Class methods -------------- - -.. classmethod:: ExtInt.regs() - - Dump the values of the EXTI registers. - - -Methods -------- - -.. method:: ExtInt.disable() - - Disable the interrupt associated with the ExtInt object. - This could be useful for debouncing. - -.. method:: ExtInt.enable() - - Enable a disabled interrupt. - -.. method:: ExtInt.line() - - Return the line number that the pin is mapped to. - -.. method:: ExtInt.swint() - - Trigger the callback from software. - - -Constants ---------- - -.. data:: ExtInt.IRQ_FALLING - - interrupt on a falling edge - -.. data:: ExtInt.IRQ_RISING - - interrupt on a rising edge - -.. data:: ExtInt.IRQ_RISING_FALLING - - interrupt on a rising or falling edge diff --git a/docs/library/pyb.I2C.rst b/docs/library/pyb.I2C.rst deleted file mode 100644 index 7400318902..0000000000 --- a/docs/library/pyb.I2C.rst +++ /dev/null @@ -1,175 +0,0 @@ -.. currentmodule:: pyb -.. _pyb.I2C: - -class I2C -- a two-wire serial protocol -======================================= - -I2C is a two-wire protocol for communicating between devices. At the physical -level it consists of 2 wires: SCL and SDA, the clock and data lines respectively. - -I2C objects are created attached to a specific bus. They can be initialised -when created, or initialised later on. - -.. only:: port_pyboard - - Example:: - - from pyb import I2C - - i2c = I2C(1) # create on bus 1 - i2c = I2C(1, I2C.MASTER) # create and init as a master - i2c.init(I2C.MASTER, baudrate=20000) # init as a master - i2c.init(I2C.SLAVE, addr=0x42) # init as a slave with given address - i2c.deinit() # turn off the peripheral - -Printing the i2c object gives you information about its configuration. - -.. only:: port_pyboard - - The basic methods are send and recv:: - - i2c.send('abc') # send 3 bytes - i2c.send(0x42) # send a single byte, given by the number - data = i2c.recv(3) # receive 3 bytes - - To receive inplace, first create a bytearray:: - - data = bytearray(3) # create a buffer - i2c.recv(data) # receive 3 bytes, writing them into data - - You can specify a timeout (in ms):: - - i2c.send(b'123', timeout=2000) # timeout after 2 seconds - - A master must specify the recipient's address:: - - i2c.init(I2C.MASTER) - i2c.send('123', 0x42) # send 3 bytes to slave with address 0x42 - i2c.send(b'456', addr=0x42) # keyword for address - - Master also has other methods:: - - i2c.is_ready(0x42) # check if slave 0x42 is ready - i2c.scan() # scan for slaves on the bus, returning - # a list of valid addresses - i2c.mem_read(3, 0x42, 2) # read 3 bytes from memory of slave 0x42, - # starting at address 2 in the slave - i2c.mem_write('abc', 0x42, 2, timeout=1000) # write 'abc' (3 bytes) to memory of slave 0x42 - # starting at address 2 in the slave, timeout after 1 second - -Constructors ------------- - -.. only:: port_pyboard - - .. class:: pyb.I2C(bus, ...) - - Construct an I2C object on the given bus. ``bus`` can be 1 or 2, 'X' or - 'Y'. With no additional parameters, the I2C object is created but not - initialised (it has the settings from the last initialisation of - the bus, if any). If extra arguments are given, the bus is initialised. - See ``init`` for parameters of initialisation. - - The physical pins of the I2C busses on Pyboards V1.0 and V1.1 are: - - - ``I2C(1)`` is on the X position: ``(SCL, SDA) = (X9, X10) = (PB6, PB7)`` - - ``I2C(2)`` is on the Y position: ``(SCL, SDA) = (Y9, Y10) = (PB10, PB11)`` - - On the Pyboard Lite: - - - ``I2C(1)`` is on the X position: ``(SCL, SDA) = (X9, X10) = (PB6, PB7)`` - - ``I2C(3)`` is on the Y position: ``(SCL, SDA) = (Y9, Y10) = (PA8, PB8)`` - - Calling the constructor with 'X' or 'Y' enables portability between Pyboard - types. - -Methods -------- - -.. method:: I2C.deinit() - - Turn off the I2C bus. - -.. only:: port_pyboard - - .. method:: I2C.init(mode, \*, addr=0x12, baudrate=400000, gencall=False, dma=False) - - Initialise the I2C bus with the given parameters: - - - ``mode`` must be either ``I2C.MASTER`` or ``I2C.SLAVE`` - - ``addr`` is the 7-bit address (only sensible for a slave) - - ``baudrate`` is the SCL clock rate (only sensible for a master) - - ``gencall`` is whether to support general call mode - - ``dma`` is whether to allow the use of DMA for the I2C transfers (note - that DMA transfers have more precise timing but currently do not handle bus - errors properly) - - .. method:: I2C.is_ready(addr) - - Check if an I2C device responds to the given address. Only valid when in master mode. - - .. method:: I2C.mem_read(data, addr, memaddr, \*, timeout=5000, addr_size=8) - - Read from the memory of an I2C device: - - - ``data`` can be an integer (number of bytes to read) or a buffer to read into - - ``addr`` is the I2C device address - - ``memaddr`` is the memory location within the I2C device - - ``timeout`` is the timeout in milliseconds to wait for the read - - ``addr_size`` selects width of memaddr: 8 or 16 bits - - Returns the read data. - This is only valid in master mode. - - .. method:: I2C.mem_write(data, addr, memaddr, \*, timeout=5000, addr_size=8) - - Write to the memory of an I2C device: - - - ``data`` can be an integer or a buffer to write from - - ``addr`` is the I2C device address - - ``memaddr`` is the memory location within the I2C device - - ``timeout`` is the timeout in milliseconds to wait for the write - - ``addr_size`` selects width of memaddr: 8 or 16 bits - - Returns ``None``. - This is only valid in master mode. - - .. method:: I2C.recv(recv, addr=0x00, \*, timeout=5000) - - Receive data on the bus: - - - ``recv`` can be an integer, which is the number of bytes to receive, - or a mutable buffer, which will be filled with received bytes - - ``addr`` is the address to receive from (only required in master mode) - - ``timeout`` is the timeout in milliseconds to wait for the receive - - Return value: if ``recv`` is an integer then a new buffer of the bytes received, - otherwise the same buffer that was passed in to ``recv``. - - .. method:: I2C.send(send, addr=0x00, \*, timeout=5000) - - Send data on the bus: - - - ``send`` is the data to send (an integer to send, or a buffer object) - - ``addr`` is the address to send to (only required in master mode) - - ``timeout`` is the timeout in milliseconds to wait for the send - - Return value: ``None``. - -.. method:: I2C.scan() - - Scan all I2C addresses from 0x01 to 0x7f and return a list of those that respond. - Only valid when in master mode. - -Constants ---------- - -.. data:: I2C.MASTER - - for initialising the bus to master mode - -.. only:: port_pyboard - - .. data:: I2C.SLAVE - - for initialising the bus to slave mode diff --git a/docs/library/pyb.LCD.rst b/docs/library/pyb.LCD.rst deleted file mode 100644 index 83cf890b63..0000000000 --- a/docs/library/pyb.LCD.rst +++ /dev/null @@ -1,96 +0,0 @@ -.. currentmodule:: pyb - -class LCD -- LCD control for the LCD touch-sensor pyskin -======================================================== - -The LCD class is used to control the LCD on the LCD touch-sensor pyskin, -LCD32MKv1.0. The LCD is a 128x32 pixel monochrome screen, part NHD-C12832A1Z. - -The pyskin must be connected in either the X or Y positions, and then -an LCD object is made using:: - - lcd = pyb.LCD('X') # if pyskin is in the X position - lcd = pyb.LCD('Y') # if pyskin is in the Y position - -Then you can use:: - - lcd.light(True) # turn the backlight on - lcd.write('Hello world!\n') # print text to the screen - -This driver implements a double buffer for setting/getting pixels. -For example, to make a bouncing dot, try:: - - x = y = 0 - dx = dy = 1 - while True: - # update the dot's position - x += dx - y += dy - - # make the dot bounce of the edges of the screen - if x <= 0 or x >= 127: dx = -dx - if y <= 0 or y >= 31: dy = -dy - - lcd.fill(0) # clear the buffer - lcd.pixel(x, y, 1) # draw the dot - lcd.show() # show the buffer - pyb.delay(50) # pause for 50ms - - -Constructors ------------- - -.. class:: pyb.LCD(skin_position) - - Construct an LCD object in the given skin position. ``skin_position`` can be 'X' or 'Y', and - should match the position where the LCD pyskin is plugged in. - - -Methods -------- - -.. method:: LCD.command(instr_data, buf) - - Send an arbitrary command to the LCD. Pass 0 for ``instr_data`` to send an - instruction, otherwise pass 1 to send data. ``buf`` is a buffer with the - instructions/data to send. - -.. method:: LCD.contrast(value) - - Set the contrast of the LCD. Valid values are between 0 and 47. - -.. method:: LCD.fill(colour) - - Fill the screen with the given colour (0 or 1 for white or black). - - This method writes to the hidden buffer. Use ``show()`` to show the buffer. - -.. method:: LCD.get(x, y) - - Get the pixel at the position ``(x, y)``. Returns 0 or 1. - - This method reads from the visible buffer. - -.. method:: LCD.light(value) - - Turn the backlight on/off. True or 1 turns it on, False or 0 turns it off. - -.. method:: LCD.pixel(x, y, colour) - - Set the pixel at ``(x, y)`` to the given colour (0 or 1). - - This method writes to the hidden buffer. Use ``show()`` to show the buffer. - -.. method:: LCD.show() - - Show the hidden buffer on the screen. - -.. method:: LCD.text(str, x, y, colour) - - Draw the given text to the position ``(x, y)`` using the given colour (0 or 1). - - This method writes to the hidden buffer. Use ``show()`` to show the buffer. - -.. method:: LCD.write(str) - - Write the string ``str`` to the screen. It will appear immediately. diff --git a/docs/library/pyb.LED.rst b/docs/library/pyb.LED.rst deleted file mode 100644 index 1ab73a69c9..0000000000 --- a/docs/library/pyb.LED.rst +++ /dev/null @@ -1,46 +0,0 @@ -.. currentmodule:: pyb -.. _pyb.LED: - -class LED -- LED object -======================= - -The LED object controls an individual LED (Light Emitting Diode). - - -Constructors ------------- - -.. class:: pyb.LED(id) - - Create an LED object associated with the given LED: - - - ``id`` is the LED number, 1-4. - - -Methods -------- - -.. method:: LED.intensity([value]) - - Get or set the LED intensity. Intensity ranges between 0 (off) and 255 (full on). - If no argument is given, return the LED intensity. - If an argument is given, set the LED intensity and return ``None``. - - *Note:* Only LED(3) and LED(4) can have a smoothly varying intensity, and - they use timer PWM to implement it. LED(3) uses Timer(2) and LED(4) uses - Timer(3). These timers are only configured for PWM if the intensity of the - relevant LED is set to a value between 1 and 254. Otherwise the timers are - free for general purpose use. - -.. method:: LED.off() - - Turn the LED off. - -.. method:: LED.on() - - Turn the LED on, to maximum intensity. - -.. method:: LED.toggle() - - Toggle the LED between on (maximum intensity) and off. If the LED is at - non-zero intensity then it is considered "on" and toggle will turn it off. diff --git a/docs/library/pyb.Pin.rst b/docs/library/pyb.Pin.rst deleted file mode 100644 index b766c5280c..0000000000 --- a/docs/library/pyb.Pin.rst +++ /dev/null @@ -1,280 +0,0 @@ -.. currentmodule:: pyb -.. _pyb.Pin: - -class Pin -- control I/O pins -============================= - -A pin is the basic object to control I/O pins. It has methods to set -the mode of the pin (input, output, etc) and methods to get and set the -digital logic level. For analog control of a pin, see the ADC class. - -Usage Model: - -.. only:: port_pyboard - - All Board Pins are predefined as pyb.Pin.board.Name:: - - x1_pin = pyb.Pin.board.X1 - - g = pyb.Pin(pyb.Pin.board.X1, pyb.Pin.IN) - - CPU pins which correspond to the board pins are available - as ``pyb.cpu.Name``. For the CPU pins, the names are the port letter - followed by the pin number. On the PYBv1.0, ``pyb.Pin.board.X1`` and - ``pyb.Pin.cpu.A0`` are the same pin. - - You can also use strings:: - - g = pyb.Pin('X1', pyb.Pin.OUT_PP) - - Users can add their own names:: - - MyMapperDict = { 'LeftMotorDir' : pyb.Pin.cpu.C12 } - pyb.Pin.dict(MyMapperDict) - g = pyb.Pin("LeftMotorDir", pyb.Pin.OUT_OD) - - and can query mappings:: - - pin = pyb.Pin("LeftMotorDir") - - Users can also add their own mapping function:: - - def MyMapper(pin_name): - if pin_name == "LeftMotorDir": - return pyb.Pin.cpu.A0 - - pyb.Pin.mapper(MyMapper) - - So, if you were to call: ``pyb.Pin("LeftMotorDir", pyb.Pin.OUT_PP)`` - then ``"LeftMotorDir"`` is passed directly to the mapper function. - - To summarise, the following order determines how things get mapped into - an ordinal pin number: - - 1. Directly specify a pin object - 2. User supplied mapping function - 3. User supplied mapping (object must be usable as a dictionary key) - 4. Supply a string which matches a board pin - 5. Supply a string which matches a CPU port/pin - - You can set ``pyb.Pin.debug(True)`` to get some debug information about - how a particular object gets mapped to a pin. - - When a pin has the ``Pin.PULL_UP`` or ``Pin.PULL_DOWN`` pull-mode enabled, - that pin has an effective 40k Ohm resistor pulling it to 3V3 or GND - respectively (except pin Y5 which has 11k Ohm resistors). - - Now every time a falling edge is seen on the gpio pin, the callback will be - executed. Caution: mechanical push buttons have "bounce" and pushing or - releasing a switch will often generate multiple edges. - See: http://www.eng.utah.edu/~cs5780/debouncing.pdf for a detailed - explanation, along with various techniques for debouncing. - - All pin objects go through the pin mapper to come up with one of the - gpio pins. - -Constructors ------------- - -.. class:: pyb.Pin(id, ...) - - Create a new Pin object associated with the id. If additional arguments are given, - they are used to initialise the pin. See :meth:`pin.init`. - -.. only:: port_pyboard - - Class methods - ------------- - - .. classmethod:: Pin.debug([state]) - - Get or set the debugging state (``True`` or ``False`` for on or off). - - .. classmethod:: Pin.dict([dict]) - - Get or set the pin mapper dictionary. - - .. classmethod:: Pin.mapper([fun]) - - Get or set the pin mapper function. - - -Methods -------- - -.. only:: port_pyboard - - .. method:: Pin.init(mode, pull=Pin.PULL_NONE, af=-1) - - Initialise the pin: - - - ``mode`` can be one of: - - - ``Pin.IN`` - configure the pin for input; - - ``Pin.OUT_PP`` - configure the pin for output, with push-pull control; - - ``Pin.OUT_OD`` - configure the pin for output, with open-drain control; - - ``Pin.AF_PP`` - configure the pin for alternate function, pull-pull; - - ``Pin.AF_OD`` - configure the pin for alternate function, open-drain; - - ``Pin.ANALOG`` - configure the pin for analog. - - - ``pull`` can be one of: - - - ``Pin.PULL_NONE`` - no pull up or down resistors; - - ``Pin.PULL_UP`` - enable the pull-up resistor; - - ``Pin.PULL_DOWN`` - enable the pull-down resistor. - - - when mode is ``Pin.AF_PP`` or ``Pin.AF_OD``, then af can be the index or name - of one of the alternate functions associated with a pin. - - Returns: ``None``. - -.. method:: Pin.value([value]) - - Get or set the digital logic level of the pin: - - - With no argument, return 0 or 1 depending on the logic level of the pin. - - With ``value`` given, set the logic level of the pin. ``value`` can be - anything that converts to a boolean. If it converts to ``True``, the pin - is set high, otherwise it is set low. - -.. only:: port_pyboard - - .. method:: Pin.__str__() - - Return a string describing the pin object. - - .. method:: Pin.af() - - Returns the currently configured alternate-function of the pin. The - integer returned will match one of the allowed constants for the af - argument to the init function. - - .. method:: Pin.af_list() - - Returns an array of alternate functions available for this pin. - - .. method:: Pin.gpio() - - Returns the base address of the GPIO block associated with this pin. - - .. method:: Pin.mode() - - Returns the currently configured mode of the pin. The integer returned - will match one of the allowed constants for the mode argument to the init - function. - - .. method:: Pin.name() - - Get the pin name. - - .. method:: Pin.names() - - Returns the cpu and board names for this pin. - - .. method:: Pin.pin() - - Get the pin number. - - .. method:: Pin.port() - - Get the pin port. - -.. method:: Pin.pull() - - Returns the currently configured pull of the pin. The integer returned - will match one of the allowed constants for the pull argument to the init - function. - -Constants ---------- - -.. only:: port_pyboard - - .. data:: Pin.AF_OD - - initialise the pin to alternate-function mode with an open-drain drive - - .. data:: Pin.AF_PP - - initialise the pin to alternate-function mode with a push-pull drive - - .. data:: Pin.ANALOG - - initialise the pin to analog mode - - .. data:: Pin.IN - - initialise the pin to input mode - - .. data:: Pin.OUT_OD - - initialise the pin to output mode with an open-drain drive - - .. data:: Pin.OUT_PP - - initialise the pin to output mode with a push-pull drive - - .. data:: Pin.PULL_DOWN - - enable the pull-down resistor on the pin - - .. data:: Pin.PULL_NONE - - don't enable any pull up or down resistors on the pin - - .. data:: Pin.PULL_UP - - enable the pull-up resistor on the pin - -.. only:: port_pyboard - - class PinAF -- Pin Alternate Functions - ====================================== - - A Pin represents a physical pin on the microprocessor. Each pin - can have a variety of functions (GPIO, I2C SDA, etc). Each PinAF - object represents a particular function for a pin. - - Usage Model:: - - x3 = pyb.Pin.board.X3 - x3_af = x3.af_list() - - x3_af will now contain an array of PinAF objects which are available on - pin X3. - - For the pyboard, x3_af would contain: - [Pin.AF1_TIM2, Pin.AF2_TIM5, Pin.AF3_TIM9, Pin.AF7_USART2] - - Normally, each peripheral would configure the af automatically, but sometimes - the same function is available on multiple pins, and having more control - is desired. - - To configure X3 to expose TIM2_CH3, you could use:: - - pin = pyb.Pin(pyb.Pin.board.X3, mode=pyb.Pin.AF_PP, af=pyb.Pin.AF1_TIM2) - - or:: - - pin = pyb.Pin(pyb.Pin.board.X3, mode=pyb.Pin.AF_PP, af=1) - - Methods - ------- - - .. method:: pinaf.__str__() - - Return a string describing the alternate function. - - .. method:: pinaf.index() - - Return the alternate function index. - - .. method:: pinaf.name() - - Return the name of the alternate function. - - .. method:: pinaf.reg() - - Return the base register associated with the peripheral assigned to this - alternate function. For example, if the alternate function were TIM2_CH3 - this would return stm.TIM2 diff --git a/docs/library/pyb.RTC.rst b/docs/library/pyb.RTC.rst deleted file mode 100644 index 2628554526..0000000000 --- a/docs/library/pyb.RTC.rst +++ /dev/null @@ -1,83 +0,0 @@ -.. currentmodule:: pyb -.. _pyb.RTC: - -class RTC -- real time clock -============================ - -The RTC is and independent clock that keeps track of the date -and time. - -Example usage:: - - rtc = pyb.RTC() - rtc.datetime((2014, 5, 1, 4, 13, 0, 0, 0)) - print(rtc.datetime()) - - -Constructors ------------- - -.. class:: pyb.RTC() - - Create an RTC object. - - -Methods -------- - -.. method:: RTC.datetime([datetimetuple]) - - Get or set the date and time of the RTC. - - With no arguments, this method returns an 8-tuple with the current - date and time. With 1 argument (being an 8-tuple) it sets the date - and time. - - .. only:: port_pyboard - - The 8-tuple has the following format: - - (year, month, day, weekday, hours, minutes, seconds, subseconds) - - ``weekday`` is 1-7 for Monday through Sunday. - - ``subseconds`` counts down from 255 to 0 - -.. only:: port_pyboard - - .. method:: RTC.wakeup(timeout, callback=None) - - Set the RTC wakeup timer to trigger repeatedly at every ``timeout`` - milliseconds. This trigger can wake the pyboard from both the sleep - states: :meth:`pyb.stop` and :meth:`pyb.standby`. - - If ``timeout`` is ``None`` then the wakeup timer is disabled. - - If ``callback`` is given then it is executed at every trigger of the - wakeup timer. ``callback`` must take exactly one argument. - - .. method:: RTC.info() - - Get information about the startup time and reset source. - - - The lower 0xffff are the number of milliseconds the RTC took to - start up. - - Bit 0x10000 is set if a power-on reset occurred. - - Bit 0x20000 is set if an external reset occurred - - .. method:: RTC.calibration(cal) - - Get or set RTC calibration. - - With no arguments, ``calibration()`` returns the current calibration - value, which is an integer in the range [-511 : 512]. With one - argument it sets the RTC calibration. - - The RTC Smooth Calibration mechanism adjusts the RTC clock rate by - adding or subtracting the given number of ticks from the 32768 Hz - clock over a 32 second period (corresponding to 2^20 clock ticks.) - Each tick added will speed up the clock by 1 part in 2^20, or 0.954 - ppm; likewise the RTC clock it slowed by negative values. The - usable calibration range is: - (-511 * 0.954) ~= -487.5 ppm up to (512 * 0.954) ~= 488.5 ppm - diff --git a/docs/library/pyb.SPI.rst b/docs/library/pyb.SPI.rst deleted file mode 100644 index fd110be190..0000000000 --- a/docs/library/pyb.SPI.rst +++ /dev/null @@ -1,132 +0,0 @@ -.. currentmodule:: pyb -.. _pyb.SPI: - -class SPI -- a master-driven serial protocol -============================================ - -SPI is a serial protocol that is driven by a master. At the physical level -there are 3 lines: SCK, MOSI, MISO. - -.. only:: port_pyboard - - See usage model of I2C; SPI is very similar. Main difference is - parameters to init the SPI bus:: - - from pyb import SPI - spi = SPI(1, SPI.MASTER, baudrate=600000, polarity=1, phase=0, crc=0x7) - - Only required parameter is mode, SPI.MASTER or SPI.SLAVE. Polarity can be - 0 or 1, and is the level the idle clock line sits at. Phase can be 0 or 1 - to sample data on the first or second clock edge respectively. Crc can be - None for no CRC, or a polynomial specifier. - - Additional methods for SPI:: - - data = spi.send_recv(b'1234') # send 4 bytes and receive 4 bytes - buf = bytearray(4) - spi.send_recv(b'1234', buf) # send 4 bytes and receive 4 into buf - spi.send_recv(buf, buf) # send/recv 4 bytes from/to buf - -Constructors ------------- - -.. only:: port_pyboard - - .. class:: pyb.SPI(bus, ...) - - Construct an SPI object on the given bus. ``bus`` can be 1 or 2, or - 'X' or 'Y'. With no additional parameters, the SPI object is created but - not initialised (it has the settings from the last initialisation of - the bus, if any). If extra arguments are given, the bus is initialised. - See ``init`` for parameters of initialisation. - - The physical pins of the SPI busses are: - - - ``SPI(1)`` is on the X position: ``(NSS, SCK, MISO, MOSI) = (X5, X6, X7, X8) = (PA4, PA5, PA6, PA7)`` - - ``SPI(2)`` is on the Y position: ``(NSS, SCK, MISO, MOSI) = (Y5, Y6, Y7, Y8) = (PB12, PB13, PB14, PB15)`` - - At the moment, the NSS pin is not used by the SPI driver and is free - for other use. - -Methods -------- - -.. method:: SPI.deinit() - - Turn off the SPI bus. - -.. only:: port_pyboard - - .. method:: SPI.init(mode, baudrate=328125, \*, prescaler, polarity=1, phase=0, bits=8, firstbit=SPI.MSB, ti=False, crc=None) - - Initialise the SPI bus with the given parameters: - - - ``mode`` must be either ``SPI.MASTER`` or ``SPI.SLAVE``. - - ``baudrate`` is the SCK clock rate (only sensible for a master). - - ``prescaler`` is the prescaler to use to derive SCK from the APB bus frequency; - use of ``prescaler`` overrides ``baudrate``. - - ``polarity`` can be 0 or 1, and is the level the idle clock line sits at. - - ``phase`` can be 0 or 1 to sample data on the first or second clock edge - respectively. - - ``bits`` can be 8 or 16, and is the number of bits in each transferred word. - - ``firstbit`` can be ``SPI.MSB`` or ``SPI.LSB``. - - ``crc`` can be None for no CRC, or a polynomial specifier. - - Note that the SPI clock frequency will not always be the requested baudrate. - The hardware only supports baudrates that are the APB bus frequency - (see :meth:`pyb.freq`) divided by a prescaler, which can be 2, 4, 8, 16, 32, - 64, 128 or 256. SPI(1) is on AHB2, and SPI(2) is on AHB1. For precise - control over the SPI clock frequency, specify ``prescaler`` instead of - ``baudrate``. - - Printing the SPI object will show you the computed baudrate and the chosen - prescaler. - -.. only:: port_pyboard - - .. method:: SPI.recv(recv, \*, timeout=5000) - - Receive data on the bus: - - - ``recv`` can be an integer, which is the number of bytes to receive, - or a mutable buffer, which will be filled with received bytes. - - ``timeout`` is the timeout in milliseconds to wait for the receive. - - Return value: if ``recv`` is an integer then a new buffer of the bytes received, - otherwise the same buffer that was passed in to ``recv``. - - .. method:: SPI.send(send, \*, timeout=5000) - - Send data on the bus: - - - ``send`` is the data to send (an integer to send, or a buffer object). - - ``timeout`` is the timeout in milliseconds to wait for the send. - - Return value: ``None``. - - .. method:: SPI.send_recv(send, recv=None, \*, timeout=5000) - - Send and receive data on the bus at the same time: - - - ``send`` is the data to send (an integer to send, or a buffer object). - - ``recv`` is a mutable buffer which will be filled with received bytes. - It can be the same as ``send``, or omitted. If omitted, a new buffer will - be created. - - ``timeout`` is the timeout in milliseconds to wait for the receive. - - Return value: the buffer with the received bytes. - -Constants ---------- - -.. only:: port_pyboard - - .. data:: SPI.MASTER - .. data:: SPI.SLAVE - - for initialising the SPI bus to master or slave mode - - .. data:: SPI.LSB - .. data:: SPI.MSB - - set the first bit to be the least or most significant bit diff --git a/docs/library/pyb.Servo.rst b/docs/library/pyb.Servo.rst deleted file mode 100644 index b3ce71d11a..0000000000 --- a/docs/library/pyb.Servo.rst +++ /dev/null @@ -1,80 +0,0 @@ -.. currentmodule:: pyb -.. _pyb.Servo: - -class Servo -- 3-wire hobby servo driver -======================================== - -Servo objects control standard hobby servo motors with 3-wires (ground, power, -signal). There are 4 positions on the pyboard where these motors can be plugged -in: pins X1 through X4 are the signal pins, and next to them are 4 sets of power -and ground pins. - -Example usage:: - - import pyb - - s1 = pyb.Servo(1) # create a servo object on position X1 - s2 = pyb.Servo(2) # create a servo object on position X2 - - s1.angle(45) # move servo 1 to 45 degrees - s2.angle(0) # move servo 2 to 0 degrees - - # move servo1 and servo2 synchronously, taking 1500ms - s1.angle(-60, 1500) - s2.angle(30, 1500) - -.. note:: The Servo objects use Timer(5) to produce the PWM output. You can - use Timer(5) for Servo control, or your own purposes, but not both at the - same time. - -Constructors ------------- - -.. class:: pyb.Servo(id) - - Create a servo object. ``id`` is 1-4, and corresponds to pins X1 through X4. - - -Methods -------- - -.. method:: Servo.angle([angle, time=0]) - - If no arguments are given, this function returns the current angle. - - If arguments are given, this function sets the angle of the servo: - - - ``angle`` is the angle to move to in degrees. - - ``time`` is the number of milliseconds to take to get to the specified - angle. If omitted, then the servo moves as quickly as possible to its - new position. - -.. method:: Servo.speed([speed, time=0]) - - If no arguments are given, this function returns the current speed. - - If arguments are given, this function sets the speed of the servo: - - - ``speed`` is the speed to change to, between -100 and 100. - - ``time`` is the number of milliseconds to take to get to the specified - speed. If omitted, then the servo accelerates as quickly as possible. - -.. method:: Servo.pulse_width([value]) - - If no arguments are given, this function returns the current raw pulse-width - value. - - If an argument is given, this function sets the raw pulse-width value. - -.. method:: Servo.calibration([pulse_min, pulse_max, pulse_centre, [pulse_angle_90, pulse_speed_100]]) - - If no arguments are given, this function returns the current calibration - data, as a 5-tuple. - - If arguments are given, this function sets the timing calibration: - - - ``pulse_min`` is the minimum allowed pulse width. - - ``pulse_max`` is the maximum allowed pulse width. - - ``pulse_centre`` is the pulse width corresponding to the centre/zero position. - - ``pulse_angle_90`` is the pulse width corresponding to 90 degrees. - - ``pulse_speed_100`` is the pulse width corresponding to a speed of 100. diff --git a/docs/library/pyb.Switch.rst b/docs/library/pyb.Switch.rst deleted file mode 100644 index 0d5dc63b74..0000000000 --- a/docs/library/pyb.Switch.rst +++ /dev/null @@ -1,45 +0,0 @@ -.. currentmodule:: pyb - -class Switch -- switch object -============================= - -A Switch object is used to control a push-button switch. - -Usage:: - - sw = pyb.Switch() # create a switch object - sw.value() # get state (True if pressed, False otherwise) - sw() # shorthand notation to get the switch state - sw.callback(f) # register a callback to be called when the - # switch is pressed down - sw.callback(None) # remove the callback - -Example:: - - pyb.Switch().callback(lambda: pyb.LED(1).toggle()) - - -Constructors ------------- - -.. class:: pyb.Switch() - - Create and return a switch object. - - -Methods -------- - -.. method:: Switch.__call__() - - Call switch object directly to get its state: ``True`` if pressed down, - ``False`` otherwise. - -.. method:: Switch.value() - - Get the switch state. Returns `True` if pressed down, otherwise `False`. - -.. method:: Switch.callback(fun) - - Register the given function to be called when the switch is pressed down. - If ``fun`` is ``None``, then it disables the callback. diff --git a/docs/library/pyb.Timer.rst b/docs/library/pyb.Timer.rst deleted file mode 100644 index 052bce2efd..0000000000 --- a/docs/library/pyb.Timer.rst +++ /dev/null @@ -1,286 +0,0 @@ -.. currentmodule:: pyb -.. _pyb.Timer: - -class Timer -- control internal timers -====================================== - -.. only:: port_pyboard - - Timers can be used for a great variety of tasks. At the moment, only - the simplest case is implemented: that of calling a function periodically. - - Each timer consists of a counter that counts up at a certain rate. The rate - at which it counts is the peripheral clock frequency (in Hz) divided by the - timer prescaler. When the counter reaches the timer period it triggers an - event, and the counter resets back to zero. By using the callback method, - the timer event can call a Python function. - - Example usage to toggle an LED at a fixed frequency:: - - tim = pyb.Timer(4) # create a timer object using timer 4 - tim.init(freq=2) # trigger at 2Hz - tim.callback(lambda t:pyb.LED(1).toggle()) - - Example using named function for the callback:: - - def tick(timer): # we will receive the timer object when being called - print(timer.counter()) # show current timer's counter value - tim = pyb.Timer(4, freq=1) # create a timer object using timer 4 - trigger at 1Hz - tim.callback(tick) # set the callback to our tick function - - Further examples:: - - tim = pyb.Timer(4, freq=100) # freq in Hz - tim = pyb.Timer(4, prescaler=0, period=99) - tim.counter() # get counter (can also set) - tim.prescaler(2) # set prescaler (can also get) - tim.period(199) # set period (can also get) - tim.callback(lambda t: ...) # set callback for update interrupt (t=tim instance) - tim.callback(None) # clear callback - - *Note:* Timer(2) and Timer(3) are used for PWM to set the intensity of LED(3) - and LED(4) respectively. But these timers are only configured for PWM if - the intensity of the relevant LED is set to a value between 1 and 254. If - the intensity feature of the LEDs is not used then these timers are free for - general purpose use. Similarly, Timer(5) controls the servo driver, and - Timer(6) is used for timed ADC/DAC reading/writing. It is recommended to - use the other timers in your programs. - -*Note:* Memory can't be allocated during a callback (an interrupt) and so -exceptions raised within a callback don't give much information. See -:func:`micropython.alloc_emergency_exception_buf` for how to get around this -limitation. - - -Constructors ------------- - -.. class:: pyb.Timer(id, ...) - - .. only:: port_pyboard - - Construct a new timer object of the given id. If additional - arguments are given, then the timer is initialised by ``init(...)``. - ``id`` can be 1 to 14. - -Methods -------- - -.. only:: port_pyboard - - .. method:: Timer.init(\*, freq, prescaler, period) - - Initialise the timer. Initialisation must be either by frequency (in Hz) - or by prescaler and period:: - - tim.init(freq=100) # set the timer to trigger at 100Hz - tim.init(prescaler=83, period=999) # set the prescaler and period directly - - Keyword arguments: - - - ``freq`` --- specifies the periodic frequency of the timer. You might also - view this as the frequency with which the timer goes through one complete cycle. - - - ``prescaler`` [0-0xffff] - specifies the value to be loaded into the - timer's Prescaler Register (PSC). The timer clock source is divided by - (``prescaler + 1``) to arrive at the timer clock. Timers 2-7 and 12-14 - have a clock source of 84 MHz (pyb.freq()[2] \* 2), and Timers 1, and 8-11 - have a clock source of 168 MHz (pyb.freq()[3] \* 2). - - - ``period`` [0-0xffff] for timers 1, 3, 4, and 6-15. [0-0x3fffffff] for timers 2 & 5. - Specifies the value to be loaded into the timer's AutoReload - Register (ARR). This determines the period of the timer (i.e. when the - counter cycles). The timer counter will roll-over after ``period + 1`` - timer clock cycles. - - - ``mode`` can be one of: - - - ``Timer.UP`` - configures the timer to count from 0 to ARR (default) - - ``Timer.DOWN`` - configures the timer to count from ARR down to 0. - - ``Timer.CENTER`` - configures the timer to count from 0 to ARR and - then back down to 0. - - - ``div`` can be one of 1, 2, or 4. Divides the timer clock to determine - the sampling clock used by the digital filters. - - - ``callback`` - as per Timer.callback() - - - ``deadtime`` - specifies the amount of "dead" or inactive time between - transitions on complimentary channels (both channels will be inactive) - for this time). ``deadtime`` may be an integer between 0 and 1008, with - the following restrictions: 0-128 in steps of 1. 128-256 in steps of - 2, 256-512 in steps of 8, and 512-1008 in steps of 16. ``deadtime`` - measures ticks of ``source_freq`` divided by ``div`` clock ticks. - ``deadtime`` is only available on timers 1 and 8. - - You must either specify freq or both of period and prescaler. - -.. method:: Timer.deinit() - - Deinitialises the timer. - - .. only:: port_pyboard - - Disables the callback (and the associated irq). - - Disables any channel callbacks (and the associated irq). - Stops the timer, and disables the timer peripheral. - -.. only:: port_pyboard - - .. method:: Timer.callback(fun) - - Set the function to be called when the timer triggers. - ``fun`` is passed 1 argument, the timer object. - If ``fun`` is ``None`` then the callback will be disabled. - -.. only:: port_pyboard - - .. method:: Timer.channel(channel, mode, ...) - - If only a channel number is passed, then a previously initialized channel - object is returned (or ``None`` if there is no previous channel). - - Otherwise, a TimerChannel object is initialized and returned. - - Each channel can be configured to perform pwm, output compare, or - input capture. All channels share the same underlying timer, which means - that they share the same timer clock. - - Keyword arguments: - - - ``mode`` can be one of: - - - ``Timer.PWM`` --- configure the timer in PWM mode (active high). - - ``Timer.PWM_INVERTED`` --- configure the timer in PWM mode (active low). - - ``Timer.OC_TIMING`` --- indicates that no pin is driven. - - ``Timer.OC_ACTIVE`` --- the pin will be made active when a compare match occurs (active is determined by polarity) - - ``Timer.OC_INACTIVE`` --- the pin will be made inactive when a compare match occurs. - - ``Timer.OC_TOGGLE`` --- the pin will be toggled when an compare match occurs. - - ``Timer.OC_FORCED_ACTIVE`` --- the pin is forced active (compare match is ignored). - - ``Timer.OC_FORCED_INACTIVE`` --- the pin is forced inactive (compare match is ignored). - - ``Timer.IC`` --- configure the timer in Input Capture mode. - - ``Timer.ENC_A`` --- configure the timer in Encoder mode. The counter only changes when CH1 changes. - - ``Timer.ENC_B`` --- configure the timer in Encoder mode. The counter only changes when CH2 changes. - - ``Timer.ENC_AB`` --- configure the timer in Encoder mode. The counter changes when CH1 or CH2 changes. - - - ``callback`` - as per TimerChannel.callback() - - - ``pin`` None (the default) or a Pin object. If specified (and not None) - this will cause the alternate function of the the indicated pin - to be configured for this timer channel. An error will be raised if - the pin doesn't support any alternate functions for this timer channel. - - Keyword arguments for Timer.PWM modes: - - - ``pulse_width`` - determines the initial pulse width value to use. - - ``pulse_width_percent`` - determines the initial pulse width percentage to use. - - Keyword arguments for Timer.OC modes: - - - ``compare`` - determines the initial value of the compare register. - - - ``polarity`` can be one of: - - - ``Timer.HIGH`` - output is active high - - ``Timer.LOW`` - output is active low - - Optional keyword arguments for Timer.IC modes: - - - ``polarity`` can be one of: - - - ``Timer.RISING`` - captures on rising edge. - - ``Timer.FALLING`` - captures on falling edge. - - ``Timer.BOTH`` - captures on both edges. - - Note that capture only works on the primary channel, and not on the - complimentary channels. - - Notes for Timer.ENC modes: - - - Requires 2 pins, so one or both pins will need to be configured to use - the appropriate timer AF using the Pin API. - - Read the encoder value using the timer.counter() method. - - Only works on CH1 and CH2 (and not on CH1N or CH2N) - - The channel number is ignored when setting the encoder mode. - - PWM Example:: - - timer = pyb.Timer(2, freq=1000) - ch2 = timer.channel(2, pyb.Timer.PWM, pin=pyb.Pin.board.X2, pulse_width=8000) - ch3 = timer.channel(3, pyb.Timer.PWM, pin=pyb.Pin.board.X3, pulse_width=16000) - -.. only:: port_pyboard - - .. method:: Timer.counter([value]) - - Get or set the timer counter. - -.. only:: port_pyboard - - .. method:: Timer.freq([value]) - - Get or set the frequency for the timer (changes prescaler and period if set). - -.. only:: port_pyboard - - .. method:: Timer.period([value]) - - Get or set the period of the timer. - - .. method:: Timer.prescaler([value]) - - Get or set the prescaler for the timer. - - .. method:: Timer.source_freq() - - Get the frequency of the source of the timer. - -class TimerChannel --- setup a channel for a timer -================================================== - -Timer channels are used to generate/capture a signal using a timer. - -TimerChannel objects are created using the Timer.channel() method. - -Methods -------- - -.. only:: port_pyboard - - .. method:: timerchannel.callback(fun) - - Set the function to be called when the timer channel triggers. - ``fun`` is passed 1 argument, the timer object. - If ``fun`` is ``None`` then the callback will be disabled. - -.. only:: port_pyboard - - .. method:: timerchannel.capture([value]) - - Get or set the capture value associated with a channel. - capture, compare, and pulse_width are all aliases for the same function. - capture is the logical name to use when the channel is in input capture mode. - - .. method:: timerchannel.compare([value]) - - Get or set the compare value associated with a channel. - capture, compare, and pulse_width are all aliases for the same function. - compare is the logical name to use when the channel is in output compare mode. - - .. method:: timerchannel.pulse_width([value]) - - Get or set the pulse width value associated with a channel. - capture, compare, and pulse_width are all aliases for the same function. - pulse_width is the logical name to use when the channel is in PWM mode. - - In edge aligned mode, a pulse_width of ``period + 1`` corresponds to a duty cycle of 100% - In center aligned mode, a pulse width of ``period`` corresponds to a duty cycle of 100% - - .. method:: timerchannel.pulse_width_percent([value]) - - Get or set the pulse width percentage associated with a channel. The value - is a number between 0 and 100 and sets the percentage of the timer period - for which the pulse is active. The value can be an integer or - floating-point number for more accuracy. For example, a value of 25 gives - a duty cycle of 25%. diff --git a/docs/library/pyb.UART.rst b/docs/library/pyb.UART.rst deleted file mode 100644 index 76f347ffa8..0000000000 --- a/docs/library/pyb.UART.rst +++ /dev/null @@ -1,245 +0,0 @@ -.. currentmodule:: pyb -.. _pyb.UART: - -class UART -- duplex serial communication bus -============================================= - -UART implements the standard UART/USART duplex serial communications protocol. At -the physical level it consists of 2 lines: RX and TX. The unit of communication -is a character (not to be confused with a string character) which can be 8 or 9 -bits wide. - -UART objects can be created and initialised using:: - - from pyb import UART - - uart = UART(1, 9600) # init with given baudrate - uart.init(9600, bits=8, parity=None, stop=1) # init with given parameters - -.. only:: port_pyboard - - Bits can be 7, 8 or 9. Parity can be None, 0 (even) or 1 (odd). Stop can be 1 or 2. - - *Note:* with parity=None, only 8 and 9 bits are supported. With parity enabled, - only 7 and 8 bits are supported. - -A UART object acts like a stream object and reading and writing is done -using the standard stream methods:: - - uart.read(10) # read 10 characters, returns a bytes object - uart.read() # read all available characters - uart.readline() # read a line - uart.readinto(buf) # read and store into the given buffer - uart.write('abc') # write the 3 characters - -.. only:: port_pyboard - - Individual characters can be read/written using:: - - uart.readchar() # read 1 character and returns it as an integer - uart.writechar(42) # write 1 character - - To check if there is anything to be read, use:: - - uart.any() # returns the number of characters waiting - - - *Note:* The stream functions ``read``, ``write``, etc. are new in MicroPython v1.3.4. - Earlier versions use ``uart.send`` and ``uart.recv``. - -Constructors ------------- - -.. only:: port_pyboard - - .. class:: pyb.UART(bus, ...) - - Construct a UART object on the given bus. ``bus`` can be 1-6, or 'XA', 'XB', 'YA', or 'YB'. - With no additional parameters, the UART object is created but not - initialised (it has the settings from the last initialisation of - the bus, if any). If extra arguments are given, the bus is initialised. - See ``init`` for parameters of initialisation. - - The physical pins of the UART busses are: - - - ``UART(4)`` is on ``XA``: ``(TX, RX) = (X1, X2) = (PA0, PA1)`` - - ``UART(1)`` is on ``XB``: ``(TX, RX) = (X9, X10) = (PB6, PB7)`` - - ``UART(6)`` is on ``YA``: ``(TX, RX) = (Y1, Y2) = (PC6, PC7)`` - - ``UART(3)`` is on ``YB``: ``(TX, RX) = (Y9, Y10) = (PB10, PB11)`` - - ``UART(2)`` is on: ``(TX, RX) = (X3, X4) = (PA2, PA3)`` - - The Pyboard Lite supports UART(1), UART(2) and UART(6) only. Pins are as above except: - - - ``UART(2)`` is on: ``(TX, RX) = (X1, X2) = (PA2, PA3)`` - -Methods -------- - -.. only:: port_pyboard - - .. method:: UART.init(baudrate, bits=8, parity=None, stop=1, \*, timeout=1000, flow=0, timeout_char=0, read_buf_len=64) - - Initialise the UART bus with the given parameters: - - - ``baudrate`` is the clock rate. - - ``bits`` is the number of bits per character, 7, 8 or 9. - - ``parity`` is the parity, ``None``, 0 (even) or 1 (odd). - - ``stop`` is the number of stop bits, 1 or 2. - - ``flow`` sets the flow control type. Can be 0, ``UART.RTS``, ``UART.CTS`` - or ``UART.RTS | UART.CTS``. - - ``timeout`` is the timeout in milliseconds to wait for writing/reading the first character. - - ``timeout_char`` is the timeout in milliseconds to wait between characters while writing or reading. - - ``read_buf_len`` is the character length of the read buffer (0 to disable). - - This method will raise an exception if the baudrate could not be set within - 5% of the desired value. The minimum baudrate is dictated by the frequency - of the bus that the UART is on; UART(1) and UART(6) are APB2, the rest are on - APB1. The default bus frequencies give a minimum baudrate of 1300 for - UART(1) and UART(6) and 650 for the others. Use :func:`pyb.freq ` - to reduce the bus frequencies to get lower baudrates. - - *Note:* with parity=None, only 8 and 9 bits are supported. With parity enabled, - only 7 and 8 bits are supported. - -.. method:: UART.deinit() - - Turn off the UART bus. - -.. only:: port_pyboard - - .. method:: UART.any() - - Returns the number of bytes waiting (may be 0). - -.. method:: UART.read([nbytes]) - - Read characters. If ``nbytes`` is specified then read at most that many bytes. - If ``nbytes`` are available in the buffer, returns immediately, otherwise returns - when sufficient characters arrive or the timeout elapses. - - If ``nbytes`` is not given then the method reads as much data as possible. It - returns after the timeout has elapsed. - - .. only:: port_pyboard - - *Note:* for 9 bit characters each character takes two bytes, ``nbytes`` must - be even, and the number of characters is ``nbytes/2``. - - Return value: a bytes object containing the bytes read in. Returns ``None`` - on timeout. - -.. method:: UART.readchar() - - Receive a single character on the bus. - - Return value: The character read, as an integer. Returns -1 on timeout. - -.. method:: UART.readinto(buf[, nbytes]) - - Read bytes into the ``buf``. If ``nbytes`` is specified then read at most - that many bytes. Otherwise, read at most ``len(buf)`` bytes. - - Return value: number of bytes read and stored into ``buf`` or ``None`` on - timeout. - -.. method:: UART.readline() - - Read a line, ending in a newline character. If such a line exists, return is - immediate. If the timeout elapses, all available data is returned regardless - of whether a newline exists. - - Return value: the line read or ``None`` on timeout if no data is available. - -.. method:: UART.write(buf) - - .. only:: port_pyboard - - Write the buffer of bytes to the bus. If characters are 7 or 8 bits wide - then each byte is one character. If characters are 9 bits wide then two - bytes are used for each character (little endian), and ``buf`` must contain - an even number of bytes. - - Return value: number of bytes written. If a timeout occurs and no bytes - were written returns ``None``. - -.. only:: port_pyboard - - .. method:: UART.writechar(char) - - Write a single character on the bus. ``char`` is an integer to write. - Return value: ``None``. See note below if CTS flow control is used. - -.. method:: UART.sendbreak() - - Send a break condition on the bus. This drives the bus low for a duration - of 13 bits. - Return value: ``None``. - -Constants ---------- - -.. only:: port_pyboard - - .. data:: UART.RTS - .. data:: UART.CTS - - to select the flow control type. - -Flow Control ------------- - -.. only:: port_pyboard - - On Pyboards V1 and V1.1 ``UART(2)`` and ``UART(3)`` support RTS/CTS hardware flow control - using the following pins: - - - ``UART(2)`` is on: ``(TX, RX, nRTS, nCTS) = (X3, X4, X2, X1) = (PA2, PA3, PA1, PA0)`` - - ``UART(3)`` is on :``(TX, RX, nRTS, nCTS) = (Y9, Y10, Y7, Y6) = (PB10, PB11, PB14, PB13)`` - - On the Pyboard Lite only ``UART(2)`` supports flow control on these pins: - - ``(TX, RX, nRTS, nCTS) = (X1, X2, X4, X3) = (PA2, PA3, PA1, PA0)`` - - In the following paragraphs the term "target" refers to the device connected to - the UART. - - When the UART's ``init()`` method is called with ``flow`` set to one or both of - ``UART.RTS`` and ``UART.CTS`` the relevant flow control pins are configured. - ``nRTS`` is an active low output, ``nCTS`` is an active low input with pullup - enabled. To achieve flow control the Pyboard's ``nCTS`` signal should be connected - to the target's ``nRTS`` and the Pyboard's ``nRTS`` to the target's ``nCTS``. - - CTS: target controls Pyboard transmitter - ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - - If CTS flow control is enabled the write behaviour is as follows: - - If the Pyboard's ``UART.write(buf)`` method is called, transmission will stall for - any periods when ``nCTS`` is ``False``. This will result in a timeout if the entire - buffer was not transmitted in the timeout period. The method returns the number of - bytes written, enabling the user to write the remainder of the data if required. In - the event of a timeout, a character will remain in the UART pending ``nCTS``. The - number of bytes composing this character will be included in the return value. - - If ``UART.writechar()`` is called when ``nCTS`` is ``False`` the method will time - out unless the target asserts ``nCTS`` in time. If it times out ``OSError 116`` - will be raised. The character will be transmitted as soon as the target asserts ``nCTS``. - - RTS: Pyboard controls target's transmitter - ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - - If RTS flow control is enabled, behaviour is as follows: - - If buffered input is used (``read_buf_len`` > 0), incoming characters are buffered. - If the buffer becomes full, the next character to arrive will cause ``nRTS`` to go - ``False``: the target should cease transmission. ``nRTS`` will go ``True`` when - characters are read from the buffer. - - Note that the ``any()`` method returns the number of bytes in the buffer. Assume a - buffer length of ``N`` bytes. If the buffer becomes full, and another character arrives, - ``nRTS`` will be set False, and ``any()`` will return the count ``N``. When - characters are read the additional character will be placed in the buffer and will - be included in the result of a subsequent ``any()`` call. - - If buffered input is not used (``read_buf_len`` == 0) the arrival of a character will - cause ``nRTS`` to go ``False`` until the character is read. diff --git a/docs/library/pyb.USB_HID.rst b/docs/library/pyb.USB_HID.rst deleted file mode 100644 index 7d17c3099f..0000000000 --- a/docs/library/pyb.USB_HID.rst +++ /dev/null @@ -1,39 +0,0 @@ -.. currentmodule:: pyb - -class USB_HID -- USB Human Interface Device (HID) -================================================= - -The USB_HID class allows creation of an object representing the USB -Human Interface Device (HID) interface. It can be used to emulate -a peripheral such as a mouse or keyboard. - -Before you can use this class, you need to use :meth:`pyb.usb_mode()` to set the USB mode to include the HID interface. - -Constructors ------------- - -.. class:: pyb.USB_HID() - - Create a new USB_HID object. - - -Methods -------- - -.. method:: USB_HID.recv(data, \*, timeout=5000) - - Receive data on the bus: - - - ``data`` can be an integer, which is the number of bytes to receive, - or a mutable buffer, which will be filled with received bytes. - - ``timeout`` is the timeout in milliseconds to wait for the receive. - - Return value: if ``data`` is an integer then a new buffer of the bytes received, - otherwise the number of bytes read into ``data`` is returned. - -.. method:: USB_HID.send(data) - - Send data over the USB HID interface: - - - ``data`` is the data to send (a tuple/list of integers, or a - bytearray). diff --git a/docs/library/pyb.USB_VCP.rst b/docs/library/pyb.USB_VCP.rst deleted file mode 100644 index 4c4fe45168..0000000000 --- a/docs/library/pyb.USB_VCP.rst +++ /dev/null @@ -1,102 +0,0 @@ -.. currentmodule:: pyb - -class USB_VCP -- USB virtual comm port -====================================== - -The USB_VCP class allows creation of an object representing the USB -virtual comm port. It can be used to read and write data over USB to -the connected host. - - -Constructors ------------- - -.. class:: pyb.USB_VCP() - - Create a new USB_VCP object. - - -Methods -------- - -.. method:: USB_VCP.setinterrupt(chr) - - Set the character which interrupts running Python code. This is set - to 3 (CTRL-C) by default, and when a CTRL-C character is received over - the USB VCP port, a KeyboardInterrupt exception is raised. - - Set to -1 to disable this interrupt feature. This is useful when you - want to send raw bytes over the USB VCP port. - -.. method:: USB_VCP.isconnected() - - Return ``True`` if USB is connected as a serial device, else ``False``. - -.. method:: USB_VCP.any() - - Return ``True`` if any characters waiting, else ``False``. - -.. method:: USB_VCP.close() - - This method does nothing. It exists so the USB_VCP object can act as - a file. - -.. method:: USB_VCP.read([nbytes]) - - Read at most ``nbytes`` from the serial device and return them as a - bytes object. If ``nbytes`` is not specified then the method reads - all available bytes from the serial device. - USB_VCP stream implicitly works in non-blocking mode, - so if no pending data available, this method will return immediately - with ``None`` value. - -.. method:: USB_VCP.readinto(buf, [maxlen]) - - Read bytes from the serial device and store them into ``buf``, which - should be a buffer-like object. At most ``len(buf)`` bytes are read. - If ``maxlen`` is given and then at most ``min(maxlen, len(buf))`` bytes - are read. - - Returns the number of bytes read and stored into ``buf`` or ``None`` - if no pending data available. - -.. method:: USB_VCP.readline() - - Read a whole line from the serial device. - - Returns a bytes object containing the data, including the trailing - newline character or ``None`` if no pending data available. - -.. method:: USB_VCP.readlines() - - Read as much data as possible from the serial device, breaking it into - lines. - - Returns a list of bytes objects, each object being one of the lines. - Each line will include the newline character. - -.. method:: USB_VCP.write(buf) - - Write the bytes from ``buf`` to the serial device. - - Returns the number of bytes written. - -.. method:: USB_VCP.recv(data, \*, timeout=5000) - - Receive data on the bus: - - - ``data`` can be an integer, which is the number of bytes to receive, - or a mutable buffer, which will be filled with received bytes. - - ``timeout`` is the timeout in milliseconds to wait for the receive. - - Return value: if ``data`` is an integer then a new buffer of the bytes received, - otherwise the number of bytes read into ``data`` is returned. - -.. method:: USB_VCP.send(data, \*, timeout=5000) - - Send data over the USB VCP: - - - ``data`` is the data to send (an integer to send, or a buffer object). - - ``timeout`` is the timeout in milliseconds to wait for the send. - - Return value: number of bytes sent. diff --git a/docs/library/pyb.rst b/docs/library/pyb.rst deleted file mode 100644 index 7991601457..0000000000 --- a/docs/library/pyb.rst +++ /dev/null @@ -1,321 +0,0 @@ -:mod:`pyb` --- functions related to the board -============================================= - -.. module:: pyb - :synopsis: functions related to the board - -The ``pyb`` module contains specific functions related to the board. - -Time related functions ----------------------- - -.. function:: delay(ms) - - Delay for the given number of milliseconds. - -.. function:: udelay(us) - - Delay for the given number of microseconds. - -.. function:: millis() - - Returns the number of milliseconds since the board was last reset. - - The result is always a MicroPython smallint (31-bit signed number), so - after 2^30 milliseconds (about 12.4 days) this will start to return - negative numbers. - - Note that if :meth:`pyb.stop()` is issued the hardware counter supporting this - function will pause for the duration of the "sleeping" state. This - will affect the outcome of :meth:`pyb.elapsed_millis()`. - -.. function:: micros() - - Returns the number of microseconds since the board was last reset. - - The result is always a MicroPython smallint (31-bit signed number), so - after 2^30 microseconds (about 17.8 minutes) this will start to return - negative numbers. - - Note that if :meth:`pyb.stop()` is issued the hardware counter supporting this - function will pause for the duration of the "sleeping" state. This - will affect the outcome of :meth:`pyb.elapsed_micros()`. - -.. function:: elapsed_millis(start) - - Returns the number of milliseconds which have elapsed since ``start``. - - This function takes care of counter wrap, and always returns a positive - number. This means it can be used to measure periods up to about 12.4 days. - - Example:: - - start = pyb.millis() - while pyb.elapsed_millis(start) < 1000: - # Perform some operation - -.. function:: elapsed_micros(start) - - Returns the number of microseconds which have elapsed since ``start``. - - This function takes care of counter wrap, and always returns a positive - number. This means it can be used to measure periods up to about 17.8 minutes. - - Example:: - - start = pyb.micros() - while pyb.elapsed_micros(start) < 1000: - # Perform some operation - pass - -Reset related functions ------------------------ - -.. function:: hard_reset() - - Resets the pyboard in a manner similar to pushing the external RESET - button. - -.. function:: bootloader() - - Activate the bootloader without BOOT\* pins. - -.. function:: fault_debug(value) - - Enable or disable hard-fault debugging. A hard-fault is when there is a fatal - error in the underlying system, like an invalid memory access. - - If the *value* argument is ``False`` then the board will automatically reset if - there is a hard fault. - - If *value* is ``True`` then, when the board has a hard fault, it will print the - registers and the stack trace, and then cycle the LEDs indefinitely. - - The default value is disabled, i.e. to automatically reset. - -Interrupt related functions ---------------------------- - -.. function:: disable_irq() - - Disable interrupt requests. - Returns the previous IRQ state: ``False``/``True`` for disabled/enabled IRQs - respectively. This return value can be passed to enable_irq to restore - the IRQ to its original state. - -.. function:: enable_irq(state=True) - - Enable interrupt requests. - If ``state`` is ``True`` (the default value) then IRQs are enabled. - If ``state`` is ``False`` then IRQs are disabled. The most common use of - this function is to pass it the value returned by ``disable_irq`` to - exit a critical section. - -Power related functions ------------------------ - -.. only:: port_pyboard - - .. function:: freq([sysclk[, hclk[, pclk1[, pclk2]]]]) - - If given no arguments, returns a tuple of clock frequencies: - (sysclk, hclk, pclk1, pclk2). - These correspond to: - - - sysclk: frequency of the CPU - - hclk: frequency of the AHB bus, core memory and DMA - - pclk1: frequency of the APB1 bus - - pclk2: frequency of the APB2 bus - - If given any arguments then the function sets the frequency of the CPU, - and the busses if additional arguments are given. Frequencies are given in - Hz. Eg freq(120000000) sets sysclk (the CPU frequency) to 120MHz. Note that - not all values are supported and the largest supported frequency not greater - than the given value will be selected. - - Supported sysclk frequencies are (in MHz): 8, 16, 24, 30, 32, 36, 40, 42, 48, - 54, 56, 60, 64, 72, 84, 96, 108, 120, 144, 168. - - The maximum frequency of hclk is 168MHz, of pclk1 is 42MHz, and of pclk2 is - 84MHz. Be sure not to set frequencies above these values. - - The hclk, pclk1 and pclk2 frequencies are derived from the sysclk frequency - using a prescaler (divider). Supported prescalers for hclk are: 1, 2, 4, 8, - 16, 64, 128, 256, 512. Supported prescalers for pclk1 and pclk2 are: 1, 2, - 4, 8. A prescaler will be chosen to best match the requested frequency. - - A sysclk frequency of - 8MHz uses the HSE (external crystal) directly and 16MHz uses the HSI - (internal oscillator) directly. The higher frequencies use the HSE to - drive the PLL (phase locked loop), and then use the output of the PLL. - - Note that if you change the frequency while the USB is enabled then - the USB may become unreliable. It is best to change the frequency - in boot.py, before the USB peripheral is started. Also note that sysclk - frequencies below 36MHz do not allow the USB to function correctly. - - .. function:: wfi() - - Wait for an internal or external interrupt. - - This executes a ``wfi`` instruction which reduces power consumption - of the MCU until any interrupt occurs (be it internal or external), - at which point execution continues. Note that the system-tick interrupt - occurs once every millisecond (1000Hz) so this function will block for - at most 1ms. - - .. function:: stop() - - Put the pyboard in a "sleeping" state. - - This reduces power consumption to less than 500 uA. To wake from this - sleep state requires an external interrupt or a real-time-clock event. - Upon waking execution continues where it left off. - - See :meth:`rtc.wakeup` to configure a real-time-clock wakeup event. - - .. function:: standby() - - Put the pyboard into a "deep sleep" state. - - This reduces power consumption to less than 50 uA. To wake from this - sleep state requires a real-time-clock event, or an external interrupt - on X1 (PA0=WKUP) or X18 (PC13=TAMP1). - Upon waking the system undergoes a hard reset. - - See :meth:`rtc.wakeup` to configure a real-time-clock wakeup event. - -Miscellaneous functions ------------------------ - -.. only:: port_pyboard - - .. function:: have_cdc() - - Return True if USB is connected as a serial device, False otherwise. - - .. note:: This function is deprecated. Use pyb.USB_VCP().isconnected() instead. - - .. function:: hid((buttons, x, y, z)) - - Takes a 4-tuple (or list) and sends it to the USB host (the PC) to - signal a HID mouse-motion event. - - .. note:: This function is deprecated. Use :meth:`pyb.USB_HID.send()` instead. - - .. function:: info([dump_alloc_table]) - - Print out lots of information about the board. - -.. function:: main(filename) - - Set the filename of the main script to run after boot.py is finished. If - this function is not called then the default file main.py will be executed. - - It only makes sense to call this function from within boot.py. - -.. only:: port_pyboard - - .. function:: mount(device, mountpoint, \*, readonly=False, mkfs=False) - - Mount a block device and make it available as part of the filesystem. - ``device`` must be an object that provides the block protocol: - - - ``readblocks(self, blocknum, buf)`` - - ``writeblocks(self, blocknum, buf)`` (optional) - - ``count(self)`` - - ``sync(self)`` (optional) - - ``readblocks`` and ``writeblocks`` should copy data between ``buf`` and - the block device, starting from block number ``blocknum`` on the device. - ``buf`` will be a bytearray with length a multiple of 512. If - ``writeblocks`` is not defined then the device is mounted read-only. - The return value of these two functions is ignored. - - ``count`` should return the number of blocks available on the device. - ``sync``, if implemented, should sync the data on the device. - - The parameter ``mountpoint`` is the location in the root of the filesystem - to mount the device. It must begin with a forward-slash. - - If ``readonly`` is ``True``, then the device is mounted read-only, - otherwise it is mounted read-write. - - If ``mkfs`` is ``True``, then a new filesystem is created if one does not - already exist. - - To unmount a device, pass ``None`` as the device and the mount location - as ``mountpoint``. - -.. function:: repl_uart(uart) - - Get or set the UART object where the REPL is repeated on. - -.. only:: port_pyboard - - .. function:: rng() - - Return a 30-bit hardware generated random number. - -.. function:: sync() - - Sync all file systems. - -.. only:: port_pyboard - - .. function:: unique_id() - - Returns a string of 12 bytes (96 bits), which is the unique ID of the MCU. - -.. function:: usb_mode([modestr], vid=0xf055, pid=0x9801, hid=pyb.hid_mouse) - - If called with no arguments, return the current USB mode as a string. - - If called with ``modestr`` provided, attempts to set USB mode. - This can only be done when called from ``boot.py`` before - :meth:`pyb.main()` has been called. The following values of - ``modestr`` are understood: - - - ``None``: disables USB - - ``'VCP'``: enable with VCP (Virtual COM Port) interface - - ``'VCP+MSC'``: enable with VCP and MSC (mass storage device class) - - ``'VCP+HID'``: enable with VCP and HID (human interface device) - - For backwards compatibility, ``'CDC'`` is understood to mean - ``'VCP'`` (and similarly for ``'CDC+MSC'`` and ``'CDC+HID'``). - - The ``vid`` and ``pid`` parameters allow you to specify the VID - (vendor id) and PID (product id). - - If enabling HID mode, you may also specify the HID details by - passing the ``hid`` keyword parameter. It takes a tuple of - (subclass, protocol, max packet length, polling interval, report - descriptor). By default it will set appropriate values for a USB - mouse. There is also a ``pyb.hid_keyboard`` constant, which is an - appropriate tuple for a USB keyboard. - -Classes -------- - -.. only:: port_pyboard - - .. toctree:: - :maxdepth: 1 - - pyb.Accel.rst - pyb.ADC.rst - pyb.CAN.rst - pyb.DAC.rst - pyb.ExtInt.rst - pyb.I2C.rst - pyb.LCD.rst - pyb.LED.rst - pyb.Pin.rst - pyb.RTC.rst - pyb.Servo.rst - pyb.SPI.rst - pyb.Switch.rst - pyb.Timer.rst - pyb.UART.rst - pyb.USB_HID.rst - pyb.USB_VCP.rst diff --git a/docs/library/sys.rst b/docs/library/sys.rst index d49577306e..de2ec2dcd2 100644 --- a/docs/library/sys.rst +++ b/docs/library/sys.rst @@ -1,10 +1,12 @@ :mod:`sys` -- system specific functions ======================================= +.. include:: ../templates/unsupported_in_circuitpython.inc + .. module:: sys :synopsis: system specific functions -|see_cpython_module| :mod:`python:sys`. +|see_cpython_module| :mod:`cpython:sys`. Functions --------- @@ -27,8 +29,7 @@ Functions ``traceback`` module in CPython. Unlike ``traceback.print_exception()``, this function takes just exception value instead of exception type, exception value, and traceback object; *file* argument should be - positional; further arguments are not supported. CPython-compatible - ``traceback`` module can be found in `micropython-lib`. + positional; further arguments are not supported. Constants --------- diff --git a/docs/library/ubinascii.rst b/docs/library/ubinascii.rst index 192d34514b..edf4a9fdf5 100644 --- a/docs/library/ubinascii.rst +++ b/docs/library/ubinascii.rst @@ -1,10 +1,12 @@ :mod:`ubinascii` -- binary/ASCII conversions ============================================ +.. include:: ../templates/unsupported_in_circuitpython.inc + .. module:: ubinascii :synopsis: binary/ASCII conversions -|see_cpython_module| :mod:`python:binascii`. +|see_cpython_module| :mod:`cpython:binascii`. This module implements conversions between binary data and various encodings of it in ASCII form (in both directions). diff --git a/docs/library/ucollections.rst b/docs/library/ucollections.rst index 96de67acc4..396ba3c87d 100644 --- a/docs/library/ucollections.rst +++ b/docs/library/ucollections.rst @@ -1,10 +1,12 @@ :mod:`ucollections` -- collection and container types ===================================================== +.. include:: ../templates/unsupported_in_circuitpython.inc + .. module:: ucollections :synopsis: collection and container types -|see_cpython_module| :mod:`python:collections`. +|see_cpython_module| :mod:`cpython:collections`. This module implements advanced collection and container types to hold/accumulate various objects. diff --git a/docs/library/uctypes.rst b/docs/library/uctypes.rst index 2a9c4dd5c0..55de9a0a24 100644 --- a/docs/library/uctypes.rst +++ b/docs/library/uctypes.rst @@ -1,6 +1,8 @@ :mod:`uctypes` -- access binary data in a structured way ======================================================== +.. include:: ../templates/unsupported_in_circuitpython.inc + .. module:: uctypes :synopsis: access binary data in a structured way @@ -13,7 +15,7 @@ sub-fields. .. seealso:: - Module :mod:`ustruct` + Module :mod:`struct` Standard Python way to access binary data structures (doesn't scale well to large and complex structures). diff --git a/docs/library/uerrno.rst b/docs/library/uerrno.rst index 0cdcc84487..72f71f0aac 100644 --- a/docs/library/uerrno.rst +++ b/docs/library/uerrno.rst @@ -1,13 +1,14 @@ :mod:`uerrno` -- system error codes =================================== +.. include:: ../templates/unsupported_in_circuitpython.inc + .. module:: uerrno :synopsis: system error codes -|see_cpython_module| :mod:`python:errno`. +|see_cpython_module| :mod:`cpython:errno`. This module provides access to symbolic error codes for `OSError` exception. -A particular inventory of codes depends on `MicroPython port`. Constants --------- @@ -15,12 +16,11 @@ Constants .. data:: EEXIST, EAGAIN, etc. Error codes, based on ANSI C/POSIX standard. All error codes start with - "E". As mentioned above, inventory of the codes depends on - `MicroPython port`. Errors are usually accessible as ``exc.args[0]`` - where `exc` is an instance of `OSError`. Usage example:: + "E". Errors are usually accessible as ``exc.args[0]`` + where ``exc`` is an instance of `OSError`. Usage example:: try: - uos.mkdir("my_dir") + os.mkdir("my_dir") except OSError as exc: if exc.args[0] == uerrno.EEXIST: print("Directory already exists") diff --git a/docs/library/uhashlib.rst b/docs/library/uhashlib.rst index 50ed658cc1..0f20413f75 100644 --- a/docs/library/uhashlib.rst +++ b/docs/library/uhashlib.rst @@ -1,10 +1,12 @@ :mod:`uhashlib` -- hashing algorithms ===================================== +.. include:: ../templates/unsupported_in_circuitpython.inc + .. module:: uhashlib :synopsis: hashing algorithms -|see_cpython_module| :mod:`python:hashlib`. +|see_cpython_module| :mod:`cpython:hashlib`. This module implements binary data hashing algorithms. The exact inventory of available algorithms depends on a board. Among the algorithms which may diff --git a/docs/library/uheapq.rst b/docs/library/uheapq.rst index f822f1e7f3..67da5f7380 100644 --- a/docs/library/uheapq.rst +++ b/docs/library/uheapq.rst @@ -1,10 +1,12 @@ :mod:`uheapq` -- heap queue algorithm ===================================== +.. include:: ../templates/unsupported_in_circuitpython.inc + .. module:: uheapq :synopsis: heap queue algorithm -|see_cpython_module| :mod:`python:heapq`. +|see_cpython_module| :mod:`cpython:heapq`. This module implements the heap queue algorithm. diff --git a/docs/library/uio.rst b/docs/library/uio.rst index 7042a9e376..5ae8b9ecba 100644 --- a/docs/library/uio.rst +++ b/docs/library/uio.rst @@ -1,10 +1,12 @@ :mod:`uio` -- input/output streams ================================== +.. include:: ../templates/unsupported_in_circuitpython.inc + .. module:: uio :synopsis: input/output streams -|see_cpython_module| :mod:`python:io`. +|see_cpython_module| :mod:`cpython:io`. This module contains additional types of stream (file-like) objects and helper functions. @@ -81,7 +83,7 @@ Functions Open a file. Builtin ``open()`` function is aliased to this function. All ports (which provide access to file system) are required to support - `mode` parameter, but support for other arguments vary by port. + ``mode`` parameter, but support for other arguments vary by port. Classes ------- diff --git a/docs/library/ujson.rst b/docs/library/ujson.rst index 0932d0ab55..080ee2d036 100644 --- a/docs/library/ujson.rst +++ b/docs/library/ujson.rst @@ -1,10 +1,12 @@ :mod:`ujson` -- JSON encoding and decoding ========================================== +.. include:: ../templates/unsupported_in_circuitpython.inc + .. module:: ujson :synopsis: JSON encoding and decoding -|see_cpython_module| :mod:`python:json`. +|see_cpython_module| :mod:`cpython:json`. This modules allows to convert between Python objects and the JSON data format. diff --git a/docs/library/uos.rst b/docs/library/uos.rst deleted file mode 100644 index 7c52c1eead..0000000000 --- a/docs/library/uos.rst +++ /dev/null @@ -1,96 +0,0 @@ -:mod:`uos` -- basic "operating system" services -=============================================== - -.. module:: uos - :synopsis: basic "operating system" services - -|see_cpython_module| :mod:`python:os`. - -The ``uos`` module contains functions for filesystem access and ``urandom`` -function. - -Functions ---------- - -.. function:: chdir(path) - - Change current directory. - -.. function:: getcwd() - - Get the current directory. - -.. function:: ilistdir([dir]) - - This function returns an iterator which then yields 3-tuples corresponding to - the entries in the directory that it is listing. With no argument it lists the - current directory, otherwise it lists the directory given by *dir*. - - The 3-tuples have the form *(name, type, inode)*: - - - *name* is a string (or bytes if *dir* is a bytes object) and is the name of - the entry; - - *type* is an integer that specifies the type of the entry, with 0x4000 for - directories and 0x8000 for regular files; - - *inode* is an integer corresponding to the inode of the file, and may be 0 - for filesystems that don't have such a notion. - -.. function:: listdir([dir]) - - With no argument, list the current directory. Otherwise list the given directory. - -.. function:: mkdir(path) - - Create a new directory. - -.. function:: remove(path) - - Remove a file. - -.. function:: rmdir(path) - - Remove a directory. - -.. function:: rename(old_path, new_path) - - Rename a file. - -.. function:: stat(path) - - Get the status of a file or directory. - -.. function:: statvfs(path) - - Get the status of a fileystem. - - Returns a tuple with the filesystem information in the following order: - - * ``f_bsize`` -- file system block size - * ``f_frsize`` -- fragment size - * ``f_blocks`` -- size of fs in f_frsize units - * ``f_bfree`` -- number of free blocks - * ``f_bavail`` -- number of free blocks for unpriviliged users - * ``f_files`` -- number of inodes - * ``f_ffree`` -- number of free inodes - * ``f_favail`` -- number of free inodes for unpriviliged users - * ``f_flag`` -- mount flags - * ``f_namemax`` -- maximum filename length - - Parameters related to inodes: ``f_files``, ``f_ffree``, ``f_avail`` - and the ``f_flags`` parameter may return ``0`` as they can be unavailable - in a port-specific implementation. - -.. function:: sync() - - Sync all filesystems. - -.. function:: urandom(n) - - Return a bytes object with n random bytes. Whenever possible, it is - generated by the hardware random number generator. - -.. function:: dupterm(stream_object) - - Duplicate or switch MicroPython terminal (the REPL) on the passed stream-like - object. The given object must implement the ``readinto()`` and ``write()`` - methods. If ``None`` is passed, previously set redirection is cancelled. diff --git a/docs/library/ure.rst b/docs/library/ure.rst index 67f4f54a1d..9adfce2f12 100644 --- a/docs/library/ure.rst +++ b/docs/library/ure.rst @@ -1,10 +1,12 @@ :mod:`ure` -- simple regular expressions ======================================== +.. include:: ../templates/unsupported_in_circuitpython.inc + .. module:: ure :synopsis: regular expressions -|see_cpython_module| :mod:`python:re`. +|see_cpython_module| :mod:`cpython:re`. This module implements regular expression operations. Regular expression syntax supported is a subset of CPython ``re`` module (and actually is diff --git a/docs/library/uselect.rst b/docs/library/uselect.rst index e330207dbd..2e2d7e5866 100644 --- a/docs/library/uselect.rst +++ b/docs/library/uselect.rst @@ -1,10 +1,12 @@ :mod:`uselect` -- wait for events on a set of streams ======================================================================== +.. include:: ../templates/unsupported_in_circuitpython.inc + .. module:: uselect :synopsis: wait for events on a set of streams -|see_cpython_module| :mod:`python:select`. +|see_cpython_module| :mod:`cpython:select`. This module provides functions to efficiently wait for events on multiple streams (select streams which are ready for operations). diff --git a/docs/library/usocket.rst b/docs/library/usocket.rst index 65e24e2662..85df66a5be 100644 --- a/docs/library/usocket.rst +++ b/docs/library/usocket.rst @@ -2,10 +2,12 @@ :mod:`usocket` -- socket module ******************************* +.. include:: ../templates/unsupported_in_circuitpython.inc + .. module:: usocket :synopsis: socket module -|see_cpython_module| :mod:`python:socket`. +|see_cpython_module| :mod:`cpython:socket`. This module provides access to the BSD socket interface. @@ -36,11 +38,7 @@ power) and portable way to work with addresses. However, ``socket`` module (note the difference with native MicroPython ``usocket`` module described here) provides CPython-compatible way to specify -addresses using tuples, as described below. Note that depending on a -`MicroPython port`, ``socket`` module can be builtin or need to be -installed from `micropython-lib` (as in the case of `MicroPython Unix port`), -and some ports still accept only numeric addresses in the tuple format, -and require to use `getaddrinfo` function to resolve domain names. +addresses using tuples, as described below. Summing up: @@ -60,8 +58,7 @@ Tuple address format for ``socket`` module: and *port* is an integer port number in the range 1-65535. *flowinfo* must be 0. *scopeid* is the interface scope identifier for link-local addresses. Note the domain names are not accepted as *ipv6_address*, - they should be resolved first using `usocket.getaddrinfo()`. Availability - of IPv6 support depends on a `MicroPython port`. + they should be resolved first using `usocket.getaddrinfo()`. Functions --------- @@ -72,8 +69,8 @@ Functions .. function:: getaddrinfo(host, port) - Translate the host/port argument into a sequence of 5-tuples that contain all the - necessary arguments for creating a socket connected to that service. The list of + Translate the host/port argument into a sequence of 5-tuples that contain all the + necessary arguments for creating a socket connected to that service. The list of 5-tuples has following structure:: (family, type, proto, canonname, sockaddr) @@ -90,7 +87,7 @@ Functions of error in this function. MicroPython doesn't have ``socket.gaierror`` and raises OSError directly. Note that error numbers of `getaddrinfo()` form a separate namespace and may not match error numbers from - `uerrno` module. To distinguish `getaddrinfo()` errors, they are + :py:mod:`uerrno` module. To distinguish `getaddrinfo()` errors, they are represented by negative numbers, whereas standard system errors are positive numbers (error numbers are accessible using ``e.args[0]`` property from an exception object). The use of negative values is a provisional @@ -142,7 +139,7 @@ Methods on the socket object will fail. The remote end will receive EOF indication if supported by protocol. - Sockets are automatically closed when they are garbage-collected, but it is recommended + Sockets are automatically closed when they are garbage-collected, but it is recommended to `close()` them explicitly as soon you finished working with them. .. method:: socket.bind(address) diff --git a/docs/library/ussl.rst b/docs/library/ussl.rst index c71b283ccb..e45bd23a2c 100644 --- a/docs/library/ussl.rst +++ b/docs/library/ussl.rst @@ -1,10 +1,12 @@ :mod:`ussl` -- SSL/TLS module ============================= +.. include:: ../templates/unsupported_in_circuitpython.inc + .. module:: ussl :synopsis: TLS/SSL wrapper for socket objects -|see_cpython_module| :mod:`python:ssl`. +|see_cpython_module| :mod:`cpython:ssl`. This module provides access to Transport Layer Security (previously and widely known as “Secure Sockets Layerâ€) encryption and peer authentication @@ -18,8 +20,8 @@ Functions Takes a stream *sock* (usually usocket.socket instance of ``SOCK_STREAM`` type), and returns an instance of ssl.SSLSocket, which wraps the underlying stream in an SSL context. Returned object has the usual stream interface methods like - `read()`, `write()`, etc. In MicroPython, the returned object does not expose - socket interface and methods like `recv()`, `send()`. In particular, a + ``read()``, ``write()``, etc. In MicroPython, the returned object does not expose + socket interface and methods like ``recv()``, ``send()``. In particular, a server-side SSL socket should be created from a normal socket returned from `accept()` on a non-SSL listening server socket. diff --git a/docs/library/ustruct.rst b/docs/library/ustruct.rst index 81915d0a8d..c378a94bbe 100644 --- a/docs/library/ustruct.rst +++ b/docs/library/ustruct.rst @@ -1,10 +1,12 @@ :mod:`ustruct` -- pack and unpack primitive data types ====================================================== +.. include:: ../templates/unsupported_in_circuitpython.inc + .. module:: ustruct :synopsis: pack and unpack primitive data types -|see_cpython_module| :mod:`python:struct`. +|see_cpython_module| :mod:`cpython:struct`. Supported size/byte order prefixes: ``@``, ``<``, ``>``, ``!``. diff --git a/docs/library/utime.rst b/docs/library/utime.rst deleted file mode 100644 index a39f5ee733..0000000000 --- a/docs/library/utime.rst +++ /dev/null @@ -1,229 +0,0 @@ -:mod:`utime` -- time related functions -====================================== - -.. module:: utime - :synopsis: time related functions - -|see_cpython_module| :mod:`python:time`. - -The ``utime`` module provides functions for getting the current time and date, -measuring time intervals, and for delays. - -**Time Epoch**: Unix port uses standard for POSIX systems epoch of -1970-01-01 00:00:00 UTC. However, embedded ports use epoch of -2000-01-01 00:00:00 UTC. - -**Maintaining actual calendar date/time**: This requires a -Real Time Clock (RTC). On systems with underlying OS (including some -RTOS), an RTC may be implicit. Setting and maintaining actual calendar -time is responsibility of OS/RTOS and is done outside of MicroPython, -it just uses OS API to query date/time. On baremetal ports however -system time depends on ``machine.RTC()`` object. The current calendar time -may be set using ``machine.RTC().datetime(tuple)`` function, and maintained -by following means: - -* By a backup battery (which may be an additional, optional component for - a particular board). -* Using networked time protocol (requires setup by a port/user). -* Set manually by a user on each power-up (many boards then maintain - RTC time across hard resets, though some may require setting it again - in such case). - -If actual calendar time is not maintained with a system/MicroPython RTC, -functions below which require reference to current absolute time may -behave not as expected. - -Functions ---------- - -.. function:: localtime([secs]) - - Convert a time expressed in seconds since the Epoch (see above) into an 8-tuple which - contains: (year, month, mday, hour, minute, second, weekday, yearday) - If secs is not provided or None, then the current time from the RTC is used. - - * year includes the century (for example 2014). - * month is 1-12 - * mday is 1-31 - * hour is 0-23 - * minute is 0-59 - * second is 0-59 - * weekday is 0-6 for Mon-Sun - * yearday is 1-366 - -.. function:: mktime() - - This is inverse function of localtime. It's argument is a full 8-tuple - which expresses a time as per localtime. It returns an integer which is - the number of seconds since Jan 1, 2000. - -.. function:: sleep(seconds) - - Sleep for the given number of seconds. Some boards may accept *seconds* as a - floating-point number to sleep for a fractional number of seconds. Note that - other boards may not accept a floating-point argument, for compatibility with - them use `sleep_ms()` and `sleep_us()` functions. - -.. function:: sleep_ms(ms) - - Delay for given number of milliseconds, should be positive or 0. - -.. function:: sleep_us(us) - - Delay for given number of microseconds, should be positive or 0. - -.. function:: ticks_ms() - - Returns an increasing millisecond counter with an arbitrary reference point, that - wraps around after some value. - - The wrap-around value is not explicitly exposed, but we will - refer to it as *TICKS_MAX* to simplify discussion. Period of the values is - *TICKS_PERIOD = TICKS_MAX + 1*. *TICKS_PERIOD* is guaranteed to be a power of - two, but otherwise may differ from port to port. The same period value is used - for all of `ticks_ms()`, `ticks_us()`, `ticks_cpu()` functions (for - simplicity). Thus, these functions will return a value in range [*0* .. - *TICKS_MAX*], inclusive, total *TICKS_PERIOD* values. Note that only - non-negative values are used. For the most part, you should treat values returned - by these functions as opaque. The only operations available for them are - `ticks_diff()` and `ticks_add()` functions described below. - - Note: Performing standard mathematical operations (+, -) or relational - operators (<, <=, >, >=) directly on these value will lead to invalid - result. Performing mathematical operations and then passing their results - as arguments to `ticks_diff()` or `ticks_add()` will also lead to - invalid results from the latter functions. - -.. function:: ticks_us() - - Just like `ticks_ms()` above, but in microseconds. - -.. function:: ticks_cpu() - - Similar to `ticks_ms()` and `ticks_us()`, but with the highest possible resolution - in the system. This is usually CPU clocks, and that's why the function is named that - way. But it doesn't have to be a CPU clock, some other timing source available in a - system (e.g. high-resolution timer) can be used instead. The exact timing unit - (resolution) of this function is not specified on ``utime`` module level, but - documentation for a specific port may provide more specific information. This - function is intended for very fine benchmarking or very tight real-time loops. - Avoid using it in portable code. - - Availability: Not every port implements this function. - - -.. function:: ticks_add(ticks, delta) - - Offset ticks value by a given number, which can be either positive or negative. - Given a *ticks* value, this function allows to calculate ticks value *delta* - ticks before or after it, following modular-arithmetic definition of tick values - (see `ticks_ms()` above). *ticks* parameter must be a direct result of call - to `ticks_ms()`, `ticks_us()`, or `ticks_cpu()` functions (or from previous - call to `ticks_add()`). However, *delta* can be an arbitrary integer number - or numeric expression. `ticks_add()` is useful for calculating deadlines for - events/tasks. (Note: you must use `ticks_diff()` function to work with - deadlines.) - - Examples:: - - # Find out what ticks value there was 100ms ago - print(ticks_add(time.ticks_ms(), -100)) - - # Calculate deadline for operation and test for it - deadline = ticks_add(time.ticks_ms(), 200) - while ticks_diff(deadline, time.ticks_ms()) > 0: - do_a_little_of_something() - - # Find out TICKS_MAX used by this port - print(ticks_add(0, -1)) - - -.. function:: ticks_diff(ticks1, ticks2) - - Measure ticks difference between values returned from `ticks_ms()`, `ticks_us()`, - or `ticks_cpu()` functions, as a signed value which may wrap around. - - The argument order is the same as for subtraction - operator, ``ticks_diff(ticks1, ticks2)`` has the same meaning as ``ticks1 - ticks2``. - However, values returned by `ticks_ms()`, etc. functions may wrap around, so - directly using subtraction on them will produce incorrect result. That is why - `ticks_diff()` is needed, it implements modular (or more specifically, ring) - arithmetics to produce correct result even for wrap-around values (as long as they not - too distant inbetween, see below). The function returns **signed** value in the range - [*-TICKS_PERIOD/2* .. *TICKS_PERIOD/2-1*] (that's a typical range definition for - two's-complement signed binary integers). If the result is negative, it means that - *ticks1* occurred earlier in time than *ticks2*. Otherwise, it means that - *ticks1* occurred after *ticks2*. This holds **only** if *ticks1* and *ticks2* - are apart from each other for no more than *TICKS_PERIOD/2-1* ticks. If that does - not hold, incorrect result will be returned. Specifically, if two tick values are - apart for *TICKS_PERIOD/2-1* ticks, that value will be returned by the function. - However, if *TICKS_PERIOD/2* of real-time ticks has passed between them, the - function will return *-TICKS_PERIOD/2* instead, i.e. result value will wrap around - to the negative range of possible values. - - Informal rationale of the constraints above: Suppose you are locked in a room with no - means to monitor passing of time except a standard 12-notch clock. Then if you look at - dial-plate now, and don't look again for another 13 hours (e.g., if you fall for a - long sleep), then once you finally look again, it may seem to you that only 1 hour - has passed. To avoid this mistake, just look at the clock regularly. Your application - should do the same. "Too long sleep" metaphor also maps directly to application - behavior: don't let your application run any single task for too long. Run tasks - in steps, and do time-keeping inbetween. - - `ticks_diff()` is designed to accommodate various usage patterns, among them: - - * Polling with timeout. In this case, the order of events is known, and you will deal - only with positive results of `ticks_diff()`:: - - # Wait for GPIO pin to be asserted, but at most 500us - start = time.ticks_us() - while pin.value() == 0: - if time.ticks_diff(time.ticks_us(), start) > 500: - raise TimeoutError - - * Scheduling events. In this case, `ticks_diff()` result may be negative - if an event is overdue:: - - # This code snippet is not optimized - now = time.ticks_ms() - scheduled_time = task.scheduled_time() - if ticks_diff(now, scheduled_time) > 0: - print("Too early, let's nap") - sleep_ms(ticks_diff(now, scheduled_time)) - task.run() - elif ticks_diff(now, scheduled_time) == 0: - print("Right at time!") - task.run() - elif ticks_diff(now, scheduled_time) < 0: - print("Oops, running late, tell task to run faster!") - task.run(run_faster=true) - - Note: Do not pass `time()` values to `ticks_diff()`, you should use - normal mathematical operations on them. But note that `time()` may (and will) - also overflow. This is known as https://en.wikipedia.org/wiki/Year_2038_problem . - - -.. function:: time() - - Returns the number of seconds, as an integer, since the Epoch, assuming that - underlying RTC is set and maintained as described above. If an RTC is not set, this - function returns number of seconds since a port-specific reference point in time (for - embedded boards without a battery-backed RTC, usually since power up or reset). If you - want to develop portable MicroPython application, you should not rely on this function - to provide higher than second precision. If you need higher precision, use - `ticks_ms()` and `ticks_us()` functions, if you need calendar time, - `localtime()` without an argument is a better choice. - - .. admonition:: Difference to CPython - :class: attention - - In CPython, this function returns number of - seconds since Unix epoch, 1970-01-01 00:00 UTC, as a floating-point, - usually having microsecond precision. With MicroPython, only Unix port - uses the same Epoch, and if floating-point precision allows, - returns sub-second precision. Embedded hardware usually doesn't have - floating-point precision to represent both long time ranges and subsecond - precision, so they use integer value with second precision. Some embedded - hardware also lacks battery-powered RTC, so returns number of seconds - since last power-up or from other relative, hardware-specific point - (e.g. reset). diff --git a/docs/library/uzlib.rst b/docs/library/uzlib.rst index fb1746fe8e..2a2d9668c4 100644 --- a/docs/library/uzlib.rst +++ b/docs/library/uzlib.rst @@ -1,10 +1,12 @@ :mod:`uzlib` -- zlib decompression ================================== +.. include:: ../templates/unsupported_in_circuitpython.inc + .. module:: uzlib :synopsis: zlib decompression -|see_cpython_module| :mod:`python:zlib`. +|see_cpython_module| :mod:`cpython:zlib`. This module allows to decompress binary data compressed with `DEFLATE algorithm `_ diff --git a/docs/library/wipy.rst b/docs/library/wipy.rst deleted file mode 100644 index cdece7b82b..0000000000 --- a/docs/library/wipy.rst +++ /dev/null @@ -1,17 +0,0 @@ -************************************* -:mod:`wipy` -- WiPy specific features -************************************* - -.. module:: wipy - :synopsis: WiPy specific features - -The ``wipy`` module contains functions to control specific features of the -WiPy, such as the heartbeat LED. - -Functions ---------- - -.. function:: heartbeat([enable]) - - Get or set the state (enabled or disabled) of the heartbeat LED. Accepts and - returns boolean values (``True`` or ``False``). diff --git a/docs/pyboard/general.rst b/docs/pyboard/general.rst deleted file mode 100644 index 97e9aabc0b..0000000000 --- a/docs/pyboard/general.rst +++ /dev/null @@ -1,80 +0,0 @@ -General information about the pyboard -===================================== - -.. contents:: - -Local filesystem and SD card ----------------------------- - -There is a small internal filesystem (a drive) on the pyboard, called ``/flash``, -which is stored within the microcontroller's flash memory. If a micro SD card -is inserted into the slot, it is available as ``/sd``. - -When the pyboard boots up, it needs to choose a filesystem to boot from. If -there is no SD card, then it uses the internal filesystem ``/flash`` as the boot -filesystem, otherwise, it uses the SD card ``/sd``. After the boot, the current -directory is set to one of the directories above. - -If needed, you can prevent the use of the SD card by creating an empty file -called ``/flash/SKIPSD``. If this file exists when the pyboard boots -up then the SD card will be skipped and the pyboard will always boot from the -internal filesystem (in this case the SD card won't be mounted but you can still -mount and use it later in your program using ``os.mount``). - -(Note that on older versions of the board, ``/flash`` is called ``0:/`` and ``/sd`` -is called ``1:/``). - -The boot filesystem is used for 2 things: it is the filesystem from which -the ``boot.py`` and ``main.py`` files are searched for, and it is the filesystem -which is made available on your PC over the USB cable. - -The filesystem will be available as a USB flash drive on your PC. You can -save files to the drive, and edit ``boot.py`` and ``main.py``. - -*Remember to eject (on Linux, unmount) the USB drive before you reset your -pyboard.* - -Boot modes ----------- - -If you power up normally, or press the reset button, the pyboard will boot -into standard mode: the ``boot.py`` file will be executed first, then the -USB will be configured, then ``main.py`` will run. - -You can override this boot sequence by holding down the user switch as -the board is booting up. Hold down user switch and press reset, and then -as you continue to hold the user switch, the LEDs will count in binary. -When the LEDs have reached the mode you want, let go of the user switch, -the LEDs for the selected mode will flash quickly, and the board will boot. - -The modes are: - -1. Green LED only, *standard boot*: run ``boot.py`` then ``main.py``. -2. Orange LED only, *safe boot*: don't run any scripts on boot-up. -3. Green and orange LED together, *filesystem reset*: resets the flash - filesystem to its factory state, then boots in safe mode. - -If your filesystem becomes corrupt, boot into mode 3 to fix it. -If resetting the filesystem while plugged into your compute doesn't work, -you can try doing the same procedure while the board is plugged into a USB -charger, or other USB power supply without data connection. - -Errors: flashing LEDs ---------------------- - -There are currently 2 kinds of errors that you might see: - -1. If the red and green LEDs flash alternatively, then a Python script - (eg ``main.py``) has an error. Use the REPL to debug it. -2. If all 4 LEDs cycle on and off slowly, then there was a hard fault. - This cannot be recovered from and you need to do a hard reset. - -Guide for using the pyboard with Windows ----------------------------------------- - -The following PDF guide gives information about using the pyboard with Windows, -including setting up the serial prompt and downloading new firmware using -DFU programming: -`PDF guide `__. - -.. include:: hardware/index.rst diff --git a/docs/pyboard/hardware/index.rst b/docs/pyboard/hardware/index.rst deleted file mode 100644 index 91fea24e7a..0000000000 --- a/docs/pyboard/hardware/index.rst +++ /dev/null @@ -1,30 +0,0 @@ -.. _hardware_index: - -The pyboard hardware --------------------- - -For the pyboard: - -* `PYBv1.0 schematics and layout `_ (2.4MiB PDF) -* `PYBv1.0 metric dimensions `_ (360KiB PDF) -* `PYBv1.0 imperial dimensions `_ (360KiB PDF) - -For the official skin modules: - -* `LCD32MKv1.0 schematics `_ (194KiB PDF) -* `AMPv1.0 schematics `_ (209KiB PDF) -* LCD160CRv1.0: see :mod:`lcd160cr` - -Datasheets for the components on the pyboard --------------------------------------------- - -* The microcontroller: `STM32F405RGT6 `_ (link to manufacturer's site) -* The accelerometer: `Freescale MMA7660 `_ (800kiB PDF) -* The LDO voltage regulator: `Microchip MCP1802 `_ (400kiB PDF) - -Datasheets for other components -------------------------------- - -* The LCD display on the LCD touch-sensor skin: `Newhaven Display NHD-C12832A1Z-FSW-FBW-3V3 `_ (460KiB PDF) -* The touch sensor chip on the LCD touch-sensor skin: `Freescale MPR121 `_ (280KiB PDF) -* The digital potentiometer on the audio skin: `Microchip MCP4541 `_ (2.7MiB PDF) diff --git a/docs/pyboard/index.rst b/docs/pyboard/index.rst deleted file mode 100644 index c05e5d47fe..0000000000 --- a/docs/pyboard/index.rst +++ /dev/null @@ -1,9 +0,0 @@ -PyBoard -======================================== - -.. toctree:: - - quickref.rst - general.rst - tutorial/index.rst - hardware/index.rst diff --git a/docs/pyboard/quickref.rst b/docs/pyboard/quickref.rst deleted file mode 100644 index 5690dddb0c..0000000000 --- a/docs/pyboard/quickref.rst +++ /dev/null @@ -1,169 +0,0 @@ -.. _quickref: - -Quick reference for the pyboard -=============================== - -The below pinout is for PYBv1.0. You can also view pinouts for -other versions of the pyboard: -`PYBv1.1 `__ -or `PYBLITEv1.0-AC `__ -or `PYBLITEv1.0 `__. - -.. image:: http://micropython.org/resources/pybv10-pinout.jpg - :alt: PYBv1.0 pinout - :width: 700px - -General board control ---------------------- - -See :mod:`pyb`. :: - - import pyb - - pyb.repl_uart(pyb.UART(1, 9600)) # duplicate REPL on UART(1) - pyb.wfi() # pause CPU, waiting for interrupt - pyb.freq() # get CPU and bus frequencies - pyb.freq(60000000) # set CPU freq to 60MHz - pyb.stop() # stop CPU, waiting for external interrupt - -Delay and timing ----------------- - -Use the :mod:`time ` module:: - - import time - - time.sleep(1) # sleep for 1 second - time.sleep_ms(500) # sleep for 500 milliseconds - time.sleep_us(10) # sleep for 10 microseconds - start = time.ticks_ms() # get value of millisecond counter - delta = time.ticks_diff(time.ticks_ms(), start) # compute time difference - -LEDs ----- - -See :ref:`pyb.LED `. :: - - from pyb import LED - - led = LED(1) # red led - led.toggle() - led.on() - led.off() - -Pins and GPIO -------------- - -See :ref:`pyb.Pin `. :: - - from pyb import Pin - - p_out = Pin('X1', Pin.OUT_PP) - p_out.high() - p_out.low() - - p_in = Pin('X2', Pin.IN, Pin.PULL_UP) - p_in.value() # get value, 0 or 1 - -Servo control -------------- - -See :ref:`pyb.Servo `. :: - - from pyb import Servo - - s1 = Servo(1) # servo on position 1 (X1, VIN, GND) - s1.angle(45) # move to 45 degrees - s1.angle(-60, 1500) # move to -60 degrees in 1500ms - s1.speed(50) # for continuous rotation servos - -External interrupts -------------------- - -See :ref:`pyb.ExtInt `. :: - - from pyb import Pin, ExtInt - - callback = lambda e: print("intr") - ext = ExtInt(Pin('Y1'), ExtInt.IRQ_RISING, Pin.PULL_NONE, callback) - -Timers ------- - -See :ref:`pyb.Timer `. :: - - from pyb import Timer - - tim = Timer(1, freq=1000) - tim.counter() # get counter value - tim.freq(0.5) # 0.5 Hz - tim.callback(lambda t: pyb.LED(1).toggle()) - -PWM (pulse width modulation) ----------------------------- - -See :ref:`pyb.Pin ` and :ref:`pyb.Timer `. :: - - from pyb import Pin, Timer - - p = Pin('X1') # X1 has TIM2, CH1 - tim = Timer(2, freq=1000) - ch = tim.channel(1, Timer.PWM, pin=p) - ch.pulse_width_percent(50) - -ADC (analog to digital conversion) ----------------------------------- - -See :ref:`pyb.Pin ` and :ref:`pyb.ADC `. :: - - from pyb import Pin, ADC - - adc = ADC(Pin('X19')) - adc.read() # read value, 0-4095 - -DAC (digital to analog conversion) ----------------------------------- - -See :ref:`pyb.Pin ` and :ref:`pyb.DAC `. :: - - from pyb import Pin, DAC - - dac = DAC(Pin('X5')) - dac.write(120) # output between 0 and 255 - -UART (serial bus) ------------------ - -See :ref:`pyb.UART `. :: - - from pyb import UART - - uart = UART(1, 9600) - uart.write('hello') - uart.read(5) # read up to 5 bytes - -SPI bus -------- - -See :ref:`pyb.SPI `. :: - - from pyb import SPI - - spi = SPI(1, SPI.MASTER, baudrate=200000, polarity=1, phase=0) - spi.send('hello') - spi.recv(5) # receive 5 bytes on the bus - spi.send_recv('hello') # send and receive 5 bytes - -I2C bus -------- - -See :ref:`pyb.I2C `. :: - - from pyb import I2C - - i2c = I2C(1, I2C.MASTER, baudrate=100000) - i2c.scan() # returns list of slave addresses - i2c.send('hello', 0x42) # send 5 bytes to slave with address 0x42 - i2c.recv(5, 0x42) # receive 5 bytes from slave - i2c.mem_read(2, 0x42, 0x10) # read 2 bytes from slave 0x42, slave memory 0x10 - i2c.mem_write('xy', 0x42, 0x10) # write 2 bytes to slave 0x42, slave memory 0x10 diff --git a/docs/pyboard/tutorial/accel.rst b/docs/pyboard/tutorial/accel.rst deleted file mode 100644 index 58170e74ff..0000000000 --- a/docs/pyboard/tutorial/accel.rst +++ /dev/null @@ -1,92 +0,0 @@ -The accelerometer -================= - -Here you will learn how to read the accelerometer and signal using LEDs states like tilt left and tilt right. - -Using the accelerometer ------------------------ - -The pyboard has an accelerometer (a tiny mass on a tiny spring) that can be used -to detect the angle of the board and motion. There is a different sensor for -each of the x, y, z directions. To get the value of the accelerometer, create a -pyb.Accel() object and then call the x() method. :: - - >>> accel = pyb.Accel() - >>> accel.x() - 7 - -This returns a signed integer with a value between around -30 and 30. Note that -the measurement is very noisy, this means that even if you keep the board -perfectly still there will be some variation in the number that you measure. -Because of this, you shouldn't use the exact value of the x() method but see if -it is in a certain range. - -We will start by using the accelerometer to turn on a light if it is not flat. :: - - accel = pyb.Accel() - light = pyb.LED(3) - SENSITIVITY = 3 - - while True: - x = accel.x() - if abs(x) > SENSITIVITY: - light.on() - else: - light.off() - - pyb.delay(100) - -We create Accel and LED objects, then get the value of the x direction of the -accelerometer. If the magnitude of x is bigger than a certain value ``SENSITIVITY``, -then the LED turns on, otherwise it turns off. The loop has a small ``pyb.delay()`` -otherwise the LED flashes annoyingly when the value of x is close to -``SENSITIVITY``. Try running this on the pyboard and tilt the board left and right -to make the LED turn on and off. - -**Exercise: Change the above script so that the blue LED gets brighter the more -you tilt the pyboard. HINT: You will need to rescale the values, intensity goes -from 0-255.** - -Making a spirit level ---------------------- - -The example above is only sensitive to the angle in the x direction but if we -use the ``y()`` value and more LEDs we can turn the pyboard into a spirit level. :: - - xlights = (pyb.LED(2), pyb.LED(3)) - ylights = (pyb.LED(1), pyb.LED(4)) - - accel = pyb.Accel() - SENSITIVITY = 3 - - while True: - x = accel.x() - if x > SENSITIVITY: - xlights[0].on() - xlights[1].off() - elif x < -SENSITIVITY: - xlights[1].on() - xlights[0].off() - else: - xlights[0].off() - xlights[1].off() - - y = accel.y() - if y > SENSITIVITY: - ylights[0].on() - ylights[1].off() - elif y < -SENSITIVITY: - ylights[1].on() - ylights[0].off() - else: - ylights[0].off() - ylights[1].off() - - pyb.delay(100) - -We start by creating a tuple of LED objects for the x and y directions. Tuples -are immutable objects in python which means they can't be modified once they are -created. We then proceed as before but turn on a different LED for positive and -negative x values. We then do the same for the y direction. This isn't -particularly sophisticated but it does the job. Run this on your pyboard and you -should see different LEDs turning on depending on how you tilt the board. diff --git a/docs/pyboard/tutorial/amp_skin.rst b/docs/pyboard/tutorial/amp_skin.rst deleted file mode 100644 index 697637f9d2..0000000000 --- a/docs/pyboard/tutorial/amp_skin.rst +++ /dev/null @@ -1,98 +0,0 @@ -The AMP audio skin -================== - -Soldering and using the AMP audio skin. - -.. image:: img/skin_amp_1.jpg - :alt: AMP skin - :width: 250px - -.. image:: img/skin_amp_2.jpg - :alt: AMP skin - :width: 250px - -The following video shows how to solder the headers, microphone and speaker onto the AMP skin. - -.. raw:: html - - - -For circuit schematics and datasheets for the components on the skin see :ref:`hardware_index`. - -Example code ------------- - -The AMP skin has a speaker which is connected to ``DAC(1)`` via a small -power amplifier. The volume of the amplifier is controlled by a digital -potentiometer, which is an I2C device with address 46 on the ``IC2(1)`` bus. - -To set the volume, define the following function:: - - import pyb - def volume(val): - pyb.I2C(1, pyb.I2C.MASTER).mem_write(val, 46, 0) - -Then you can do:: - - >>> volume(0) # minimum volume - >>> volume(127) # maximum volume - -To play a sound, use the ``write_timed`` method of the ``DAC`` object. -For example:: - - import math - from pyb import DAC - - # create a buffer containing a sine-wave - buf = bytearray(100) - for i in range(len(buf)): - buf[i] = 128 + int(127 * math.sin(2 * math.pi * i / len(buf))) - - # output the sine-wave at 400Hz - dac = DAC(1) - dac.write_timed(buf, 400 * len(buf), mode=DAC.CIRCULAR) - -You can also play WAV files using the Python ``wave`` module. You can get -the wave module `here `__ and you will also need -the chunk module available `here `__. Put these -on your pyboard (either on the flash or the SD card in the top-level directory). You will need an -8-bit WAV file to play, such as `this one `_, -or to convert any file you have with the command:: - - avconv -i original.wav -ar 22050 -codec pcm_u8 test.wav - -Then you can do:: - - >>> import wave - >>> from pyb import DAC - >>> dac = DAC(1) - >>> f = wave.open('test.wav') - >>> dac.write_timed(f.readframes(f.getnframes()), f.getframerate()) - -This should play the WAV file. Note that this will read the whole file into RAM -so it has to be small enough to fit in it. - -To play larger wave files you will have to use the micro-SD card to store it. -Also the file must be read and sent to the DAC in small chunks that will fit -the RAM limit of the microcontroller. Here is an example function that can -play 8-bit wave files with up to 16kHz sampling:: - - import wave - from pyb import DAC - from pyb import delay - dac = DAC(1) - - def play(filename): - f = wave.open(filename, 'r') - total_frames = f.getnframes() - framerate = f.getframerate() - - for position in range(0, total_frames, framerate): - f.setpos(position) - dac.write_timed(f.readframes(framerate), framerate) - delay(1000) - -This function reads one second worth of data and sends it to DAC. It then waits -one second and moves the file cursor to the new position to read the next second -of data in the next iteration of the for-loop. It plays one second of audio at -a time every one second. diff --git a/docs/pyboard/tutorial/assembler.rst b/docs/pyboard/tutorial/assembler.rst deleted file mode 100644 index 1fe2bc4b07..0000000000 --- a/docs/pyboard/tutorial/assembler.rst +++ /dev/null @@ -1,131 +0,0 @@ -.. _pyboard_tutorial_assembler: - -Inline assembler -================ - -Here you will learn how to write inline assembler in MicroPython. - -**Note**: this is an advanced tutorial, intended for those who already -know a bit about microcontrollers and assembly language. - -MicroPython includes an inline assembler. It allows you to write -assembly routines as a Python function, and you can call them as you would -a normal Python function. - -Returning a value ------------------ - -Inline assembler functions are denoted by a special function decorator. -Let's start with the simplest example:: - - @micropython.asm_thumb - def fun(): - movw(r0, 42) - -You can enter this in a script or at the REPL. This function takes no -arguments and returns the number 42. ``r0`` is a register, and the value -in this register when the function returns is the value that is returned. -MicroPython always interprets the ``r0`` as an integer, and converts it to an -integer object for the caller. - -If you run ``print(fun())`` you will see it print out 42. - -Accessing peripherals ---------------------- - -For something a bit more complicated, let's turn on an LED:: - - @micropython.asm_thumb - def led_on(): - movwt(r0, stm.GPIOA) - movw(r1, 1 << 13) - strh(r1, [r0, stm.GPIO_BSRRL]) - -This code uses a few new concepts: - - - ``stm`` is a module which provides a set of constants for easy - access to the registers of the pyboard's microcontroller. Try - running ``import stm`` and then ``help(stm)`` at the REPL. It will - give you a list of all the available constants. - - - ``stm.GPIOA`` is the address in memory of the GPIOA peripheral. - On the pyboard, the red LED is on port A, pin PA13. - - - ``movwt`` moves a 32-bit number into a register. It is a convenience - function that turns into 2 thumb instructions: ``movw`` followed by ``movt``. - The ``movt`` also shifts the immediate value right by 16 bits. - - - ``strh`` stores a half-word (16 bits). The instruction above stores - the lower 16-bits of ``r1`` into the memory location ``r0 + stm.GPIO_BSRRL``. - This has the effect of setting high all those pins on port A for which - the corresponding bit in ``r0`` is set. In our example above, the 13th - bit in ``r0`` is set, so PA13 is pulled high. This turns on the red LED. - -Accepting arguments -------------------- - -Inline assembler functions can accept up to 4 arguments. If they are -used, they must be named ``r0``, ``r1``, ``r2`` and ``r3`` to reflect the registers -and the calling conventions. - -Here is a function that adds its arguments:: - - @micropython.asm_thumb - def asm_add(r0, r1): - add(r0, r0, r1) - -This performs the computation ``r0 = r0 + r1``. Since the result is put -in ``r0``, that is what is returned. Try ``asm_add(1, 2)``, it should return -3. - -Loops ------ - -We can assign labels with ``label(my_label)``, and branch to them using -``b(my_label)``, or a conditional branch like ``bgt(my_label)``. - -The following example flashes the green LED. It flashes it ``r0`` times. :: - - @micropython.asm_thumb - def flash_led(r0): - # get the GPIOA address in r1 - movwt(r1, stm.GPIOA) - - # get the bit mask for PA14 (the pin LED #2 is on) - movw(r2, 1 << 14) - - b(loop_entry) - - label(loop1) - - # turn LED on - strh(r2, [r1, stm.GPIO_BSRRL]) - - # delay for a bit - movwt(r4, 5599900) - label(delay_on) - sub(r4, r4, 1) - cmp(r4, 0) - bgt(delay_on) - - # turn LED off - strh(r2, [r1, stm.GPIO_BSRRH]) - - # delay for a bit - movwt(r4, 5599900) - label(delay_off) - sub(r4, r4, 1) - cmp(r4, 0) - bgt(delay_off) - - # loop r0 times - sub(r0, r0, 1) - label(loop_entry) - cmp(r0, 0) - bgt(loop1) - -Further reading ---------------- - -For further information about supported instructions of the inline assembler, -see the :ref:`reference documentation `. diff --git a/docs/pyboard/tutorial/debounce.rst b/docs/pyboard/tutorial/debounce.rst deleted file mode 100644 index f730e1d340..0000000000 --- a/docs/pyboard/tutorial/debounce.rst +++ /dev/null @@ -1,37 +0,0 @@ -Debouncing a pin input -====================== - -A pin used as input from a switch or other mechanical device can have a lot -of noise on it, rapidly changing from low to high when the switch is first -pressed or released. This noise can be eliminated using a capacitor (a -debouncing circuit). It can also be eliminated using a simple function that -makes sure the value on the pin is stable. - -The following function does just this. It gets the current value of the given -pin, and then waits for the value to change. The new pin value must be stable -for a continuous 20ms for it to register the change. You can adjust this time -(to say 50ms) if you still have noise. :: - - import pyb - - def wait_pin_change(pin): - # wait for pin to change value - # it needs to be stable for a continuous 20ms - cur_value = pin.value() - active = 0 - while active < 20: - if pin.value() != cur_value: - active += 1 - else: - active = 0 - pyb.delay(1) - - -Use it something like this:: - - import pyb - - pin_x1 = pyb.Pin('X1', pyb.Pin.IN, pyb.Pin.PULL_DOWN) - while True: - wait_pin_change(pin_x1) - pyb.LED(4).toggle() diff --git a/docs/pyboard/tutorial/fading_led.rst b/docs/pyboard/tutorial/fading_led.rst deleted file mode 100644 index 0a4b5c5039..0000000000 --- a/docs/pyboard/tutorial/fading_led.rst +++ /dev/null @@ -1,89 +0,0 @@ -Fading LEDs -=========== - -In addition to turning LEDs on and off, it is also possible to control the brightness of an LED using `Pulse-Width Modulation (PWM) `_, a common technique for obtaining variable output from a digital pin. This allows us to fade an LED: - -.. image:: http://upload.wikimedia.org/wikipedia/commons/a/a9/Fade.gif - -Components ----------- - -You will need: - -- Standard 5 or 3 mm LED -- 100 Ohm resistor -- Wires -- `Breadboard `_ (optional, but makes things easier) - -Connecting Things Up --------------------- - -For this tutorial, we will use the ``X1`` pin. Connect one end of the resistor to ``X1``, and the other end to the **anode** of the LED, which is the longer leg. Connect the **cathode** of the LED to ground. - -.. image:: img/fading_leds_breadboard_fritzing.png - -Code ----- -By examining the :ref:`quickref`, we see that ``X1`` is connected to channel 1 of timer 5 (``TIM5 CH1``). Therefore we will first create a ``Timer`` object for timer 5, then create a ``TimerChannel`` object for channel 1:: - - from pyb import Timer - from time import sleep - - # timer 5 will be created with a frequency of 100 Hz - tim = pyb.Timer(5, freq=100) - tchannel = tim.channel(1, Timer.PWM, pin=pyb.Pin.board.X1, pulse_width=0) - -Brightness of the LED in PWM is controlled by controlling the pulse-width, that is the amount of time the LED is on every cycle. With a timer frequency of 100 Hz, each cycle takes 0.01 second, or 10 ms. - -To achieve the fading effect shown at the beginning of this tutorial, we want to set the pulse-width to a small value, then slowly increase the pulse-width to brighten the LED, and start over when we reach some maximum brightness:: - - # maximum and minimum pulse-width, which corresponds to maximum - # and minimum brightness - max_width = 200000 - min_width = 20000 - - # how much to change the pulse-width by each step - wstep = 1500 - cur_width = min_width - - while True: - tchannel.pulse_width(cur_width) - - # this determines how often we change the pulse-width. It is - # analogous to frames-per-second - sleep(0.01) - - cur_width += wstep - - if cur_width > max_width: - cur_width = min_width - -Breathing Effect ----------------- - -If we want to have a breathing effect, where the LED fades from dim to bright then bright to dim, then we simply need to reverse the sign of ``wstep`` when we reach maximum brightness, and reverse it again at minimum brightness. To do this we modify the ``while`` loop to be:: - - while True: - tchannel.pulse_width(cur_width) - - sleep(0.01) - - cur_width += wstep - - if cur_width > max_width: - cur_width = max_width - wstep *= -1 - elif cur_width < min_width: - cur_width = min_width - wstep *= -1 - -Advanced Exercise ------------------ - -You may have noticed that the LED brightness seems to fade slowly, but increases quickly. This is because our eyes interprets brightness logarithmically (`Weber's Law `_ -), while the LED's brightness changes linearly, that is by the same amount each time. How do you solve this problem? (Hint: what is the opposite of the logarithmic function?) - -Addendum --------- - -We could have also used the digital-to-analog converter (DAC) to achieve the same effect. The PWM method has the advantage that it drives the LED with the same current each time, but for different lengths of time. This allows better control over the brightness, because LEDs do not necessarily exhibit a linear relationship between the driving current and brightness. diff --git a/docs/pyboard/tutorial/img/fading_leds_breadboard_fritzing.png b/docs/pyboard/tutorial/img/fading_leds_breadboard_fritzing.png deleted file mode 100644 index a8eec4eb620ba21c4385dfd646399e958d32d096..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 61821 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

nFlWTP`G>1T>fBFB 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 Yn8ip03P2~P%>W1S6aYB@H2{DA*=^3ALjV8( diff --git a/docs/pyboard/tutorial/img/pyboard_usb_micro.jpg b/docs/pyboard/tutorial/img/pyboard_usb_micro.jpg deleted file mode 100644 index bc1c2b832337b04bc4e243c0dccb879a940e5598..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 86846 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

+4Ckft+NOxG^2^4m-)Xodk& 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 U{|8I_|5y9}H}yXOfq!QI2PM1gbN~PV diff --git a/docs/pyboard/tutorial/img/skin_amp_2.jpg b/docs/pyboard/tutorial/img/skin_amp_2.jpg deleted file mode 100644 index 7631b3b6334dd3d82d64b79ec98e6fffc6f503d8..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 75075 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

G0nmI zB5iBP8>j%j7EaT>}6%`*O)`hlPN+=ZY$It_No!`C0*OYti; zHG=vIdDKnrJppKZ+hkpqQL_V{o%2(_;irZ-&k5D;<^7LYgwxN;sI-~-G{d%Wi<_3% z;k`^6+)ESRbMncU!3smf*bMp&=orn8PrB8s6o>L3N$mM@OJ60$PR=SiqH7=TV?0}3 zBR!hg$Nhcw->ZABt}j?>!jbCtnhG4d5Q>H!ZiakH25@wYb^Om#uXehedjk2#Jco>5S^og6PJS6> z`jQS#88mg14cnSlt$7~QXPi$s#R>7AD`3_;g+JOwdgd5r#2ww{%%29sZ{Df`!*`R$ zuBHTc{mcB&$uuv>j-PXLu$4rJ(?~Ol*SJKP3rZNX`sZ?*B4qb=wC((kg|~}_VJ{74 zC`&O+X*f9`#_OG_nU4azdhiUv@UTRmtsvSH*jd8HPU(xipY@I2t;+tFwHgGE>*g(x z>&c?nRD{3)yd{%1AJwc&!BHylGT6w%czH*P{D?}Yf!U6ka|ePMbtQh_1aXH;7s@+2 zKFu!;;5W_-NwCf(_|6Y?l?j;)tU(2wUpBzYi&ULwhLEfvVLg-mfSbSyM}Uz4Ea#Nx z%k;raK5I(rB=jzCJ6m(#;paguhmg%Vq62c{UH{WTvsJ6LVyIS>7UN_a`98({>c0M$ zO-GIkknP8&hgYtU?>(JAJE4YT#MHt44??XaCiNC<1a#oFy4g~?2Yrrs%m&~ut4%l> zZ`?9O_clmoR2m-rM?cdoKXH+py<<5Gzv8GA)Iga!A& zEce#|VTj4j&3pF1>gu`0CvzRK)KbR^<-6dl1Y!w&_}s0(Z)e>wf$u3zP+$y=J3m^KPe8J+qdw>hXh%pbvjs zHG3+d)>M~FY|_kfTF_7C!o%lZIahIue?cYLSV|U`h)pvNj2foYt?VOo-?+c4=6jEk zK!$E`vjX`}ti7B&49x8fsOC--Si77+u8gD~_ul{ZL@F>v?q#hFwM(&Lz6ZE`ayIb2 zF)kX@8tNbj!~j3(C{1g#5LWYbM_i&=h{$x`Oc^sE@c>3}!aIE(b7uzl@x)eJ zI+qm7r*t(xcogY(D+Q)t(9{_xn16)5=x|N82x79bcU)G#T#J0vS8g&swCFdbur^@n zd2IFm6PY+Co2(O;GRlRbpEe7w9X5Jpv6U5PB&$1*IdcL#Gr9z@)|X>Z4{X}tC! zc)A}{f_avkGL~%fW)^q*B^xffJxkk`m<8}kN1`| zu4%lSQc+-Y8O#nn^w+hcbE}iJh}GT7wS>QKB0N#MXkT$cVQ3sBF0$(k0apZFikmV# z#e>NIg2uF{sLcf^$?PMm5E-&8vckqc7z;Txh00{z8hzKNP)s7lIg)WZGLzmn)7zMOJ;(3`j2*rKhBRIO}X8cUR9TUjW0X1T3M9)IV-O8 zQbQ~Bxu`GZh-)pkN;0CO%=cO{W5Ore)D=9^xsd5!Al!Ja&*AT8iYA<2faZ@Wk@;Sx zuyh{rv8nXuTPBBTrL6o-=g9Rl8(SpSegCTMKJE`hRLE?j=G(yR1gAEoRan1x%QcRy z(Z-R9+31vk5M98>)`gV2Ce=lQ6mDV~Ig43{HI<3=(bOp04?A71b2LS_sob?uy8d%U|M?QF$EXYZHchS`X88m-1;Kqx>OvwW!+nzToB({n}uUio=KM1~sBPb8m9OPYTkW->&Z_hE@fW$!i0>?m%<+%i+-%>bLEU9h>ek7SR1jdBr>^@-g>=M1$u_5vMQ?- zdiA+56e7I4b)9iHgUBnRO`TX&>L$PB#-U*CsqqD9_jG+Rv*W@s970b_0Zd!&o(Ciaf8~ zGCvmCn%ho<#}S~wabsFR(4t0?`*GmosTG|?o)TDH!m@I}cR()xwB`dpiTO-Ev5cyN z%Ec?CrI?n%#M2`KI4On2au*?E^dke`KdC$e)BT6b{{SP6jZeO{gyh@m#hMsgYdnN{ z(F0sucW5qaoy0ws(1_81HkVj-wbX-Afjb@X;V3I5H~fM-PSU|&=Ar1Vl!(bAMDmlL z6_TMh3b-{8Hket_pm*@)463<|hosBFyA{8m953kwqoQCCVGE!}A~-=f;EZbi2QX

B=+ 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 diff --git a/docs/pyboard/tutorial/img/skin_lcd_2.jpg b/docs/pyboard/tutorial/img/skin_lcd_2.jpg deleted file mode 100644 index 6e3e1033efce6149d14f6d3a45dfe7c2f25f0ae1..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 69460 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%0Don7tbHl^;9jsWuEueM{(NFV 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%0AE~SYQF&C_nrN~acnVEVOVo;&6D@&P|$2xT; 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. You -can also find the driver in the GitHub repository -`here `__, and to use this version you will need to copy the file to your -board, into a directory that is searched by import (usually the lib/ -directory). - -Once you have the driver installed you need to import it to use it:: - - import lcd160cr - -Testing the display -------------------- - -There is a test program which you can use to test the features of the display, -and which also serves as a basis to start creating your own code that uses the -LCD. This test program is included in recent versions of the pyboard firmware -and is also available on GitHub -`here `__. - -To run the test from the MicroPython prompt do:: - - >>> import lcd160cr_test - -It will then print some brief instructions. You will need to know which -position your display is connected to (X or Y) and then you can run (assuming -you have the display on position X):: - - >>> test_all('X') - -Drawing some graphics ---------------------- - -You must first create an LCD160CR object which will control the display. Do this -using:: - - >>> import lcd160cr - >>> lcd = lcd160cr.LCD160CR('X') - -This assumes your display is connected in the X position. If it's in the Y -position then use ``lcd = lcd160cr.LCD160CR('Y')`` instead. - -To erase the screen and draw a line, try:: - - >>> lcd.set_pen(lcd.rgb(255, 0, 0), lcd.rgb(64, 64, 128)) - >>> lcd.erase() - >>> lcd.line(10, 10, 50, 80) - -The next example draws random rectangles on the screen. You can copy-and-paste it -into the MicroPython prompt by first pressing "Ctrl-E" at the prompt, then "Ctrl-D" -once you have pasted the text. :: - - from random import randint - for i in range(1000): - fg = lcd.rgb(randint(128, 255), randint(128, 255), randint(128, 255)) - bg = lcd.rgb(randint(0, 128), randint(0, 128), randint(0, 128)) - lcd.set_pen(fg, bg) - lcd.rect(randint(0, lcd.w), randint(0, lcd.h), randint(10, 40), randint(10, 40)) - -Using the touch sensor ----------------------- - -The display includes a resistive touch sensor that can report the position (in -pixels) of a single force-based touch on the screen. To see if there is a touch -on the screen use:: - - >>> lcd.is_touched() - -This will return either ``False`` or ``True``. Run the above command while touching -the screen to see the result. - -To get the location of the touch you can use the method:: - - >>> lcd.get_touch() - -This will return a 3-tuple, with the first entry being 0 or 1 depending on whether -there is currently anything touching the screen (1 if there is), and the second and -third entries in the tuple being the x and y coordinates of the current (or most -recent) touch. - -Directing the MicroPython output to the display ------------------------------------------------ - -The display supports input from a UART and implements basic VT100 commands, which -means it can be used as a simple, general purpose terminal. Let's set up the -pyboard to redirect its output to the display. - -First you need to create a UART object:: - - >>> import pyb - >>> uart = pyb.UART('XA', 115200) - -This assumes your display is connected to position X. If it's on position Y then -use ``uart = pyb.UART('YA', 115200)`` instead. - -Now, connect the REPL output to this UART:: - - >>> pyb.repl_uart(uart) - -From now on anything you type at the MicroPython prompt, and any output you -receive, will appear on the display. - -No set-up commands are required for this mode to work and you can use the display -to monitor the output of any UART, not just from the pyboard. All that is needed -is for the display to have power, ground and the power/enable pin driven high. -Then any characters on the display's UART input will be printed to the screen. -You can adjust the UART baudrate from the default of 115200 using the -`set_uart_baudrate` method. diff --git a/docs/pyboard/tutorial/lcd_skin.rst b/docs/pyboard/tutorial/lcd_skin.rst deleted file mode 100644 index 288ac1bf08..0000000000 --- a/docs/pyboard/tutorial/lcd_skin.rst +++ /dev/null @@ -1,86 +0,0 @@ -The LCD and touch-sensor skin -============================= - -Soldering and using the LCD and touch-sensor skin. - -.. image:: img/skin_lcd_1.jpg - :alt: pyboard with LCD skin - :width: 250px - -.. image:: img/skin_lcd_2.jpg - :alt: pyboard with LCD skin - :width: 250px - -The following video shows how to solder the headers onto the LCD skin. -At the end of the video, it shows you how to correctly connect the LCD skin to the pyboard. - -.. raw:: html - - - -For circuit schematics and datasheets for the components on the skin see :ref:`hardware_index`. - -Using the LCD -------------- - -To get started using the LCD, try the following at the MicroPython prompt. -Make sure the LCD skin is attached to the pyboard as pictured at the top of this page. :: - - >>> import pyb - >>> lcd = pyb.LCD('X') - >>> lcd.light(True) - >>> lcd.write('Hello uPy!\n') - -You can make a simple animation using the code:: - - import pyb - lcd = pyb.LCD('X') - lcd.light(True) - for x in range(-80, 128): - lcd.fill(0) - lcd.text('Hello uPy!', x, 10, 1) - lcd.show() - pyb.delay(25) - -Using the touch sensor ----------------------- - -To read the touch-sensor data you need to use the I2C bus. The -MPR121 capacitive touch sensor has address 90. - -To get started, try:: - - >>> import pyb - >>> i2c = pyb.I2C(1, pyb.I2C.MASTER) - >>> i2c.mem_write(4, 90, 0x5e) - >>> touch = i2c.mem_read(1, 90, 0)[0] - -The first line above makes an I2C object, and the second line -enables the 4 touch sensors. The third line reads the touch -status and the ``touch`` variable holds the state of the 4 touch -buttons (A, B, X, Y). - -There is a simple driver `here `__ -which allows you to set the threshold and debounce parameters, and -easily read the touch status and electrode voltage levels. Copy -this script to your pyboard (either flash or SD card, in the top -directory or ``lib/`` directory) and then try:: - - >>> import pyb - >>> import mpr121 - >>> m = mpr121.MPR121(pyb.I2C(1, pyb.I2C.MASTER)) - >>> for i in range(100): - ... print(m.touch_status()) - ... pyb.delay(100) - ... - -This will continuously print out the touch status of all electrodes. -Try touching each one in turn. - -Note that if you put the LCD skin in the Y-position, then you need to -initialise the I2C bus using:: - - >>> m = mpr121.MPR121(pyb.I2C(2, pyb.I2C.MASTER)) - -There is also a demo which uses the LCD and the touch sensors together, -and can be found `here `__. diff --git a/docs/pyboard/tutorial/leds.rst b/docs/pyboard/tutorial/leds.rst deleted file mode 100644 index 763eedf01c..0000000000 --- a/docs/pyboard/tutorial/leds.rst +++ /dev/null @@ -1,75 +0,0 @@ -Turning on LEDs and basic Python concepts -========================================= - -The easiest thing to do on the pyboard is to turn on the LEDs attached to the board. Connect the board, and log in as described in tutorial 1. We will start by turning and LED on in the interpreter, type the following :: - - >>> myled = pyb.LED(1) - >>> myled.on() - >>> myled.off() - -These commands turn the LED on and off. - -This is all very well but we would like this process to be automated. Open the file MAIN.PY on the pyboard in your favourite text editor. Write or paste the following lines into the file. If you are new to python, then make sure you get the indentation correct since this matters! :: - - led = pyb.LED(2) - while True: - led.toggle() - pyb.delay(1000) - -When you save, the red light on the pyboard should turn on for about a second. To run the script, do a soft reset (CTRL-D). The pyboard will then restart and you should see a green light continuously flashing on and off. Success, the first step on your path to building an army of evil robots! When you are bored of the annoying flashing light then press CTRL-C at your terminal to stop it running. - -So what does this code do? First we need some terminology. Python is an object-oriented language, almost everything in python is a *class* and when you create an instance of a class you get an *object*. Classes have *methods* associated to them. A method (also called a member function) is used to interact with or control the object. - -The first line of code creates an LED object which we have then called led. When we create the object, it takes a single parameter which must be between 1 and 4, corresponding to the 4 LEDs on the board. The pyb.LED class has three important member functions that we will use: on(), off() and toggle(). The other function that we use is pyb.delay() this simply waits for a given time in miliseconds. Once we have created the LED object, the statement while True: creates an infinite loop which toggles the led between on and off and waits for 1 second. - -**Exercise: Try changing the time between toggling the led and turning on a different LED.** - -**Exercise: Connect to the pyboard directly, create a pyb.LED object and turn it on using the on() method.** - -A Disco on your pyboard ------------------------ - -So far we have only used a single LED but the pyboard has 4 available. Let's start by creating an object for each LED so we can control each of them. We do that by creating a list of LEDS with a list comprehension. :: - - leds = [pyb.LED(i) for i in range(1,5)] - -If you call pyb.LED() with a number that isn't 1,2,3,4 you will get an error message. -Next we will set up an infinite loop that cycles through each of the LEDs turning them on and off. :: - - n = 0 - while True: - n = (n + 1) % 4 - leds[n].toggle() - pyb.delay(50) - -Here, n keeps track of the current LED and every time the loop is executed we cycle to the next n (the % sign is a modulus operator that keeps n between 0 and 3.) Then we access the nth LED and toggle it. If you run this you should see each of the LEDs turning on then all turning off again in sequence. - -One problem you might find is that if you stop the script and then start it again that the LEDs are stuck on from the previous run, ruining our carefully choreographed disco. We can fix this by turning all the LEDs off when we initialise the script and then using a try/finally block. When you press CTRL-C, MicroPython generates a VCPInterrupt exception. Exceptions normally mean something has gone wrong and you can use a try: command to "catch" an exception. In this case it is just the user interrupting the script, so we don't need to catch the error but just tell MicroPython what to do when we exit. The finally block does this, and we use it to make sure all the LEDs are off. The full code is:: - - leds = [pyb.LED(i) for i in range(1,5)] - for l in leds: - l.off() - - n = 0 - try: - while True: - n = (n + 1) % 4 - leds[n].toggle() - pyb.delay(50) - finally: - for l in leds: - l.off() - -The Fourth Special LED ----------------------- - -The blue LED is special. As well as turning it on and off, you can control the intensity using the intensity() method. This takes a number between 0 and 255 that determines how bright it is. The following script makes the blue LED gradually brighter then turns it off again. :: - - led = pyb.LED(4) - intensity = 0 - while True: - intensity = (intensity + 1) % 255 - led.intensity(intensity) - pyb.delay(20) - -You can call intensity() on the other LEDs but they can only be off or on. 0 sets them off and any other number up to 255 turns them on. diff --git a/docs/pyboard/tutorial/pass_through.rst b/docs/pyboard/tutorial/pass_through.rst deleted file mode 100644 index a94e7363d2..0000000000 --- a/docs/pyboard/tutorial/pass_through.rst +++ /dev/null @@ -1,18 +0,0 @@ -Making a UART - USB pass through -================================ - -It's as simple as:: - - import pyb - import select - - def pass_through(usb, uart): - usb.setinterrupt(-1) - while True: - select.select([usb, uart], [], []) - if usb.any(): - uart.write(usb.read(256)) - if uart.any(): - usb.write(uart.read(256)) - - pass_through(pyb.USB_VCP(), pyb.UART(1, 9600)) diff --git a/docs/pyboard/tutorial/power_ctrl.rst b/docs/pyboard/tutorial/power_ctrl.rst deleted file mode 100644 index 877b7cd7ee..0000000000 --- a/docs/pyboard/tutorial/power_ctrl.rst +++ /dev/null @@ -1,13 +0,0 @@ -Power control -============= - -:meth:`pyb.wfi` is used to reduce power consumption while waiting for an -event such as an interrupt. You would use it in the following situation:: - - while True: - do_some_processing() - pyb.wfi() - -Control the frequency using :meth:`pyb.freq`:: - - pyb.freq(30000000) # set CPU frequency to 30MHz diff --git a/docs/pyboard/tutorial/repl.rst b/docs/pyboard/tutorial/repl.rst deleted file mode 100644 index 646ecbc237..0000000000 --- a/docs/pyboard/tutorial/repl.rst +++ /dev/null @@ -1,110 +0,0 @@ -Getting a MicroPython REPL prompt -================================= - -REPL stands for Read Evaluate Print Loop, and is the name given to the -interactive MicroPython prompt that you can access on the pyboard. Using -the REPL is by far the easiest way to test out your code and run commands. -You can use the REPL in addition to writing scripts in ``main.py``. - -To use the REPL, you must connect to the serial USB device on the pyboard. -How you do this depends on your operating system. - -Windows -------- - -You need to install the pyboard driver to use the serial USB device. -The driver is on the pyboard's USB flash drive, and is called ``pybcdc.inf``. - -To install this driver you need to go to Device Manager -for your computer, find the pyboard in the list of devices (it should have -a warning sign next to it because it's not working yet), right click on -the pyboard device, select Properties, then Install Driver. You need to -then select the option to find the driver manually (don't use Windows auto update), -navigate to the pyboard's USB drive, and select that. It should then install. -After installing, go back to the Device Manager to find the installed pyboard, -and see which COM port it is (eg COM4). -More comprehensive instructions can be found in the -`Guide for pyboard on Windows (PDF) `_. -Please consult this guide if you are having problems installing the driver. - -You now need to run your terminal program. You can use HyperTerminal if you -have it installed, or download the free program PuTTY: -`putty.exe `_. -Using your serial program you must connect to the COM port that you found in the -previous step. With PuTTY, click on "Session" in the left-hand panel, then click -the "Serial" radio button on the right, then enter you COM port (eg COM4) in the -"Serial Line" box. Finally, click the "Open" button. - -Mac OS X --------- - -Open a terminal and run:: - - screen /dev/tty.usbmodem* - -When you are finished and want to exit screen, type CTRL-A CTRL-\\. - -Linux ------ - -Open a terminal and run:: - - screen /dev/ttyACM0 - -You can also try ``picocom`` or ``minicom`` instead of screen. You may have to -use ``/dev/ttyACM1`` or a higher number for ``ttyACM``. And, you may need to give -yourself the correct permissions to access this devices (eg group ``uucp`` or ``dialout``, -or use sudo). - -Using the REPL prompt ---------------------- - -Now let's try running some MicroPython code directly on the pyboard. - -With your serial program open (PuTTY, screen, picocom, etc) you may see a blank -screen with a flashing cursor. Press Enter and you should be presented with a -MicroPython prompt, i.e. ``>>>``. Let's make sure it is working with the obligatory test:: - - >>> print("hello pyboard!") - hello pyboard! - -In the above, you should not type in the ``>>>`` characters. They are there to -indicate that you should type the text after it at the prompt. In the end, once -you have entered the text ``print("hello pyboard!")`` and pressed Enter, the output -on your screen should look like it does above. - -If you already know some python you can now try some basic commands here. - -If any of this is not working you can try either a hard reset or a soft reset; -see below. - -Go ahead and try typing in some other commands. For example:: - - >>> pyb.LED(1).on() - >>> pyb.LED(2).on() - >>> 1 + 2 - 3 - >>> 1 / 2 - 0.5 - >>> 20 * 'py' - 'pypypypypypypypypypypypypypypypypypypypy' - -Resetting the board -------------------- - -If something goes wrong, you can reset the board in two ways. The first is to press CTRL-D -at the MicroPython prompt, which performs a soft reset. You will see a message something like :: - - >>> - PYB: sync filesystems - PYB: soft reboot - Micro Python v1.0 on 2014-05-03; PYBv1.0 with STM32F405RG - Type "help()" for more information. - >>> - -If that isn't working you can perform a hard reset (turn-it-off-and-on-again) by pressing the RST -switch (the small black button closest to the micro-USB socket on the board). This will end your -session, disconnecting whatever program (PuTTY, screen, etc) that you used to connect to the pyboard. - -If you are going to do a hard-reset, it's recommended to first close your serial program and eject/unmount -the pyboard drive. diff --git a/docs/pyboard/tutorial/reset.rst b/docs/pyboard/tutorial/reset.rst deleted file mode 100644 index 0cd5ac21c8..0000000000 --- a/docs/pyboard/tutorial/reset.rst +++ /dev/null @@ -1,60 +0,0 @@ -Safe mode and factory reset -=========================== - -If something goes wrong with your pyboard, don't panic! It is almost -impossible for you to break the pyboard by programming the wrong thing. - -The first thing to try is to enter safe mode: this temporarily skips -execution of ``boot.py`` and ``main.py`` and gives default USB settings. - -If you have problems with the filesystem you can do a factory reset, -which restores the filesystem to its original state. - -Safe mode ---------- - -To enter safe mode, do the following steps: - -1. Connect the pyboard to USB so it powers up. -2. Hold down the USR switch. -3. While still holding down USR, press and release the RST switch. -4. The LEDs will then cycle green to orange to green+orange and back again. -5. Keep holding down USR until *only the orange LED is lit*, and then let - go of the USR switch. -6. The orange LED should flash quickly 4 times, and then turn off. -7. You are now in safe mode. - -In safe mode, the ``boot.py`` and ``main.py`` files are not executed, and so -the pyboard boots up with default settings. This means you now have access -to the filesystem (the USB drive should appear), and you can edit ``boot.py`` -and ``main.py`` to fix any problems. - -Entering safe mode is temporary, and does not make any changes to the -files on the pyboard. - -Factory reset the filesystem ----------------------------- - -If you pyboard's filesystem gets corrupted (for example, you forgot to -eject/unmount it), or you have some code in ``boot.py`` or ``main.py`` which -you can't escape from, then you can reset the filesystem. - -Resetting the filesystem deletes all files on the internal pyboard storage -(not the SD card), and restores the files ``boot.py``, ``main.py``, ``README.txt`` -and ``pybcdc.inf`` back to their original state. - -To do a factory reset of the filesystem you follow a similar procedure as -you did to enter safe mode, but release USR on green+orange: - -1. Connect the pyboard to USB so it powers up. -2. Hold down the USR switch. -3. While still holding down USR, press and release the RST switch. -4. The LEDs will then cycle green to orange to green+orange and back again. -5. Keep holding down USR until *both the green and orange LEDs are lit*, and - then let go of the USR switch. -6. The green and orange LEDs should flash quickly 4 times. -7. The red LED will turn on (so red, green and orange are now on). -8. The pyboard is now resetting the filesystem (this takes a few seconds). -9. The LEDs all turn off. -10. You now have a reset filesystem, and are in safe mode. -11. Press and release the RST switch to boot normally. diff --git a/docs/pyboard/tutorial/script.rst b/docs/pyboard/tutorial/script.rst deleted file mode 100644 index 75dd324e3c..0000000000 --- a/docs/pyboard/tutorial/script.rst +++ /dev/null @@ -1,105 +0,0 @@ -Running your first script -========================= - -Let's jump right in and get a Python script running on the pyboard. After -all, that's what it's all about! - -Connecting your pyboard ------------------------ - -Connect your pyboard to your PC (Windows, Mac or Linux) with a micro USB cable. -There is only one way that the cable will connect, so you can't get it wrong. - -.. image:: img/pyboard_usb_micro.jpg - -When the pyboard is connected to your PC it will power on and enter the start up -process (the boot process). The green LED should light up for half a second or -less, and when it turns off it means the boot process has completed. - -Opening the pyboard USB drive ------------------------------ - -Your PC should now recognise the pyboard. It depends on the type of PC you -have as to what happens next: - - - **Windows**: Your pyboard will appear as a removable USB flash drive. - Windows may automatically pop-up a window, or you may need to go there - using Explorer. - - Windows will also see that the pyboard has a serial device, and it will - try to automatically configure this device. If it does, cancel the process. - We will get the serial device working in the next tutorial. - - - **Mac**: Your pyboard will appear on the desktop as a removable disc. - It will probably be called "NONAME". Click on it to open the pyboard folder. - - - **Linux**: Your pyboard will appear as a removable medium. On Ubuntu - it will mount automatically and pop-up a window with the pyboard folder. - On other Linux distributions, the pyboard may be mounted automatically, - or you may need to do it manually. At a terminal command line, type ``lsblk`` - to see a list of connected drives, and then ``mount /dev/sdb1`` (replace ``sdb1`` - with the appropriate device). You may need to be root to do this. - -Okay, so you should now have the pyboard connected as a USB flash drive, and -a window (or command line) should be showing the files on the pyboard drive. - -The drive you are looking at is known as ``/flash`` by the pyboard, and should contain -the following 4 files: - -* `boot.py `_ -- this script is executed when the pyboard boots up. It sets - up various configuration options for the pyboard. - -* `main.py `_ -- this is the main script that will contain your Python program. - It is executed after ``boot.py``. - -* `README.txt `_ -- this contains some very basic information about getting - started with the pyboard. - -* `pybcdc.inf `_ -- this is a Windows driver file to configure the serial USB - device. More about this in the next tutorial. - -Editing ``main.py`` -------------------- - -Now we are going to write our Python program, so open the ``main.py`` -file in a text editor. On Windows you can use notepad, or any other editor. -On Mac and Linux, use your favourite text editor. With the file open you will -see it contains 1 line:: - - # main.py -- put your code here! - -This line starts with a # character, which means that it is a *comment*. Such -lines will not do anything, and are there for you to write notes about your -program. - -Let's add 2 lines to this ``main.py`` file, to make it look like this:: - - # main.py -- put your code here! - import pyb - pyb.LED(4).on() - -The first line we wrote says that we want to use the ``pyb`` module. -This module contains all the functions and classes to control the features -of the pyboard. - -The second line that we wrote turns the blue LED on: it first gets the ``LED`` -class from the ``pyb`` module, creates LED number 4 (the blue LED), and then -turns it on. - -Resetting the pyboard ---------------------- - -To run this little script, you need to first save and close the ``main.py`` file, -and then eject (or unmount) the pyboard USB drive. Do this like you would a -normal USB flash drive. - -When the drive is safely ejected/unmounted you can get to the fun part: -press the RST switch on the pyboard to reset and run your script. The RST -switch is the small black button just below the USB connector on the board, -on the right edge. - -When you press RST the green LED will flash quickly, and then the blue -LED should turn on and stay on. - -Congratulations! You have written and run your very first MicroPython -program! diff --git a/docs/pyboard/tutorial/servo.rst b/docs/pyboard/tutorial/servo.rst deleted file mode 100644 index 83d1b0cc15..0000000000 --- a/docs/pyboard/tutorial/servo.rst +++ /dev/null @@ -1,146 +0,0 @@ -Controlling hobby servo motors -============================== - -There are 4 dedicated connection points on the pyboard for connecting up -hobby servo motors (see eg -[Wikipedia](http://en.wikipedia.org/wiki/Servo_%28radio_control%29)). -These motors have 3 wires: ground, power and signal. On the pyboard you -can connect them in the bottom right corner, with the signal pin on the -far right. Pins X1, X2, X3 and X4 are the 4 dedicated servo signal pins. - -.. image:: img/pyboard_servo.jpg - -In this picture there are male-male double adaptors to connect the servos -to the header pins on the pyboard. - -The ground wire on a servo is usually the darkest coloured one, either -black or dark brown. The power wire will most likely be red. - -The power pin for the servos (labelled VIN) is connected directly to the -input power source of the pyboard. When powered via USB, VIN is powered -through a diode by the 5V USB power line. Connect to USB, the pyboard can -power at least 4 small to medium sized servo motors. - -If using a battery to power the pyboard and run servo motors, make sure it -is not greater than 6V, since this is the maximum voltage most servo motors -can take. (Some motors take only up to 4.8V, so check what type you are -using.) - -Creating a Servo object ------------------------ - -Plug in a servo to position 1 (the one with pin X1) and create a servo object -using:: - - >>> servo1 = pyb.Servo(1) - -To change the angle of the servo use the ``angle`` method:: - - >>> servo1.angle(45) - >>> servo1.angle(-60) - -The angle here is measured in degrees, and ranges from about -90 to +90, -depending on the motor. Calling ``angle`` without parameters will return -the current angle:: - - >>> servo1.angle() - -60 - -Note that for some angles, the returned angle is not exactly the same as -the angle you set, due to rounding errors in setting the pulse width. - -You can pass a second parameter to the ``angle`` method, which specifies how -long to take (in milliseconds) to reach the desired angle. For example, to -take 1 second (1000 milliseconds) to go from the current position to 50 degrees, -use :: - - >>> servo1.angle(50, 1000) - -This command will return straight away and the servo will continue to move -to the desired angle, and stop when it gets there. You can use this feature -as a speed control, or to synchronise 2 or more servo motors. If we have -another servo motor (``servo2 = pyb.Servo(2)``) then we can do :: - - >>> servo1.angle(-45, 2000); servo2.angle(60, 2000) - -This will move the servos together, making them both take 2 seconds to -reach their final angles. - -Note: the semicolon between the 2 expressions above is used so that they -are executed one after the other when you press enter at the REPL prompt. -In a script you don't need to do this, you can just write them one line -after the other. - -Continuous rotation servos --------------------------- - -So far we have been using standard servos that move to a specific angle -and stay at that angle. These servo motors are useful to create joints -of a robot, or things like pan-tilt mechanisms. Internally, the motor -has a variable resistor (potentiometer) which measures the current angle -and applies power to the motor proportional to how far it is from the -desired angle. The desired angle is set by the width of a high-pulse on -the servo signal wire. A pulse width of 1500 microsecond corresponds -to the centre position (0 degrees). The pulses are sent at 50 Hz, ie -50 pulses per second. - -You can also get **continuous rotation** servo motors which turn -continuously clockwise or counterclockwise. The direction and speed of -rotation is set by the pulse width on the signal wire. A pulse width -of 1500 microseconds corresponds to a stopped motor. A pulse width -smaller or larger than this means rotate one way or the other, at a -given speed. - -On the pyboard, the servo object for a continuous rotation motor is -the same as before. In fact, using ``angle`` you can set the speed. But -to make it easier to understand what is intended, there is another method -called ``speed`` which sets the speed:: - - >>> servo1.speed(30) - -``speed`` has the same functionality as ``angle``: you can get the speed, -set it, and set it with a time to reach the final speed. :: - - >>> servo1.speed() - 30 - >>> servo1.speed(-20) - >>> servo1.speed(0, 2000) - -The final command above will set the motor to stop, but take 2 seconds -to do it. This is essentially a control over the acceleration of the -continuous servo. - -A servo speed of 100 (or -100) is considered maximum speed, but actually -you can go a bit faster than that, depending on the particular motor. - -The only difference between the ``angle`` and ``speed`` methods (apart from -the name) is the way the input numbers (angle or speed) are converted to -a pulse width. - -Calibration ------------ - -The conversion from angle or speed to pulse width is done by the servo -object using its calibration values. To get the current calibration, -use :: - - >>> servo1.calibration() - (640, 2420, 1500, 2470, 2200) - -There are 5 numbers here, which have meaning: - -1. Minimum pulse width; the smallest pulse width that the servo accepts. -2. Maximum pulse width; the largest pulse width that the servo accepts. -3. Centre pulse width; the pulse width that puts the servo at 0 degrees - or 0 speed. -4. The pulse width corresponding to 90 degrees. This sets the conversion - in the method ``angle`` of angle to pulse width. -5. The pulse width corresponding to a speed of 100. This sets the conversion - in the method ``speed`` of speed to pulse width. - -You can recalibrate the servo (change its default values) by using:: - - >>> servo1.calibration(700, 2400, 1510, 2500, 2000) - -Of course, you would change the above values to suit your particular -servo motor. diff --git a/docs/pyboard/tutorial/switch.rst b/docs/pyboard/tutorial/switch.rst deleted file mode 100644 index 91683fba45..0000000000 --- a/docs/pyboard/tutorial/switch.rst +++ /dev/null @@ -1,113 +0,0 @@ -The Switch, callbacks and interrupts -==================================== - -The pyboard has 2 small switches, labelled USR and RST. The RST switch -is a hard-reset switch, and if you press it then it restarts the pyboard -from scratch, equivalent to turning the power off then back on. - -The USR switch is for general use, and is controlled via a Switch object. -To make a switch object do:: - - >>> sw = pyb.Switch() - -Remember that you may need to type ``import pyb`` if you get an error that -the name ``pyb`` does not exist. - -With the switch object you can get its status:: - - >>> sw.value() - False - -This will print ``False`` if the switch is not held, or ``True`` if it is held. -Try holding the USR switch down while running the above command. - -There is also a shorthand notation to get the switch status, by "calling" the -switch object:: - - >>> sw() - False - -Switch callbacks ----------------- - -The switch is a very simple object, but it does have one advanced feature: -the ``sw.callback()`` function. The callback function sets up something to -run when the switch is pressed, and uses an interrupt. It's probably best -to start with an example before understanding how interrupts work. Try -running the following at the prompt:: - - >>> sw.callback(lambda:print('press!')) - -This tells the switch to print ``press!`` each time the switch is pressed -down. Go ahead and try it: press the USR switch and watch the output on -your PC. Note that this print will interrupt anything you are typing, and -is an example of an interrupt routine running asynchronously. - -As another example try:: - - >>> sw.callback(lambda:pyb.LED(1).toggle()) - -This will toggle the red LED each time the switch is pressed. And it will -even work while other code is running. - -To disable the switch callback, pass ``None`` to the callback function:: - - >>> sw.callback(None) - -You can pass any function (that takes zero arguments) to the switch callback. -Above we used the ``lambda`` feature of Python to create an anonymous function -on the fly. But we could equally do:: - - >>> def f(): - ... pyb.LED(1).toggle() - ... - >>> sw.callback(f) - -This creates a function called ``f`` and assigns it to the switch callback. -You can do things this way when your function is more complicated than a -``lambda`` will allow. - -Note that your callback functions must not allocate any memory (for example -they cannot create a tuple or list). Callback functions should be relatively -simple. If you need to make a list, make it beforehand and store it in a -global variable (or make it local and close over it). If you need to do -a long, complicated calculation, then use the callback to set a flag which -some other code then responds to. - -Technical details of interrupts -------------------------------- - -Let's step through the details of what is happening with the switch -callback. When you register a function with ``sw.callback()``, the switch -sets up an external interrupt trigger (falling edge) on the pin that the -switch is connected to. This means that the microcontroller will listen -on the pin for any changes, and the following will occur: - -1. When the switch is pressed a change occurs on the pin (the pin goes - from low to high), and the microcontroller registers this change. -2. The microcontroller finishes executing the current machine instruction, - stops execution, and saves its current state (pushes the registers on - the stack). This has the effect of pausing any code, for example your - running Python script. -3. The microcontroller starts executing the special interrupt handler - associated with the switch's external trigger. This interrupt handler - get the function that you registered with ``sw.callback()`` and executes - it. -4. Your callback function is executed until it finishes, returning control - to the switch interrupt handler. -5. The switch interrupt handler returns, and the microcontroller is - notified that the interrupt has been dealt with. -6. The microcontroller restores the state that it saved in step 2. -7. Execution continues of the code that was running at the beginning. Apart - from the pause, this code does not notice that it was interrupted. - -The above sequence of events gets a bit more complicated when multiple -interrupts occur at the same time. In that case, the interrupt with the -highest priority goes first, then the others in order of their priority. -The switch interrupt is set at the lowest priority. - -Further reading ---------------- - -For further information about using hardware interrupts see -:ref:`writing interrupt handlers `. diff --git a/docs/pyboard/tutorial/timer.rst b/docs/pyboard/tutorial/timer.rst deleted file mode 100644 index aedaaa13c5..0000000000 --- a/docs/pyboard/tutorial/timer.rst +++ /dev/null @@ -1,114 +0,0 @@ -The Timers -========== - -The pyboard has 14 timers which each consist of an independent counter -running at a user-defined frequency. They can be set up to run a function -at specific intervals. -The 14 timers are numbered 1 through 14, but 3 is reserved -for internal use, and 5 and 6 are used for servo and ADC/DAC control. -Avoid using these timers if possible. - -Let's create a timer object:: - - >>> tim = pyb.Timer(4) - -Now let's see what we just created:: - - >>> tim - Timer(4) - -The pyboard is telling us that ``tim`` is attached to timer number 4, but -it's not yet initialised. So let's initialise it to trigger at 10 Hz -(that's 10 times per second):: - - >>> tim.init(freq=10) - -Now that it's initialised, we can see some information about the timer:: - - >>> tim - Timer(4, prescaler=624, period=13439, mode=UP, div=1) - -The information means that this timer is set to run at the peripheral -clock speed divided by 624+1, and it will count from 0 up to 13439, at which -point it triggers an interrupt, and then starts counting again from 0. These -numbers are set to make the timer trigger at 10 Hz: the source frequency -of the timer is 84MHz (found by running ``tim.source_freq()``) so we -get 84MHz / 625 / 13440 = 10Hz. - -Timer counter -------------- - -So what can we do with our timer? The most basic thing is to get the -current value of its counter:: - - >>> tim.counter() - 21504 - -This counter will continuously change, and counts up. - -Timer callbacks ---------------- - -The next thing we can do is register a callback function for the timer to -execute when it triggers (see the [switch tutorial](tut-switch) for an -introduction to callback functions):: - - >>> tim.callback(lambda t:pyb.LED(1).toggle()) - -This should start the red LED flashing right away. It will be flashing -at 5 Hz (2 toggle's are needed for 1 flash, so toggling at 10 Hz makes -it flash at 5 Hz). You can change the frequency by re-initialising the -timer:: - - >>> tim.init(freq=20) - -You can disable the callback by passing it the value ``None``:: - - >>> tim.callback(None) - -The function that you pass to callback must take 1 argument, which is -the timer object that triggered. This allows you to control the timer -from within the callback function. - -We can create 2 timers and run them independently:: - - >>> tim4 = pyb.Timer(4, freq=10) - >>> tim7 = pyb.Timer(7, freq=20) - >>> tim4.callback(lambda t: pyb.LED(1).toggle()) - >>> tim7.callback(lambda t: pyb.LED(2).toggle()) - -Because the callbacks are proper hardware interrupts, we can continue -to use the pyboard for other things while these timers are running. - -Making a microsecond counter ----------------------------- - -You can use a timer to create a microsecond counter, which might be -useful when you are doing something which requires accurate timing. -We will use timer 2 for this, since timer 2 has a 32-bit counter (so -does timer 5, but if you use timer 5 then you can't use the Servo -driver at the same time). - -We set up timer 2 as follows:: - - >>> micros = pyb.Timer(2, prescaler=83, period=0x3fffffff) - -The prescaler is set at 83, which makes this timer count at 1 MHz. -This is because the CPU clock, running at 168 MHz, is divided by -2 and then by prescaler+1, giving a frequency of 168 MHz/2/(83+1)=1 MHz -for timer 2. The period is set to a large number so that the timer -can count up to a large number before wrapping back around to zero. -In this case it will take about 17 minutes before it cycles back to -zero. - -To use this timer, it's best to first reset it to 0:: - - >>> micros.counter(0) - -and then perform your timing:: - - >>> start_micros = micros.counter() - - ... do some stuff ... - - >>> end_micros = micros.counter() diff --git a/docs/pyboard/tutorial/usb_mouse.rst b/docs/pyboard/tutorial/usb_mouse.rst deleted file mode 100644 index 6f8831edb4..0000000000 --- a/docs/pyboard/tutorial/usb_mouse.rst +++ /dev/null @@ -1,131 +0,0 @@ -Making the pyboard act as a USB mouse -===================================== - -The pyboard is a USB device, and can configured to act as a mouse instead -of the default USB flash drive. - -To do this we must first edit the ``boot.py`` file to change the USB -configuration. If you have not yet touched your ``boot.py`` file then it -will look something like this:: - - # boot.py -- run on boot-up - # can run arbitrary Python, but best to keep it minimal - - import pyb - #pyb.main('main.py') # main script to run after this one - #pyb.usb_mode('VCP+MSC') # act as a serial and a storage device - #pyb.usb_mode('VCP+HID') # act as a serial device and a mouse - -To enable the mouse mode, uncomment the last line of the file, to -make it look like:: - - pyb.usb_mode('VCP+HID') # act as a serial device and a mouse - -If you already changed your ``boot.py`` file, then the minimum code it -needs to work is:: - - import pyb - pyb.usb_mode('VCP+HID') - -This tells the pyboard to configure itself as a VCP (Virtual COM Port, -ie serial port) and HID (human interface device, in our case a mouse) -USB device when it boots up. - -Eject/unmount the pyboard drive and reset it using the RST switch. -Your PC should now detect the pyboard as a mouse! - -Sending mouse events by hand ----------------------------- - -To get the py-mouse to do anything we need to send mouse events to the PC. -We will first do this manually using the REPL prompt. Connect to your -pyboard using your serial program and type the following:: - - >>> hid = pyb.USB_HID() - >>> hid.send((0, 10, 0, 0)) - -Your mouse should move 10 pixels to the right! In the command above you -are sending 4 pieces of information: button status, x, y and scroll. The -number 10 is telling the PC that the mouse moved 10 pixels in the x direction. - -Let's make the mouse oscillate left and right:: - - >>> import math - >>> def osc(n, d): - ... for i in range(n): - ... hid.send((0, int(20 * math.sin(i / 10)), 0, 0)) - ... pyb.delay(d) - ... - >>> osc(100, 50) - -The first argument to the function ``osc`` is the number of mouse events to send, -and the second argument is the delay (in milliseconds) between events. Try -playing around with different numbers. - -**Exercise: make the mouse go around in a circle.** - -Making a mouse with the accelerometer -------------------------------------- - -Now lets make the mouse move based on the angle of the pyboard, using the -accelerometer. The following code can be typed directly at the REPL prompt, -or put in the ``main.py`` file. Here, we'll put in in ``main.py`` because to do -that we will learn how to go into safe mode. - -At the moment the pyboard is acting as a serial USB device and an HID (a mouse). -So you cannot access the filesystem to edit your ``main.py`` file. - -You also can't edit your ``boot.py`` to get out of HID-mode and back to normal -mode with a USB drive... - -To get around this we need to go into *safe mode*. This was described in -the [safe mode tutorial](tut-reset), but we repeat the instructions here: - -1. Hold down the USR switch. -2. While still holding down USR, press and release the RST switch. -3. The LEDs will then cycle green to orange to green+orange and back again. -4. Keep holding down USR until *only the orange LED is lit*, and then let - go of the USR switch. -5. The orange LED should flash quickly 4 times, and then turn off. -6. You are now in safe mode. - -In safe mode, the ``boot.py`` and ``main.py`` files are not executed, and so -the pyboard boots up with default settings. This means you now have access -to the filesystem (the USB drive should appear), and you can edit ``main.py``. -(Leave ``boot.py`` as-is, because we still want to go back to HID-mode after -we finish editing ``main.py``.) - -In ``main.py`` put the following code:: - - import pyb - - switch = pyb.Switch() - accel = pyb.Accel() - hid = pyb.USB_HID() - - while not switch(): - hid.send((0, accel.x(), accel.y(), 0)) - pyb.delay(20) - -Save your file, eject/unmount your pyboard drive, and reset it using the RST -switch. It should now act as a mouse, and the angle of the board will move -the mouse around. Try it out, and see if you can make the mouse stand still! - -Press the USR switch to stop the mouse motion. - -You'll note that the y-axis is inverted. That's easy to fix: just put a -minus sign in front of the y-coordinate in the ``hid.send()`` line above. - -Restoring your pyboard to normal --------------------------------- - -If you leave your pyboard as-is, it'll behave as a mouse everytime you plug -it in. You probably want to change it back to normal. To do this you need -to first enter safe mode (see above), and then edit the ``boot.py`` file. -In the ``boot.py`` file, comment out (put a # in front of) the line with the -``VCP+HID`` setting, so it looks like:: - - #pyb.usb_mode('VCP+HID') # act as a serial device and a mouse - -Save your file, eject/unmount the drive, and reset the pyboard. It is now -back to normal operating mode. diff --git a/docs/pyboard_index.rst b/docs/pyboard_index.rst deleted file mode 100644 index 2255a75607..0000000000 --- a/docs/pyboard_index.rst +++ /dev/null @@ -1,12 +0,0 @@ -MicroPython documentation and references -======================================== - -.. toctree:: - - pyboard/quickref.rst - pyboard/general.rst - pyboard/tutorial/index.rst - library/index.rst - reference/index.rst - genrst/index.rst - license.rst diff --git a/docs/reference/asm_thumb2_arith.rst b/docs/reference/asm_thumb2_arith.rst deleted file mode 100644 index da4a688525..0000000000 --- a/docs/reference/asm_thumb2_arith.rst +++ /dev/null @@ -1,50 +0,0 @@ -Arithmetic instructions -======================= - -Document conventions --------------------- - -Notation: ``Rd, Rm, Rn`` denote ARM registers R0-R7. ``immN`` denotes an immediate -value having a width of N bits e.g. ``imm8``, ``imm3``. ``carry`` denotes -the carry condition flag, ``not(carry)`` denotes its complement. In the case of instructions -with more than one register argument, it is permissible for some to be identical. For example -the following will add the contents of R0 to itself, placing the result in R0: - -* add(r0, r0, r0) - -Arithmetic instructions affect the condition flags except where stated. - -Addition --------- - -* add(Rdn, imm8) ``Rdn = Rdn + imm8`` -* add(Rd, Rn, imm3) ``Rd = Rn + imm3`` -* add(Rd, Rn, Rm) ``Rd = Rn +Rm`` -* adc(Rd, Rn) ``Rd = Rd + Rn + carry`` - -Subtraction ------------ - -* sub(Rdn, imm8) ``Rdn = Rdn - imm8`` -* sub(Rd, Rn, imm3) ``Rd = Rn - imm3`` -* sub(Rd, Rn, Rm) ``Rd = Rn - Rm`` -* sbc(Rd, Rn) ``Rd = Rd - Rn - not(carry)`` - -Negation --------- - -* neg(Rd, Rn) ``Rd = -Rn`` - -Multiplication and division ---------------------------- - -* mul(Rd, Rn) ``Rd = Rd * Rn`` - -This produces a 32 bit result with overflow lost. The result may be treated as -signed or unsigned according to the definition of the operands. - -* sdiv(Rd, Rn, Rm) ``Rd = Rn / Rm`` -* udiv(Rd, Rn, Rm) ``Rd = Rn / Rm`` - -These functions perform signed and unsigned division respectively. Condition flags -are not affected. diff --git a/docs/reference/asm_thumb2_compare.rst b/docs/reference/asm_thumb2_compare.rst deleted file mode 100644 index 521af69da3..0000000000 --- a/docs/reference/asm_thumb2_compare.rst +++ /dev/null @@ -1,90 +0,0 @@ -Comparison instructions -======================= - -These perform an arithmetic or logical instruction on two arguments, discarding the result -but setting the condition flags. Typically these are used to test data values without changing -them prior to executing a conditional branch. - -Document conventions --------------------- - -Notation: ``Rd, Rm, Rn`` denote ARM registers R0-R7. ``imm8`` denotes an immediate -value having a width of 8 bits. - -The Application Program Status Register (APSR) ----------------------------------------------- - -This contains four bits which are tested by the conditional branch instructions. Typically a -conditional branch will test multiple bits, for example ``bge(LABEL)``. The meaning of -condition codes can depend on whether the operands of an arithmetic instruction are viewed as -signed or unsigned integers. Thus ``bhi(LABEL)`` assumes unsigned numbers were processed while -``bgt(LABEL)`` assumes signed operands. - -APSR Bits ---------- - -* Z (zero) - -This is set if the result of an operation is zero or the operands of a comparison are equal. - -* N (negative) - -Set if the result is negative. - -* C (carry) - -An addition sets the carry flag when the result overflows out of the MSB, for example adding -0x80000000 and 0x80000000. By the nature of two's complement arithmetic this behaviour is reversed -on subtraction, with a borrow indicated by the carry bit being clear. Thus 0x10 - 0x01 is executed -as 0x10 + 0xffffffff which will set the carry bit. - -* V (overflow) - -The overflow flag is set if the result, viewed as a two's compliment number, has the "wrong" sign -in relation to the operands. For example adding 1 to 0x7fffffff will set the overflow bit because -the result (0x8000000), viewed as a two's complement integer, is negative. Note that in this instance -the carry bit is not set. - -Comparison instructions ------------------------ - -These set the APSR (Application Program Status Register) N (negative), Z (zero), C (carry) and V -(overflow) flags. - -* cmp(Rn, imm8) ``Rn - imm8`` -* cmp(Rn, Rm) ``Rn - Rm`` -* cmn(Rn, Rm) ``Rn + Rm`` -* tst(Rn, Rm) ``Rn & Rm`` - -Conditional execution ---------------------- - -The ``it`` and ``ite`` instructions provide a means of conditionally executing from one to four subsequent -instructions without the need for a label. - -* it() If then - -Execute the next instruction if is true: - -:: - - cmp(r0, r1) - it(eq) - mov(r0, 100) # runs if r0 == r1 - # execution continues here - -* ite() If then else - -If is true, execute the next instruction, otherwise execute the -subsequent one. Thus: - -:: - - cmp(r0, r1) - ite(eq) - mov(r0, 100) # runs if r0 == r1 - mov(r0, 200) # runs if r0 != r1 - # execution continues here - -This may be extended to control the execution of upto four subsequent instructions: it[x[y[z]]] -where x,y,z=t/e; e.g. itt, itee, itete, ittte, itttt, iteee, etc. diff --git a/docs/reference/asm_thumb2_directives.rst b/docs/reference/asm_thumb2_directives.rst deleted file mode 100644 index 95acd7781f..0000000000 --- a/docs/reference/asm_thumb2_directives.rst +++ /dev/null @@ -1,36 +0,0 @@ -Assembler Directives -==================== - -Labels ------- - -* label(INNER1) - -This defines a label for use in a branch instruction. Thus elsewhere in the code a ``b(INNER1)`` -will cause execution to continue with the instruction after the label directive. - -Defining inline data --------------------- - -The following assembler directives facilitate embedding data in an assembler code block. - -* data(size, d0, d1 .. dn) - -The data directive creates n array of data values in memory. The first argument specifies the -size in bytes of the subsequent arguments. Hence the first statement below will cause the -assembler to put three bytes (with values 2, 3 and 4) into consecutive memory locations -while the second will cause it to emit two four byte words. - -:: - - data(1, 2, 3, 4) - data(4, 2, 100000) - -Data values longer than a single byte are stored in memory in little-endian format. - -* align(nBytes) - -Align the following instruction to an nBytes value. ARM Thumb-2 instructions must be two -byte aligned, hence it's advisable to issue ``align(2)`` after ``data`` directives and -prior to any subsequent code. This ensures that the code will run irrespective of the -size of the data array. diff --git a/docs/reference/asm_thumb2_float.rst b/docs/reference/asm_thumb2_float.rst deleted file mode 100644 index 4acb734eeb..0000000000 --- a/docs/reference/asm_thumb2_float.rst +++ /dev/null @@ -1,77 +0,0 @@ -Floating Point instructions -============================== - -These instructions support the use of the ARM floating point coprocessor -(on platforms such as the Pyboard which are equipped with one). The FPU -has 32 registers known as ``s0-s31`` each of which can hold a single -precision float. Data can be passed between the FPU registers and the -ARM core registers with the ``vmov`` instruction. - -Note that MicroPython doesn't support passing floats to -assembler functions, nor can you put a float into ``r0`` and expect a -reasonable result. There are two ways to overcome this. The first is to -use arrays, and the second is to pass and/or return integers and convert -to and from floats in code. - -Document conventions --------------------- - -Notation: ``Sd, Sm, Sn`` denote FPU registers, ``Rd, Rm, Rn`` denote ARM core -registers. The latter can be any ARM core register although registers -``R13-R15`` are unlikely to be appropriate in this context. - -Arithmetic ----------- - -* vadd(Sd, Sn, Sm) ``Sd = Sn + Sm`` -* vsub(Sd, Sn, Sm) ``Sd = Sn - Sm`` -* vneg(Sd, Sm) ``Sd = -Sm`` -* vmul(Sd, Sn, Sm) ``Sd = Sn * Sm`` -* vdiv(Sd, Sn, Sm) ``Sd = Sn / Sm`` -* vsqrt(Sd, Sm) ``Sd = sqrt(Sm)`` - -Registers may be identical: ``vmul(S0, S0, S0)`` will execute ``S0 = S0*S0`` - -Move between ARM core and FPU registers ---------------------------------------- - -* vmov(Sd, Rm) ``Sd = Rm`` -* vmov(Rd, Sm) ``Rd = Sm`` - -The FPU has a register known as FPSCR, similar to the ARM core's APSR, which stores condition -codes plus other data. The following instructions provide access to this. - -* vmrs(APSR\_nzcv, FPSCR) - -Move the floating-point N, Z, C, and V flags to the APSR N, Z, C, and V flags. - -This is done after an instruction such as an FPU -comparison to enable the condition codes to be tested by the assembler -code. The following is a more general form of the instruction. - -* vmrs(Rd, FPSCR) ``Rd = FPSCR`` - -Move between FPU register and memory ------------------------------------- - -* vldr(Sd, [Rn, offset]) ``Sd = [Rn + offset]`` -* vstr(Sd, [Rn, offset]) ``[Rn + offset] = Sd`` - -Where ``[Rn + offset]`` denotes the memory address obtained by adding Rn to the offset. This -is specified in bytes. Since each float value occupies a 32 bit word, when accessing arrays of -floats the offset must always be a multiple of four bytes. - -Data Comparison ---------------- - -* vcmp(Sd, Sm) - -Compare the values in Sd and Sm and set the FPU N, Z, -C, and V flags. This would normally be followed by ``vmrs(APSR_nzcv, FPSCR)`` -to enable the results to be tested. - -Convert between integer and float ---------------------------------- - -* vcvt\_f32\_s32(Sd, Sm) ``Sd = float(Sm)`` -* vcvt\_s32\_f32(Sd, Sm) ``Sd = int(Sm)`` diff --git a/docs/reference/asm_thumb2_hints_tips.rst b/docs/reference/asm_thumb2_hints_tips.rst deleted file mode 100644 index 062a3c8448..0000000000 --- a/docs/reference/asm_thumb2_hints_tips.rst +++ /dev/null @@ -1,244 +0,0 @@ -Hints and tips -============== - -The following are some examples of the use of the inline assembler and some -information on how to work around its limitations. In this document the term -"assembler function" refers to a function declared in Python with the -``@micropython.asm_thumb`` decorator, whereas "subroutine" refers to assembler -code called from within an assembler function. - -Code branches and subroutines ------------------------------ - -It is important to appreciate that labels are local to an assembler function. -There is currently no way for a subroutine defined in one function to be called -from another. - -To call a subroutine the instruction ``bl(LABEL)`` is issued. This transfers -control to the instruction following the ``label(LABEL)`` directive and stores -the return address in the link register (``lr`` or ``r14``). To return the -instruction ``bx(lr)`` is issued which causes execution to continue with -the instruction following the subroutine call. This mechanism implies that, if -a subroutine is to call another, it must save the link register prior to -the call and restore it before terminating. - -The following rather contrived example illustrates a function call. Note that -it's necessary at the start to branch around all subroutine calls: subroutines -end execution with ``bx(lr)`` while the outer function simply "drops off the end" -in the style of Python functions. - -:: - - @micropython.asm_thumb - def quad(r0): - b(START) - label(DOUBLE) - add(r0, r0, r0) - bx(lr) - label(START) - bl(DOUBLE) - bl(DOUBLE) - - print(quad(10)) - -The following code example demonstrates a nested (recursive) call: the classic -Fibonacci sequence. Here, prior to a recursive call, the link register is saved -along with other registers which the program logic requires to be preserved. - -:: - - @micropython.asm_thumb - def fib(r0): - b(START) - label(DOFIB) - push({r1, r2, lr}) - cmp(r0, 1) - ble(FIBDONE) - sub(r0, 1) - mov(r2, r0) # r2 = n -1 - bl(DOFIB) - mov(r1, r0) # r1 = fib(n -1) - sub(r0, r2, 1) - bl(DOFIB) # r0 = fib(n -2) - add(r0, r0, r1) - label(FIBDONE) - pop({r1, r2, lr}) - bx(lr) - label(START) - bl(DOFIB) - - for n in range(10): - print(fib(n)) - -Argument passing and return ---------------------------- - -The tutorial details the fact that assembler functions can support from zero to -three arguments, which must (if used) be named ``r0``, ``r1`` and ``r2``. When -the code executes the registers will be initialised to those values. - -The data types which can be passed in this way are integers and memory -addresses. With current firmware all possible 32 bit values may be passed and -returned. If the return value may have the most significant bit set a Python -type hint should be employed to enable MicroPython to determine whether the -value should be interpreted as a signed or unsigned integer: types are -``int`` or ``uint``. - -:: - - @micropython.asm_thumb - def uadd(r0, r1) -> uint: - add(r0, r0, r1) - -``hex(uadd(0x40000000,0x40000000))`` will return 0x80000000, demonstrating the -passing and return of integers where bits 30 and 31 differ. - -The limitations on the number of arguments and return values can be overcome by means -of the ``array`` module which enables any number of values of any type to be accessed. - -Multiple arguments -~~~~~~~~~~~~~~~~~~ - -If a Python array of integers is passed as an argument to an assembler -function, the function will receive the address of a contiguous set of integers. -Thus multiple arguments can be passed as elements of a single array. Similarly a -function can return multiple values by assigning them to array elements. -Assembler functions have no means of determining the length of an array: -this will need to be passed to the function. - -This use of arrays can be extended to enable more than three arrays to be used. -This is done using indirection: the ``uctypes`` module supports ``addressof()`` -which will return the address of an array passed as its argument. Thus you can -populate an integer array with the addresses of other arrays: - -:: - - from uctypes import addressof - @micropython.asm_thumb - def getindirect(r0): - ldr(r0, [r0, 0]) # Address of array loaded from passed array - ldr(r0, [r0, 4]) # Return element 1 of indirect array (24) - - def testindirect(): - a = array.array('i',[23, 24]) - b = array.array('i',[0,0]) - b[0] = addressof(a) - print(getindirect(b)) - -Non-integer data types -~~~~~~~~~~~~~~~~~~~~~~ - -These may be handled by means of arrays of the appropriate data type. For -example, single precision floating point data may be processed as follows. -This code example takes an array of floats and replaces its contents with -their squares. - -:: - - from array import array - - @micropython.asm_thumb - def square(r0, r1): - label(LOOP) - vldr(s0, [r0, 0]) - vmul(s0, s0, s0) - vstr(s0, [r0, 0]) - add(r0, 4) - sub(r1, 1) - bgt(LOOP) - - a = array('f', (x for x in range(10))) - square(a, len(a)) - print(a) - -The uctypes module supports the use of data structures beyond simple -arrays. It enables a Python data structure to be mapped onto a bytearray -instance which may then be passed to the assembler function. - -Named constants ---------------- - -Assembler code may be made more readable and maintainable by using named -constants rather than littering code with numbers. This may be achieved -thus: - -:: - - MYDATA = const(33) - - @micropython.asm_thumb - def foo(): - mov(r0, MYDATA) - -The const() construct causes MicroPython to replace the variable name -with its value at compile time. If constants are declared in an outer -Python scope they can be shared between multiple assembler functions and -with Python code. - -Assembler code as class methods -------------------------------- - -MicroPython passes the address of the object instance as the first argument -to class methods. This is normally of little use to an assembler function. -It can be avoided by declaring the function as a static method thus: - -:: - - class foo: - @staticmethod - @micropython.asm_thumb - def bar(r0): - add(r0, r0, r0) - -Use of unsupported instructions -------------------------------- - -These can be coded using the data statement as shown below. While -``push()`` and ``pop()`` are supported the example below illustrates the -principle. The necessary machine code may be found in the ARM v7-M -Architecture Reference Manual. Note that the first argument of data -calls such as - -:: - - data(2, 0xe92d, 0x0f00) # push r8,r9,r10,r11 - -indicates that each subsequent argument is a two byte quantity. - -Overcoming MicroPython's integer restriction --------------------------------------------- - -The Pyboard chip includes a CRC generator. Its use presents a problem in -MicroPython because the returned values cover the full gamut of 32 bit -quantities whereas small integers in MicroPython cannot have differing values -in bits 30 and 31. This limitation is overcome with the following code, which -uses assembler to put the result into an array and Python code to -coerce the result into an arbitrary precision unsigned integer. - -:: - - from array import array - import stm - - def enable_crc(): - stm.mem32[stm.RCC + stm.RCC_AHB1ENR] |= 0x1000 - - def reset_crc(): - stm.mem32[stm.CRC+stm.CRC_CR] = 1 - - @micropython.asm_thumb - def getval(r0, r1): - movwt(r3, stm.CRC + stm.CRC_DR) - str(r1, [r3, 0]) - ldr(r2, [r3, 0]) - str(r2, [r0, 0]) - - def getcrc(value): - a = array('i', [0]) - getval(a, value) - return a[0] & 0xffffffff # coerce to arbitrary precision - - enable_crc() - reset_crc() - for x in range(20): - print(hex(getcrc(0))) diff --git a/docs/reference/asm_thumb2_index.rst b/docs/reference/asm_thumb2_index.rst deleted file mode 100644 index f066e6acec..0000000000 --- a/docs/reference/asm_thumb2_index.rst +++ /dev/null @@ -1,73 +0,0 @@ -.. _asm_thumb2_index: - -Inline Assembler for Thumb2 architectures -========================================= - -This document assumes some familiarity with assembly language programming and should be read after studying -the :ref:`tutorial `. For a detailed description of the instruction set consult the -Architecture Reference Manual detailed below. -The inline assembler supports a subset of the ARM Thumb-2 instruction set described here. The syntax tries -to be as close as possible to that defined in the above ARM manual, converted to Python function calls. - -Instructions operate on 32 bit signed integer data except where stated otherwise. Most supported instructions -operate on registers ``R0-R7`` only: where ``R8-R15`` are supported this is stated. Registers ``R8-R12`` must be -restored to their initial value before return from a function. Registers ``R13-R15`` constitute the Link Register, -Stack Pointer and Program Counter respectively. - -Document conventions --------------------- - -Where possible the behaviour of each instruction is described in Python, for example - -* add(Rd, Rn, Rm) ``Rd = Rn + Rm`` - -This enables the effect of instructions to be demonstrated in Python. In certain case this is impossible -because Python doesn't support concepts such as indirection. The pseudocode employed in such cases is -described on the relevant page. - -Instruction Categories ----------------------- - -The following sections details the subset of the ARM Thumb-2 instruction set supported by MicroPython. - -.. toctree:: - :maxdepth: 1 - :numbered: - - asm_thumb2_mov.rst - asm_thumb2_ldr.rst - asm_thumb2_str.rst - asm_thumb2_logical_bit.rst - asm_thumb2_arith.rst - asm_thumb2_compare.rst - asm_thumb2_label_branch.rst - asm_thumb2_stack.rst - asm_thumb2_misc.rst - asm_thumb2_float.rst - asm_thumb2_directives.rst - -Usage examples --------------- - -These sections provide further code examples and hints on the use of the assembler. - -.. toctree:: - :maxdepth: 1 - :numbered: - - asm_thumb2_hints_tips.rst - -References ----------- - -- :ref:`Assembler Tutorial ` -- `Wiki hints and tips - `__ -- `uPy Inline Assembler source-code, - emitinlinethumb.c `__ -- `ARM Thumb2 Instruction Set Quick Reference - Card `__ -- `RM0090 Reference - Manual `__ -- ARM v7-M Architecture Reference Manual (Available on the - ARM site after a simple registration procedure. Also available on academic sites but beware of out of date versions.) diff --git a/docs/reference/asm_thumb2_label_branch.rst b/docs/reference/asm_thumb2_label_branch.rst deleted file mode 100644 index 8c85e55f0e..0000000000 --- a/docs/reference/asm_thumb2_label_branch.rst +++ /dev/null @@ -1,85 +0,0 @@ -Branch instructions -=================== - -These cause execution to jump to a target location usually specified by a label (see the ``label`` -assembler directive). Conditional branches and the ``it`` and ``ite`` instructions test -the Application Program Status Register (APSR) N (negative), Z (zero), C (carry) and V -(overflow) flags to determine whether the branch should be executed. - -Most of the exposed assembler instructions (including move operations) set the flags but -there are explicit comparison instructions to enable values to be tested. - -Further detail on the meaning of the condition flags is provided in the section -describing comparison functions. - -Document conventions --------------------- - -Notation: ``Rm`` denotes ARM registers R0-R15. ``LABEL`` denotes a label defined with the -``label()`` assembler directive. ```` indicates one of the following condition -specifiers: - -* eq Equal to (result was zero) -* ne Not equal -* cs Carry set -* cc Carry clear -* mi Minus (negative) -* pl Plus (positive) -* vs Overflow set -* vc Overflow clear -* hi > (unsigned comparison) -* ls <= (unsigned comparison) -* ge >= (signed comparison) -* lt < (signed comparison) -* gt > (signed comparison) -* le <= (signed comparison) - -Branch to label ---------------- - -* b(LABEL) Unconditional branch -* beq(LABEL) branch if equal -* bne(LABEL) branch if not equal -* bge(LABEL) branch if greater than or equal -* bgt(LABEL) branch if greater than -* blt(LABEL) branch if less than (<) (signed) -* ble(LABEL) branch if less than or equal to (<=) (signed) -* bcs(LABEL) branch if carry flag is set -* bcc(LABEL) branch if carry flag is clear -* bmi(LABEL) branch if negative -* bpl(LABEL) branch if positive -* bvs(LABEL) branch if overflow flag set -* bvc(LABEL) branch if overflow flag is clear -* bhi(LABEL) branch if higher (unsigned) -* bls(LABEL) branch if lower or equal (unsigned) - -Long branches -------------- - -The code produced by the branch instructions listed above uses a fixed bit width to specify the -branch destination, which is PC relative. Consequently in long programs where the -branch instruction is remote from its destination the assembler will produce a "branch not in -range" error. This can be overcome with the "wide" variants such as - -* beq\_w(LABEL) long branch if equal - -Wide branches use 4 bytes to encode the instruction (compared with 2 bytes for standard branch instructions). - -Subroutines (functions) ------------------------ - -When entering a subroutine the processor stores the return address in register r14, also -known as the link register (lr). Return to the instruction after the subroutine call is -performed by updating the program counter (r15 or pc) from the link register, This -process is handled by the following instructions. - -* bl(LABEL) - -Transfer execution to the instruction after ``LABEL`` storing the return address in -the link register (r14). - -* bx(Rm) Branch to address specified by Rm. - -Typically ``bx(lr)`` is issued to return from a subroutine. For nested subroutines the -link register of outer scopes must be saved (usually on the stack) before performing -inner subroutine calls. diff --git a/docs/reference/asm_thumb2_ldr.rst b/docs/reference/asm_thumb2_ldr.rst deleted file mode 100644 index 16b7729592..0000000000 --- a/docs/reference/asm_thumb2_ldr.rst +++ /dev/null @@ -1,23 +0,0 @@ -Load register from memory -========================= - -Document conventions --------------------- - -Notation: ``Rt, Rn`` denote ARM registers R0-R7 except where stated. ``immN`` represents an immediate -value having a width of N bits hence ``imm5`` is constrained to the range 0-31. ``[Rn + immN]`` is the contents -of the memory address obtained by adding Rn and the offset ``immN``. Offsets are measured in -bytes. These instructions affect the condition flags. - -Register Load -------------- - -* ldr(Rt, [Rn, imm7]) ``Rt = [Rn + imm7]`` Load a 32 bit word -* ldrb(Rt, [Rn, imm5]) ``Rt = [Rn + imm5]`` Load a byte -* ldrh(Rt, [Rn, imm6]) ``Rt = [Rn + imm6]`` Load a 16 bit half word - -Where a byte or half word is loaded, it is zero-extended to 32 bits. - -The specified immediate offsets are measured in bytes. Hence in the case of ``ldr`` the 7 bit value -enables 32 bit word aligned values to be accessed with a maximum offset of 31 words. In the case of ``ldrh`` the -6 bit value enables 16 bit half-word aligned values to be accessed with a maximum offset of 31 half-words. diff --git a/docs/reference/asm_thumb2_logical_bit.rst b/docs/reference/asm_thumb2_logical_bit.rst deleted file mode 100644 index 8c51feaf45..0000000000 --- a/docs/reference/asm_thumb2_logical_bit.rst +++ /dev/null @@ -1,53 +0,0 @@ -Logical & Bitwise instructions -============================== - -Document conventions --------------------- - -Notation: ``Rd, Rn`` denote ARM registers R0-R7 except in the case of the -special instructions where R0-R15 may be used. ``Rn`` denotes an ARM register -whose contents must lie in range ``a <= contents <= b``. In the case of instructions -with two register arguments, it is permissible for them to be identical. For example -the following will zero R0 (Python ``R0 ^= R0``) regardless of its initial contents. - -* eor(r0, r0) - -These instructions affect the condition flags except where stated. - -Logical instructions --------------------- - -* and\_(Rd, Rn) ``Rd &= Rn`` -* orr(Rd, Rn) ``Rd |= Rn`` -* eor(Rd, Rn) ``Rd ^= Rn`` -* mvn(Rd, Rn) ``Rd = Rn ^ 0xffffffff`` i.e. Rd = 1's complement of Rn -* bic(Rd, Rn) ``Rd &= ~Rn`` bit clear Rd using mask in Rn - -Note the use of "and\_" instead of "and", because "and" is a reserved keyword in Python. - -Shift and rotation instructions -------------------------------- - -* lsl(Rd, Rn<0-31>) ``Rd <<= Rn`` -* lsr(Rd, Rn<1-32>) ``Rd = (Rd & 0xffffffff) >> Rn`` Logical shift right -* asr(Rd, Rn<1-32>) ``Rd >>= Rn`` arithmetic shift right -* ror(Rd, Rn<1-31>) ``Rd = rotate_right(Rd, Rn)`` Rd is rotated right Rn bits. - -A rotation by (for example) three bits works as follows. If Rd initially -contains bits ``b31 b30..b0`` after rotation it will contain ``b2 b1 b0 b31 b30..b3`` - -Special instructions --------------------- - -Condition codes are unaffected by these instructions. - -* clz(Rd, Rn) ``Rd = count_leading_zeros(Rn)`` - -count_leading_zeros(Rn) returns the number of binary zero bits before the first binary one bit in Rn. - -* rbit(Rd, Rn) ``Rd = bit_reverse(Rn)`` - -bit_reverse(Rn) returns the bit-reversed contents of Rn. If Rn contains bits ``b31 b30..b0`` Rd will be set -to ``b0 b1 b2..b31`` - -Trailing zeros may be counted by performing a bit reverse prior to executing clz. diff --git a/docs/reference/asm_thumb2_misc.rst b/docs/reference/asm_thumb2_misc.rst deleted file mode 100644 index ca3f878cca..0000000000 --- a/docs/reference/asm_thumb2_misc.rst +++ /dev/null @@ -1,13 +0,0 @@ -Miscellaneous instructions -========================== - -* nop() ``pass`` no operation. -* wfi() Suspend execution in a low power state until an interrupt occurs. -* cpsid(flags) set the Priority Mask Register - disable interrupts. -* cpsie(flags) clear the Priority Mask Register - enable interrupts. -* mrs(Rd, special_reg) ``Rd = special_reg`` copy a special register to a general register. The special register - may be IPSR (Interrupt Status Register) or BASEPRI (Base Priority Register). The IPSR provides a means of determining - the exception number of an interrupt being processed. It contains zero if no interrupt is being processed. - -Currently the ``cpsie()`` and ``cpsid()`` functions are partially implemented. -They require but ignore the flags argument and serve as a means of enabling and disabling interrupts. diff --git a/docs/reference/asm_thumb2_mov.rst b/docs/reference/asm_thumb2_mov.rst deleted file mode 100644 index 900bf957b6..0000000000 --- a/docs/reference/asm_thumb2_mov.rst +++ /dev/null @@ -1,27 +0,0 @@ -Register move instructions -========================== - -Document conventions --------------------- - -Notation: ``Rd, Rn`` denote ARM registers R0-R15. ``immN`` denotes an immediate -value having a width of N bits. These instructions affect the condition flags. - -Register moves --------------- - -Where immediate values are used, these are zero-extended to 32 bits. Thus -``mov(R0, 0xff)`` will set R0 to 255. - -* mov(Rd, imm8) ``Rd = imm8`` -* mov(Rd, Rn) ``Rd = Rn`` -* movw(Rd, imm16) ``Rd = imm16`` -* movt(Rd, imm16) ``Rd = (Rd & 0xffff) | (imm16 << 16)`` - -movt writes an immediate value to the top halfword of the destination register. -It does not affect the contents of the bottom halfword. - -* movwt(Rd, imm32) ``Rd = imm32`` - -movwt is a pseudo-instruction: the MicroPython assembler emits a ``movw`` followed -by a ``movt`` to move a 32-bit value into Rd. diff --git a/docs/reference/asm_thumb2_stack.rst b/docs/reference/asm_thumb2_stack.rst deleted file mode 100644 index bffbab277c..0000000000 --- a/docs/reference/asm_thumb2_stack.rst +++ /dev/null @@ -1,20 +0,0 @@ -Stack push and pop -================== - -Document conventions --------------------- - -The ``push()`` and ``pop()`` instructions accept as their argument a register set containing -a subset, or possibly all, of the general-purpose registers R0-R12 and the link register (lr or R14). -As with any Python set the order in which the registers are specified is immaterial. Thus the -in the following example the pop() instruction would restore R1, R7 and R8 to their contents prior -to the push(): - -* push({r1, r8, r7}) Save three registers on the stack. -* pop({r7, r1, r8}) Restore them - -Stack operations ----------------- - -* push({regset}) Push a set of registers onto the stack -* pop({regset}) Restore a set of registers from the stack diff --git a/docs/reference/asm_thumb2_str.rst b/docs/reference/asm_thumb2_str.rst deleted file mode 100644 index 5a88b091bd..0000000000 --- a/docs/reference/asm_thumb2_str.rst +++ /dev/null @@ -1,21 +0,0 @@ -Store register to memory -======================== - -Document conventions --------------------- - -Notation: ``Rt, Rn`` denote ARM registers R0-R7 except where stated. ``immN`` represents an immediate -value having a width of N bits hence ``imm5`` is constrained to the range 0-31. ``[Rn + imm5]`` is the -contents of the memory address obtained by adding Rn and the offset ``imm5``. Offsets are measured in -bytes. These instructions do not affect the condition flags. - -Register Store --------------- - -* str(Rt, [Rn, imm7]) ``[Rn + imm7] = Rt`` Store a 32 bit word -* strb(Rt, [Rn, imm5]) ``[Rn + imm5] = Rt`` Store a byte (b0-b7) -* strh(Rt, [Rn, imm6]) ``[Rn + imm6] = Rt`` Store a 16 bit half word (b0-b15) - -The specified immediate offsets are measured in bytes. Hence in the case of ``str`` the 7 bit value -enables 32 bit word aligned values to be accessed with a maximum offset of 31 words. In the case of ``strh`` the -6 bit value enables 16 bit half-word aligned values to be accessed with a maximum offset of 31 half-words. diff --git a/docs/reference/constrained.rst b/docs/reference/constrained.rst deleted file mode 100644 index 14286aa262..0000000000 --- a/docs/reference/constrained.rst +++ /dev/null @@ -1,456 +0,0 @@ -.. _constrained: - -MicroPython on Microcontrollers -=============================== - -MicroPython is designed to be capable of running on microcontrollers. These -have hardware limitations which may be unfamiliar to programmers more familiar -with conventional computers. In particular the amount of RAM and nonvolatile -"disk" (flash memory) storage is limited. This tutorial offers ways to make -the most of the limited resources. Because MicroPython runs on controllers -based on a variety of architectures, the methods presented are generic: in some -cases it will be necessary to obtain detailed information from platform specific -documentation. - -Flash Memory ------------- - -On the Pyboard the simple way to address the limited capacity is to fit a micro -SD card. In some cases this is impractical, either because the device does not -have an SD card slot or for reasons of cost or power consumption; hence the -on-chip flash must be used. The firmware including the MicroPython subsystem is -stored in the onboard flash. The remaining capacity is available for use. For -reasons connected with the physical architecture of the flash memory part of -this capacity may be inaccessible as a filesystem. In such cases this space may -be employed by incorporating user modules into a firmware build which is then -flashed to the device. - -There are two ways to achieve this: frozen modules and frozen bytecode. Frozen -modules store the Python source with the firmware. Frozen bytecode uses the -cross compiler to convert the source to bytecode which is then stored with the -firmware. In either case the module may be accessed with an import statement: - -.. code:: - - import mymodule - -The procedure for producing frozen modules and bytecode is platform dependent; -instructions for building the firmware can be found in the README files in the -relevant part of the source tree. - -In general terms the steps are as follows: - -* Clone the MicroPython `repository `_. -* Acquire the (platform specific) toolchain to build the firmware. -* Build the cross compiler. -* Place the modules to be frozen in a specified directory (dependent on whether - the module is to be frozen as source or as bytecode). -* Build the firmware. A specific command may be required to build frozen - code of either type - see the platform documentation. -* Flash the firmware to the device. - -RAM ---- - -When reducing RAM usage there are two phases to consider: compilation and -execution. In addition to memory consumption, there is also an issue known as -heap fragmentation. In general terms it is best to minimise the repeated -creation and destruction of objects. The reason for this is covered in the -section covering the `heap`_. - -Compilation Phase -~~~~~~~~~~~~~~~~~ - -When a module is imported, MicroPython compiles the code to bytecode which is -then executed by the MicroPython virtual machine (VM). The bytecode is stored -in RAM. The compiler itself requires RAM, but this becomes available for use -when the compilation has completed. - -If a number of modules have already been imported the situation can arise where -there is insufficient RAM to run the compiler. In this case the import -statement will produce a memory exception. - -If a module instantiates global objects on import it will consume RAM at the -time of import, which is then unavailable for the compiler to use on subsequent -imports. In general it is best to avoid code which runs on import; a better -approach is to have initialisation code which is run by the application after -all modules have been imported. This maximises the RAM available to the -compiler. - -If RAM is still insufficient to compile all modules one solution is to -precompile modules. MicroPython has a cross compiler capable of compiling Python -modules to bytecode (see the README in the mpy-cross directory). The resulting -bytecode file has a .mpy extension; it may be copied to the filesystem and -imported in the usual way. Alternatively some or all modules may be implemented -as frozen bytecode: on most platforms this saves even more RAM as the bytecode -is run directly from flash rather than being stored in RAM. - -Execution Phase -~~~~~~~~~~~~~~~ - -There are a number of coding techniques for reducing RAM usage. - -**Constants** - -MicroPython provides a ``const`` keyword which may be used as follows: - -.. code:: - - from micropython import const - ROWS = const(33) - _COLS = const(0x10) - a = ROWS - b = _COLS - -In both instances where the constant is assigned to a variable the compiler -will avoid coding a lookup to the name of the constant by substituting its -literal value. This saves bytecode and hence RAM. However the ``ROWS`` value -will occupy at least two machine words, one each for the key and value in the -globals dictionary. The presence in the dictionary is necessary because another -module might import or use it. This RAM can be saved by prepending the name -with an underscore as in ``_COLS``: this symbol is not visible outside the -module so will not occupy RAM. - -The argument to ``const()`` may be anything which, at compile time, evaluates -to an integer e.g. ``0x100`` or ``1 << 8``. It can even include other const -symbols that have already been defined, e.g. ``1 << BIT``. - -**Constant data structures** - -Where there is a substantial volume of constant data and the platform supports -execution from Flash, RAM may be saved as follows. The data should be located in -Python modules and frozen as bytecode. The data must be defined as `bytes` -objects. The compiler 'knows' that `bytes` objects are immutable and ensures -that the objects remain in flash memory rather than being copied to RAM. The -`ustruct` module can assist in converting between `bytes` types and other -Python built-in types. - -When considering the implications of frozen bytecode, note that in Python -strings, floats, bytes, integers and complex numbers are immutable. Accordingly -these will be frozen into flash. Thus, in the line - -.. code:: - - mystring = "The quick brown fox" - -the actual string "The quick brown fox" will reside in flash. At runtime a -reference to the string is assigned to the *variable* ``mystring``. The reference -occupies a single machine word. In principle a long integer could be used to -store constant data: - -.. code:: - - bar = 0xDEADBEEF0000DEADBEEF - -As in the string example, at runtime a reference to the arbitrarily large -integer is assigned to the variable ``bar``. That reference occupies a -single machine word. - -It might be expected that tuples of integers could be employed for the purpose -of storing constant data with minimal RAM use. With the current compiler this -is ineffective (the code works, but RAM is not saved). - -.. code:: - - foo = (1, 2, 3, 4, 5, 6, 100000) - -At runtime the tuple will be located in RAM. This may be subject to future -improvement. - -**Needless object creation** - -There are a number of situations where objects may unwittingly be created and -destroyed. This can reduce the usability of RAM through fragmentation. The -following sections discuss instances of this. - -**String concatenation** - -Consider the following code fragments which aim to produce constant strings: - -.. code:: - - var = "foo" + "bar" - var1 = "foo" "bar" - var2 = """\ - foo\ - bar""" - -Each produces the same outcome, however the first needlessly creates two string -objects at runtime, allocates more RAM for concatenation before producing the -third. The others perform the concatenation at compile time which is more -efficient, reducing fragmentation. - -Where strings must be dynamically created before being fed to a stream such as -a file it will save RAM if this is done in a piecemeal fashion. Rather than -creating a large string object, create a substring and feed it to the stream -before dealing with the next. - -The best way to create dynamic strings is by means of the string `format` -method: - -.. code:: - - var = "Temperature {:5.2f} Pressure {:06d}\n".format(temp, press) - -**Buffers** - -When accessing devices such as instances of UART, I2C and SPI interfaces, using -pre-allocated buffers avoids the creation of needless objects. Consider these -two loops: - -.. code:: - - while True: - var = spi.read(100) - # process data - - buf = bytearray(100) - while True: - spi.readinto(buf) - # process data in buf - -The first creates a buffer on each pass whereas the second re-uses a pre-allocated -buffer; this is both faster and more efficient in terms of memory fragmentation. - -**Bytes are smaller than ints** - -On most platforms an integer consumes four bytes. Consider the two calls to the -function ``foo()``: - -.. code:: - - def foo(bar): - for x in bar: - print(x) - foo((1, 2, 0xff)) - foo(b'\1\2\xff') - -In the first call a tuple of integers is created in RAM. The second efficiently -creates a `bytes` object consuming the minimum amount of RAM. If the module -were frozen as bytecode, the `bytes` object would reside in flash. - -**Strings Versus Bytes** - -Python3 introduced Unicode support. This introduced a distinction between a -string and an array of bytes. MicroPython ensures that Unicode strings take no -additional space so long as all characters in the string are ASCII (i.e. have -a value < 126). If values in the full 8-bit range are required `bytes` and -`bytearray` objects can be used to ensure that no additional space will be -required. Note that most string methods (e.g. :meth:`str.strip()`) apply also to `bytes` -instances so the process of eliminating Unicode can be painless. - -.. code:: - - s = 'the quick brown fox' # A string instance - b = b'the quick brown fox' # A bytes instance - -Where it is necessary to convert between strings and bytes the :meth:`str.encode` -and the :meth:`bytes.decode` methods can be used. Note that both strings and bytes -are immutable. Any operation which takes as input such an object and produces -another implies at least one RAM allocation to produce the result. In the -second line below a new bytes object is allocated. This would also occur if ``foo`` -were a string. - -.. code:: - - foo = b' empty whitespace' - foo = foo.lstrip() - -**Runtime compiler execution** - -The Python funcitons `eval` and `exec` invoke the compiler at runtime, which -requires significant amounts of RAM. Note that the `pickle` library from -`micropython-lib` employs `exec`. It may be more RAM efficient to use the -`ujson` library for object serialisation. - -**Storing strings in flash** - -Python strings are immutable hence have the potential to be stored in read only -memory. The compiler can place in flash strings defined in Python code. As with -frozen modules it is necessary to have a copy of the source tree on the PC and -the toolchain to build the firmware. The procedure will work even if the -modules have not been fully debugged, so long as they can be imported and run. - -After importing the modules, execute: - -.. code:: - - micropython.qstr_info(1) - -Then copy and paste all the Q(xxx) lines into a text editor. Check for and -remove lines which are obviously invalid. Open the file qstrdefsport.h which -will be found in stmhal (or the equivalent directory for the architecture in -use). Copy and paste the corrected lines at the end of the file. Save the file, -rebuild and flash the firmware. The outcome can be checked by importing the -modules and again issuing: - -.. code:: - - micropython.qstr_info(1) - -The Q(xxx) lines should be gone. - -.. _heap: - -The Heap --------- - -When a running program instantiates an object the necessary RAM is allocated -from a fixed size pool known as the heap. When the object goes out of scope (in -other words becomes inaccessible to code) the redundant object is known as -"garbage". A process known as "garbage collection" (GC) reclaims that memory, -returning it to the free heap. This process runs automatically, however it can -be invoked directly by issuing `gc.collect()`. - -The discourse on this is somewhat involved. For a 'quick fix' issue the -following periodically: - -.. code:: - - gc.collect() - gc.threshold(gc.mem_free() // 4 + gc.mem_alloc()) - -Fragmentation -~~~~~~~~~~~~~ - -Say a program creates an object ``foo``, then an object ``bar``. Subsequently -``foo`` goes out of scope but ``bar`` remains. The RAM used by ``foo`` will be -reclaimed by GC. However if ``bar`` was allocated to a higher address, the -RAM reclaimed from ``foo`` will only be of use for objects no bigger than -``foo``. In a complex or long running program the heap can become fragmented: -despite there being a substantial amount of RAM available, there is insufficient -contiguous space to allocate a particular object, and the program fails with a -memory error. - -The techniques outlined above aim to minimise this. Where large permanent buffers -or other objects are required it is best to instantiate these early in the -process of program execution before fragmentation can occur. Further improvements -may be made by monitoring the state of the heap and by controlling GC; these are -outlined below. - -Reporting -~~~~~~~~~ - -A number of library functions are available to report on memory allocation and -to control GC. These are to be found in the `gc` and `micropython` modules. -The following example may be pasted at the REPL (``ctrl e`` to enter paste mode, -``ctrl d`` to run it). - -.. code:: - - import gc - import micropython - gc.collect() - micropython.mem_info() - print('-----------------------------') - print('Initial free: {} allocated: {}'.format(gc.mem_free(), gc.mem_alloc())) - def func(): - a = bytearray(10000) - gc.collect() - print('Func definition: {} allocated: {}'.format(gc.mem_free(), gc.mem_alloc())) - func() - print('Func run free: {} allocated: {}'.format(gc.mem_free(), gc.mem_alloc())) - gc.collect() - print('Garbage collect free: {} allocated: {}'.format(gc.mem_free(), gc.mem_alloc())) - print('-----------------------------') - micropython.mem_info(1) - -Methods employed above: - -* `gc.collect()` Force a garbage collection. See footnote. -* `micropython.mem_info()` Print a summary of RAM utilisation. -* `gc.mem_free()` Return the free heap size in bytes. -* `gc.mem_alloc()` Return the number of bytes currently allocated. -* ``micropython.mem_info(1)`` Print a table of heap utilisation (detailed below). - -The numbers produced are dependent on the platform, but it can be seen that -declaring the function uses a small amount of RAM in the form of bytecode -emitted by the compiler (the RAM used by the compiler has been reclaimed). -Running the function uses over 10KiB, but on return ``a`` is garbage because it -is out of scope and cannot be referenced. The final `gc.collect()` recovers -that memory. - -The final output produced by ``micropython.mem_info(1)`` will vary in detail but -may be interpreted as follows: - -====== ================= -Symbol Meaning -====== ================= - . free block - h head block - = tail block - m marked head block - T tuple - L list - D dict - F float - B byte code - M module -====== ================= - -Each letter represents a single block of memory, a block being 16 bytes. So each -line of the heap dump represents 0x400 bytes or 1KiB of RAM. - -Control of Garbage Collection -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -A GC can be demanded at any time by issuing `gc.collect()`. It is advantageous -to do this at intervals, firstly to pre-empt fragmentation and secondly for -performance. A GC can take several milliseconds but is quicker when there is -little work to do (about 1ms on the Pyboard). An explicit call can minimise that -delay while ensuring it occurs at points in the program when it is acceptable. - -Automatic GC is provoked under the following circumstances. When an attempt at -allocation fails, a GC is performed and the allocation re-tried. Only if this -fails is an exception raised. Secondly an automatic GC will be triggered if the -amount of free RAM falls below a threshold. This threshold can be adapted as -execution progresses: - -.. code:: - - gc.collect() - gc.threshold(gc.mem_free() // 4 + gc.mem_alloc()) - -This will provoke a GC when more than 25% of the currently free heap becomes -occupied. - -In general modules should instantiate data objects at runtime using constructors -or other initialisation functions. The reason is that if this occurs on -initialisation the compiler may be starved of RAM when subsequent modules are -imported. If modules do instantiate data on import then `gc.collect()` issued -after the import will ameliorate the problem. - -String Operations ------------------ - -MicroPython handles strings in an efficient manner and understanding this can -help in designing applications to run on microcontrollers. When a module -is compiled, strings which occur multiple times are stored once only, a process -known as string interning. In MicroPython an interned string is known as a ``qstr``. -In a module imported normally that single instance will be located in RAM, but -as described above, in modules frozen as bytecode it will be located in flash. - -String comparisons are also performed efficiently using hashing rather than -character by character. The penalty for using strings rather than integers may -hence be small both in terms of performance and RAM usage - a fact which may -come as a surprise to C programmers. - -Postscript ----------- - -MicroPython passes, returns and (by default) copies objects by reference. A -reference occupies a single machine word so these processes are efficient in -RAM usage and speed. - -Where variables are required whose size is neither a byte nor a machine word -there are standard libraries which can assist in storing these efficiently and -in performing conversions. See the `array`, `ustruct` and `uctypes` -modules. - -Footnote: gc.collect() return value -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -On Unix and Windows platforms the `gc.collect()` method returns an integer -which signifies the number of distinct memory regions that were reclaimed in the -collection (more precisely, the number of heads that were turned into frees). For -efficiency reasons bare metal ports do not return this value. diff --git a/docs/reference/glossary.rst b/docs/reference/glossary.rst deleted file mode 100644 index 98979afa92..0000000000 --- a/docs/reference/glossary.rst +++ /dev/null @@ -1,105 +0,0 @@ -Glossary -======== - -.. glossary:: - - baremetal - A system without (full-fledged) OS, like an :term:`MCU`. When - running on a baremetal system, MicroPython effectively becomes - its user-facing OS with a command interpreter (REPL). - - board - A PCB board. Oftentimes, the term is used to denote a particular - model of an :term:`MCU` system. Sometimes, it is used to actually - refer to :term:`MicroPython port` to a particular board (and then - may also refer to "boardless" ports like - :term:`Unix port `). - - CPython - CPython is the reference implementation of Python programming - language, and the most well-known one, which most of the people - run. It is however one of many implementations (among which - Jython, IronPython, PyPy, and many more, including MicroPython). - As there is no formal specification of the Python language, only - CPython documentation, it is not always easy to draw a line - between Python the language and CPython its particular - implementation. This however leaves more freedom for other - implementations. For example, MicroPython does a lot of things - differently than CPython, while still aspiring to be a Python - language implementation. - - GPIO - General-purpose input/output. The simplest means to control - electrical signals. With GPIO, user can configure hardware - signal pin to be either input or output, and set or get - its digital signal value (logical "0" or "1"). MicroPython - abstracts GPIO access using :class:`machine.Pin` and :class:`machine.Signal` - classes. - - GPIO port - A group of :term:`GPIO` pins, usually based on hardware - properties of these pins (e.g. controllable by the same - register). - - MCU - Microcontroller. Microcontrollers usually have much less resources - than a full-fledged computing system, but smaller, cheaper and - require much less power. MicroPython is designed to be small and - optimized enough to run on an average modern microcontroller. - - micropython-lib - MicroPython is (usually) distributed as a single executable/binary - file with just few builtin modules. There is no extensive standard - library comparable with :term:`CPython`. Instead, there is a related, but - separate project - `micropython-lib `_ - which provides implementations for many modules from CPython's - standard library. However, large subset of these modules require - POSIX-like environment (Linux, MacOS, Windows may be partially - supported), and thus would work or make sense only with MicroPython - Unix port. Some subset of modules is however usable for baremetal ports - too. - - Unlike monolithic :term:`CPython` stdlib, micropython-lib modules - are intended to be installed individually - either using manual - copying or using :term:`upip`. - - MicroPython port - MicroPython supports different :term:`boards `, RTOSes, - and OSes, and can be relatively easily adapted to new systems. - MicroPython with support for a particular system is called a - "port" to that system. Different ports may have widely different - functionality. This documentation is intended to be a reference - of the generic APIs available across different ports ("MicroPython - core"). Note that some ports may still omit some APIs described - here (e.g. due to resource constraints). Any such differences, - and port-specific extensions beyond MicroPython core functionality, - would be described in the separate port-specific documentation. - - MicroPython Unix port - Unix port is one of the major :term:`MicroPython ports `. - It is intended to run on POSIX-compatible operating systems, like - Linux, MacOS, FreeBSD, Solaris, etc. It also serves as the basis - of Windows port. The importance of Unix port lies in the fact - that while there are many different :term:`boards `, so - two random users unlikely have the same board, almost all modern - OSes have some level of POSIX compatibility, so Unix port serves - as a kind of "common ground" to which any user can have access. - So, Unix port is used for initial prototyping, different kinds - of testing, development of machine-independent features, etc. - All users of MicroPython, even those which are interested only - in running MicroPython on :term:`MCU` systems, are recommended - to be familiar with Unix (or Windows) port, as it is important - productivity helper and a part of normal MicroPython workflow. - - port - Either :term:`MicroPython port` or :term:`GPIO port`. If not clear - from context, it's recommended to use full specification like one - of the above. - - upip - (Literally, "micro pip"). A package manage for MicroPython, inspired - by :term:`CPython`'s pip, but much smaller and with reduced functionality. - upip runs both on :term:`Unix port ` and on - :term:`baremetal` ports (those which offer filesystem and networking - support). diff --git a/docs/reference/index.rst b/docs/reference/index.rst deleted file mode 100644 index 4d822d6fa6..0000000000 --- a/docs/reference/index.rst +++ /dev/null @@ -1,33 +0,0 @@ -The MicroPython language -======================== - -MicroPython aims to implement the Python 3.4 standard (with selected -features from later versions) with respect to language syntax, and most -of the features of MicroPython are identical to those described by the -"Language Reference" documentation at -`docs.python.org `_. - -The MicroPython standard library is described in the -:ref:`corresponding chapter `. The :ref:`cpython_diffs` -chapter describes differences between MicroPython and CPython (which -mostly concern standard library and types, but also some language-level -features). - -This chapter describes features and peculiarities of MicroPython -implementation and the best practices to use them. - -.. toctree:: - :maxdepth: 1 - - glossary.rst - repl.rst - isr_rules.rst - speed_python.rst - constrained.rst - -.. only:: port_pyboard - - .. toctree:: - :maxdepth: 1 - - asm_thumb2_index.rst diff --git a/docs/reference/isr_rules.rst b/docs/reference/isr_rules.rst deleted file mode 100644 index 23dcfd01f4..0000000000 --- a/docs/reference/isr_rules.rst +++ /dev/null @@ -1,332 +0,0 @@ -.. _isr_rules: - -Writing interrupt handlers -========================== - -On suitable hardware MicroPython offers the ability to write interrupt handlers in Python. Interrupt handlers -- also known as interrupt service routines (ISR's) - are defined as callback functions. These are executed -in response to an event such as a timer trigger or a voltage change on a pin. Such events can occur at any point -in the execution of the program code. This carries significant consequences, some specific to the MicroPython -language. Others are common to all systems capable of responding to real time events. This document covers -the language specific issues first, followed by a brief introduction to real time programming for those new to it. - -This introduction uses vague terms like "slow" or "as fast as possible". This is deliberate, as speeds are -application dependent. Acceptable durations for an ISR are dependent on the rate at which interrupts occur, -the nature of the main program, and the presence of other concurrent events. - -Tips and recommended practices ------------------------------- - -This summarises the points detailed below and lists the principal recommendations for interrupt handler code. - -* Keep the code as short and simple as possible. -* Avoid memory allocation: no appending to lists or insertion into dictionaries, no floating point. -* Where an ISR returns multiple bytes use a pre-allocated ``bytearray``. If multiple integers are to be - shared between an ISR and the main program consider an array (``array.array``). -* Where data is shared between the main program and an ISR, consider disabling interrupts prior to accessing - the data in the main program and re-enabling them immediately afterwards (see Critical Sections). -* Allocate an emergency exception buffer (see below). - - -MicroPython Issues ------------------- - -The emergency exception buffer -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -If an error occurs in an ISR, MicroPython is unable to produce an error report unless a special buffer is created -for the purpose. Debugging is simplified if the following code is included in any program using interrupts. - -.. code:: python - - import micropython - micropython.alloc_emergency_exception_buf(100) - -Simplicity -~~~~~~~~~~ - -For a variety of reasons it is important to keep ISR code as short and simple as possible. It should do only what -has to be done immediately after the event which caused it: operations which can be deferred should be delegated -to the main program loop. Typically an ISR will deal with the hardware device which caused the interrupt, making -it ready for the next interrupt to occur. It will communicate with the main loop by updating shared data to indicate -that the interrupt has occurred, and it will return. An ISR should return control to the main loop as quickly -as possible. This is not a specific MicroPython issue so is covered in more detail :ref:`below `. - -Communication between an ISR and the main program -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -Normally an ISR needs to communicate with the main program. The simplest means of doing this is via one or more -shared data objects, either declared as global or shared via a class (see below). There are various restrictions -and hazards around doing this, which are covered in more detail below. Integers, ``bytes`` and ``bytearray`` objects -are commonly used for this purpose along with arrays (from the array module) which can store various data types. - -The use of object methods as callbacks -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -MicroPython supports this powerful technique which enables an ISR to share instance variables with the underlying -code. It also enables a class implementing a device driver to support multiple device instances. The following -example causes two LED's to flash at different rates. - -.. code:: python - - import pyb, micropython - micropython.alloc_emergency_exception_buf(100) - class Foo(object): - def __init__(self, timer, led): - self.led = led - timer.callback(self.cb) - def cb(self, tim): - self.led.toggle() - - red = Foo(pyb.Timer(4, freq=1), pyb.LED(1)) - greeen = Foo(pyb.Timer(2, freq=0.8), pyb.LED(2)) - -In this example the ``red`` instance associates timer 4 with LED 1: when a timer 4 interrupt occurs ``red.cb()`` -is called causing LED 1 to change state. The ``green`` instance operates similarly: a timer 2 interrupt -results in the execution of ``green.cb()`` and toggles LED 2. The use of instance methods confers two -benefits. Firstly a single class enables code to be shared between multiple hardware instances. Secondly, as -a bound method the callback function's first argument is ``self``. This enables the callback to access instance -data and to save state between successive calls. For example, if the class above had a variable ``self.count`` -set to zero in the constructor, ``cb()`` could increment the counter. The ``red`` and ``green`` instances would -then maintain independent counts of the number of times each LED had changed state. - -Creation of Python objects -~~~~~~~~~~~~~~~~~~~~~~~~~~ - -ISR's cannot create instances of Python objects. This is because MicroPython needs to allocate memory for the -object from a store of free memory block called the heap. This is not permitted in an interrupt handler because -heap allocation is not re-entrant. In other words the interrupt might occur when the main program is part way -through performing an allocation - to maintain the integrity of the heap the interpreter disallows memory -allocations in ISR code. - -A consequence of this is that ISR's can't use floating point arithmetic; this is because floats are Python objects. Similarly -an ISR can't append an item to a list. In practice it can be hard to determine exactly which code constructs will -attempt to perform memory allocation and provoke an error message: another reason for keeping ISR code short and simple. - -One way to avoid this issue is for the ISR to use pre-allocated buffers. For example a class constructor -creates a ``bytearray`` instance and a boolean flag. The ISR method assigns data to locations in the buffer and sets -the flag. The memory allocation occurs in the main program code when the object is instantiated rather than in the ISR. - -The MicroPython library I/O methods usually provide an option to use a pre-allocated buffer. For -example ``pyb.i2c.recv()`` can accept a mutable buffer as its first argument: this enables its use in an ISR. - -A means of creating an object without employing a class or globals is as follows: - -.. code:: python - - def set_volume(t, buf=bytearray(3)): - buf[0] = 0xa5 - buf[1] = t >> 4 - buf[2] = 0x5a - return buf - -The compiler instantiates the default ``buf`` argument when the function is -loaded for the first time (usually when the module it's in is imported). - -Use of Python objects -~~~~~~~~~~~~~~~~~~~~~ - -A further restriction on objects arises because of the way Python works. When an ``import`` statement is executed the -Python code is compiled to bytecode, with one line of code typically mapping to multiple bytecodes. When the code -runs the interpreter reads each bytecode and executes it as a series of machine code instructions. Given that an -interrupt can occur at any time between machine code instructions, the original line of Python code may be only -partially executed. Consequently a Python object such as a set, list or dictionary modified in the main loop -may lack internal consistency at the moment the interrupt occurs. - -A typical outcome is as follows. On rare occasions the ISR will run at the precise moment in time when the object -is partially updated. When the ISR tries to read the object, a crash results. Because such problems typically occur -on rare, random occasions they can be hard to diagnose. There are ways to circumvent this issue, described in -:ref:`Critical Sections ` below. - -It is important to be clear about what constitutes the modification of an object. An alteration to a built-in type -such as a dictionary is problematic. Altering the contents of an array or bytearray is not. This is because bytes -or words are written as a single machine code instruction which is not interruptible: in the parlance of real time -programming the write is atomic. A user defined object might instantiate an integer, array or bytearray. It is valid -for both the main loop and the ISR to alter the contents of these. - -MicroPython supports integers of arbitrary precision. Values between 2**30 -1 and -2**30 will be stored in -a single machine word. Larger values are stored as Python objects. Consequently changes to long integers cannot -be considered atomic. The use of long integers in ISR's is unsafe because memory allocation may be -attempted as the variable's value changes. - -Overcoming the float limitation -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -In general it is best to avoid using floats in ISR code: hardware devices normally handle integers and conversion -to floats is normally done in the main loop. However there are a few DSP algorithms which require floating point. -On platforms with hardware floating point (such as the Pyboard) the inline ARM Thumb assembler can be used to work -round this limitation. This is because the processor stores float values in a machine word; values can be shared -between the ISR and main program code via an array of floats. - -Exceptions ----------- - -If an ISR raises an exception it will not propagate to the main loop. The interrupt will be disabled unless the -exception is handled by the ISR code. - -General Issues --------------- - -This is merely a brief introduction to the subject of real time programming. Beginners should note -that design errors in real time programs can lead to faults which are particularly hard to diagnose. This is because -they can occur rarely and at intervals which are essentially random. It is crucial to get the initial design right and -to anticipate issues before they arise. Both interrupt handlers and the main program need to be designed -with an appreciation of the following issues. - -.. _ISR: - -Interrupt Handler Design -~~~~~~~~~~~~~~~~~~~~~~~~ - -As mentioned above, ISR's should be designed to be as simple as possible. They should always return in a short, -predictable period of time. This is important because when the ISR is running, the main loop is not: inevitably -the main loop experiences pauses in its execution at random points in the code. Such pauses can be a source of hard -to diagnose bugs particularly if their duration is long or variable. In order to understand the implications of -ISR run time, a basic grasp of interrupt priorities is required. - -Interrupts are organised according to a priority scheme. ISR code may itself be interrupted by a higher priority -interrupt. This has implications if the two interrupts share data (see Critical Sections below). If such an interrupt -occurs it interposes a delay into the ISR code. If a lower priority interrupt occurs while the ISR is running, it -will be delayed until the ISR is complete: if the delay is too long, the lower priority interrupt may fail. A -further issue with slow ISR's is the case where a second interrupt of the same type occurs during its execution. -The second interrupt will be handled on termination of the first. However if the rate of incoming interrupts -consistently exceeds the capacity of the ISR to service them the outcome will not be a happy one. - -Consequently looping constructs should be avoided or minimised. I/O to devices other than to the interrupting device -should normally be avoided: I/O such as disk access, ``print`` statements and UART access is relatively slow, and -its duration may vary. A further issue here is that filesystem functions are not reentrant: using filesystem I/O -in an ISR and the main program would be hazardous. Crucially ISR code should not wait on an event. I/O is acceptable -if the code can be guaranteed to return in a predictable period, for example toggling a pin or LED. Accessing the -interrupting device via I2C or SPI may be necessary but the time taken for such accesses should be calculated or -measured and its impact on the application assessed. - -There is usually a need to share data between the ISR and the main loop. This may be done either through global -variables or via class or instance variables. Variables are typically integer or boolean types, or integer or byte -arrays (a pre-allocated integer array offers faster access than a list). Where multiple values are modified by -the ISR it is necessary to consider the case where the interrupt occurs at a time when the main program has -accessed some, but not all, of the values. This can lead to inconsistencies. - -Consider the following design. An ISR stores incoming data in a bytearray, then adds the number of bytes -received to an integer representing total bytes ready for processing. The main program reads the number of bytes, -processes the bytes, then clears down the number of bytes ready. This will work until an interrupt occurs just -after the main program has read the number of bytes. The ISR puts the added data into the buffer and updates -the number received, but the main program has already read the number, so processes the data originally received. -The newly arrived bytes are lost. - -There are various ways of avoiding this hazard, the simplest being to use a circular buffer. If it is not possible -to use a structure with inherent thread safety other ways are described below. - -Reentrancy -~~~~~~~~~~ - -A potential hazard may occur if a function or method is shared between the main program and one or more ISR's or -between multiple ISR's. The issue here is that the function may itself be interrupted and a further instance of -that function run. If this is to occur, the function must be designed to be reentrant. How this is done is an -advanced topic beyond the scope of this tutorial. - -.. _Critical: - -Critical Sections -~~~~~~~~~~~~~~~~~ - -An example of a critical section of code is one which accesses more than one variable which can be affected by an ISR. If -the interrupt happens to occur between accesses to the individual variables, their values will be inconsistent. This is -an instance of a hazard known as a race condition: the ISR and the main program loop race to alter the variables. To -avoid inconsistency a means must be employed to ensure that the ISR does not alter the values for the duration of -the critical section. One way to achieve this is to issue ``pyb.disable_irq()`` before the start of the section, and -``pyb.enable_irq()`` at the end. Here is an example of this approach: - -.. code:: python - - import pyb, micropython, array - micropython.alloc_emergency_exception_buf(100) - - class BoundsException(Exception): - pass - - ARRAYSIZE = const(20) - index = 0 - data = array.array('i', 0 for x in range(ARRAYSIZE)) - - def callback1(t): - global data, index - for x in range(5): - data[index] = pyb.rng() # simulate input - index += 1 - if index >= ARRAYSIZE: - raise BoundsException('Array bounds exceeded') - - tim4 = pyb.Timer(4, freq=100, callback=callback1) - - for loop in range(1000): - if index > 0: - irq_state = pyb.disable_irq() # Start of critical section - for x in range(index): - print(data[x]) - index = 0 - pyb.enable_irq(irq_state) # End of critical section - print('loop {}'.format(loop)) - pyb.delay(1) - - tim4.callback(None) - -A critical section can comprise a single line of code and a single variable. Consider the following code fragment. - -.. code:: python - - count = 0 - def cb(): # An interrupt callback - count +=1 - def main(): - # Code to set up the interrupt callback omitted - while True: - count += 1 - -This example illustrates a subtle source of bugs. The line ``count += 1`` in the main loop carries a specific race -condition hazard known as a read-modify-write. This is a classic cause of bugs in real time systems. In the main loop -MicroPython reads the value of ``t.counter``, adds 1 to it, and writes it back. On rare occasions the interrupt occurs -after the read and before the write. The interrupt modifies ``t.counter`` but its change is overwritten by the main -loop when the ISR returns. In a real system this could lead to rare, unpredictable failures. - -As mentioned above, care should be taken if an instance of a Python built in type is modified in the main code and -that instance is accessed in an ISR. The code performing the modification should be regarded as a critical -section to ensure that the instance is in a valid state when the ISR runs. - -Particular care needs to be taken if a dataset is shared between different ISR's. The hazard here is that the higher -priority interrupt may occur when the lower priority one has partially updated the shared data. Dealing with this -situation is an advanced topic beyond the scope of this introduction other than to note that mutex objects described -below can sometimes be used. - -Disabling interrupts for the duration of a critical section is the usual and simplest way to proceed, but it disables -all interrupts rather than merely the one with the potential to cause problems. It is generally undesirable to disable -an interrupt for long. In the case of timer interrupts it introduces variability to the time when a callback occurs. -In the case of device interrupts, it can lead to the device being serviced too late with possible loss of data or -overrun errors in the device hardware. Like ISR's, a critical section in the main code should have a short, predictable -duration. - -An approach to dealing with critical sections which radically reduces the time for which interrupts are disabled is to -use an object termed a mutex (name derived from the notion of mutual exclusion). The main program locks the mutex -before running the critical section and unlocks it at the end. The ISR tests whether the mutex is locked. If it is, -it avoids the critical section and returns. The design challenge is defining what the ISR should do in the event -that access to the critical variables is denied. A simple example of a mutex may be found -`here `_. Note that the mutex code does disable interrupts, -but only for the duration of eight machine instructions: the benefit of this approach is that other interrupts are -virtually unaffected. - -Interrupts and the REPL -~~~~~~~~~~~~~~~~~~~~~~~ - -Interrupt handlers, such as those associated with timers, can continue to run -after a program terminates. This may produce unexpected results where you might -have expected the object raising the callback to have gone out of scope. For -example on the Pyboard: - -.. code:: python - - def bar(): - foo = pyb.Timer(2, freq=4, callback=lambda t: print('.', end='')) - - bar() - -This continues to run until the timer is explicitly disabled or the board is -reset with ``ctrl D``. diff --git a/docs/reference/repl.rst b/docs/reference/repl.rst deleted file mode 100644 index 7a683ca220..0000000000 --- a/docs/reference/repl.rst +++ /dev/null @@ -1,211 +0,0 @@ -The MicroPython Interactive Interpreter Mode (aka REPL) -======================================================= - -This section covers some characteristics of the MicroPython Interactive -Interpreter Mode. A commonly used term for this is REPL (read-eval-print-loop) -which will be used to refer to this interactive prompt. - -Auto-indent ------------ - -When typing python statements which end in a colon (for example if, for, while) -then the prompt will change to three dots (...) and the cursor will be indented -by 4 spaces. When you press return, the next line will continue at the same -level of indentation for regular statements or an additional level of indentation -where appropriate. If you press the backspace key then it will undo one -level of indentation. - -If your cursor is all the way back at the beginning, pressing RETURN will then -execute the code that you've entered. The following shows what you'd see -after entering a for statement (the underscore shows where the cursor winds up): - - >>> for i in range(3): - ... _ - -If you then enter an if statement, an additional level of indentation will be -provided: - - >>> for i in range(30): - ... if i > 3: - ... _ - -Now enter ``break`` followed by RETURN and press BACKSPACE: - - >>> for i in range(30): - ... if i > 3: - ... break - ... _ - -Finally type ``print(i)``, press RETURN, press BACKSPACE and press RETURN again: - - >>> for i in range(30): - ... if i > 3: - ... break - ... print(i) - ... - 0 - 1 - 2 - 3 - >>> - -Auto-indent won't be applied if the previous two lines were all spaces. This -means that you can finish entering a compound statement by pressing RETURN -twice, and then a third press will finish and execute. - -Auto-completion ---------------- - -While typing a command at the REPL, if the line typed so far corresponds to -the beginning of the name of something, then pressing TAB will show -possible things that could be entered. For example type ``m`` and press TAB -and it should expand to ``machine``. Enter a dot ``.`` and press TAB again. You -should see something like: - - >>> machine. - __name__ info unique_id reset - bootloader freq rng idle - sleep deepsleep disable_irq enable_irq - Pin - -The word will be expanded as much as possible until multiple possibilities exist. -For example, type ``machine.Pin.AF3`` and press TAB and it will expand to -``machine.Pin.AF3_TIM``. Pressing TAB a second time will show the possible -expansions: - - >>> machine.Pin.AF3_TIM - AF3_TIM10 AF3_TIM11 AF3_TIM8 AF3_TIM9 - >>> machine.Pin.AF3_TIM - -Interrupting a running program ------------------------------- - -You can interrupt a running program by pressing Ctrl-C. This will raise a KeyboardInterrupt -which will bring you back to the REPL, providing your program doesn't intercept the -KeyboardInterrupt exception. - -For example: - - >>> for i in range(1000000): - ... print(i) - ... - 0 - 1 - 2 - 3 - ... - 6466 - 6467 - 6468 - Traceback (most recent call last): - File "", line 2, in - KeyboardInterrupt: - >>> - -Paste Mode ----------- - -If you want to paste some code into your terminal window, the auto-indent feature -will mess things up. For example, if you had the following python code: :: - - def foo(): - print('This is a test to show paste mode') - print('Here is a second line') - foo() - -and you try to paste this into the normal REPL, then you will see something like -this: - - >>> def foo(): - ... print('This is a test to show paste mode') - ... print('Here is a second line') - ... foo() - ... - Traceback (most recent call last): - File "", line 3 - IndentationError: unexpected indent - -If you press Ctrl-E, then you will enter paste mode, which essentially turns off -the auto-indent feature, and changes the prompt from ``>>>`` to ``===``. For example: - - >>> - paste mode; Ctrl-C to cancel, Ctrl-D to finish - === def foo(): - === print('This is a test to show paste mode') - === print('Here is a second line') - === foo() - === - This is a test to show paste mode - Here is a second line - >>> - -Paste Mode allows blank lines to be pasted. The pasted text is compiled as if -it were a file. Pressing Ctrl-D exits paste mode and initiates the compilation. - -Soft Reset ----------- - -A soft reset will reset the python interpreter, but tries not to reset the -method by which you're connected to the MicroPython board (USB-serial, or Wifi). - -You can perform a soft reset from the REPL by pressing Ctrl-D, or from your python -code by executing: :: - - raise SystemExit - -For example, if you reset your MicroPython board, and you execute a dir() -command, you'd see something like this: - - >>> dir() - ['__name__', 'pyb'] - -Now create some variables and repeat the dir() command: - - >>> i = 1 - >>> j = 23 - >>> x = 'abc' - >>> dir() - ['j', 'x', '__name__', 'pyb', 'i'] - >>> - -Now if you enter Ctrl-D, and repeat the dir() command, you'll see that your -variables no longer exist: - -.. code-block:: python - - PYB: sync filesystems - PYB: soft reboot - MicroPython v1.5-51-g6f70283-dirty on 2015-10-30; PYBv1.0 with STM32F405RG - Type "help()" for more information. - >>> dir() - ['__name__', 'pyb'] - >>> - -The special variable _ (underscore) ------------------------------------ - -When you use the REPL, you may perform computations and see the results. -MicroPython stores the results of the previous statement in the variable _ (underscore). -So you can use the underscore to save the result in a variable. For example: - - >>> 1 + 2 + 3 + 4 + 5 - 15 - >>> x = _ - >>> x - 15 - >>> - -Raw Mode --------- - -Raw mode is not something that a person would normally use. It is intended for -programmatic use. It essentially behaves like paste mode with echo turned off. - -Raw mode is entered using Ctrl-A. You then send your python code, followed by -a Ctrl-D. The Ctrl-D will be acknowledged by 'OK' and then the python code will -be compiled and executed. Any output (or errors) will be sent back. Entering -Ctrl-B will leave raw mode and return the the regular (aka friendly) REPL. - -The ``tools/pyboard.py`` program uses the raw REPL to execute python files on the -MicroPython board. - diff --git a/docs/reference/speed_python.rst b/docs/reference/speed_python.rst deleted file mode 100644 index 279a1bbcdc..0000000000 --- a/docs/reference/speed_python.rst +++ /dev/null @@ -1,342 +0,0 @@ -Maximising MicroPython Speed -============================ - -.. contents:: - -This tutorial describes ways of improving the performance of MicroPython code. -Optimisations involving other languages are covered elsewhere, namely the use -of modules written in C and the MicroPython inline assembler. - -The process of developing high performance code comprises the following stages -which should be performed in the order listed. - -* Design for speed. -* Code and debug. - -Optimisation steps: - -* Identify the slowest section of code. -* Improve the efficiency of the Python code. -* Use the native code emitter. -* Use the viper code emitter. -* Use hardware-specific optimisations. - -Designing for speed -------------------- - -Performance issues should be considered at the outset. This involves taking a view -on the sections of code which are most performance critical and devoting particular -attention to their design. The process of optimisation begins when the code has -been tested: if the design is correct at the outset optimisation will be -straightforward and may actually be unnecessary. - -Algorithms -~~~~~~~~~~ - -The most important aspect of designing any routine for performance is ensuring that -the best algorithm is employed. This is a topic for textbooks rather than for a -MicroPython guide but spectacular performance gains can sometimes be achieved -by adopting algorithms known for their efficiency. - -RAM Allocation -~~~~~~~~~~~~~~ - -To design efficient MicroPython code it is necessary to have an understanding of the -way the interpreter allocates RAM. When an object is created or grows in size -(for example where an item is appended to a list) the necessary RAM is allocated -from a block known as the heap. This takes a significant amount of time; -further it will on occasion trigger a process known as garbage collection which -can take several milliseconds. - -Consequently the performance of a function or method can be improved if an object is created -once only and not permitted to grow in size. This implies that the object persists -for the duration of its use: typically it will be instantiated in a class constructor -and used in various methods. - -This is covered in further detail :ref:`Controlling garbage collection ` below. - -Buffers -~~~~~~~ - -An example of the above is the common case where a buffer is required, such as one -used for communication with a device. A typical driver will create the buffer in the -constructor and use it in its I/O methods which will be called repeatedly. - -The MicroPython libraries typically provide support for pre-allocated buffers. For -example, objects which support stream interface (e.g., file or UART) provide `read()` -method which allocates new buffer for read data, but also a `readinto()` method -to read data into an existing buffer. - -Floating Point -~~~~~~~~~~~~~~ - -Some MicroPython ports allocate floating point numbers on heap. Some other ports -may lack dedicated floating-point coprocessor, and perform arithmetic operations -on them in "software" at considerably lower speed than on integers. Where -performance is important, use integer operations and restrict the use of floating -point to sections of the code where performance is not paramount. For example, -capture ADC readings as integers values to an array in one quick go, and only then -convert them to floating-point numbers for signal processing. - -Arrays -~~~~~~ - -Consider the use of the various types of array classes as an alternative to lists. -The `array` module supports various element types with 8-bit elements supported -by Python's built in `bytes` and `bytearray` classes. These data structures all store -elements in contiguous memory locations. Once again to avoid memory allocation in critical -code these should be pre-allocated and passed as arguments or as bound objects. - -When passing slices of objects such as `bytearray` instances, Python creates -a copy which involves allocation of the size proportional to the size of slice. -This can be alleviated using a `memoryview` object. `memoryview` itself -is allocated on heap, but is a small, fixed-size object, regardless of the size -of slice it points too. - -.. code:: python - - ba = bytearray(10000) # big array - func(ba[30:2000]) # a copy is passed, ~2K new allocation - mv = memoryview(ba) # small object is allocated - func(mv[30:2000]) # a pointer to memory is passed - -A `memoryview` can only be applied to objects supporting the buffer protocol - this -includes arrays but not lists. Small caveat is that while memoryview object is live, -it also keeps alive the original buffer object. So, a memoryview isn't a universal -panacea. For instance, in the example above, if you are done with 10K buffer and -just need those bytes 30:2000 from it, it may be better to make a slice, and let -the 10K buffer go (be ready for garbage collection), instead of making a -long-living memoryview and keeping 10K blocked for GC. - -Nonetheless, `memoryview` is indispensable for advanced preallocated buffer -management. `readinto()` method discussed above puts data at the beginning -of buffer and fills in entire buffer. What if you need to put data in the -middle of existing buffer? Just create a memoryview into the needed section -of buffer and pass it to `readinto()`. - -Identifying the slowest section of code ---------------------------------------- - -This is a process known as profiling and is covered in textbooks and -(for standard Python) supported by various software tools. For the type of -smaller embedded application likely to be running on MicroPython platforms -the slowest function or method can usually be established by judicious use -of the timing ``ticks`` group of functions documented in `utime`. -Code execution time can be measured in ms, us, or CPU cycles. - -The following enables any function or method to be timed by adding an -``@timed_function`` decorator: - -.. code:: python - - def timed_function(f, *args, **kwargs): - myname = str(f).split(' ')[1] - def new_func(*args, **kwargs): - t = utime.ticks_us() - result = f(*args, **kwargs) - delta = utime.ticks_diff(utime.ticks_us(), t) - print('Function {} Time = {:6.3f}ms'.format(myname, delta/1000)) - return result - return new_func - -MicroPython code improvements ------------------------------ - -The const() declaration -~~~~~~~~~~~~~~~~~~~~~~~ - -MicroPython provides a ``const()`` declaration. This works in a similar way -to ``#define`` in C in that when the code is compiled to bytecode the compiler -substitutes the numeric value for the identifier. This avoids a dictionary -lookup at runtime. The argument to ``const()`` may be anything which, at -compile time, evaluates to an integer e.g. ``0x100`` or ``1 << 8``. - -.. _Caching: - -Caching object references -~~~~~~~~~~~~~~~~~~~~~~~~~~ - -Where a function or method repeatedly accesses objects performance is improved -by caching the object in a local variable: - -.. code:: python - - class foo(object): - def __init__(self): - ba = bytearray(100) - def bar(self, obj_display): - ba_ref = self.ba - fb = obj_display.framebuffer - # iterative code using these two objects - -This avoids the need repeatedly to look up ``self.ba`` and ``obj_display.framebuffer`` -in the body of the method ``bar()``. - -.. _controlling_gc: - -Controlling garbage collection -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -When memory allocation is required, MicroPython attempts to locate an adequately -sized block on the heap. This may fail, usually because the heap is cluttered -with objects which are no longer referenced by code. If a failure occurs, the -process known as garbage collection reclaims the memory used by these redundant -objects and the allocation is then tried again - a process which can take several -milliseconds. - -There may be benefits in pre-empting this by periodically issuing `gc.collect()`. -Firstly doing a collection before it is actually required is quicker - typically on the -order of 1ms if done frequently. Secondly you can determine the point in code -where this time is used rather than have a longer delay occur at random points, -possibly in a speed critical section. Finally performing collections regularly -can reduce fragmentation in the heap. Severe fragmentation can lead to -non-recoverable allocation failures. - -The Native code emitter ------------------------ - -This causes the MicroPython compiler to emit native CPU opcodes rather than -bytecode. It covers the bulk of the MicroPython functionality, so most functions will require -no adaptation (but see below). It is invoked by means of a function decorator: - -.. code:: python - - @micropython.native - def foo(self, arg): - buf = self.linebuf # Cached object - # code - -There are certain limitations in the current implementation of the native code emitter. - -* Context managers are not supported (the ``with`` statement). -* Generators are not supported. -* If ``raise`` is used an argument must be supplied. - -The trade-off for the improved performance (roughly twices as fast as bytecode) is an -increase in compiled code size. - -The Viper code emitter ----------------------- - -The optimisations discussed above involve standards-compliant Python code. The -Viper code emitter is not fully compliant. It supports special Viper native data types -in pursuit of performance. Integer processing is non-compliant because it uses machine -words: arithmetic on 32 bit hardware is performed modulo 2**32. - -Like the Native emitter Viper produces machine instructions but further optimisations -are performed, substantially increasing performance especially for integer arithmetic and -bit manipulations. It is invoked using a decorator: - -.. code:: python - - @micropython.viper - def foo(self, arg: int) -> int: - # code - -As the above fragment illustrates it is beneficial to use Python type hints to assist the Viper optimiser. -Type hints provide information on the data types of arguments and of the return value; these -are a standard Python language feature formally defined here `PEP0484 `_. -Viper supports its own set of types namely ``int``, ``uint`` (unsigned integer), ``ptr``, ``ptr8``, -``ptr16`` and ``ptr32``. The ``ptrX`` types are discussed below. Currently the ``uint`` type serves -a single purpose: as a type hint for a function return value. If such a function returns ``0xffffffff`` -Python will interpret the result as 2**32 -1 rather than as -1. - -In addition to the restrictions imposed by the native emitter the following constraints apply: - -* Functions may have up to four arguments. -* Default argument values are not permitted. -* Floating point may be used but is not optimised. - -Viper provides pointer types to assist the optimiser. These comprise - -* ``ptr`` Pointer to an object. -* ``ptr8`` Points to a byte. -* ``ptr16`` Points to a 16 bit half-word. -* ``ptr32`` Points to a 32 bit machine word. - -The concept of a pointer may be unfamiliar to Python programmers. It has similarities -to a Python `memoryview` object in that it provides direct access to data stored in memory. -Items are accessed using subscript notation, but slices are not supported: a pointer can return -a single item only. Its purpose is to provide fast random access to data stored in contiguous -memory locations - such as data stored in objects which support the buffer protocol, and -memory-mapped peripheral registers in a microcontroller. It should be noted that programming -using pointers is hazardous: bounds checking is not performed and the compiler does nothing to -prevent buffer overrun errors. - -Typical usage is to cache variables: - -.. code:: python - - @micropython.viper - def foo(self, arg: int) -> int: - buf = ptr8(self.linebuf) # self.linebuf is a bytearray or bytes object - for x in range(20, 30): - bar = buf[x] # Access a data item through the pointer - # code omitted - -In this instance the compiler "knows" that ``buf`` is the address of an array of bytes; -it can emit code to rapidly compute the address of ``buf[x]`` at runtime. Where casts are -used to convert objects to Viper native types these should be performed at the start of -the function rather than in critical timing loops as the cast operation can take several -microseconds. The rules for casting are as follows: - -* Casting operators are currently: ``int``, ``bool``, ``uint``, ``ptr``, ``ptr8``, ``ptr16`` and ``ptr32``. -* The result of a cast will be a native Viper variable. -* Arguments to a cast can be a Python object or a native Viper variable. -* If argument is a native Viper variable, then cast is a no-op (i.e. costs nothing at runtime) - that just changes the type (e.g. from ``uint`` to ``ptr8``) so that you can then store/load - using this pointer. -* If the argument is a Python object and the cast is ``int`` or ``uint``, then the Python object - must be of integral type and the value of that integral object is returned. -* The argument to a bool cast must be integral type (boolean or integer); when used as a return - type the viper function will return True or False objects. -* If the argument is a Python object and the cast is ``ptr``, ``ptr``, ``ptr16`` or ``ptr32``, - then the Python object must either have the buffer protocol with read-write capabilities - (in which case a pointer to the start of the buffer is returned) or it must be of integral - type (in which case the value of that integral object is returned). - -The following example illustrates the use of a ``ptr16`` cast to toggle pin X1 ``n`` times: - -.. code:: python - - BIT0 = const(1) - @micropython.viper - def toggle_n(n: int): - odr = ptr16(stm.GPIOA + stm.GPIO_ODR) - for _ in range(n): - odr[0] ^= BIT0 - -A detailed technical description of the three code emitters may be found -on Kickstarter here `Note 1 `_ -and here `Note 2 `_ - -Accessing hardware directly ---------------------------- - -.. note:: - - Code examples in this section are given for the Pyboard. The techniques - described however may be applied to other MicroPython ports too. - -This comes into the category of more advanced programming and involves some knowledge -of the target MCU. Consider the example of toggling an output pin on the Pyboard. The -standard approach would be to write - -.. code:: python - - mypin.value(mypin.value() ^ 1) # mypin was instantiated as an output pin - -This involves the overhead of two calls to the `Pin` instance's :meth:`~machine.Pin.value()` -method. This overhead can be eliminated by performing a read/write to the relevant bit -of the chip's GPIO port output data register (odr). To facilitate this the ``stm`` -module provides a set of constants providing the addresses of the relevant registers. -A fast toggle of pin ``P4`` (CPU pin ``A14``) - corresponding to the green LED - -can be performed as follows: - -.. code:: python - - import machine - import stm - - BIT14 = const(1 << 14) - machine.mem16[stm.GPIOA + stm.GPIO_ODR] ^= BIT14 diff --git a/docs/sphinx_selective_exclude/LICENSE b/docs/sphinx_selective_exclude/LICENSE deleted file mode 100644 index 0b47ced8a1..0000000000 --- a/docs/sphinx_selective_exclude/LICENSE +++ /dev/null @@ -1,25 +0,0 @@ -Copyright (c) 2016 by the sphinx_selective_exclude authors. -All rights reserved. - -Redistribution and use in source and binary forms, with or without -modification, are permitted provided that the following conditions are -met: - -* Redistributions of source code must retain the above copyright - notice, this list of conditions and the following disclaimer. - -* Redistributions in binary form must reproduce the above copyright - notice, this list of conditions and the following disclaimer in the - documentation and/or other materials provided with the distribution. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. diff --git a/docs/sphinx_selective_exclude/README.md b/docs/sphinx_selective_exclude/README.md deleted file mode 100644 index dab1407392..0000000000 --- a/docs/sphinx_selective_exclude/README.md +++ /dev/null @@ -1,138 +0,0 @@ -Sphinx eager ".. only::" directive and other selective rendition extensions -=========================================================================== - -Project home page: https://github.com/pfalcon/sphinx_selective_exclude - -The implementation of ".. only::" directive in Sphinx documentation -generation tool is known to violate principles of least user surprise -and user expectations in general. Instead of excluding content early -in the pipeline (pre-processor style), Sphinx defers exclusion until -output phase, and what's the worst, various stages processing ignore -"only" blocks and their exclusion status, so they may leak unexpected -information into ToC, indexes, etc. - -There's multiple issues submitted upstream on this matter: - -* https://github.com/sphinx-doc/sphinx/issues/2150 -* https://github.com/sphinx-doc/sphinx/issues/1717 -* https://github.com/sphinx-doc/sphinx/issues/1488 -* etc. - -They are largely ignored by Sphinx maintainers. - -This projects tries to rectify situation on users' side. It actually -changes the way Sphinx processes "only" directive, but does this -without forking the project, and instead is made as a standard -Sphinx extension, which a user may add to their documentation config. -Unlike normal extensions, extensions provided in this package -monkey-patch Sphinx core to work in a way expected by users. - -eager_only ----------- - -The core extension provided by the package is called `eager_only` and -is based on the idea by Andrea Cassioli (see bugreports above) to -process "only" directive as soon as possible during parsing phase. -This approach has some drawbacks, like producing warnings like -"WARNING: document isn't included in any toctree" if "only" is used -to shape up a toctree, or the fact that changing a documentation -builder (html/latex/etc.) will almost certainly require complete -rebuild of documentation. But these are relatively minor issues -comparing to completely broken way "only" works in upstream Sphinx. - -modindex_exclude ----------------- - -"only" directive allows for fine-grained conditional exclusion, but -sometimes you may want to exclude entire module(s) at once. Even if -you wrap an entire module description in "only" directive, like: - - .. only: option1 - .. module:: my_module - - ... - -You will still have an HTML page generated, albeit empty. It may also -go into indexes, so will be discoverable by users, leading to less -than ideal experience. `modindex_exclude` extension is design to -resolve this issue, by making sure that any reference of a module -is excluded from Python module index ("modindex"), as well as -general cross-reference index ("genindex"). In the latter case, -any symbol belong to a module will be excluded. Unlike `eager_only` -extension which appear to have issued with "latexpdf" builder, -`modindex_exclude` is useful for PDF, and allows to get cleaner -index for PDF, just the same as for HTML. - -search_auto_exclude -------------------- - -Even if you exclude some documents from toctree:: using only:: -directive, they will be indexed for full-text search, so user may -find them and get confused. This plugin follows very simple idea -that if you didn't include some documents in the toctree, then -you didn't want them to be accessible (e.g. for a particular -configuration), and so will make sure they aren't indexed either. - -This extension depends on `eager_only` and won't work without it. -Note that Sphinx will issue warnings, as usual, for any documents -not included in a toctree. This is considered a feature, and gives -you a chance to check that document exclusions are indeed right -for a particular configuration you build (and not that you forgot -to add something to a toctree). - -Summary -------- - -Based on the above, sphinx_selective_exclude offers extension to let -you: - -* Make "only::" directive work in an expected, intuitive manner, using - `eager_only` extension. -* However, if you apply only:: to toctree::, excluded documents will - still be available via full-text search, so you need to use - `search_auto_exclude` for that to work as expected. -* Similar to search, indexes may also require special treatment, hence - there's the `modindex_exclude` extension. - -Most likely, you will want to use all 3 extensions together - if you -really want build subsets of docimentation covering sufficiently different -configurations from a single doctree. However, if one of them is enough -to cover your usecase, that's OK to (and why they were separated into -3 extensions, to follow KISS and "least surprise" principles and to -not make people deal with things they aren't interested in). In this case, -however remember there're other extensions, if you later hit a usecase -when they're needed. - -Usage ------ - -To use these extensions, add https://github.com/pfalcon/sphinx_selective_exclude -as a git submodule to your project, in documentation folder (where -Sphinx conf.py is located). Alternatively, commit sphinx_selective_exclude -directory instead of making it a submodule (you will need to pick up -any project updates manually then). - -Add following lines to "extensions" settings in your conf.py (you -likely already have some standard Sphinx extensions enabled): - - extensions = [ - ... - 'sphinx_selective_exclude.eager_only', - 'sphinx_selective_exclude.search_auto_exclude', - 'sphinx_selective_exclude.modindex_exclude', - ] - -As discussed above, you may enable all extensions, or one by one. - -Please note that to make sure these extensions work well and avoid producing -output docs with artifacts, it is IMPERATIVE to remove cached doctree if -you rebuild documentation with another builder (i.e. with different output -format). Also, to stay on safe side, it's recommended to remove old doctree -anyway before generating production-ready documentation for publishing. To -do that, run something like: - - rm -rf _build/doctrees/ - -A typical artificat when not following these simple rules is that content -of some sections may be missing. If you face anything like that, just -remember what's written above and remove cached doctrees. diff --git a/docs/sphinx_selective_exclude/__init__.py b/docs/sphinx_selective_exclude/__init__.py deleted file mode 100644 index e69de29bb2..0000000000 diff --git a/docs/sphinx_selective_exclude/eager_only.py b/docs/sphinx_selective_exclude/eager_only.py deleted file mode 100644 index 82766c2e64..0000000000 --- a/docs/sphinx_selective_exclude/eager_only.py +++ /dev/null @@ -1,45 +0,0 @@ -# -# This is a Sphinx documentation tool extension which makes .only:: -# directives be eagerly processed early in the parsing stage. This -# makes sure that content in .only:: blocks gets actually excluded -# as a typical user expects, instead of bits of information in -# these blocks leaking to documentation in various ways (e.g., -# indexes containing entries for functions which are actually in -# .only:: blocks and thus excluded from documentation, etc.) -# Note that with this extension, you may need to completely -# rebuild a doctree when switching builders (i.e. completely -# remove _build/doctree dir between generation of HTML vs PDF -# documentation). -# -# This extension works by monkey-patching Sphinx core, so potentially -# may not work with untested Sphinx versions. It tested to work with -# 1.2.2 and 1.4.2 -# -# Copyright (c) 2016 Paul Sokolovsky -# Based on idea by Andrea Cassioli: -# https://github.com/sphinx-doc/sphinx/issues/2150#issuecomment-171912290 -# Licensed under the terms of BSD license, see LICENSE file. -# -import sphinx -from docutils.parsers.rst import directives - - -class EagerOnly(sphinx.directives.other.Only): - - def run(self, *args): - # Evaluate the condition eagerly, and if false return no nodes right away - env = self.state.document.settings.env - env.app.builder.tags.add('TRUE') - #print(repr(self.arguments[0])) - if not env.app.builder.tags.eval_condition(self.arguments[0]): - return [] - - # Otherwise, do the usual processing - nodes = super(EagerOnly, self).run() - if len(nodes) == 1: - nodes[0]['expr'] = 'TRUE' - return nodes - - -def setup(app): - directives.register_directive('only', EagerOnly) diff --git a/docs/sphinx_selective_exclude/modindex_exclude.py b/docs/sphinx_selective_exclude/modindex_exclude.py deleted file mode 100644 index bf8db795e6..0000000000 --- a/docs/sphinx_selective_exclude/modindex_exclude.py +++ /dev/null @@ -1,75 +0,0 @@ -# -# This is a Sphinx documentation tool extension which allows to -# exclude some Python modules from the generated indexes. Modules -# are excluded both from "modindex" and "genindex" index tables -# (in the latter case, all members of a module are excluded). -# To control exclusion, set "modindex_exclude" variable in Sphinx -# conf.py to the list of modules to exclude. Note: these should be -# modules (as defined by py:module directive, not just raw filenames). -# This extension works by monkey-patching Sphinx core, so potentially -# may not work with untested Sphinx versions. It tested to work with -# 1.2.2 and 1.4.2 -# -# Copyright (c) 2016 Paul Sokolovsky -# Licensed under the terms of BSD license, see LICENSE file. -# -import sphinx - - -#org_PythonModuleIndex_generate = None -org_PyObject_add_target_and_index = None -org_PyModule_run = None - -EXCLUDES = {} - -# No longer used, PyModule_run() monkey-patch does all the job -def PythonModuleIndex_generate(self, docnames=None): - docnames = [] - excludes = self.domain.env.config['modindex_exclude'] - for modname, (docname, synopsis, platforms, deprecated) in self.domain.data['modules'].items(): - #print(docname) - if modname not in excludes: - docnames.append(docname) - - return org_PythonModuleIndex_generate(self, docnames) - - -def PyObject_add_target_and_index(self, name_cls, sig, signode): - if hasattr(self.env, "ref_context"): - # Sphinx 1.4 - ref_context = self.env.ref_context - else: - # Sphinx 1.2 - ref_context = self.env.temp_data - modname = self.options.get( - 'module', ref_context.get('py:module')) - #print("*", modname, name_cls) - if modname in self.env.config['modindex_exclude']: - return None - return org_PyObject_add_target_and_index(self, name_cls, sig, signode) - - -def PyModule_run(self): - env = self.state.document.settings.env - modname = self.arguments[0].strip() - excl = env.config['modindex_exclude'] - if modname in excl: - self.options['noindex'] = True - EXCLUDES.setdefault(modname, []).append(env.docname) - return org_PyModule_run(self) - - -def setup(app): - app.add_config_value('modindex_exclude', [], 'html') - -# global org_PythonModuleIndex_generate -# org_PythonModuleIndex_generate = sphinx.domains.python.PythonModuleIndex.generate -# sphinx.domains.python.PythonModuleIndex.generate = PythonModuleIndex_generate - - global org_PyObject_add_target_and_index - org_PyObject_add_target_and_index = sphinx.domains.python.PyObject.add_target_and_index - sphinx.domains.python.PyObject.add_target_and_index = PyObject_add_target_and_index - - global org_PyModule_run - org_PyModule_run = sphinx.domains.python.PyModule.run - sphinx.domains.python.PyModule.run = PyModule_run diff --git a/docs/sphinx_selective_exclude/search_auto_exclude.py b/docs/sphinx_selective_exclude/search_auto_exclude.py deleted file mode 100644 index b8b326dd2c..0000000000 --- a/docs/sphinx_selective_exclude/search_auto_exclude.py +++ /dev/null @@ -1,34 +0,0 @@ -# -# This is a Sphinx documentation tool extension which allows to -# automatically exclude from full-text search index document -# which are not referenced via toctree::. It's intended to be -# used with toctrees conditional on only:: directive, with the -# idea being that if you didn't include it in the ToC, you don't -# want the docs being findable by search either (for example, -# because these docs contain information not pertinent to a -# particular product configuration). -# -# This extension depends on "eager_only" extension and won't work -# without it. -# -# Copyright (c) 2016 Paul Sokolovsky -# Licensed under the terms of BSD license, see LICENSE file. -# -import sphinx - - -org_StandaloneHTMLBuilder_index_page = None - - -def StandaloneHTMLBuilder_index_page(self, pagename, doctree, title): - if pagename not in self.env.files_to_rebuild: - if pagename != self.env.config.master_doc and 'orphan' not in self.env.metadata[pagename]: - print("Excluding %s from full-text index because it's not referenced in ToC" % pagename) - return - return org_StandaloneHTMLBuilder_index_page(self, pagename, doctree, title) - - -def setup(app): - global org_StandaloneHTMLBuilder_index_page - org_StandaloneHTMLBuilder_index_page = sphinx.builders.html.StandaloneHTMLBuilder.index_page - sphinx.builders.html.StandaloneHTMLBuilder.index_page = StandaloneHTMLBuilder_index_page diff --git a/docs/supported_ports.rst b/docs/supported_ports.rst index 2a5b71a192..d793708d4d 100644 --- a/docs/supported_ports.rst +++ b/docs/supported_ports.rst @@ -1,11 +1,11 @@ Supported Ports ============================== -Adafruit's CircuitPython derivative currently has limited support with a focus on -the Atmel SAMD21 port and ESP8266 port. +Adafruit's CircuitPython currently has limited support with a focus on supporting the Atmel SAMD +and ESP8266. .. toctree:: :maxdepth: 2 ../atmel-samd/README - esp8266/index.rst + ../esp8266/README diff --git a/docs/templates/layout.html b/docs/templates/layout.html deleted file mode 100644 index a6caa0bc5a..0000000000 --- a/docs/templates/layout.html +++ /dev/null @@ -1,6 +0,0 @@ -{% extends "!layout.html" %} -{% set css_files = css_files + ["_static/customstyle.css"] %} - -{# we change the master_doc variable so that links to the index - page are to index.html instead of _index.html #} -{% set master_doc = "index" %} diff --git a/docs/templates/replace.inc b/docs/templates/replace.inc index 319c53735f..2636045f6e 100644 --- a/docs/templates/replace.inc +++ b/docs/templates/replace.inc @@ -4,6 +4,6 @@ .. |see_cpython_module| replace:: - *This module implements a subset of the corresponding* `CPython` *module, - as described below. For more information, refer to the original - CPython documentation:* + *This module implements a subset of the corresponding* ``CPython`` *module, + as described below. For more information, refer to the original* + ``CPython`` *documentation:* diff --git a/docs/templates/topindex.html b/docs/templates/topindex.html deleted file mode 100644 index 76e5e18d72..0000000000 --- a/docs/templates/topindex.html +++ /dev/null @@ -1,112 +0,0 @@ -{% extends "defindex.html" %} -{% block body %} - -

MicroPython documentation

- -

- {{ _('Welcome! This is the documentation for MicroPython') }} - v{{ release|e }}{% if last_updated %}, {{ _('last updated') }} {{ last_updated|e }}{% endif %}. -

- -

- MicroPython runs on a variety of systems and each has their own specific - documentation. You are currently viewing the documentation for - {{ port_name }}. -

- - - -

Documentation for MicroPython and {{ port_name }}:

- - - - -
- {% if port in ("pyboard", "wipy", "esp8266") %} - - - - {% endif %} - - - - - -
- -

Indices and tables:

- - - -
- - - - - -
- -

External links:

- - - - -
- - - - -
- -{% endblock %} diff --git a/docs/templates/unsupported_in_circuitpython.inc b/docs/templates/unsupported_in_circuitpython.inc new file mode 100644 index 0000000000..18c9215a84 --- /dev/null +++ b/docs/templates/unsupported_in_circuitpython.inc @@ -0,0 +1,5 @@ +.. warning:: + + This module is inherited from MicroPython and may not work in CircuitPython + as documented or at all! If they do work, they may change at any time. It is + unsupported. diff --git a/docs/templates/versions.html b/docs/templates/versions.html deleted file mode 100644 index 198630dd77..0000000000 --- a/docs/templates/versions.html +++ /dev/null @@ -1,37 +0,0 @@ -
- - Ports and Versions - {{ port }} ({{ port_version }}) - - -
-
-
Ports
- {% for slug, url in all_ports %} -
{{ slug }}
- {% endfor %} -
-
-
Versions
- {% for slug, url in all_versions %} -
{{ slug }}
- {% endfor %} -
-
-
Downloads
- {% for type, url in downloads %} -
{{ type }}
- {% endfor %} -
-
-
-
External links
-
- micropython.org -
-
- GitHub -
-
-
-
diff --git a/docs/troubleshooting.rst b/docs/troubleshooting.rst index 1c7e87f61b..66bcc2764c 100644 --- a/docs/troubleshooting.rst +++ b/docs/troubleshooting.rst @@ -23,7 +23,7 @@ happen on Linux and Mac OSX but its less likely. such as Feather M0 Express, Metro M0 Express and Circuit Playground Express:** -#. Download the appropriate flash .erase uf2 from `here `_. +#. Download the appropriate flash .erase uf2 from `the Adafruit_SPIFlash repo `_. #. Double-click the reset button. #. Copy the appropriate .uf2 to the xxxBOOT drive. #. The on-board NeoPixel will turn blue, indicating the erase has started. @@ -32,7 +32,7 @@ such as Feather M0 Express, Metro M0 Express and Circuit Playground Express:** **For boards without SPI flash, such as Feather M0 Proto, Gemma M0 and, Trinket M0:** -#. Download the appropriate erase .uf2 from `here `_. +#. Download the appropriate erase .uf2 from `the Learn repo `_. #. Double-click the reset button. #. Copy the appropriate .uf2 to the xxxBOOT drive. #. The boot LED will start pulsing again, and the xxxBOOT drive will appear again. diff --git a/docs/unix_index.rst b/docs/unix_index.rst deleted file mode 100644 index 1bfeb0bdac..0000000000 --- a/docs/unix_index.rst +++ /dev/null @@ -1,9 +0,0 @@ -MicroPython documentation and references -======================================== - -.. toctree:: - - library/index.rst - reference/index.rst - genrst/index.rst - license.rst diff --git a/docs/unsupported_ports.rst b/docs/unsupported_ports.rst deleted file mode 100644 index e04537656b..0000000000 --- a/docs/unsupported_ports.rst +++ /dev/null @@ -1,14 +0,0 @@ -Unsupported Ports -============================== - -Adafruit's MicroPython derivative currently has limited support with a focus on -the Atmel SAMD21 port. The ports below still exist in the code to preserve -upstream compatibility but are not tested. Use at your own risk. - -We recommend using `upstream MicroPython `_ for the below ports. - -.. toctree:: - :maxdepth: 2 - - pyboard/index.rst - wipy/index.rst diff --git a/docs/wipy/general.rst b/docs/wipy/general.rst deleted file mode 100644 index f28edb4e4b..0000000000 --- a/docs/wipy/general.rst +++ /dev/null @@ -1,385 +0,0 @@ -General information about the WiPy -================================== - -No floating point support -------------------------- - -Due to space reasons, there's no floating point support, and no math module. This -means that floating point numbers cannot be used anywhere in the code, and that -all divisions must be performed using '//' instead of '/'. Example:: - - >>> r = 4 // 2 # this will work - >>> r = 4 / 2 # this WON'T - -Before applying power ---------------------- - -.. warning:: - - The GPIO pins of the WiPy are NOT 5V tolerant, connecting them to voltages higher - than 3.6V will cause irreparable damage to the board. ADC pins, when configured - in analog mode cannot withstand voltages above 1.8V. Keep these considerations in - mind when wiring your electronics. - -WLAN default behaviour ----------------------- - -When the WiPy boots with the default factory configuration starts in Access Point -mode with ``ssid`` that starts with: ``wipy-wlan`` and ``key: www.wipy.io``. -Connect to this network and the WiPy will be reachable at ``192.168.1.1``. In order -to gain access to the interactive prompt, open a telnet session to that IP address on -the default port (23). You will be asked for credentials: -``login: micro`` and ``password: python`` - -.. _wipy_telnet: - -Telnet REPL ------------ - -Linux stock telnet works like a charm (also on OSX), but other tools like putty -work quite well too. The default credentials are: **user:** ``micro``, **password:** ``python``. -See :ref:`network.server ` for info on how to change the defaults. -For instance, on a linux shell (when connected to the WiPy in AP mode):: - - $ telnet 192.168.1.1 - -.. _wipy_filesystem: - -Local file system and FTP access --------------------------------- - -There is a small internal file system (a drive) on the WiPy, called ``/flash``, -which is stored within the external serial flash memory. If a micro SD card -is hooked-up and mounted, it will be available as well. - -When the WiPy starts up, it always boots from the ``boot.py`` located in the -``/flash`` file system. On boot up, the current directory is ``/flash``. - -The file system is accessible via the native FTP server running in the WiPy. -Open your FTP client of choice and connect to: - -**url:** ``ftp://192.168.1.1``, **user:** ``micro``, **password:** ``python`` - -See :ref:`network.server ` for info on how to change the defaults. -The recommended clients are: Linux stock FTP (also in OSX), Filezilla and FireFTP. -For example, on a linux shell:: - - $ ftp 192.168.1.1 - -The FTP server on the WiPy doesn't support active mode, only passive, therefore, -if using the native unix ftp client, just after logging in do:: - - ftp> passive - -Besides that, the FTP server only supports one data connection at a time. Check out -the Filezilla settings section below for more info. - -FileZilla settings ------------------- -Do not use the quick connect button, instead, open the site manager and create a new -configuration. In the ``General`` tab make sure that encryption is set to: ``Only use -plain FTP (insecure)``. In the Transfer Settings tab limit the max number of connections -to one, otherwise FileZilla will try to open a second command connection when retrieving -and saving files, and for simplicity and to reduce code size, only one command and one -data connections are possible. Other FTP clients might behave in a similar way. - -.. _wipy_firmware_upgrade: - -Upgrading the firmware Over The Air ------------------------------------ - -OTA software updates can be performed through the FTP server. Upload the ``mcuimg.bin`` file -to: ``/flash/sys/mcuimg.bin`` it will take around 6s. You won't see the file being stored -inside ``/flash/sys/`` because it's actually saved bypassing the user file system, so it -ends up inside the internal **hidden** file system, but rest assured that it was successfully -transferred, and it has been signed with a MD5 checksum to verify its integrity. Now, reset -the WiPy by pressing the switch on the board, or by typing:: - - >>> import machine - >>> machine.reset() - -Software updates can be found in: https://github.com/wipy/wipy/releases (**Binaries.zip**). -It's always recommended to update to the latest software, but make sure to -read the **release notes** before. - -.. note:: - - The ``bootloader.bin`` found inside ``Binaries.zip`` is there only for reference, it's not - needed for the Over The Air update. - -In order to check your software version, do:: - - >>> import os - >>> os.uname().release - -If the version number is lower than the latest release found in -`the releases `_, go ahead and update your WiPy! - - -.. _wipy_boot_modes: - -Boot modes and safe boot ------------------------- - -If you power up normally, or press the reset button, the WiPy will boot -into standard mode; the ``boot.py`` file will be executed first, then -``main.py`` will run. - -You can override this boot sequence by pulling ``GP28`` **up** (connect -it to the 3v3 output pin) during reset. This procedure also allows going -back in time to old firmware versions. The WiPy can hold up to 3 different -firmware versions, which are: the factory firmware plus 2 user updates. - -After reset, if ``GP28`` is held high, the heartbeat LED will start flashing -slowly, if after 3 seconds the pin is still being held high, the LED will start -blinking a bit faster and the WiPy will select the previous user update to boot. -If the previous user update is the desired firmware image, ``GP28`` must be -released before 3 more seconds elapse. If 3 seconds later the pin is still high, -the factory firmware will be selected, the LED will flash quickly for 1.5 seconds -and the WiPy will proceed to boot. The firmware selection mechanism is as follows: - - -**Safe Boot Pin** ``GP28`` **released during:** - -+-------------------------+-------------------------+----------------------------+ -| 1st 3 secs window | 2nd 3 secs window | Final 1.5 secs window | -+=========================+=========================+============================+ -| | Safe boot, *latest* | | Safe boot, *previous* | | Safe boot, the *factory* | -| | firmware is selected | | user update selected | | firmware is selected | -+-------------------------+-------------------------+----------------------------+ - -On all of the above 3 scenarios, safe boot mode is entered, meaning that -the execution of both ``boot.py`` and ``main.py`` is skipped. This is -useful to recover from crash situations caused by the user scripts. The selection -made during safe boot is not persistent, therefore after the next normal reset -the latest firmware will run again. - -The heartbeat LED ------------------- - -By default the heartbeat LED flashes once every 4s to signal that the system is -alive. This can be overridden through the :mod:`wipy` module:: - - >>> import wipy - >>> wipy.heartbeat(False) - -There are currently 2 kinds of errors that you might see: - -1. If the heartbeat LED flashes quickly, then a Python script (eg ``main.py``) - has an error. Use the REPL to debug it. -2. If the heartbeat LED stays on, then there was a hard fault, you cannot - recover from this, the only way out is to press the reset switch. - -Details on sleep modes ----------------------- - -* ``machine.idle()``: Power consumption: ~12mA (in WLAN STA mode). Wake sources: - any hardware interrupt (including systick with period of 1ms), no special - configuration required. -* ``machine.sleep()``: 950uA (in WLAN STA mode). Wake sources are ``Pin``, ``RTC`` - and ``WLAN`` -* ``machine.deepsleep()``: ~350uA. Wake sources are ``Pin`` and ``RTC``. - -Additional details for machine.Pin ----------------------------------- - -On the WiPy board the pins are identified by their string id:: - - from machine import Pin - g = machine.Pin('GP9', mode=Pin.OUT, pull=None, drive=Pin.MED_POWER, alt=-1) - -You can also configure the Pin to generate interrupts. For instance:: - - from machine import Pin - - def pincb(pin): - print(pin.id()) - - pin_int = Pin('GP10', mode=Pin.IN, pull=Pin.PULL_DOWN) - pin_int.irq(trigger=Pin.IRQ_RISING, handler=pincb) - # the callback can be triggered manually - pin_int.irq()() - # to disable the callback - pin_int.irq().disable() - -Now every time a falling edge is seen on the gpio pin, the callback will be -executed. Caution: mechanical push buttons have "bounce" and pushing or -releasing a switch will often generate multiple edges. -See: http://www.eng.utah.edu/~cs5780/debouncing.pdf for a detailed -explanation, along with various techniques for debouncing. - -All pin objects go through the pin mapper to come up with one of the -gpio pins. - -For the ``drive`` parameter the strengths are: - - - ``Pin.LOW_POWER`` - 2mA drive capability. - - ``Pin.MED_POWER`` - 4mA drive capability. - - ``Pin.HIGH_POWER`` - 6mA drive capability. - -For the ``alt`` parameter please refer to the pinout and alternate functions -table at `_ -for the specific alternate functions that each pin supports. - -For interrupts, the ``priority`` can take values in the range 1-7. And the -``wake`` parameter has the following properties: - - - If ``wake_from=machine.Sleep.ACTIVE`` any pin can wake the board. - - If ``wake_from=machine.Sleep.SUSPENDED`` pins ``GP2``, ``GP4``, ``GP10``, - ``GP11``, GP17`` or ``GP24`` can wake the board. Note that only 1 - of this pins can be enabled as a wake source at the same time, so, only - the last enabled pin as a ``machine.Sleep.SUSPENDED`` wake source will have effect. - - If ``wake_from=machine.Sleep.SUSPENDED`` pins ``GP2``, ``GP4``, ``GP10``, - ``GP11``, ``GP17`` and ``GP24`` can wake the board. In this case all of the - 6 pins can be enabled as a ``machine.Sleep.HIBERNATE`` wake source at the same time. - -Additional Pin methods: - -.. method:: machine.Pin.alt_list() - - Returns a list of the alternate functions supported by the pin. List items are - a tuple of the form: ``('ALT_FUN_NAME', ALT_FUN_INDEX)`` - -Additional details for machine.I2C ----------------------------------- - -On the WiPy there is a single hardware I2C peripheral, identified by "0". By -default this is the peripheral that is used when constructing an I2C instance. -The default pins are GP23 for SCL and GP13 for SDA, and one can create the -default I2C peripheral simply by doing:: - - i2c = machine.I2C() - -The pins and frequency can be specified as:: - - i2c = machine.I2C(freq=400000, scl='GP23', sda='GP13') - -Only certain pins can be used as SCL/SDA. Please refer to the pinout for further -information. - -Known issues ------------- - -Incompatible way to create SSL sockets -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -SSL sockets need to be created the following way before wrapping them with. -``ssl.wrap_socket``:: - - import socket - import ssl - s = socket(socket.AF_INET, socket.SOCK_STREAM, socket.IPPROTO_SEC) - ss = ssl.wrap_socket(s) - -Certificates must be used in order to validate the other side of the connection, and also to -authenticate ourselves with the other end. Such certificates must be stored as files using the -FTP server, and they must be placed in specific paths with specific names. - -- The certificate to validate the other side goes in: **'/flash/cert/ca.pem'** -- The certificate to authenticate ourselves goes in: **'/flash/cert/cert.pem'** -- The key for our own certificate goes in: **'/flash/cert/private.key'** - -.. note:: - - When these files are stored, they are placed inside the internal **hidden** file system - (just like firmware updates), and therefore they are never visible. - -For instance to connect to the Blynk servers using certificates, take the file ``ca.pem`` located -in the `blynk examples folder `_. -and put it in '/flash/cert/'. Then do:: - - import socket - import ssl - s = socket.socket(socket.AF_INET, socket.SOCK_STREAM, socket.IPPROTO_SEC) - ss = ssl.wrap_socket(s, cert_reqs=ssl.CERT_REQUIRED, ca_certs='/flash/cert/ca.pem') - ss.connect(socket.getaddrinfo('cloud.blynk.cc', 8441)[0][-1]) - -Incompatibilities in uhashlib module -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -Due to hardware implementation details of the WiPy, data must be buffered before being -digested, which would make it impossible to calculate the hash of big blocks of data that -do not fit in RAM. In this case, since most likely the total size of the data is known -in advance, the size can be passed to the constructor and hence the HASH hardware engine -of the WiPy can be properly initialized without needing buffering. If ``block_size`` is -to be given, an initial chunk of ``data`` must be passed as well. **When using this extension, -care must be taken to make sure that the length of all intermediate chunks (including the -initial one) is a multiple of 4 bytes.** The last chunk may be of any length. - -Example:: - - hash = uhashlib.sha1('abcd1234', 1001) # length of the initial piece is multiple of 4 bytes - hash.update('1234') # also multiple of 4 bytes - ... - hash.update('12345') # last chunk may be of any length - hash.digest() - -Unrelated function in machine module -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -.. function:: main(filename) - - Set the filename of the main script to run after boot.py is finished. If - this function is not called then the default file main.py will be executed. - - It only makes sense to call this function from within boot.py. - -Adhoc way to control telnet/FTP server via network module -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -The ``Server`` class controls the behaviour and the configuration of the FTP and telnet -services running on the WiPy. Any changes performed using this class' methods will -affect both. - -Example:: - - import network - server = network.Server() - server.deinit() # disable the server - # enable the server again with new settings - server.init(login=('user', 'password'), timeout=600) - -.. class:: network.Server(id, ...) - - Create a server instance, see ``init`` for parameters of initialization. - -.. method:: server.init(\*, login=('micro', 'python'), timeout=300) - - Init (and effectively start the server). Optionally a new ``user``, ``password`` - and ``timeout`` (in seconds) can be passed. - -.. method:: server.deinit() - - Stop the server - -.. method:: server.timeout([timeout_in_seconds]) - - Get or set the server timeout. - -.. method:: server.isrunning() - - Returns ``True`` if the server is running, ``False`` otherwise. - -Adhoc VFS-like support -~~~~~~~~~~~~~~~~~~~~~~ - -WiPy doesn't implement full MicroPython VFS support, instead following -functions are defined in ``uos`` module: - -.. function:: mount(block_device, mount_point, \*, readonly=False) - - Mounts a block device (like an ``SD`` object) in the specified mount - point. Example:: - - os.mount(sd, '/sd') - -.. function:: unmount(path) - - Unmounts a previously mounted block device from the given path. - -.. function:: mkfs(block_device or path) - - Formats the specified path, must be either ``/flash`` or ``/sd``. - A block device can also be passed like an ``SD`` object before - being mounted. - diff --git a/docs/wipy/index.rst b/docs/wipy/index.rst deleted file mode 100644 index 9b355d4963..0000000000 --- a/docs/wipy/index.rst +++ /dev/null @@ -1,8 +0,0 @@ -WiPy -================================== - -.. toctree:: - - quickref.rst - general.rst - tutorial/index.rst diff --git a/docs/wipy/quickref.rst b/docs/wipy/quickref.rst deleted file mode 100644 index f60c81f5fe..0000000000 --- a/docs/wipy/quickref.rst +++ /dev/null @@ -1,218 +0,0 @@ -.. _quickref_: - -Quick reference for the WiPy -============================ - -.. image:: https://raw.githubusercontent.com/wipy/wipy/master/docs/PinOUT.png - :alt: WiPy pinout and alternate functions table - :width: 800px - -General board control (including sleep modes) ---------------------------------------------- - -See the :mod:`machine` module:: - - import machine - - help(machine) # display all members from the machine module - machine.freq() # get the CPU frequency - machine.unique_id() # return the 6-byte unique id of the board (the WiPy's MAC address) - - machine.idle() # average current decreases to (~12mA), any interrupts wake it up - machine.sleep() # everything except for WLAN is powered down (~950uA avg. current) - # wakes from Pin, RTC or WLAN - machine.deepsleep() # deepest sleep mode, MCU starts from reset. Wakes from Pin and RTC. - -Pins and GPIO -------------- - -See :ref:`machine.Pin `. :: - - from machine import Pin - - # initialize GP2 in gpio mode (alt=0) and make it an output - p_out = Pin('GP2', mode=Pin.OUT) - p_out.value(1) - p_out.value(0) - p_out.toggle() - p_out(True) - - # make GP1 an input with the pull-up enabled - p_in = Pin('GP1', mode=Pin.IN, pull=Pin.PULL_UP) - p_in() # get value, 0 or 1 - -Timers ------- - -See :ref:`machine.Timer ` and :ref:`machine.Pin `. -Timer ``id``'s take values from 0 to 3.:: - - from machine import Timer - from machine import Pin - - tim = Timer(0, mode=Timer.PERIODIC) - tim_a = tim.channel(Timer.A, freq=1000) - tim_a.freq(5) # 5 Hz - - p_out = Pin('GP2', mode=Pin.OUT) - tim_a.irq(trigger=Timer.TIMEOUT, handler=lambda t: p_out.toggle()) - -PWM (pulse width modulation) ----------------------------- - -See :ref:`machine.Pin ` and :ref:`machine.Timer `. :: - - from machine import Timer - - # timer 1 in PWM mode and width must be 16 buts - tim = Timer(1, mode=Timer.PWM, width=16) - - # enable channel A @1KHz with a 50.55% duty cycle - tim_a = tim.channel(Timer.A, freq=1000, duty_cycle=5055) - -ADC (analog to digital conversion) ----------------------------------- - -See :ref:`machine.ADC `. :: - - from machine import ADC - - adc = ADC() - apin = adc.channel(pin='GP3') - apin() # read value, 0-4095 - -UART (serial bus) ------------------ - -See :ref:`machine.UART `. :: - - from machine import UART - uart = UART(0, baudrate=9600) - uart.write('hello') - uart.read(5) # read up to 5 bytes - -SPI bus -------- - -See :ref:`machine.SPI `. :: - - from machine import SPI - - # configure the SPI master @ 2MHz - spi = SPI(0, SPI.MASTER, baudrate=200000, polarity=0, phase=0) - spi.write('hello') - spi.read(5) # receive 5 bytes on the bus - rbuf = bytearray(5) - spi.write_readinto('hello', rbuf) # send and receive 5 bytes - -I2C bus -------- - -See :ref:`machine.I2C `. :: - - from machine import I2C - # configure the I2C bus - i2c = I2C(baudrate=100000) - i2c.scan() # returns list of slave addresses - i2c.writeto(0x42, 'hello') # send 5 bytes to slave with address 0x42 - i2c.readfrom(0x42, 5) # receive 5 bytes from slave - i2c.readfrom_mem(0x42, 0x10, 2) # read 2 bytes from slave 0x42, slave memory 0x10 - i2c.writeto_mem(0x42, 0x10, 'xy') # write 2 bytes to slave 0x42, slave memory 0x10 - -Watchdog timer (WDT) --------------------- - -See :ref:`machine.WDT `. :: - - from machine import WDT - - # enable the WDT with a timeout of 5s (1s is the minimum) - wdt = WDT(timeout=5000) - wdt.feed() - -Real time clock (RTC) ---------------------- - -See :ref:`machine.RTC ` :: - - from machine import RTC - - rtc = RTC() # init with default time and date - rtc = RTC(datetime=(2015, 8, 29, 9, 0, 0, 0, None)) # init with a specific time and date - print(rtc.now()) - - def alarm_handler (rtc_o): - pass - # do some non blocking operations - # warning printing on an irq via telnet is not - # possible, only via UART - - # create a RTC alarm that expires after 5 seconds - rtc.alarm(time=5000, repeat=False) - - # enable RTC interrupts - rtc_i = rtc.irq(trigger=RTC.ALARM0, handler=alarm_handler, wake=machine.SLEEP) - - # go into suspended mode waiting for the RTC alarm to expire and wake us up - machine.sleep() - -SD card -------- - -See :ref:`machine.SD `. :: - - from machine import SD - import os - - # clock pin, cmd pin, data0 pin - sd = SD(pins=('GP10', 'GP11', 'GP15')) - # or use default ones for the expansion board - sd = SD() - os.mount(sd, '/sd') - -WLAN (WiFi) ------------ - -See :ref:`network.WLAN ` and :mod:`machine`. :: - - import machine - from network import WLAN - - # configure the WLAN subsystem in station mode (the default is AP) - wlan = WLAN(mode=WLAN.STA) - # go for fixed IP settings - wlan.ifconfig(config=('192.168.0.107', '255.255.255.0', '192.168.0.1', '8.8.8.8')) - wlan.scan() # scan for available networks - wlan.connect(ssid='mynetwork', auth=(WLAN.WPA2, 'mynetworkkey')) - while not wlan.isconnected(): - pass - print(wlan.ifconfig()) - # enable wake on WLAN - wlan.irq(trigger=WLAN.ANY_EVENT, wake=machine.SLEEP) - # go to sleep - machine.sleep() - # now, connect to the FTP or the Telnet server and the WiPy will wake-up - -Telnet and FTP server ---------------------- - -See :ref:`network.Server ` :: - - from network import Server - - # init with new user, password and seconds timeout - server = Server(login=('user', 'password'), timeout=60) - server.timeout(300) # change the timeout - server.timeout() # get the timeout - server.isrunning() # check whether the server is running or not - -Heart beat LED --------------- - -See :mod:`wipy`. :: - - import wipy - - wipy.heartbeat(False) # disable the heartbeat LED - wipy.heartbeat(True) # enable the heartbeat LED - wipy.heartbeat() # get the heartbeat state diff --git a/docs/wipy/tutorial/blynk.rst b/docs/wipy/tutorial/blynk.rst deleted file mode 100644 index b5a2f24a47..0000000000 --- a/docs/wipy/tutorial/blynk.rst +++ /dev/null @@ -1,19 +0,0 @@ -Getting started with Blynk and the WiPy ---------------------------------------- - -Blynk is a platform with iOS and Android apps to control -Arduino, Raspberry Pi and the likes over the Internet. -You can easily build graphic interfaces for all your -projects by simply dragging and dropping widgets. - -There are several examples available that work out-of-the-box with -the WiPy. Before anything else, make sure that your WiPy is running -the latest software, check :ref:`OTA How-To ` for instructions. - -1. Get the `Blynk library `_ and put it in ``/flash/lib/`` via FTP. -2. Get the `Blynk examples `_, edit the network settings, and afterwards - upload them to ``/flash/lib/`` via FTP as well. -3. Follow the instructions on each example to setup the Blynk dashboard on your smartphone or tablet. -4. Give it a try, for instance:: - - >>> execfile('01_simple.py') diff --git a/docs/wipy/tutorial/index.rst b/docs/wipy/tutorial/index.rst deleted file mode 100644 index 816de27b5a..0000000000 --- a/docs/wipy/tutorial/index.rst +++ /dev/null @@ -1,18 +0,0 @@ -.. _wipy_tutorial_index: - -WiPy tutorials and examples -=========================== - -Before starting, make sure that you are running the latest firmware, -for instructions see :ref:`OTA How-To `. - -.. toctree:: - :maxdepth: 1 - :numbered: - - intro.rst - repl.rst - blynk.rst - wlan.rst - timer.rst - reset.rst diff --git a/docs/wipy/tutorial/intro.rst b/docs/wipy/tutorial/intro.rst deleted file mode 100644 index 3acc0510f1..0000000000 --- a/docs/wipy/tutorial/intro.rst +++ /dev/null @@ -1,64 +0,0 @@ -Introduction to the WiPy -======================== - -To get the most out of your WiPy, there are a few basic things to -understand about how it works. - -Caring for your WiPy and expansion board ----------------------------------------- - -Because the WiPy/expansion board does not have a housing it needs a bit of care: - - - Be gentle when plugging/unplugging the USB cable. Whilst the USB connector - is well soldered and is relatively strong, if it breaks off it can be very - difficult to fix. - - - Static electricity can shock the components on the WiPy and destroy them. - If you experience a lot of static electricity in your area (eg dry and cold - climates), take extra care not to shock the WiPy. If your WiPy came - in a ESD bag, then this bag is the best way to store and carry the - WiPy as it will protect it against static discharges. - -As long as you take care of the hardware, you should be okay. It's almost -impossible to break the software on the WiPy, so feel free to play around -with writing code as much as you like. If the filesystem gets corrupt, see -below on how to reset it. In the worst case you might need to do a safe boot, -which is explained in detail :ref:`here `. - -Plugging into the expansion board and powering on -------------------------------------------------- - -The expansion board can power the WiPy via USB. The WiPy comes with a sticker -on top of the RF shield that labels all pins, and this should match the label -numbers on the expansion board headers. When plugging it in, the WiPy antenna -will end up on top of the SD card connector of the expansion board. A video -showing how to do this can be found `here `_. - -Expansion board hardware guide ------------------------------- - -The document explaining the hardware details of the expansion board can be found -`here `_. - -Powering by an external power source ------------------------------------- - -The WiPy can be powered by a battery or other external power source. - -**Be sure to connect the positive lead of the power supply to VIN, and -ground to GND. There is no polarity protection on the WiPy so you -must be careful when connecting anything to VIN.** - -- When powering via ``VIN``: - - **The input voltage must be between 3.6V and 5.5V.** - -- When powering via ``3V3``: - - **The input voltage must be exactly 3V3, ripple free and from a supply capable - of sourcing at least 300mA of current** - -Performing firmware upgrades ----------------------------- - -For detailed instructions see :ref:`OTA How-To `. diff --git a/docs/wipy/tutorial/repl.rst b/docs/wipy/tutorial/repl.rst deleted file mode 100644 index e7b51f9c59..0000000000 --- a/docs/wipy/tutorial/repl.rst +++ /dev/null @@ -1,130 +0,0 @@ -Getting a MicroPython REPL prompt -================================= - -REPL stands for Read Evaluate Print Loop, and is the name given to the -interactive MicroPython prompt that you can access on the WiPy. Using -the REPL is by far the easiest way to test out your code and run commands. -You can use the REPL in addition to writing scripts in ``main.py``. - -.. _wipy_uart: - -To use the REPL, you must connect to the WiPy either via :ref:`telnet `, -or with a USB to serial converter wired to one of the two UARTs on the -WiPy. To enable REPL duplication on UART0 (the one accessible via the expansion board) -do:: - - >>> from machine import UART - >>> import os - >>> uart = UART(0, 115200) - >>> os.dupterm(uart) - -Place this piece of code inside your `boot.py` so that it's done automatically after -reset. - -Windows -------- - -First you need to install the FTDI drivers for the expansion board's USB to serial -converter. Then you need a terminal software. The best option is to download the -free program PuTTY: `putty.exe `_. - -**In order to get to the telnet REPL:** - -Using putty, select ``Telnet`` as connection type, leave the default port (23) -and enter the IP address of your WiPy (192.168.1.1 when in ``WLAN.AP`` mode), -then click open. - -**In order to get to the REPL UART:** - -Using your serial program you must connect to the COM port that you found in the -previous step. With PuTTY, click on "Session" in the left-hand panel, then click -the "Serial" radio button on the right, then enter you COM port (eg COM4) in the -"Serial Line" box. Finally, click the "Open" button. - -Mac OS X --------- - -Open a terminal and run:: - - $ telnet 192.168.1.1 - -or:: - - $ screen /dev/tty.usbmodem* 115200 - -When you are finished and want to exit ``screen``, type CTRL-A CTRL-\\. If your keyboard does not have a \\-key (i.e. you need an obscure combination for \\ like ALT-SHIFT-7) you can remap the ``quit`` command: - -- create ``~/.screenrc`` -- add ``bind q quit`` - -This will allow you to quit ``screen`` by hitting CTRL-A Q. - -Linux ------ - -Open a terminal and run:: - - $ telnet 192.168.1.1 - -or:: - - $ screen /dev/ttyUSB0 115200 - -You can also try ``picocom`` or ``minicom`` instead of screen. You may have to -use ``/dev/ttyUSB01`` or a higher number for ``ttyUSB``. And, you may need to give -yourself the correct permissions to access this devices (eg group ``uucp`` or ``dialout``, -or use sudo). - -Using the REPL prompt ---------------------- - -Now let's try running some MicroPython code directly on the WiPy. - -With your serial program open (PuTTY, screen, picocom, etc) you may see a blank -screen with a flashing cursor. Press Enter and you should be presented with a -MicroPython prompt, i.e. ``>>>``. Let's make sure it is working with the obligatory test:: - - >>> print("hello WiPy!") - hello WiPy! - -In the above, you should not type in the ``>>>`` characters. They are there to -indicate that you should type the text after it at the prompt. In the end, once -you have entered the text ``print("hello WiPy!")`` and pressed Enter, the output -on your screen should look like it does above. - -If you already know some Python you can now try some basic commands here. - -If any of this is not working you can try either a hard reset or a soft reset; -see below. - -Go ahead and try typing in some other commands. For example:: - - >>> from machine import Pin - >>> import wipy - >>> wipy.heartbeat(False) # disable the heartbeat - >>> led = Pin('GP25', mode=Pin.OUT) - >>> led(1) - >>> led(0) - >>> led.toggle() - >>> 1 + 2 - 3 - >>> 4 // 2 - 2 - >>> 20 * 'py' - 'pypypypypypypypypypypypypypypypypypypypy' - -Resetting the board -------------------- - -If something goes wrong, you can reset the board in two ways. The first is to press CTRL-D -at the MicroPython prompt, which performs a soft reset. You will see a message something like:: - - >>> - PYB: soft reboot - MicroPython v1.4.6-146-g1d8b5e5 on 2015-10-21; WiPy with CC3200 - Type "help()" for more information. - >>> - -If that isn't working you can perform a hard reset (turn-it-off-and-on-again) by pressing the -RST switch (the small black button next to the heartbeat LED). During telnet, this will end -your session, disconnecting whatever program that you used to connect to the WiPy. diff --git a/docs/wipy/tutorial/reset.rst b/docs/wipy/tutorial/reset.rst deleted file mode 100644 index ece28498b8..0000000000 --- a/docs/wipy/tutorial/reset.rst +++ /dev/null @@ -1,54 +0,0 @@ -Reset and boot modes -==================== - -There are soft resets and hard resets. - - - A soft reset simply clears the state of the MicroPython virtual machine, - but leaves hardware peripherals unaffected. To do a soft reset, simply press - **Ctrl+D** on the REPL, or within a script do:: - - import sys - sys.exit() - - - A hard reset is the same as performing a power cycle to the board. In order to - hard reset the WiPy, press the switch on the board or:: - - import machine - machine.reset() - -Safe boot ---------- - -If something goes wrong with your WiPy, don't panic! It is almost -impossible for you to break the WiPy by programming the wrong thing. - -The first thing to try is to boot in safe mode: this temporarily skips -execution of ``boot.py`` and ``main.py`` and gives default WLAN settings. - -If you have problems with the filesystem you can :ref:`format the internal flash -drive `. - -To boot in safe mode, follow the detailed instructions described :ref:`here `. - -In safe mode, the ``boot.py`` and ``main.py`` files are not executed, and so -the WiPy boots up with default settings. This means you now have access -to the filesystem, and you can edit ``boot.py`` and ``main.py`` to fix any problems. - -Entering safe mode is temporary, and does not make any changes to the -files on the WiPy. - -.. _wipy_factory_reset: - -Factory reset the filesystem ----------------------------- - -If you WiPy's filesystem gets corrupted (very unlikely, but possible), you -can format it very easily by doing:: - - >>> import os - >>> os.mkfs('/flash') - -Resetting the filesystem deletes all files on the internal WiPy storage -(not the SD card), and restores the files ``boot.py`` and ``main.py`` back -to their original state after the next reset. - diff --git a/docs/wipy/tutorial/timer.rst b/docs/wipy/tutorial/timer.rst deleted file mode 100644 index c87ac44959..0000000000 --- a/docs/wipy/tutorial/timer.rst +++ /dev/null @@ -1,70 +0,0 @@ -Hardware timers -=============== - -Timers can be used for a great variety of tasks, calling a function periodically, -counting events, and generating a PWM signal are among the most common use cases. -Each timer consists of two 16-bit channels and this channels can be tied together to -form one 32-bit timer. The operating mode needs to be configured per timer, but then -the period (or the frequency) can be independently configured on each channel. -By using the callback method, the timer event can call a Python function. - -Example usage to toggle an LED at a fixed frequency:: - - from machine import Timer - from machine import Pin - led = Pin('GP16', mode=Pin.OUT) # enable GP16 as output to drive the LED - tim = Timer(3) # create a timer object using timer 3 - tim.init(mode=Timer.PERIODIC) # initialize it in periodic mode - tim_ch = tim.channel(Timer.A, freq=5) # configure channel A at a frequency of 5Hz - tim_ch.irq(handler=lambda t:led.toggle(), trigger=Timer.TIMEOUT) # toggle a LED on every cycle of the timer - -Example using named function for the callback:: - - from machine import Timer - from machine import Pin - tim = Timer(1, mode=Timer.PERIODIC, width=32) - tim_a = tim.channel(Timer.A | Timer.B, freq=1) # 1 Hz frequency requires a 32 bit timer - - led = Pin('GP16', mode=Pin.OUT) # enable GP16 as output to drive the LED - - def tick(timer): # we will receive the timer object when being called - global led - led.toggle() # toggle the LED - - tim_a.irq(handler=tick, trigger=Timer.TIMEOUT) # create the interrupt - -Further examples:: - - from machine import Timer - tim1 = Timer(1, mode=Timer.ONE_SHOT) # initialize it in one shot mode - tim2 = Timer(2, mode=Timer.PWM) # initialize it in PWM mode - tim1_ch = tim1.channel(Timer.A, freq=10, polarity=Timer.POSITIVE) # start the event counter with a frequency of 10Hz and triggered by positive edges - tim2_ch = tim2.channel(Timer.B, freq=10000, duty_cycle=5000) # start the PWM on channel B with a 50% duty cycle - tim2_ch.freq(20) # set the frequency (can also get) - tim2_ch.duty_cycle(3010) # set the duty cycle to 30.1% (can also get) - tim2_ch.duty_cycle(3020, Timer.NEGATIVE) # set the duty cycle to 30.2% and change the polarity to negative - tim2_ch.period(2000000) # change the period to 2 seconds - - -Additional constants for Timer class ------------------------------------- - -.. data:: Timer.PWM - - PWM timer operating mode. - -.. data:: Timer.A -.. data:: Timer.B - - Selects the timer channel. Must be ORed (``Timer.A`` | ``Timer.B``) when - using a 32-bit timer. - -.. data:: Timer.POSITIVE -.. data:: Timer.NEGATIVE - - Timer channel polarity selection (only relevant in PWM mode). - -.. data:: Timer.TIMEOUT -.. data:: Timer.MATCH - - Timer channel IRQ triggers. diff --git a/docs/wipy/tutorial/wlan.rst b/docs/wipy/tutorial/wlan.rst deleted file mode 100644 index 434367cd93..0000000000 --- a/docs/wipy/tutorial/wlan.rst +++ /dev/null @@ -1,71 +0,0 @@ -WLAN step by step -================= - -The WLAN is a system feature of the WiPy, therefore it is always enabled -(even while in ``machine.SLEEP``), except when deepsleep mode is entered. - -In order to retrieve the current WLAN instance, do:: - - >>> from network import WLAN - >>> wlan = WLAN() # we call the constructor without params - -You can check the current mode (which is always ``WLAN.AP`` after power up):: - - >>> wlan.mode() - -.. warning:: - When you change the WLAN mode following the instructions below, your WLAN - connection to the WiPy will be broken. This means you will not be able - to run these commands interactively over the WLAN. - - There are two ways around this:: - 1. put this setup code into your :ref:`boot.py file` so that it gets executed automatically after reset. - 2. :ref:`duplicate the REPL on UART `, so that you can run commands via USB. - -Connecting to your home router ------------------------------- - -The WLAN network card always boots in ``WLAN.AP`` mode, so we must first configure -it as a station:: - - from network import WLAN - wlan = WLAN(mode=WLAN.STA) - - -Now you can proceed to scan for networks:: - - nets = wlan.scan() - for net in nets: - if net.ssid == 'mywifi': - print('Network found!') - wlan.connect(net.ssid, auth=(net.sec, 'mywifikey'), timeout=5000) - while not wlan.isconnected(): - machine.idle() # save power while waiting - print('WLAN connection succeeded!') - break - -Assigning a static IP address when booting ------------------------------------------- - -If you want your WiPy to connect to your home router after boot-up, and with a fixed -IP address so that you can access it via telnet or FTP, use the following script as /flash/boot.py:: - - import machine - from network import WLAN - wlan = WLAN() # get current object, without changing the mode - - if machine.reset_cause() != machine.SOFT_RESET: - wlan.init(WLAN.STA) - # configuration below MUST match your home router settings!! - wlan.ifconfig(config=('192.168.178.107', '255.255.255.0', '192.168.178.1', '8.8.8.8')) - - if not wlan.isconnected(): - # change the line below to match your network ssid, security and password - wlan.connect('mywifi', auth=(WLAN.WPA2, 'mywifikey'), timeout=5000) - while not wlan.isconnected(): - machine.idle() # save power while waiting - -.. note:: - - Notice how we check for the reset cause and the connection status, this is crucial in order - to be able to soft reset the WiPy during a telnet session without breaking the connection. diff --git a/docs/wipy_index.rst b/docs/wipy_index.rst deleted file mode 100644 index 15c04c0fba..0000000000 --- a/docs/wipy_index.rst +++ /dev/null @@ -1,12 +0,0 @@ -MicroPython documentation and references -======================================== - -.. toctree:: - - wipy/quickref.rst - wipy/general.rst - wipy/tutorial/index.rst - library/index.rst - reference/index.rst - genrst/index.rst - license.rst diff --git a/drivers/README.md b/drivers/README.md deleted file mode 100644 index 854acc50b6..0000000000 --- a/drivers/README.md +++ /dev/null @@ -1,2 +0,0 @@ -This directory contains drivers for specific hardware. The drivers are -intended to work across multiple ports. diff --git a/drivers/cc3000/inc/cc3000_common.h b/drivers/cc3000/inc/cc3000_common.h deleted file mode 100644 index aa16242310..0000000000 --- a/drivers/cc3000/inc/cc3000_common.h +++ /dev/null @@ -1,365 +0,0 @@ -/***************************************************************************** -* -* cc3000_common.h - CC3000 Host Driver Implementation. -* Copyright (C) 2011 Texas Instruments Incorporated - http://www.ti.com/ -* -* Redistribution and use in source and binary forms, with or without -* modification, are permitted provided that the following conditions -* are met: -* -* Redistributions of source code must retain the above copyright -* notice, this list of conditions and the following disclaimer. -* -* Redistributions in binary form must reproduce the above copyright -* notice, this list of conditions and the following disclaimer in the -* documentation and/or other materials provided with the -* distribution. -* -* Neither the name of Texas Instruments Incorporated nor the names of -* its contributors may be used to endorse or promote products derived -* from this software without specific prior written permission. -* -* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -* -*****************************************************************************/ -#ifndef __CC3000_COMMON_H__ -#define __CC3000_COMMON_H__ - -#include "data_types.h" - -//****************************************************************************** -// Include files -//****************************************************************************** -#include -#include - -//***************************************************************************** -// Prefix exported names to avoid name clash -//***************************************************************************** -#define CC3000_EXPORT(name) cc3000_ ## name - -//***************************************************************************** -// -// If building with a C++ compiler, make all of the definitions in this header -// have a C binding. -// -//***************************************************************************** -#ifdef __cplusplus -extern "C" { -#endif - -extern int CC3000_EXPORT(errno); - -//***************************************************************************** -// ERROR CODES -//***************************************************************************** -#define ESUCCESS 0 -#define EFAIL -1 -#define EERROR EFAIL - -//***************************************************************************** -// COMMON DEFINES -//***************************************************************************** -#define ERROR_SOCKET_INACTIVE -57 - -#define WLAN_ENABLE (1) -#define WLAN_DISABLE (0) - -#define MAC_ADDR_LEN (6) - -#define SP_PORTION_SIZE (32) - -/*Defines for minimal and maximal RX buffer size. This size includes the spi - header and hci header. - The maximal buffer size derives from: - MTU + HCI header + SPI header + sendto() agrs size - The minimum buffer size derives from: - HCI header + SPI header + max args size - - This buffer is used for receiving events and data. - The packet can not be longer than MTU size and CC3000 does not support - fragmentation. Note that the same buffer is used for reception of the data - and events from CC3000. That is why the minimum is defined. - The calculation for the actual size of buffer for reception is: - Given the maximal data size MAX_DATA that is expected to be received by - application, the required buffer is: - Using recv() or recvfrom(): - - max(CC3000_MINIMAL_RX_SIZE, MAX_DATA + HEADERS_SIZE_DATA + fromlen - + ucArgsize + 1) - - Using gethostbyname() with minimal buffer size will limit the host name - returned to 99 bytes only. - The 1 is used for the overrun detection - - Buffer size increased to 130 following the add_profile() with WEP security - which requires TX buffer size of 130 bytes: - HEADERS_SIZE_EVNT + WLAN_ADD_PROFILE_WEP_PARAM_LEN + MAX SSID LEN + 4 * MAX KEY LEN = 130 - MAX SSID LEN = 32 - MAX SSID LEN = 13 (with add_profile only ascii key setting is supported, - therfore maximum key size is 13) -*/ - -#define CC3000_MINIMAL_RX_SIZE (130 + 1) -#define CC3000_MAXIMAL_RX_SIZE (1519 + 1) - -/*Defines for minimal and maximal TX buffer size. - This buffer is used for sending events and data. - The packet can not be longer than MTU size and CC3000 does not support - fragmentation. Note that the same buffer is used for transmission of the data - and commands. That is why the minimum is defined. - The calculation for the actual size of buffer for transmission is: - Given the maximal data size MAX_DATA, the required buffer is: - Using Sendto(): - - max(CC3000_MINIMAL_TX_SIZE, MAX_DATA + SPI_HEADER_SIZE - + SOCKET_SENDTO_PARAMS_LEN + SIMPLE_LINK_HCI_DATA_HEADER_SIZE + 1) - - Using Send(): - - max(CC3000_MINIMAL_TX_SIZE, MAX_DATA + SPI_HEADER_SIZE - + HCI_CMND_SEND_ARG_LENGTH + SIMPLE_LINK_HCI_DATA_HEADER_SIZE + 1) - - The 1 is used for the overrun detection */ - -#define CC3000_MINIMAL_TX_SIZE (130 + 1) -#define CC3000_MAXIMAL_TX_SIZE (1519 + 1) - -//TX and RX buffer sizes, allow to receive and transmit maximum data at length 8. -#ifdef CC3000_TINY_DRIVER -#define TINY_CC3000_MAXIMAL_RX_SIZE 44 -#define TINY_CC3000_MAXIMAL_TX_SIZE 59 -#endif - -/*In order to determine your preferred buffer size, - change CC3000_MAXIMAL_RX_SIZE and CC3000_MAXIMAL_TX_SIZE to a value between - the minimal and maximal specified above. - Note that the buffers are allocated by SPI. - In case you change the size of those buffers, you might need also to change - the linker file, since for example on MSP430 FRAM devices the buffers are - allocated in the FRAM section that is allocated manually and not by IDE. -*/ - -#ifndef CC3000_TINY_DRIVER - - #define CC3000_RX_BUFFER_SIZE (CC3000_MAXIMAL_RX_SIZE) - #define CC3000_TX_BUFFER_SIZE (CC3000_MAXIMAL_TX_SIZE) - -//if defined TINY DRIVER we use smaller RX and TX buffer in order to minimize RAM consumption -#else - #define CC3000_RX_BUFFER_SIZE (TINY_CC3000_MAXIMAL_RX_SIZE) - #define CC3000_TX_BUFFER_SIZE (TINY_CC3000_MAXIMAL_TX_SIZE) - -#endif - -//***************************************************************************** -// Compound Types -//***************************************************************************** -typedef INT32 time_t; -typedef UINT32 clock_t; -typedef INT32 suseconds_t; - -typedef struct cc3000_timeval cc3000_timeval; - -struct cc3000_timeval -{ - time_t tv_sec; /* seconds */ - suseconds_t tv_usec; /* microseconds */ -}; - -typedef CHAR *(*tFWPatches)(UINT32 *usLength); - -typedef CHAR *(*tDriverPatches)(UINT32 *usLength); - -typedef CHAR *(*tBootLoaderPatches)(UINT32 *usLength); - -typedef void (*tWlanCB)(INT32 event_type, CHAR * data, UINT8 length ); - -typedef INT32 (*tWlanReadInteruptPin)(void); - -typedef void (*tWlanInterruptEnable)(void); - -typedef void (*tWlanInterruptDisable)(void); - -typedef void (*tWriteWlanPin)(UINT8 val); - -typedef struct -{ - UINT16 usRxEventOpcode; - UINT16 usEventOrDataReceived; - UINT8 *pucReceivedData; - UINT8 *pucTxCommandBuffer; - - tFWPatches sFWPatches; - tDriverPatches sDriverPatches; - tBootLoaderPatches sBootLoaderPatches; - tWlanCB sWlanCB; - tWlanReadInteruptPin ReadWlanInterruptPin; - tWlanInterruptEnable WlanInterruptEnable; - tWlanInterruptDisable WlanInterruptDisable; - tWriteWlanPin WriteWlanPin; - - INT32 slTransmitDataError; - UINT16 usNumberOfFreeBuffers; - UINT16 usSlBufferLength; - UINT16 usBufferSize; - UINT16 usRxDataPending; - - UINT32 NumberOfSentPackets; - UINT32 NumberOfReleasedPackets; - - UINT8 InformHostOnTxComplete; -}sSimplLinkInformation; - -extern volatile sSimplLinkInformation tSLInformation; - - -//***************************************************************************** -// Prototypes for the APIs. -//***************************************************************************** - - - -//***************************************************************************** -// -//! SimpleLinkWaitEvent -//! -//! @param usOpcode command operation code -//! @param pRetParams command return parameters -//! -//! @return none -//! -//! @brief Wait for event, pass it to the hci_event_handler and -//! update the event opcode in a global variable. -// -//***************************************************************************** - -extern void SimpleLinkWaitEvent(UINT16 usOpcode, void *pRetParams); - -//***************************************************************************** -// -//! SimpleLinkWaitData -//! -//! @param pBuf data buffer -//! @param from from information -//! @param fromlen from information length -//! -//! @return none -//! -//! @brief Wait for data, pass it to the hci_event_handler -//! and update in a global variable that there is -//! data to read. -// -//***************************************************************************** - -extern void SimpleLinkWaitData(UINT8 *pBuf, UINT8 *from, UINT8 *fromlen); - -//***************************************************************************** -// -//! UINT32_TO_STREAM_f -//! -//! \param p pointer to the new stream -//! \param u32 pointer to the 32 bit -//! -//! \return pointer to the new stream -//! -//! \brief This function is used for copying 32 bit to stream -//! while converting to little endian format. -// -//***************************************************************************** - -extern UINT8* UINT32_TO_STREAM_f (UINT8 *p, UINT32 u32); - -//***************************************************************************** -// -//! UINT16_TO_STREAM_f -//! -//! \param p pointer to the new stream -//! \param u32 pointer to the 16 bit -//! -//! \return pointer to the new stream -//! -//! \brief This function is used for copying 16 bit to stream -//! while converting to little endian format. -// -//***************************************************************************** - -extern UINT8* UINT16_TO_STREAM_f (UINT8 *p, UINT16 u16); - -//***************************************************************************** -// -//! STREAM_TO_UINT16_f -//! -//! \param p pointer to the stream -//! \param offset offset in the stream -//! -//! \return pointer to the new 16 bit -//! -//! \brief This function is used for copying received stream to -//! 16 bit in little endian format. -// -//***************************************************************************** - -extern UINT16 STREAM_TO_UINT16_f(CHAR* p, UINT16 offset); - -//***************************************************************************** -// -//! STREAM_TO_UINT32_f -//! -//! \param p pointer to the stream -//! \param offset offset in the stream -//! -//! \return pointer to the new 32 bit -//! -//! \brief This function is used for copying received stream to -//! 32 bit in little endian format. -// -//***************************************************************************** - -extern UINT32 STREAM_TO_UINT32_f(CHAR* p, UINT16 offset); - - -//***************************************************************************** -// COMMON MACROs -//***************************************************************************** - - -//This macro is used for copying 8 bit to stream while converting to little endian format. -#define UINT8_TO_STREAM(_p, _val) {*(_p)++ = (_val);} -//This macro is used for copying 16 bit to stream while converting to little endian format. -#define UINT16_TO_STREAM(_p, _u16) (UINT16_TO_STREAM_f(_p, _u16)) -//This macro is used for copying 32 bit to stream while converting to little endian format. -#define UINT32_TO_STREAM(_p, _u32) (UINT32_TO_STREAM_f(_p, _u32)) -//This macro is used for copying a specified value length bits (l) to stream while converting to little endian format. -#define ARRAY_TO_STREAM(p, a, l) {register INT16 _i; for (_i = 0; _i < l; _i++) *(p)++ = ((UINT8 *) a)[_i];} -//This macro is used for copying received stream to 8 bit in little endian format. -#define STREAM_TO_UINT8(_p, _offset, _u8) {_u8 = (UINT8)(*(_p + _offset));} -//This macro is used for copying received stream to 16 bit in little endian format. -#define STREAM_TO_UINT16(_p, _offset, _u16) {_u16 = STREAM_TO_UINT16_f(_p, _offset);} -//This macro is used for copying received stream to 32 bit in little endian format. -#define STREAM_TO_UINT32(_p, _offset, _u32) {_u32 = STREAM_TO_UINT32_f(_p, _offset);} -#define STREAM_TO_STREAM(p, a, l) {register INT16 _i; for (_i = 0; _i < l; _i++) *(a)++= ((UINT8 *) p)[_i];} - - - - -//***************************************************************************** -// -// Mark the end of the C bindings section for C++ compilers. -// -//***************************************************************************** -#ifdef __cplusplus -} -#endif // __cplusplus - -#endif // __CC3000_COMMON_H__ diff --git a/drivers/cc3000/inc/ccspi.h b/drivers/cc3000/inc/ccspi.h deleted file mode 100644 index 8fa3ecd10c..0000000000 --- a/drivers/cc3000/inc/ccspi.h +++ /dev/null @@ -1,84 +0,0 @@ -/***************************************************************************** -* -* spi.h - CC3000 Host Driver Implementation. -* Copyright (C) 2011 Texas Instruments Incorporated - http://www.ti.com/ -* -* Redistribution and use in source and binary forms, with or without -* modification, are permitted provided that the following conditions -* are met: -* -* Redistributions of source code must retain the above copyright -* notice, this list of conditions and the following disclaimer. -* -* Redistributions in binary form must reproduce the above copyright -* notice, this list of conditions and the following disclaimer in the -* documentation and/or other materials provided with the -* distribution. -* -* Neither the name of Texas Instruments Incorporated nor the names of -* its contributors may be used to endorse or promote products derived -* from this software without specific prior written permission. -* -* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -* -*****************************************************************************/ - - -#ifndef __CC3000_SPI_H__ -#define __CC3000_SPI_H__ - -//***************************************************************************** -// -// If building with a C++ compiler, make all of the definitions in this header -// have a C binding. -// -//***************************************************************************** -#ifdef __cplusplus -extern "C" { -#endif - -typedef void (*gcSpiHandleRx)(void *p); -typedef void (*gcSpiHandleTx)(void); -extern unsigned char wlan_tx_buffer[]; - -//***************************************************************************** -// -// Prototypes for the APIs. -// -//***************************************************************************** - -// the arguments must be of type pin_obj_t* and SPI_HandleTypeDef* -extern void SpiInit(void *spi, const void *pin_cs, const void *pin_en, const void *pin_irq); - -extern void SpiOpen(gcSpiHandleRx pfRxHandler); -extern void SpiClose(void); -extern void SpiPauseSpi(void); -extern void SpiResumeSpi(void); -extern long SpiWrite(unsigned char *pUserBuffer, unsigned short usLength); -extern void SpiConfigureHwMapping(void); -extern void SpiCleanGPIOISR(void); -extern void SSIConfigure(unsigned long ulSSIFreq, unsigned long bForceGpioConfiguration, unsigned long uiReconfigureSysClock); -extern int init_spi(void); -extern long ReadWlanInterruptPin(void); -extern void WriteWlanPin(unsigned char val); -//***************************************************************************** -// -// Mark the end of the C bindings section for C++ compilers. -// -//***************************************************************************** -#ifdef __cplusplus -} -#endif // __cplusplus - -#endif - diff --git a/drivers/cc3000/inc/data_types.h b/drivers/cc3000/inc/data_types.h deleted file mode 100644 index 0520a9202f..0000000000 --- a/drivers/cc3000/inc/data_types.h +++ /dev/null @@ -1,107 +0,0 @@ -/***************************************************************************** -* -* data_types.h - CC3000 Host Driver Implementation. -* Copyright (C) 2011 Texas Instruments Incorporated - http://www.ti.com/ -* -* Redistribution and use in source and binary forms, with or without -* modification, are permitted provided that the following conditions -* are met: -* -* Redistributions of source code must retain the above copyright -* notice, this list of conditions and the following disclaimer. -* -* Redistributions in binary form must reproduce the above copyright -* notice, this list of conditions and the following disclaimer in the -* documentation and/or other materials provided with the -* distribution. -* -* Neither the name of Texas Instruments Incorporated nor the names of -* its contributors may be used to endorse or promote products derived -* from this software without specific prior written permission. -* -* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -* -*****************************************************************************/ -#ifndef __CC3000_DATA_TYPES__ -#define __CC3000_DATA_TYPES__ - -//***************************************************************************** -// -// If building with a C++ compiler, make all of the definitions in this header -// have a C binding. -// -//***************************************************************************** -#ifdef __cplusplus -extern "C" { -#endif - - -#ifndef NULL -#define NULL (0) -#endif - -#ifndef FALSE -#define FALSE (0) -#endif - -#ifndef TRUE -#define TRUE (!FALSE) -#endif - -#ifndef OK -#define OK (0) -#endif - -#ifndef _INT8 -#define _INT8 -typedef signed char INT8; -#endif - -#ifndef _UINT8 -#define _UINT8 -typedef unsigned char UINT8; -#endif - -#ifndef _INT16 -#define _INT16 -typedef signed short INT16; -#endif - -#ifndef _UINT16 -#define _UINT16 -typedef unsigned short UINT16; -#endif - -#ifndef _BOOLEAN -#define _BOOLEAN -typedef unsigned char BOOLEAN; -#endif - -#ifndef _INT32 -#define _INT32 -typedef signed long INT32; -#endif - -#ifndef _UINT32 -#define _UINT32 -typedef unsigned long UINT32; -#endif - -typedef int INT; -typedef char CHAR; - -#ifdef __cplusplus -} -#endif /* __cplusplus */ - -#endif /* __CC3000_DATA_TYPES__ */ diff --git a/drivers/cc3000/inc/evnt_handler.h b/drivers/cc3000/inc/evnt_handler.h deleted file mode 100644 index d05a442f05..0000000000 --- a/drivers/cc3000/inc/evnt_handler.h +++ /dev/null @@ -1,166 +0,0 @@ -/***************************************************************************** -* -* evnt_handler.h - CC3000 Host Driver Implementation. -* Copyright (C) 2011 Texas Instruments Incorporated - http://www.ti.com/ -* -* Redistribution and use in source and binary forms, with or without -* modification, are permitted provided that the following conditions -* are met: -* -* Redistributions of source code must retain the above copyright -* notice, this list of conditions and the following disclaimer. -* -* Redistributions in binary form must reproduce the above copyright -* notice, this list of conditions and the following disclaimer in the -* documentation and/or other materials provided with the -* distribution. -* -* Neither the name of Texas Instruments Incorporated nor the names of -* its contributors may be used to endorse or promote products derived -* from this software without specific prior written permission. -* -* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -* -*****************************************************************************/ -#ifndef __CC3000_EVENT_HANDLER_H__ -#define __CC3000_EVENT_HANDLER_H__ -#include "hci.h" -#include "socket.h" - -//***************************************************************************** -// -// If building with a C++ compiler, make all of the definitions in this header -// have a C binding. -// -//***************************************************************************** -#ifdef __cplusplus -extern "C" { -#endif - -//***************************************************************************** -// -// Prototypes for the APIs. -// -//***************************************************************************** - -//***************************************************************************** -// -//! hci_event_handler -//! -//! @param pRetParams incoming data buffer -//! @param from from information (in case of data received) -//! @param fromlen from information length (in case of data received) -//! -//! @return none -//! -//! @brief Parse the incoming events packets and issues corresponding -//! event handler from global array of handlers pointers -// -//***************************************************************************** -extern UINT8 *hci_event_handler(void *pRetParams, UINT8 *from, UINT8 *fromlen); - -//***************************************************************************** -// -//! hci_unsol_event_handler -//! -//! @param event_hdr event header -//! -//! @return 1 if event supported and handled -//! 0 if event is not supported -//! -//! @brief Handle unsolicited events -// -//***************************************************************************** -extern INT32 hci_unsol_event_handler(CHAR *event_hdr); - -//***************************************************************************** -// -//! hci_unsolicited_event_handler -//! -//! @param None -//! -//! @return ESUCCESS if successful, EFAIL if an error occurred -//! -//! @brief Parse the incoming unsolicited event packets and issues -//! corresponding event handler. -// -//***************************************************************************** -extern INT32 hci_unsolicited_event_handler(void); - -#define M_BSD_RESP_PARAMS_OFFSET(hci_event_hdr)((CHAR *)(hci_event_hdr) + HCI_EVENT_HEADER_SIZE) - -#define SOCKET_STATUS_ACTIVE 0 -#define SOCKET_STATUS_INACTIVE 1 -/* Init socket_active_status = 'all ones': init all sockets with SOCKET_STATUS_INACTIVE. - Will be changed by 'set_socket_active_status' upon 'connect' and 'accept' calls */ -#define SOCKET_STATUS_INIT_VAL 0xFFFF -#define M_IS_VALID_SD(sd) ((0 <= (sd)) && ((sd) <= 7)) -#define M_IS_VALID_STATUS(status) (((status) == SOCKET_STATUS_ACTIVE)||((status) == SOCKET_STATUS_INACTIVE)) - -extern UINT32 socket_active_status; - -extern void set_socket_active_status(INT32 Sd, INT32 Status); -extern INT32 get_socket_active_status(INT32 Sd); - -typedef struct _bsd_accept_return_t -{ - INT32 iSocketDescriptor; - INT32 iStatus; - sockaddr tSocketAddress; - -} tBsdReturnParams; - - -typedef struct _bsd_read_return_t -{ - INT32 iSocketDescriptor; - INT32 iNumberOfBytes; - UINT32 uiFlags; -} tBsdReadReturnParams; - -#define BSD_RECV_FROM_FROMLEN_OFFSET (4) -#define BSD_RECV_FROM_FROM_OFFSET (16) - - -typedef struct _bsd_select_return_t -{ - INT32 iStatus; - UINT32 uiRdfd; - UINT32 uiWrfd; - UINT32 uiExfd; -} tBsdSelectRecvParams; - - -typedef struct _bsd_getsockopt_return_t -{ - UINT8 ucOptValue[4]; - CHAR iStatus; -} tBsdGetSockOptReturnParams; - -typedef struct _bsd_gethostbyname_return_t -{ - INT32 retVal; - INT32 outputAddress; -} tBsdGethostbynameParams; - -//***************************************************************************** -// -// Mark the end of the C bindings section for C++ compilers. -// -//***************************************************************************** -#ifdef __cplusplus -} -#endif // __cplusplus - -#endif // __CC3000_EVENT_HANDLER_H__ - diff --git a/drivers/cc3000/inc/hci.h b/drivers/cc3000/inc/hci.h deleted file mode 100644 index f12b00e918..0000000000 --- a/drivers/cc3000/inc/hci.h +++ /dev/null @@ -1,330 +0,0 @@ -/***************************************************************************** -* -* hci.h - CC3000 Host Driver Implementation. -* Copyright (C) 2011 Texas Instruments Incorporated - http://www.ti.com/ -* -* Redistribution and use in source and binary forms, with or without -* modification, are permitted provided that the following conditions -* are met: -* -* Redistributions of source code must retain the above copyright -* notice, this list of conditions and the following disclaimer. -* -* Redistributions in binary form must reproduce the above copyright -* notice, this list of conditions and the following disclaimer in the -* documentation and/or other materials provided with the -* distribution. -* -* Neither the name of Texas Instruments Incorporated nor the names of -* its contributors may be used to endorse or promote products derived -* from this software without specific prior written permission. -* -* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -* -*****************************************************************************/ -#ifndef __CC3000_HCI_H__ -#define __CC3000_HCI_H__ - -#include "cc3000_common.h" - -//***************************************************************************** -// -// If building with a C++ compiler, make all of the definitions in this header -// have a C binding. -// -//***************************************************************************** -#ifdef __cplusplus -extern "C" { -#endif - - -#define SPI_HEADER_SIZE (5) -#define SIMPLE_LINK_HCI_CMND_HEADER_SIZE (4) -#define HEADERS_SIZE_CMD (SPI_HEADER_SIZE + SIMPLE_LINK_HCI_CMND_HEADER_SIZE) -#define SIMPLE_LINK_HCI_DATA_CMND_HEADER_SIZE (5) -#define SIMPLE_LINK_HCI_DATA_HEADER_SIZE (5) -#define SIMPLE_LINK_HCI_PATCH_HEADER_SIZE (2) - - -//***************************************************************************** -// -// Values that can be used as HCI Commands and HCI Packet header defines -// -//***************************************************************************** -#define HCI_TYPE_CMND 0x1 -#define HCI_TYPE_DATA 0x2 -#define HCI_TYPE_PATCH 0x3 -#define HCI_TYPE_EVNT 0x4 - - -#define HCI_EVENT_PATCHES_DRV_REQ (1) -#define HCI_EVENT_PATCHES_FW_REQ (2) -#define HCI_EVENT_PATCHES_BOOTLOAD_REQ (3) - - -#define HCI_CMND_WLAN_BASE (0x0000) -#define HCI_CMND_WLAN_CONNECT 0x0001 -#define HCI_CMND_WLAN_DISCONNECT 0x0002 -#define HCI_CMND_WLAN_IOCTL_SET_SCANPARAM 0x0003 -#define HCI_CMND_WLAN_IOCTL_SET_CONNECTION_POLICY 0x0004 -#define HCI_CMND_WLAN_IOCTL_ADD_PROFILE 0x0005 -#define HCI_CMND_WLAN_IOCTL_DEL_PROFILE 0x0006 -#define HCI_CMND_WLAN_IOCTL_GET_SCAN_RESULTS 0x0007 -#define HCI_CMND_EVENT_MASK 0x0008 -#define HCI_CMND_WLAN_IOCTL_STATUSGET 0x0009 -#define HCI_CMND_WLAN_IOCTL_SIMPLE_CONFIG_START 0x000A -#define HCI_CMND_WLAN_IOCTL_SIMPLE_CONFIG_STOP 0x000B -#define HCI_CMND_WLAN_IOCTL_SIMPLE_CONFIG_SET_PREFIX 0x000C -#define HCI_CMND_WLAN_CONFIGURE_PATCH 0x000D - - -#define HCI_CMND_SOCKET_BASE 0x1000 -#define HCI_CMND_SOCKET 0x1001 -#define HCI_CMND_BIND 0x1002 -#define HCI_CMND_RECV 0x1004 -#define HCI_CMND_ACCEPT 0x1005 -#define HCI_CMND_LISTEN 0x1006 -#define HCI_CMND_CONNECT 0x1007 -#define HCI_CMND_BSD_SELECT 0x1008 -#define HCI_CMND_SETSOCKOPT 0x1009 -#define HCI_CMND_GETSOCKOPT 0x100A -#define HCI_CMND_CLOSE_SOCKET 0x100B -#define HCI_CMND_RECVFROM 0x100D -#define HCI_CMND_GETHOSTNAME 0x1010 -#define HCI_CMND_MDNS_ADVERTISE 0x1011 -#define HCI_CMND_GETMSSVALUE 0x1012 - - -#define HCI_DATA_BASE 0x80 - -#define HCI_CMND_SEND (0x01 + HCI_DATA_BASE) -#define HCI_CMND_SENDTO (0x03 + HCI_DATA_BASE) -#define HCI_DATA_BSD_RECVFROM (0x04 + HCI_DATA_BASE) -#define HCI_DATA_BSD_RECV (0x05 + HCI_DATA_BASE) - - -#define HCI_CMND_NVMEM_CBASE (0x0200) - - -#define HCI_CMND_NVMEM_CREATE_ENTRY (0x0203) -#define HCI_CMND_NVMEM_SWAP_ENTRY (0x0205) -#define HCI_CMND_NVMEM_READ (0x0201) -#define HCI_CMND_NVMEM_WRITE (0x0090) -#define HCI_CMND_NVMEM_WRITE_PATCH (0x0204) -#define HCI_CMND_READ_SP_VERSION (0x0207) - -#define HCI_CMND_READ_BUFFER_SIZE 0x400B -#define HCI_CMND_SIMPLE_LINK_START 0x4000 - -#define HCI_CMND_NETAPP_BASE 0x2000 - -#define HCI_NETAPP_DHCP (0x0001 + HCI_CMND_NETAPP_BASE) -#define HCI_NETAPP_PING_SEND (0x0002 + HCI_CMND_NETAPP_BASE) -#define HCI_NETAPP_PING_REPORT (0x0003 + HCI_CMND_NETAPP_BASE) -#define HCI_NETAPP_PING_STOP (0x0004 + HCI_CMND_NETAPP_BASE) -#define HCI_NETAPP_IPCONFIG (0x0005 + HCI_CMND_NETAPP_BASE) -#define HCI_NETAPP_ARP_FLUSH (0x0006 + HCI_CMND_NETAPP_BASE) -#define HCI_NETAPP_SET_DEBUG_LEVEL (0x0008 + HCI_CMND_NETAPP_BASE) -#define HCI_NETAPP_SET_TIMERS (0x0009 + HCI_CMND_NETAPP_BASE) - - - - - - -//***************************************************************************** -// -// Values that can be used as HCI Events defines -// -//***************************************************************************** -#define HCI_EVNT_WLAN_BASE 0x0000 -#define HCI_EVNT_WLAN_CONNECT 0x0001 -#define HCI_EVNT_WLAN_DISCONNECT \ - 0x0002 -#define HCI_EVNT_WLAN_IOCTL_ADD_PROFILE \ - 0x0005 - - -#define HCI_EVNT_SOCKET HCI_CMND_SOCKET -#define HCI_EVNT_BIND HCI_CMND_BIND -#define HCI_EVNT_RECV HCI_CMND_RECV -#define HCI_EVNT_ACCEPT HCI_CMND_ACCEPT -#define HCI_EVNT_LISTEN HCI_CMND_LISTEN -#define HCI_EVNT_CONNECT HCI_CMND_CONNECT -#define HCI_EVNT_SELECT HCI_CMND_BSD_SELECT -#define HCI_EVNT_CLOSE_SOCKET HCI_CMND_CLOSE_SOCKET -#define HCI_EVNT_RECVFROM HCI_CMND_RECVFROM -#define HCI_EVNT_SETSOCKOPT HCI_CMND_SETSOCKOPT -#define HCI_EVNT_GETSOCKOPT HCI_CMND_GETSOCKOPT -#define HCI_EVNT_BSD_GETHOSTBYNAME HCI_CMND_GETHOSTNAME -#define HCI_EVNT_MDNS_ADVERTISE HCI_CMND_MDNS_ADVERTISE -#define HCI_EVNT_GETMSSVALUE HCI_CMND_GETMSSVALUE - -#define HCI_EVNT_SEND 0x1003 -#define HCI_EVNT_WRITE 0x100E -#define HCI_EVNT_SENDTO 0x100F - -#define HCI_EVNT_PATCHES_REQ 0x1000 - -#define HCI_EVNT_UNSOL_BASE 0x4000 - -#define HCI_EVNT_WLAN_UNSOL_BASE (0x8000) - -#define HCI_EVNT_WLAN_UNSOL_CONNECT (0x0001 + HCI_EVNT_WLAN_UNSOL_BASE) -#define HCI_EVNT_WLAN_UNSOL_DISCONNECT (0x0002 + HCI_EVNT_WLAN_UNSOL_BASE) -#define HCI_EVNT_WLAN_UNSOL_INIT (0x0004 + HCI_EVNT_WLAN_UNSOL_BASE) -#define HCI_EVNT_WLAN_TX_COMPLETE (0x0008 + HCI_EVNT_WLAN_UNSOL_BASE) -#define HCI_EVNT_WLAN_UNSOL_DHCP (0x0010 + HCI_EVNT_WLAN_UNSOL_BASE) -#define HCI_EVNT_WLAN_ASYNC_PING_REPORT (0x0040 + HCI_EVNT_WLAN_UNSOL_BASE) -#define HCI_EVNT_WLAN_ASYNC_SIMPLE_CONFIG_DONE (0x0080 + HCI_EVNT_WLAN_UNSOL_BASE) -#define HCI_EVNT_WLAN_KEEPALIVE (0x0200 + HCI_EVNT_WLAN_UNSOL_BASE) -#define HCI_EVNT_BSD_TCP_CLOSE_WAIT (0x0800 + HCI_EVNT_WLAN_UNSOL_BASE) - -#define HCI_EVNT_DATA_UNSOL_FREE_BUFF \ - 0x4100 - -#define HCI_EVNT_NVMEM_CREATE_ENTRY \ - HCI_CMND_NVMEM_CREATE_ENTRY -#define HCI_EVNT_NVMEM_SWAP_ENTRY HCI_CMND_NVMEM_SWAP_ENTRY - -#define HCI_EVNT_NVMEM_READ HCI_CMND_NVMEM_READ -#define HCI_EVNT_NVMEM_WRITE (0x0202) - -#define HCI_EVNT_READ_SP_VERSION \ - HCI_CMND_READ_SP_VERSION - -#define HCI_EVNT_INPROGRESS 0xFFFF - - -#define HCI_DATA_RECVFROM 0x84 -#define HCI_DATA_RECV 0x85 -#define HCI_DATA_NVMEM 0x91 - -#define HCI_EVENT_CC3000_CAN_SHUT_DOWN 0x99 - -//***************************************************************************** -// -// Prototypes for the structures for APIs. -// -//***************************************************************************** - -#define HCI_DATA_HEADER_SIZE (5) -#define HCI_EVENT_HEADER_SIZE (5) -#define HCI_DATA_CMD_HEADER_SIZE (5) -#define HCI_PATCH_HEADER_SIZE (6) - -#define HCI_PACKET_TYPE_OFFSET (0) -#define HCI_PACKET_ARGSIZE_OFFSET (2) -#define HCI_PACKET_LENGTH_OFFSET (3) - - -#define HCI_EVENT_OPCODE_OFFSET (1) -#define HCI_EVENT_LENGTH_OFFSET (3) -#define HCI_EVENT_STATUS_OFFSET (4) -#define HCI_DATA_LENGTH_OFFSET (3) - - - - -//***************************************************************************** -// -// Prototypes for the APIs. -// -//***************************************************************************** - -//***************************************************************************** -// -//! hci_command_send -//! -//! @param usOpcode command operation code -//! @param pucBuff pointer to the command's arguments buffer -//! @param ucArgsLength length of the arguments -//! -//! @return none -//! -//! @brief Initiate an HCI command. -// -//***************************************************************************** -extern UINT16 hci_command_send(UINT16 usOpcode, - UINT8 *ucArgs, - UINT8 ucArgsLength); - - -//***************************************************************************** -// -//! hci_data_send -//! -//! @param usOpcode command operation code -//! @param ucArgs pointer to the command's arguments buffer -//! @param usArgsLength length of the arguments -//! @param ucTail pointer to the data buffer -//! @param usTailLength buffer length -//! -//! @return none -//! -//! @brief Initiate an HCI data write operation -// -//***************************************************************************** -extern INT32 hci_data_send(UINT8 ucOpcode, - UINT8 *ucArgs, - UINT16 usArgsLength, - UINT16 usDataLength, - const UINT8 *ucTail, - UINT16 usTailLength); - - -//***************************************************************************** -// -//! hci_data_command_send -//! -//! @param usOpcode command operation code -//! @param pucBuff pointer to the data buffer -//! @param ucArgsLength arguments length -//! @param ucDataLength data length -//! -//! @return none -//! -//! @brief Prepare HCI header and initiate an HCI data write operation -// -//***************************************************************************** -extern void hci_data_command_send(UINT16 usOpcode, UINT8 *pucBuff, - UINT8 ucArgsLength, UINT16 ucDataLength); - -//***************************************************************************** -// -//! hci_patch_send -//! -//! @param usOpcode command operation code -//! @param pucBuff pointer to the command's arguments buffer -//! @param patch pointer to patch content buffer -//! @param usDataLength data length -//! -//! @return none -//! -//! @brief Prepare HCI header and initiate an HCI patch write operation -// -//***************************************************************************** -extern void hci_patch_send(UINT8 ucOpcode, UINT8 *pucBuff, CHAR *patch, UINT16 usDataLength); - - - -//***************************************************************************** -// -// Mark the end of the C bindings section for C++ compilers. -// -//***************************************************************************** -#ifdef __cplusplus -} -#endif // __cplusplus - -#endif // __CC3000_HCI_H__ diff --git a/drivers/cc3000/inc/host_driver_version.h b/drivers/cc3000/inc/host_driver_version.h deleted file mode 100644 index a28d21f1be..0000000000 --- a/drivers/cc3000/inc/host_driver_version.h +++ /dev/null @@ -1,40 +0,0 @@ -/***************************************************************************** -* -* host_driver_version.h - CC3000 Host Driver Implementation. -* Copyright (C) 2011 Texas Instruments Incorporated - http://www.ti.com/ -* -* Redistribution and use in source and binary forms, with or without -* modification, are permitted provided that the following conditions -* are met: -* -* Redistributions of source code must retain the above copyright -* notice, this list of conditions and the following disclaimer. -* -* Redistributions in binary form must reproduce the above copyright -* notice, this list of conditions and the following disclaimer in the -* documentation and/or other materials provided with the -* distribution. -* -* Neither the name of Texas Instruments Incorporated nor the names of -* its contributors may be used to endorse or promote products derived -* from this software without specific prior written permission. -* -* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -* -*****************************************************************************/ -#ifndef __CC3000_HOST_DRIVER_VERSION_H__ -#define __CC3000_HOST_DRIVER_VERSION_H__ - -#define DRIVER_VERSION_NUMBER 15 - -#endif // __CC3000_HOST_DRIVER_VERSION_H__ diff --git a/drivers/cc3000/inc/inet_ntop.h b/drivers/cc3000/inc/inet_ntop.h deleted file mode 100644 index fa70806206..0000000000 --- a/drivers/cc3000/inc/inet_ntop.h +++ /dev/null @@ -1,4 +0,0 @@ -#ifndef __INET_NTOP_H -#define __INET_NTOP_H -char *inet_ntop(int af, const void *addr, char *buf, size_t size); -#endif /* __INET_NTOP_H */ diff --git a/drivers/cc3000/inc/inet_pton.h b/drivers/cc3000/inc/inet_pton.h deleted file mode 100644 index 0896d5d29f..0000000000 --- a/drivers/cc3000/inc/inet_pton.h +++ /dev/null @@ -1,4 +0,0 @@ -#ifndef __INET_PTON_H -#define __INET_PTON_H -int inet_pton(int, const char *, void *); -#endif /* __INET_PTON_H */ diff --git a/drivers/cc3000/inc/netapp.h b/drivers/cc3000/inc/netapp.h deleted file mode 100644 index 1e4f265896..0000000000 --- a/drivers/cc3000/inc/netapp.h +++ /dev/null @@ -1,343 +0,0 @@ -/***************************************************************************** -* -* netapp.h - CC3000 Host Driver Implementation. -* Copyright (C) 2011 Texas Instruments Incorporated - http://www.ti.com/ -* -* Redistribution and use in source and binary forms, with or without -* modification, are permitted provided that the following conditions -* are met: -* -* Redistributions of source code must retain the above copyright -* notice, this list of conditions and the following disclaimer. -* -* Redistributions in binary form must reproduce the above copyright -* notice, this list of conditions and the following disclaimer in the -* documentation and/or other materials provided with the -* distribution. -* -* Neither the name of Texas Instruments Incorporated nor the names of -* its contributors may be used to endorse or promote products derived -* from this software without specific prior written permission. -* -* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -* -*****************************************************************************/ -#ifndef __CC3000_NETAPP_H__ -#define __CC3000_NETAPP_H__ - -#include "data_types.h" - -//***************************************************************************** -// -// If building with a C++ compiler, make all of the definitions in this header -// have a C binding. -// -//***************************************************************************** -#ifdef __cplusplus -extern "C" { -#endif - -//***************************************************************************** -// -//! \addtogroup netapp_api -//! @{ -// -//***************************************************************************** - -typedef struct _netapp_dhcp_ret_args_t -{ - UINT8 aucIP[4]; - UINT8 aucSubnetMask[4]; - UINT8 aucDefaultGateway[4]; - UINT8 aucDHCPServer[4]; - UINT8 aucDNSServer[4]; -}tNetappDhcpParams; - -typedef struct _netapp_ipconfig_ret_args_t -{ - UINT8 aucIP[4]; - UINT8 aucSubnetMask[4]; - UINT8 aucDefaultGateway[4]; - UINT8 aucDHCPServer[4]; - UINT8 aucDNSServer[4]; - UINT8 uaMacAddr[6]; - UINT8 uaSSID[32]; -}tNetappIpconfigRetArgs; - - -/*Ping send report parameters*/ -typedef struct _netapp_pingreport_args -{ - UINT32 packets_sent; - UINT32 packets_received; - UINT32 min_round_time; - UINT32 max_round_time; - UINT32 avg_round_time; -} netapp_pingreport_args_t; - - -//***************************************************************************** -// -//! netapp_config_mac_adrress -//! -//! @param mac device mac address, 6 bytes. Saved: yes -//! -//! @return return on success 0, otherwise error. -//! -//! @brief Configure device MAC address and store it in NVMEM. -//! The value of the MAC address configured through the API will -//! be stored in CC3000 non volatile memory, thus preserved -//! over resets. -// -//***************************************************************************** -extern INT32 netapp_config_mac_adrress( UINT8 *mac ); - -//***************************************************************************** -// -//! netapp_dhcp -//! -//! @param aucIP device mac address, 6 bytes. Saved: yes -//! @param aucSubnetMask device mac address, 6 bytes. Saved: yes -//! @param aucDefaultGateway device mac address, 6 bytes. Saved: yes -//! @param aucDNSServer device mac address, 6 bytes. Saved: yes -//! -//! @return return on success 0, otherwise error. -//! -//! @brief netapp_dhcp is used to configure the network interface, -//! static or dynamic (DHCP).\n In order to activate DHCP mode, -//! aucIP, aucSubnetMask, aucDefaultGateway must be 0. -//! The default mode of CC3000 is DHCP mode. -//! Note that the configuration is saved in non volatile memory -//! and thus preserved over resets. -//! -//! @note If the mode is altered a reset of CC3000 device is required -//! in order to apply changes.\nAlso note that asynchronous event -//! of DHCP_EVENT, which is generated when an IP address is -//! allocated either by the DHCP server or due to static -//! allocation is generated only upon a connection to the -//! AP was established. -//! -//***************************************************************************** -extern INT32 netapp_dhcp(UINT32 *aucIP, UINT32 *aucSubnetMask,UINT32 *aucDefaultGateway, UINT32 *aucDNSServer); - - - -//***************************************************************************** -// -//! netapp_timeout_values -//! -//! @param aucDHCP DHCP lease time request, also impact -//! the DHCP renew timeout. Range: [0-0xffffffff] seconds, -//! 0 or 0xffffffff == infinity lease timeout. -//! Resolution:10 seconds. Influence: only after -//! reconnecting to the AP. -//! Minimal bound value: MIN_TIMER_VAL_SECONDS - 10 seconds. -//! The parameter is saved into the CC3000 NVMEM. -//! The default value on CC3000 is 14400 seconds. -//! -//! @param aucARP ARP refresh timeout, if ARP entry is not updated by -//! incoming packet, the ARP entry will be deleted by -//! the end of the timeout. -//! Range: [0-0xffffffff] seconds, 0 == infinity ARP timeout -//! Resolution: 10 seconds. Influence: on runtime. -//! Minimal bound value: MIN_TIMER_VAL_SECONDS - 10 seconds -//! The parameter is saved into the CC3000 NVMEM. -//! The default value on CC3000 is 3600 seconds. -//! -//! @param aucKeepalive Keepalive event sent by the end of keepalive timeout -//! Range: [0-0xffffffff] seconds, 0 == infinity timeout -//! Resolution: 10 seconds. -//! Influence: on runtime. -//! Minimal bound value: MIN_TIMER_VAL_SECONDS - 10 sec -//! The parameter is saved into the CC3000 NVMEM. -//! The default value on CC3000 is 10 seconds. -//! -//! @param aucInactivity Socket inactivity timeout, socket timeout is -//! refreshed by incoming or outgoing packet, by the -//! end of the socket timeout the socket will be closed -//! Range: [0-0xffffffff] sec, 0 == infinity timeout. -//! Resolution: 10 seconds. Influence: on runtime. -//! Minimal bound value: MIN_TIMER_VAL_SECONDS - 10 sec -//! The parameter is saved into the CC3000 NVMEM. -//! The default value on CC3000 is 60 seconds. -//! -//! @return return on success 0, otherwise error. -//! -//! @brief Set new timeout values. Function set new timeout values for: -//! DHCP lease timeout, ARP refresh timeout, keepalive event -//! timeout and socket inactivity timeout -//! -//! @note If a parameter set to non zero value which is less than 10s, -//! it will be set automatically to 10s. -//! -//***************************************************************************** -#ifndef CC3000_TINY_DRIVER -extern INT32 netapp_timeout_values(UINT32 *aucDHCP, UINT32 *aucARP, UINT32 *aucKeepalive, UINT32 *aucInactivity); -#endif - -//***************************************************************************** -// -//! netapp_ping_send -//! -//! @param ip destination IP address -//! @param pingAttempts number of echo requests to send -//! @param pingSize send buffer size which may be up to 1400 bytes -//! @param pingTimeout Time to wait for a response,in milliseconds. -//! -//! @return return on success 0, otherwise error. -//! -//! @brief send ICMP ECHO_REQUEST to network hosts -//! -//! @note If an operation finished successfully asynchronous ping report -//! event will be generated. The report structure is as defined -//! by structure netapp_pingreport_args_t. -//! -//! @warning Calling this function while a previous Ping Requests are in -//! progress will stop the previous ping request. -//***************************************************************************** - - #ifndef CC3000_TINY_DRIVER -extern INT32 netapp_ping_send(UINT32 *ip, UINT32 ulPingAttempts, UINT32 ulPingSize, UINT32 ulPingTimeout); -#endif - -//***************************************************************************** -// -//! netapp_ping_stop -//! -//! @param none -//! -//! @return On success, zero is returned. On error, -1 is returned. -//! -//! @brief Stop any ping request. -//! -//! -//***************************************************************************** - -#ifndef CC3000_TINY_DRIVER -extern INT32 netapp_ping_stop(); -#endif -//***************************************************************************** -// -//! netapp_ping_report -//! -//! @param none -//! -//! @return none -//! -//! @brief Request for ping status. This API triggers the CC3000 to send -//! asynchronous events: HCI_EVNT_WLAN_ASYNC_PING_REPORT. -//! This event will carry the report structure: -//! netapp_pingreport_args_t. This structure is filled in with ping -//! results up till point of triggering API. -//! netapp_pingreport_args_t:\n packets_sent - echo sent, -//! packets_received - echo reply, min_round_time - minimum -//! round time, max_round_time - max round time, -//! avg_round_time - average round time -//! -//! @note When a ping operation is not active, the returned structure -//! fields are 0. -//! -//***************************************************************************** -#ifndef CC3000_TINY_DRIVER -extern void netapp_ping_report(); -#endif - - -//***************************************************************************** -// -//! netapp_ipconfig -//! -//! @param[out] ipconfig This argument is a pointer to a -//! tNetappIpconfigRetArgs structure. This structure is -//! filled in with the network interface configuration. -//! tNetappIpconfigRetArgs:\n aucIP - ip address, -//! aucSubnetMask - mask, aucDefaultGateway - default -//! gateway address, aucDHCPServer - dhcp server address -//! aucDNSServer - dns server address, uaMacAddr - mac -//! address, uaSSID - connected AP ssid -//! -//! @return none -//! -//! @brief Obtain the CC3000 Network interface information. -//! Note that the information is available only after the WLAN -//! connection was established. Calling this function before -//! associated, will cause non-defined values to be returned. -//! -//! @note The function is useful for figuring out the IP Configuration of -//! the device when DHCP is used and for figuring out the SSID of -//! the Wireless network the device is associated with. -//! -//***************************************************************************** - -extern void netapp_ipconfig( tNetappIpconfigRetArgs * ipconfig ); - - -//***************************************************************************** -// -//! netapp_arp_flush -//! -//! @param none -//! -//! @return none -//! -//! @brief Flushes ARP table -//! -//***************************************************************************** - -#ifndef CC3000_TINY_DRIVER -extern INT32 netapp_arp_flush(); -#endif - - -//***************************************************************************** -// -//! netapp_set_debug_level -//! -//! @param[in] level debug level. Bitwise [0-8], -//! 0(disable)or 1(enable).\n Bitwise map: 0 - Critical -//! message, 1 information message, 2 - core messages, 3 - -//! HCI messages, 4 - Network stack messages, 5 - wlan -//! messages, 6 - wlan driver messages, 7 - epprom messages, -//! 8 - general messages. Default: 0x13f. Saved: no -//! -//! @return On success, zero is returned. On error, -1 is returned -//! -//! @brief Debug messages sent via the UART debug channel, this function -//! enable/disable the debug level -//! -//***************************************************************************** - - -#ifndef CC3000_TINY_DRIVER -INT32 netapp_set_debug_level(UINT32 ulLevel); -#endif -//***************************************************************************** -// -// Close the Doxygen group. -//! @} -// -//***************************************************************************** - - - -//***************************************************************************** -// -// Mark the end of the C bindings section for C++ compilers. -// -//***************************************************************************** -#ifdef __cplusplus -} -#endif // __cplusplus - -#endif // __CC3000_NETAPP_H__ - diff --git a/drivers/cc3000/inc/nvmem.h b/drivers/cc3000/inc/nvmem.h deleted file mode 100644 index b99a2e7b9e..0000000000 --- a/drivers/cc3000/inc/nvmem.h +++ /dev/null @@ -1,248 +0,0 @@ -/***************************************************************************** -* -* nvmem.h - CC3000 Host Driver Implementation. -* Copyright (C) 2011 Texas Instruments Incorporated - http://www.ti.com/ -* -* Redistribution and use in source and binary forms, with or without -* modification, are permitted provided that the following conditions -* are met: -* -* Redistributions of source code must retain the above copyright -* notice, this list of conditions and the following disclaimer. -* -* Redistributions in binary form must reproduce the above copyright -* notice, this list of conditions and the following disclaimer in the -* documentation and/or other materials provided with the -* distribution. -* -* Neither the name of Texas Instruments Incorporated nor the names of -* its contributors may be used to endorse or promote products derived -* from this software without specific prior written permission. -* -* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -* -*****************************************************************************/ -#ifndef __CC3000_NVRAM_H__ -#define __CC3000_NVRAM_H__ - -#include "cc3000_common.h" - - -//***************************************************************************** -// -// If building with a C++ compiler, make all of the definitions in this header -// have a C binding. -// -//***************************************************************************** -#ifdef __cplusplus -extern "C" { -#endif - - -//***************************************************************************** -// -//! \addtogroup nvmem_api -//! @{ -// -//***************************************************************************** - -/**************************************************************************** -** -** Definitions for File IDs -** -****************************************************************************/ -/* NVMEM file ID - system files*/ -#define NVMEM_NVS_FILEID (0) -#define NVMEM_NVS_SHADOW_FILEID (1) -#define NVMEM_WLAN_CONFIG_FILEID (2) -#define NVMEM_WLAN_CONFIG_SHADOW_FILEID (3) -#define NVMEM_WLAN_DRIVER_SP_FILEID (4) -#define NVMEM_WLAN_FW_SP_FILEID (5) -#define NVMEM_MAC_FILEID (6) -#define NVMEM_FRONTEND_VARS_FILEID (7) -#define NVMEM_IP_CONFIG_FILEID (8) -#define NVMEM_IP_CONFIG_SHADOW_FILEID (9) -#define NVMEM_BOOTLOADER_SP_FILEID (10) -#define NVMEM_RM_FILEID (11) - -/* NVMEM file ID - user files*/ -#define NVMEM_AES128_KEY_FILEID (12) -#define NVMEM_SHARED_MEM_FILEID (13) - -/* max entry in order to invalid nvmem */ -#define NVMEM_MAX_ENTRY (16) - - -//***************************************************************************** -// -//! nvmem_read -//! -//! @param ulFileId nvmem file id:\n -//! NVMEM_NVS_FILEID, NVMEM_NVS_SHADOW_FILEID, -//! NVMEM_WLAN_CONFIG_FILEID, NVMEM_WLAN_CONFIG_SHADOW_FILEID, -//! NVMEM_WLAN_DRIVER_SP_FILEID, NVMEM_WLAN_FW_SP_FILEID, -//! NVMEM_MAC_FILEID, NVMEM_FRONTEND_VARS_FILEID, -//! NVMEM_IP_CONFIG_FILEID, NVMEM_IP_CONFIG_SHADOW_FILEID, -//! NVMEM_BOOTLOADER_SP_FILEID, NVMEM_RM_FILEID, -//! and user files 12-15. -//! @param ulLength number of bytes to read -//! @param ulOffset ulOffset in file from where to read -//! @param buff output buffer pointer -//! -//! @return on success 0, error otherwise. -//! -//! @brief Reads data from the file referred by the ulFileId parameter. -//! Reads data from file ulOffset till length. Err if the file can't -//! be used, is invalid, or if the read is out of bounds. -//! -//***************************************************************************** - -extern INT32 nvmem_read(UINT32 file_id, UINT32 length, UINT32 offset, UINT8 *buff); - -//***************************************************************************** -// -//! nvmem_write -//! -//! @param ulFileId nvmem file id:\n -//! NVMEM_WLAN_DRIVER_SP_FILEID, NVMEM_WLAN_FW_SP_FILEID, -//! NVMEM_MAC_FILEID, NVMEM_BOOTLOADER_SP_FILEID, -//! and user files 12-15. -//! @param ulLength number of bytes to write -//! @param ulEntryOffset offset in file to start write operation from -//! @param buff data to write -//! -//! @return on success 0, error otherwise. -//! -//! @brief Write data to nvmem. -//! writes data to file referred by the ulFileId parameter. -//! Writes data to file ulOffset till ulLength.The file id will be -//! marked invalid till the write is done. The file entry doesn't -//! need to be valid - only allocated. -//! -//***************************************************************************** - -extern INT32 nvmem_write(UINT32 ulFileId, UINT32 ulLength, UINT32 ulEntryOffset, UINT8 *buff); - - -//***************************************************************************** -// -//! nvmem_set_mac_address -//! -//! @param mac mac address to be set -//! -//! @return on success 0, error otherwise. -//! -//! @brief Write MAC address to EEPROM. -//! mac address as appears over the air (OUI first) -//! -//***************************************************************************** -extern UINT8 nvmem_set_mac_address(UINT8 *mac); - - -//***************************************************************************** -// -//! nvmem_get_mac_address -//! -//! @param[out] mac mac address -//! -//! @return on success 0, error otherwise. -//! -//! @brief Read MAC address from EEPROM. -//! mac address as appears over the air (OUI first) -//! -//***************************************************************************** -extern UINT8 nvmem_get_mac_address(UINT8 *mac); - - -//***************************************************************************** -// -//! nvmem_write_patch -//! -//! @param ulFileId nvmem file id:\n -//! NVMEM_WLAN_DRIVER_SP_FILEID, NVMEM_WLAN_FW_SP_FILEID, -//! @param spLength number of bytes to write -//! @param spData SP data to write -//! -//! @return on success 0, error otherwise. -//! -//! @brief program a patch to a specific file ID. -//! The SP data is assumed to be organized in 2-dimensional. -//! Each line is SP_PORTION_SIZE bytes long. Actual programming is -//! applied in SP_PORTION_SIZE bytes portions. -//! -//***************************************************************************** -extern UINT8 nvmem_write_patch(UINT32 ulFileId, UINT32 spLength, const UINT8 *spData); - - -//***************************************************************************** -// -//! nvmem_read_sp_version -//! -//! @param[out] patchVer first number indicates package ID and the second -//! number indicates package build number -//! -//! @return on success 0, error otherwise. -//! -//! @brief Read patch version. read package version (WiFi FW patch, -//! driver-supplicant-NS patch, bootloader patch) -//! -//***************************************************************************** -#ifndef CC3000_TINY_DRIVER -extern UINT8 nvmem_read_sp_version(UINT8* patchVer); -#endif - -//***************************************************************************** -// -//! nvmem_create_entry -//! -//! @param ulFileId nvmem file Id:\n -//! * NVMEM_AES128_KEY_FILEID: 12 -//! * NVMEM_SHARED_MEM_FILEID: 13 -//! * and fileIDs 14 and 15 -//! @param ulNewLen entry ulLength -//! -//! @return on success 0, error otherwise. -//! -//! @brief Create new file entry and allocate space on the NVMEM. -//! Applies only to user files. -//! Modify the size of file. -//! If the entry is unallocated - allocate it to size -//! ulNewLen (marked invalid). -//! If it is allocated then deallocate it first. -//! To just mark the file as invalid without resizing - -//! set ulNewLen=0. -//! -//***************************************************************************** -extern INT32 nvmem_create_entry(UINT32 file_id, UINT32 newlen); - - -//***************************************************************************** -// -// Mark the end of the C bindings section for C++ compilers. -// -//***************************************************************************** - - -//***************************************************************************** -// -// Close the Doxygen group. -//! @} -// -//***************************************************************************** - - -#ifdef __cplusplus -} -#endif // __cplusplus - -#endif // __CC3000_NVRAM_H__ diff --git a/drivers/cc3000/inc/patch_prog.h b/drivers/cc3000/inc/patch_prog.h deleted file mode 100644 index 0a141a0cb5..0000000000 --- a/drivers/cc3000/inc/patch_prog.h +++ /dev/null @@ -1,11 +0,0 @@ -#ifndef __CC3000_PATCH_PROG_H__ -#define __CC3000_PATCH_PROG_H__ -extern unsigned short fw_length; -extern const unsigned char fw_patch[]; - -extern unsigned short drv_length; -extern const unsigned char wlan_drv_patch[]; -extern const unsigned char cRMdefaultParams[128]; - -void patch_prog_start(); -#endif //__CC3000_PATCH_PROG_H__ diff --git a/drivers/cc3000/inc/security.h b/drivers/cc3000/inc/security.h deleted file mode 100644 index cd1baf5541..0000000000 --- a/drivers/cc3000/inc/security.h +++ /dev/null @@ -1,130 +0,0 @@ -/***************************************************************************** -* -* security.h - CC3000 Host Driver Implementation. -* Copyright (C) 2011 Texas Instruments Incorporated - http://www.ti.com/ -* -* Redistribution and use in source and binary forms, with or without -* modification, are permitted provided that the following conditions -* are met: -* -* Redistributions of source code must retain the above copyright -* notice, this list of conditions and the following disclaimer. -* -* Redistributions in binary form must reproduce the above copyright -* notice, this list of conditions and the following disclaimer in the -* documentation and/or other materials provided with the -* distribution. -* -* Neither the name of Texas Instruments Incorporated nor the names of -* its contributors may be used to endorse or promote products derived -* from this software without specific prior written permission. -* -* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -* -*****************************************************************************/ -#ifndef __CC3000_SECURITY__ -#define __CC3000_SECURITY__ - -#include "nvmem.h" - -//***************************************************************************** -// -// If building with a C++ compiler, make all of the definitions in this header -// have a C binding. -// -//***************************************************************************** -#ifdef __cplusplus -extern "C" { -#endif - - -#define AES128_KEY_SIZE 16 - -#ifndef CC3000_UNENCRYPTED_SMART_CONFIG - - -//***************************************************************************** -// -//! aes_encrypt -//! -//! @param[in] key AES128 key of size 16 bytes -//! @param[in\out] state 16 bytes of plain text and cipher text -//! -//! @return none -//! -//! @brief AES128 encryption: -//! Given AES128 key and 16 bytes plain text, cipher text of 16 bytes -//! is computed. The AES implementation is in mode ECB (Electronic -//! Code Book). -//! -//! -//***************************************************************************** -extern void aes_encrypt(UINT8 *state, UINT8 *key); - -//***************************************************************************** -// -//! aes_decrypt -//! -//! @param[in] key AES128 key of size 16 bytes -//! @param[in\out] state 16 bytes of cipher text and plain text -//! -//! @return none -//! -//! @brief AES128 decryption: -//! Given AES128 key and 16 bytes cipher text, plain text of 16 bytes -//! is computed The AES implementation is in mode ECB -//! (Electronic Code Book). -//! -//! -//***************************************************************************** -extern void aes_decrypt(UINT8 *state, UINT8 *key); - - -//***************************************************************************** -// -//! aes_read_key -//! -//! @param[out] key AES128 key of size 16 bytes -//! -//! @return on success 0, error otherwise. -//! -//! @brief Reads AES128 key from EEPROM -//! Reads the AES128 key from fileID #12 in EEPROM -//! returns an error if the key does not exist. -//! -//! -//***************************************************************************** -extern INT32 aes_read_key(UINT8 *key); - -//***************************************************************************** -// -//! aes_write_key -//! -//! @param[out] key AES128 key of size 16 bytes -//! -//! @return on success 0, error otherwise. -//! -//! @brief writes AES128 key from EEPROM -//! Writes the AES128 key to fileID #12 in EEPROM -//! -//! -//***************************************************************************** -extern INT32 aes_write_key(UINT8 *key); - -#endif //CC3000_UNENCRYPTED_SMART_CONFIG - -#ifdef __cplusplus -} -#endif // __cplusplus - -#endif diff --git a/drivers/cc3000/inc/socket.h b/drivers/cc3000/inc/socket.h deleted file mode 100644 index 96c814bf77..0000000000 --- a/drivers/cc3000/inc/socket.h +++ /dev/null @@ -1,676 +0,0 @@ -/***************************************************************************** -* -* socket.h - CC3000 Host Driver Implementation. -* Copyright (C) 2011 Texas Instruments Incorporated - http://www.ti.com/ -* -* Redistribution and use in source and binary forms, with or without -* modification, are permitted provided that the following conditions -* are met: -* -* Redistributions of source code must retain the above copyright -* notice, this list of conditions and the following disclaimer. -* -* Redistributions in binary form must reproduce the above copyright -* notice, this list of conditions and the following disclaimer in the -* documentation and/or other materials provided with the -* distribution. -* -* Neither the name of Texas Instruments Incorporated nor the names of -* its contributors may be used to endorse or promote products derived -* from this software without specific prior written permission. -* -* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -* -*****************************************************************************/ -#ifndef __CC3000_SOCKET_H__ -#define __CC3000_SOCKET_H__ - -#include "cc3000_common.h" - -//***************************************************************************** -// -//! \addtogroup socket_api -//! @{ -// -//***************************************************************************** - - -//***************************************************************************** -// -// If building with a C++ compiler, make all of the definitions in this header -// have a C binding. -// -//***************************************************************************** -#ifdef __cplusplus -extern "C" { -#endif - -#define HOSTNAME_MAX_LENGTH (230) // 230 bytes + header shouldn't exceed 8 bit value - -//--------- Address Families -------- - -#define AF_INET 2 -#define AF_INET6 23 - -//------------ Socket Types ------------ - -#define SOCK_STREAM 1 -#define SOCK_DGRAM 2 -#define SOCK_RAW 3 // Raw sockets allow new IPv4 protocols to be implemented in user space. A raw socket receives or sends the raw datagram not including link level headers -#define SOCK_RDM 4 -#define SOCK_SEQPACKET 5 - -//----------- Socket Protocol ---------- - -#define IPPROTO_IP 0 // dummy for IP -#define IPPROTO_ICMP 1 // control message protocol -#define IPPROTO_IPV4 IPPROTO_IP // IP inside IP -#define IPPROTO_TCP 6 // tcp -#define IPPROTO_UDP 17 // user datagram protocol -#define IPPROTO_IPV6 41 // IPv6 in IPv6 -#define IPPROTO_NONE 59 // No next header -#define IPPROTO_RAW 255 // raw IP packet -#define IPPROTO_MAX 256 - -//----------- Socket retunr codes ----------- - -#define SOC_ERROR (-1) // error -#define SOC_IN_PROGRESS (-2) // socket in progress - -//----------- Socket Options ----------- -#define SOL_SOCKET 0xffff // socket level -#define SOCKOPT_RECV_NONBLOCK 0 // recv non block mode, set SOCK_ON or SOCK_OFF (default block mode) -#define SOCKOPT_RECV_TIMEOUT 1 // optname to configure recv and recvfromtimeout -#define SOCKOPT_ACCEPT_NONBLOCK 2 // accept non block mode, set SOCK_ON or SOCK_OFF (default block mode) -#define SOCK_ON 0 // socket non-blocking mode is enabled -#define SOCK_OFF 1 // socket blocking mode is enabled - -#define MAX_PACKET_SIZE 1500 -#define MAX_LISTEN_QUEUE 4 - -#define IOCTL_SOCKET_EVENTMASK - -#define ENOBUFS 55 // No buffer space available - -#define __FD_SETSIZE 32 - -#define ASIC_ADDR_LEN 8 - -#define NO_QUERY_RECIVED -3 - - -typedef struct _in_addr_t -{ - UINT32 s_addr; // load with inet_aton() -} in_addr; - -typedef struct _sockaddr_t -{ - UINT16 sa_family; - UINT8 sa_data[14]; -} sockaddr; - -typedef struct _sockaddr_in_t -{ - INT16 sin_family; // e.g. AF_INET - UINT16 sin_port; // e.g. htons(3490) - in_addr sin_addr; // see struct in_addr, below - CHAR sin_zero[8]; // zero this if you want to -} sockaddr_in; - -typedef UINT32 socklen_t; - -// The fd_set member is required to be an array of INT32s. -typedef INT32 __fd_mask; - -// It's easier to assume 8-bit bytes than to get CHAR_BIT. -#define __NFDBITS (8 * sizeof (__fd_mask)) -#define __FDELT(d) ((d) / __NFDBITS) -#define __FDMASK(d) ((__fd_mask) 1 << ((d) % __NFDBITS)) - -// fd_set for select and pselect. -typedef struct -{ - __fd_mask fds_bits[__FD_SETSIZE / __NFDBITS]; -#define __FDS_BITS(set) ((set)->fds_bits) -} fd_set; - -// We don't use `memset' because this would require a prototype and -// the array isn't too big. -#define __FD_ZERO(set) \ - do { \ - UINT16 __i; \ - fd_set *__arr = (set); \ - for (__i = 0; __i < sizeof (fd_set) / sizeof (__fd_mask); ++__i) \ - __FDS_BITS (__arr)[__i] = 0; \ - } while (0) -#define __FD_SET(d, set) (__FDS_BITS (set)[__FDELT (d)] |= __FDMASK (d)) -#define __FD_CLR(d, set) (__FDS_BITS (set)[__FDELT (d)] &= ~__FDMASK (d)) -#define __FD_ISSET(d, set) (__FDS_BITS (set)[__FDELT (d)] & __FDMASK (d)) - -// Access macros for 'fd_set'. -#define FD_SET(fd, fdsetp) __FD_SET (fd, fdsetp) -#define FD_CLR(fd, fdsetp) __FD_CLR (fd, fdsetp) -#define FD_ISSET(fd, fdsetp) __FD_ISSET (fd, fdsetp) -#define FD_ZERO(fdsetp) __FD_ZERO (fdsetp) - -//Use in case of Big Endian only - -#define htonl(A) ((((UINT32)(A) & 0xff000000) >> 24) | \ - (((UINT32)(A) & 0x00ff0000) >> 8) | \ - (((UINT32)(A) & 0x0000ff00) << 8) | \ - (((UINT32)(A) & 0x000000ff) << 24)) - -#define ntohl htonl - -//Use in case of Big Endian only -#define htons(A) ((((UINT32)(A) & 0xff00) >> 8) | \ - (((UINT32)(A) & 0x00ff) << 8)) - - -#define ntohs htons - -// mDNS port - 5353 mDNS multicast address - 224.0.0.251 -#define SET_mDNS_ADD(sockaddr) sockaddr.sa_data[0] = 0x14; \ - sockaddr.sa_data[1] = 0xe9; \ - sockaddr.sa_data[2] = 0xe0; \ - sockaddr.sa_data[3] = 0x0; \ - sockaddr.sa_data[4] = 0x0; \ - sockaddr.sa_data[5] = 0xfb; - - -//***************************************************************************** -// -// Prototypes for the APIs. -// -//***************************************************************************** - -//***************************************************************************** -// -//! socket -//! -//! @param domain selects the protocol family which will be used for -//! communication. On this version only AF_INET is supported -//! @param type specifies the communication semantics. On this version -//! only SOCK_STREAM, SOCK_DGRAM, SOCK_RAW are supported -//! @param protocol specifies a particular protocol to be used with the -//! socket IPPROTO_TCP, IPPROTO_UDP or IPPROTO_RAW are -//! supported. -//! -//! @return On success, socket handle that is used for consequent socket -//! operations. On error, -1 is returned. -//! -//! @brief create an endpoint for communication -//! The socket function creates a socket that is bound to a specific -//! transport service provider. This function is called by the -//! application layer to obtain a socket handle. -// -//***************************************************************************** -extern INT16 CC3000_EXPORT(socket)(INT32 domain, INT32 type, INT32 protocol); - -//***************************************************************************** -// -//! closesocket -//! -//! @param sd socket handle. -//! -//! @return On success, zero is returned. On error, -1 is returned. -//! -//! @brief The socket function closes a created socket. -// -//***************************************************************************** -extern INT32 CC3000_EXPORT(closesocket)(INT32 sd); - -//***************************************************************************** -// -//! accept -//! -//! @param[in] sd socket descriptor (handle) -//! @param[out] addr the argument addr is a pointer to a sockaddr structure -//! This structure is filled in with the address of the -//! peer socket, as known to the communications layer. -//! determined. The exact format of the address returned -//! addr is by the socket's address sockaddr. -//! On this version only AF_INET is supported. -//! This argument returns in network order. -//! @param[out] addrlen the addrlen argument is a value-result argument: -//! it should initially contain the size of the structure -//! pointed to by addr. -//! -//! @return For socket in blocking mode: -//! On success, socket handle. on failure negative -//! For socket in non-blocking mode: -//! - On connection establishment, socket handle -//! - On connection pending, SOC_IN_PROGRESS (-2) -//! - On failure, SOC_ERROR (-1) -//! -//! @brief accept a connection on a socket: -//! This function is used with connection-based socket types -//! (SOCK_STREAM). It extracts the first connection request on the -//! queue of pending connections, creates a new connected socket, and -//! returns a new file descriptor referring to that socket. -//! The newly created socket is not in the listening state. -//! The original socket sd is unaffected by this call. -//! The argument sd is a socket that has been created with socket(), -//! bound to a local address with bind(), and is listening for -//! connections after a listen(). The argument addr is a pointer -//! to a sockaddr structure. This structure is filled in with the -//! address of the peer socket, as known to the communications layer. -//! The exact format of the address returned addr is determined by the -//! socket's address family. The addrlen argument is a value-result -//! argument: it should initially contain the size of the structure -//! pointed to by addr, on return it will contain the actual -//! length (in bytes) of the address returned. -//! -//! @sa socket ; bind ; listen -// -//***************************************************************************** -extern INT32 CC3000_EXPORT(accept)(INT32 sd, sockaddr *addr, socklen_t *addrlen); - -//***************************************************************************** -// -//! bind -//! -//! @param[in] sd socket descriptor (handle) -//! @param[out] addr specifies the destination address. On this version -//! only AF_INET is supported. -//! @param[out] addrlen contains the size of the structure pointed to by addr. -//! -//! @return On success, zero is returned. On error, -1 is returned. -//! -//! @brief assign a name to a socket -//! This function gives the socket the local address addr. -//! addr is addrlen bytes long. Traditionally, this is called when a -//! socket is created with socket, it exists in a name space (address -//! family) but has no name assigned. -//! It is necessary to assign a local address before a SOCK_STREAM -//! socket may receive connections. -//! -//! @sa socket ; accept ; listen -// -//***************************************************************************** -extern INT32 CC3000_EXPORT(bind)(INT32 sd, const sockaddr *addr, INT32 addrlen); - -//***************************************************************************** -// -//! listen -//! -//! @param[in] sd socket descriptor (handle) -//! @param[in] backlog specifies the listen queue depth. On this version -//! backlog is not supported. -//! @return On success, zero is returned. On error, -1 is returned. -//! -//! @brief listen for connections on a socket -//! The willingness to accept incoming connections and a queue -//! limit for incoming connections are specified with listen(), -//! and then the connections are accepted with accept. -//! The listen() call applies only to sockets of type SOCK_STREAM -//! The backlog parameter defines the maximum length the queue of -//! pending connections may grow to. -//! -//! @sa socket ; accept ; bind -//! -//! @note On this version, backlog is not supported -// -//***************************************************************************** -extern INT32 CC3000_EXPORT(listen)(INT32 sd, INT32 backlog); - -//***************************************************************************** -// -//! gethostbyname -//! -//! @param[in] hostname host name -//! @param[in] usNameLen name length -//! @param[out] out_ip_addr This parameter is filled in with host IP address. -//! In case that host name is not resolved, -//! out_ip_addr is zero. -//! @return On success, positive is returned. On error, negative is returned -//! -//! @brief Get host IP by name. Obtain the IP Address of machine on network, -//! by its name. -//! -//! @note On this version, only blocking mode is supported. Also note that -//! the function requires DNS server to be configured prior to its usage. -// -//***************************************************************************** -#ifndef CC3000_TINY_DRIVER -extern INT16 CC3000_EXPORT(gethostbyname)(CHAR * hostname, UINT16 usNameLen, UINT32* out_ip_addr); -#endif - - -//***************************************************************************** -// -//! connect -//! -//! @param[in] sd socket descriptor (handle) -//! @param[in] addr specifies the destination addr. On this version -//! only AF_INET is supported. -//! @param[out] addrlen contains the size of the structure pointed to by addr -//! @return On success, zero is returned. On error, -1 is returned -//! -//! @brief initiate a connection on a socket -//! Function connects the socket referred to by the socket descriptor -//! sd, to the address specified by addr. The addrlen argument -//! specifies the size of addr. The format of the address in addr is -//! determined by the address space of the socket. If it is of type -//! SOCK_DGRAM, this call specifies the peer with which the socket is -//! to be associated; this address is that to which datagrams are to be -//! sent, and the only address from which datagrams are to be received. -//! If the socket is of type SOCK_STREAM, this call attempts to make a -//! connection to another socket. The other socket is specified by -//! address, which is an address in the communications space of the -//! socket. Note that the function implements only blocking behavior -//! thus the caller will be waiting either for the connection -//! establishment or for the connection establishment failure. -//! -//! @sa socket -// -//***************************************************************************** -extern INT32 CC3000_EXPORT(connect)(INT32 sd, const sockaddr *addr, INT32 addrlen); - -//***************************************************************************** -// -//! select -//! -//! @param[in] nfds the highest-numbered file descriptor in any of the -//! three sets, plus 1. -//! @param[out] writesds socket descriptors list for write monitoring -//! @param[out] readsds socket descriptors list for read monitoring -//! @param[out] exceptsds socket descriptors list for exception monitoring -//! @param[in] timeout is an upper bound on the amount of time elapsed -//! before select() returns. Null means infinity -//! timeout. The minimum timeout is 5 milliseconds, -//! less than 5 milliseconds will be set -//! automatically to 5 milliseconds. -//! @return On success, select() returns the number of file descriptors -//! contained in the three returned descriptor sets (that is, the -//! total number of bits that are set in readfds, writefds, -//! exceptfds) which may be zero if the timeout expires before -//! anything interesting happens. -//! On error, -1 is returned. -//! *readsds - return the sockets on which Read request will -//! return without delay with valid data. -//! *writesds - return the sockets on which Write request -//! will return without delay. -//! *exceptsds - return the sockets which closed recently. -//! -//! @brief Monitor socket activity -//! Select allow a program to monitor multiple file descriptors, -//! waiting until one or more of the file descriptors become -//! "ready" for some class of I/O operation -//! -//! @Note If the timeout value set to less than 5ms it will automatically set -//! to 5ms to prevent overload of the system -//! -//! @sa socket -// -//***************************************************************************** -extern INT16 CC3000_EXPORT(select)(INT32 nfds, fd_set *readsds, fd_set *writesds, - fd_set *exceptsds, struct cc3000_timeval *timeout); - -//***************************************************************************** -// -//! setsockopt -//! -//! @param[in] sd socket handle -//! @param[in] level defines the protocol level for this option -//! @param[in] optname defines the option name to Interrogate -//! @param[in] optval specifies a value for the option -//! @param[in] optlen specifies the length of the option value -//! @return On success, zero is returned. On error, -1 is returned -//! -//! @brief set socket options -//! This function manipulate the options associated with a socket. -//! Options may exist at multiple protocol levels; they are always -//! present at the uppermost socket level. -//! When manipulating socket options the level at which the option -//! resides and the name of the option must be specified. -//! To manipulate options at the socket level, level is specified as -//! SOL_SOCKET. To manipulate options at any other level the protocol -//! number of the appropriate protocol controlling the option is -//! supplied. For example, to indicate that an option is to be -//! interpreted by the TCP protocol, level should be set to the -//! protocol number of TCP; -//! The parameters optval and optlen are used to access optval - -//! use for setsockopt(). For getsockopt() they identify a buffer -//! in which the value for the requested option(s) are to -//! be returned. For getsockopt(), optlen is a value-result -//! parameter, initially containing the size of the buffer -//! pointed to by option_value, and modified on return to -//! indicate the actual size of the value returned. If no option -//! value is to be supplied or returned, option_value may be NULL. -//! -//! @Note On this version the following two socket options are enabled: -//! The only protocol level supported in this version -//! is SOL_SOCKET (level). -//! 1. SOCKOPT_RECV_TIMEOUT (optname) -//! SOCKOPT_RECV_TIMEOUT configures recv and recvfrom timeout -//! in milliseconds. -//! In that case optval should be pointer to UINT32. -//! 2. SOCKOPT_NONBLOCK (optname). sets the socket non-blocking mode on -//! or off. -//! In that case optval should be SOCK_ON or SOCK_OFF (optval). -//! -//! @sa getsockopt -// -//***************************************************************************** -#ifndef CC3000_TINY_DRIVER -extern INT16 CC3000_EXPORT(setsockopt)(INT32 sd, INT32 level, INT32 optname, const void *optval, - socklen_t optlen); -#endif -//***************************************************************************** -// -//! getsockopt -//! -//! @param[in] sd socket handle -//! @param[in] level defines the protocol level for this option -//! @param[in] optname defines the option name to Interrogate -//! @param[out] optval specifies a value for the option -//! @param[out] optlen specifies the length of the option value -//! @return On success, zero is returned. On error, -1 is returned -//! -//! @brief set socket options -//! This function manipulate the options associated with a socket. -//! Options may exist at multiple protocol levels; they are always -//! present at the uppermost socket level. -//! When manipulating socket options the level at which the option -//! resides and the name of the option must be specified. -//! To manipulate options at the socket level, level is specified as -//! SOL_SOCKET. To manipulate options at any other level the protocol -//! number of the appropriate protocol controlling the option is -//! supplied. For example, to indicate that an option is to be -//! interpreted by the TCP protocol, level should be set to the -//! protocol number of TCP; -//! The parameters optval and optlen are used to access optval - -//! use for setsockopt(). For getsockopt() they identify a buffer -//! in which the value for the requested option(s) are to -//! be returned. For getsockopt(), optlen is a value-result -//! parameter, initially containing the size of the buffer -//! pointed to by option_value, and modified on return to -//! indicate the actual size of the value returned. If no option -//! value is to be supplied or returned, option_value may be NULL. -//! -//! @Note On this version the following two socket options are enabled: -//! The only protocol level supported in this version -//! is SOL_SOCKET (level). -//! 1. SOCKOPT_RECV_TIMEOUT (optname) -//! SOCKOPT_RECV_TIMEOUT configures recv and recvfrom timeout -//! in milliseconds. -//! In that case optval should be pointer to UINT32. -//! 2. SOCKOPT_NONBLOCK (optname). sets the socket non-blocking mode on -//! or off. -//! In that case optval should be SOCK_ON or SOCK_OFF (optval). -//! -//! @sa setsockopt -// -//***************************************************************************** -extern INT16 CC3000_EXPORT(getsockopt)(INT32 sd, INT32 level, INT32 optname, void *optval, - socklen_t *optlen); - -//***************************************************************************** -// -//! recv -//! -//! @param[in] sd socket handle -//! @param[out] buf Points to the buffer where the message should be stored -//! @param[in] len Specifies the length in bytes of the buffer pointed to -//! by the buffer argument. -//! @param[in] flags Specifies the type of message reception. -//! On this version, this parameter is not supported. -//! -//! @return Return the number of bytes received, or -1 if an error -//! occurred -//! -//! @brief function receives a message from a connection-mode socket -//! -//! @sa recvfrom -//! -//! @Note On this version, only blocking mode is supported. -// -//***************************************************************************** -extern INT16 CC3000_EXPORT(recv)(INT32 sd, void *buf, INT32 len, INT32 flags); - -//***************************************************************************** -// -//! recvfrom -//! -//! @param[in] sd socket handle -//! @param[out] buf Points to the buffer where the message should be stored -//! @param[in] len Specifies the length in bytes of the buffer pointed to -//! by the buffer argument. -//! @param[in] flags Specifies the type of message reception. -//! On this version, this parameter is not supported. -//! @param[in] from pointer to an address structure indicating the source -//! address: sockaddr. On this version only AF_INET is -//! supported. -//! @param[in] fromlen source address structure size -//! -//! @return Return the number of bytes received, or -1 if an error -//! occurred -//! -//! @brief read data from socket -//! function receives a message from a connection-mode or -//! connectionless-mode socket. Note that raw sockets are not -//! supported. -//! -//! @sa recv -//! -//! @Note On this version, only blocking mode is supported. -// -//***************************************************************************** -extern INT16 CC3000_EXPORT(recvfrom)(INT32 sd, void *buf, INT32 len, INT32 flags, sockaddr *from, - socklen_t *fromlen); - -//***************************************************************************** -// -//! send -//! -//! @param sd socket handle -//! @param buf Points to a buffer containing the message to be sent -//! @param len message size in bytes -//! @param flags On this version, this parameter is not supported -//! -//! @return Return the number of bytes transmitted, or -1 if an -//! error occurred -//! -//! @brief Write data to TCP socket -//! This function is used to transmit a message to another -//! socket. -//! -//! @Note On this version, only blocking mode is supported. -//! -//! @sa sendto -// -//***************************************************************************** - -extern INT16 CC3000_EXPORT(send)(INT32 sd, const void *buf, INT32 len, INT32 flags); - -//***************************************************************************** -// -//! sendto -//! -//! @param sd socket handle -//! @param buf Points to a buffer containing the message to be sent -//! @param len message size in bytes -//! @param flags On this version, this parameter is not supported -//! @param to pointer to an address structure indicating the destination -//! address: sockaddr. On this version only AF_INET is -//! supported. -//! @param tolen destination address structure size -//! -//! @return Return the number of bytes transmitted, or -1 if an -//! error occurred -//! -//! @brief Write data to TCP socket -//! This function is used to transmit a message to another -//! socket. -//! -//! @Note On this version, only blocking mode is supported. -//! -//! @sa send -// -//***************************************************************************** - -extern INT16 CC3000_EXPORT(sendto)(INT32 sd, const void *buf, INT32 len, INT32 flags, - const sockaddr *to, socklen_t tolen); - -//***************************************************************************** -// -//! mdnsAdvertiser -//! -//! @param[in] mdnsEnabled flag to enable/disable the mDNS feature -//! @param[in] deviceServiceName Service name as part of the published -//! canonical domain name -//! @param[in] deviceServiceNameLength Length of the service name - up to 32 chars -//! -//! -//! @return On success, zero is returned, return SOC_ERROR if socket was not -//! opened successfully, or if an error occurred. -//! -//! @brief Set CC3000 in mDNS advertiser mode in order to advertise itself. -// -//***************************************************************************** -extern INT16 CC3000_EXPORT(mdnsAdvertiser)(UINT16 mdnsEnabled, CHAR * deviceServiceName, UINT16 deviceServiceNameLength); - - -//***************************************************************************** -// -//! getmssvalue -//! -//! @param[in] sd socket descriptor -//! -//! @return On success, returns the MSS value of a TCP connection -//! -//! @brief Returns the MSS value of a TCP connection according to the socket descriptor -// -//***************************************************************************** -extern UINT16 CC3000_EXPORT(getmssvalue) (INT32 sd); - -//***************************************************************************** -// -// Close the Doxygen group. -//! @} -// -//***************************************************************************** - - -//***************************************************************************** -// -// Mark the end of the C bindings section for C++ compilers. -// -//***************************************************************************** -#ifdef __cplusplus -} -#endif // __cplusplus - -#endif // __SOCKET_H__ diff --git a/drivers/cc3000/inc/wlan.h b/drivers/cc3000/inc/wlan.h deleted file mode 100644 index 48d195b32a..0000000000 --- a/drivers/cc3000/inc/wlan.h +++ /dev/null @@ -1,518 +0,0 @@ -/***************************************************************************** -* -* wlan.h - CC3000 Host Driver Implementation. -* Copyright (C) 2011 Texas Instruments Incorporated - http://www.ti.com/ -* -* Redistribution and use in source and binary forms, with or without -* modification, are permitted provided that the following conditions -* are met: -* -* Redistributions of source code must retain the above copyright -* notice, this list of conditions and the following disclaimer. -* -* Redistributions in binary form must reproduce the above copyright -* notice, this list of conditions and the following disclaimer in the -* documentation and/or other materials provided with the -* distribution. -* -* Neither the name of Texas Instruments Incorporated nor the names of -* its contributors may be used to endorse or promote products derived -* from this software without specific prior written permission. -* -* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -* -*****************************************************************************/ -#ifndef __CC3000_WLAN_H__ -#define __CC3000_WLAN_H__ - -#include "cc3000_common.h" - -//***************************************************************************** -// -// If building with a C++ compiler, make all of the definitions in this header -// have a C binding. -// -//***************************************************************************** -#ifdef __cplusplus -extern "C" { -#endif - -#define WLAN_SEC_UNSEC (0) -#define WLAN_SEC_WEP (1) -#define WLAN_SEC_WPA (2) -#define WLAN_SEC_WPA2 (3) -//***************************************************************************** -// -//! \addtogroup wlan_api -//! @{ -// -//***************************************************************************** - - -//***************************************************************************** -// -//! wlan_init -//! -//! @param sWlanCB Asynchronous events callback. -//! 0 no event call back. -//! -call back parameters: -//! 1) event_type: HCI_EVNT_WLAN_UNSOL_CONNECT connect event, -//! HCI_EVNT_WLAN_UNSOL_DISCONNECT disconnect event, -//! HCI_EVNT_WLAN_ASYNC_SIMPLE_CONFIG_DONE config done, -//! HCI_EVNT_WLAN_UNSOL_DHCP dhcp report, -//! HCI_EVNT_WLAN_ASYNC_PING_REPORT ping report OR -//! HCI_EVNT_WLAN_KEEPALIVE keepalive. -//! 2) data: pointer to extra data that received by the event -//! (NULL no data). -//! 3) length: data length. -//! -Events with extra data: -//! HCI_EVNT_WLAN_UNSOL_DHCP: 4 bytes IP, 4 bytes Mask, -//! 4 bytes default gateway, 4 bytes DHCP server and 4 bytes -//! for DNS server. -//! HCI_EVNT_WLAN_ASYNC_PING_REPORT: 4 bytes Packets sent, -//! 4 bytes Packets received, 4 bytes Min round time, -//! 4 bytes Max round time and 4 bytes for Avg round time. -//! -//! @param sFWPatches 0 no patch or pointer to FW patches -//! @param sDriverPatches 0 no patch or pointer to driver patches -//! @param sBootLoaderPatches 0 no patch or pointer to bootloader patches -//! @param sReadWlanInterruptPin init callback. the callback read wlan -//! interrupt status. -//! @param sWlanInterruptEnable init callback. the callback enable wlan -//! interrupt. -//! @param sWlanInterruptDisable init callback. the callback disable wlan -//! interrupt. -//! @param sWriteWlanPin init callback. the callback write value -//! to device pin. -//! -//! @return none -//! -//! @sa wlan_set_event_mask , wlan_start , wlan_stop -//! -//! @brief Initialize wlan driver -//! -//! @warning This function must be called before ANY other wlan driver function -// -//***************************************************************************** -extern void wlan_init( tWlanCB sWlanCB, - tFWPatches sFWPatches, - tDriverPatches sDriverPatches, - tBootLoaderPatches sBootLoaderPatches, - tWlanReadInteruptPin sReadWlanInterruptPin, - tWlanInterruptEnable sWlanInterruptEnable, - tWlanInterruptDisable sWlanInterruptDisable, - tWriteWlanPin sWriteWlanPin); - - - -//***************************************************************************** -// -//! wlan_start -//! -//! @param usPatchesAvailableAtHost - flag to indicate if patches available -//! from host or from EEPROM. Due to the -//! fact the patches are burn to the EEPROM -//! using the patch programmer utility, the -//! patches will be available from the EEPROM -//! and not from the host. -//! -//! @return none -//! -//! @brief Start WLAN device. This function asserts the enable pin of -//! the device (WLAN_EN), starting the HW initialization process. -//! The function blocked until device Initialization is completed. -//! Function also configure patches (FW, driver or bootloader) -//! and calls appropriate device callbacks. -//! -//! @Note Prior calling the function wlan_init shall be called. -//! @Warning This function must be called after wlan_init and before any -//! other wlan API -//! @sa wlan_init , wlan_stop -//! -// -//***************************************************************************** -extern int wlan_start(UINT16 usPatchesAvailableAtHost); - -//***************************************************************************** -// -//! wlan_stop -//! -//! @param none -//! -//! @return none -//! -//! @brief Stop WLAN device by putting it into reset state. -//! -//! @sa wlan_start -// -//***************************************************************************** -extern void wlan_stop(void); - -//***************************************************************************** -// -//! wlan_connect -//! -//! @param sec_type security options: -//! WLAN_SEC_UNSEC, -//! WLAN_SEC_WEP (ASCII support only), -//! WLAN_SEC_WPA or WLAN_SEC_WPA2 -//! @param ssid up to 32 bytes and is ASCII SSID of the AP -//! @param ssid_len length of the SSID -//! @param bssid 6 bytes specified the AP bssid -//! @param key up to 32 bytes specified the AP security key -//! @param key_len key length -//! -//! @return On success, zero is returned. On error, negative is returned. -//! Note that even though a zero is returned on success to trigger -//! connection operation, it does not mean that CCC3000 is already -//! connected. An asynchronous "Connected" event is generated when -//! actual association process finishes and CC3000 is connected to -//! the AP. If DHCP is set, An asynchronous "DHCP" event is -//! generated when DHCP process is finish. -//! -//! -//! @brief Connect to AP -//! @warning Please Note that when connection to AP configured with security -//! type WEP, please confirm that the key is set as ASCII and not -//! as HEX. -//! @sa wlan_disconnect -// -//***************************************************************************** -#ifndef CC3000_TINY_DRIVER -extern INT32 wlan_connect(UINT32 ulSecType, CHAR *ssid, INT32 ssid_len, - UINT8 *bssid, UINT8 *key, INT32 key_len); -#else -extern INT32 wlan_connect(CHAR *ssid, INT32 ssid_len); - -#endif - -//***************************************************************************** -// -//! wlan_disconnect -//! -//! @return 0 disconnected done, other CC3000 already disconnected -//! -//! @brief Disconnect connection from AP. -//! -//! @sa wlan_connect -// -//***************************************************************************** - -extern INT32 wlan_disconnect(void); - -//***************************************************************************** -// -//! wlan_add_profile -//! -//! @param ulSecType WLAN_SEC_UNSEC,WLAN_SEC_WEP,WLAN_SEC_WPA,WLAN_SEC_WPA2 -//! @param ucSsid ssid SSID up to 32 bytes -//! @param ulSsidLen ssid length -//! @param ucBssid bssid 6 bytes -//! @param ulPriority ulPriority profile priority. Lowest priority:0. -//! @param ulPairwiseCipher_Or_TxKeyLen key length for WEP security -//! @param ulGroupCipher_TxKeyIndex key index -//! @param ulKeyMgmt KEY management -//! @param ucPf_OrKey security key -//! @param ulPassPhraseLen security key length for WPA\WPA2 -//! -//! @return On success, index (1-7) of the stored profile is returned. -//! On error, -1 is returned. -//! -//! @brief When auto start is enabled, the device connects to -//! station from the profiles table. Up to 7 profiles are supported. -//! If several profiles configured the device choose the highest -//! priority profile, within each priority group, device will choose -//! profile based on security policy, signal strength, etc -//! parameters. All the profiles are stored in CC3000 NVMEM. -//! -//! @sa wlan_ioctl_del_profile -// -//***************************************************************************** - -extern INT32 wlan_add_profile(UINT32 ulSecType, UINT8* ucSsid, - UINT32 ulSsidLen, - UINT8 *ucBssid, - UINT32 ulPriority, - UINT32 ulPairwiseCipher_Or_Key, - UINT32 ulGroupCipher_TxKeyLen, - UINT32 ulKeyMgmt, - UINT8* ucPf_OrKey, - UINT32 ulPassPhraseLen); - - - -//***************************************************************************** -// -//! wlan_ioctl_del_profile -//! -//! @param index number of profile to delete -//! -//! @return On success, zero is returned. On error, -1 is returned -//! -//! @brief Delete WLAN profile -//! -//! @Note In order to delete all stored profile, set index to 255. -//! -//! @sa wlan_add_profile -// -//***************************************************************************** -extern INT32 wlan_ioctl_del_profile(UINT32 ulIndex); - -//***************************************************************************** -// -//! wlan_set_event_mask -//! -//! @param mask mask option: -//! HCI_EVNT_WLAN_UNSOL_CONNECT connect event -//! HCI_EVNT_WLAN_UNSOL_DISCONNECT disconnect event -//! HCI_EVNT_WLAN_ASYNC_SIMPLE_CONFIG_DONE smart config done -//! HCI_EVNT_WLAN_UNSOL_INIT init done -//! HCI_EVNT_WLAN_UNSOL_DHCP dhcp event report -//! HCI_EVNT_WLAN_ASYNC_PING_REPORT ping report -//! HCI_EVNT_WLAN_KEEPALIVE keepalive -//! HCI_EVNT_WLAN_TX_COMPLETE - disable information on end of transmission -//! Saved: no. -//! -//! @return On success, zero is returned. On error, -1 is returned -//! -//! @brief Mask event according to bit mask. In case that event is -//! masked (1), the device will not send the masked event to host. -// -//***************************************************************************** -extern INT32 wlan_set_event_mask(UINT32 ulMask); - -//***************************************************************************** -// -//! wlan_ioctl_statusget -//! -//! @param none -//! -//! @return WLAN_STATUS_DISCONNECTED, WLAN_STATUS_SCANING, -//! STATUS_CONNECTING or WLAN_STATUS_CONNECTED -//! -//! @brief get wlan status: disconnected, scanning, connecting or connected -// -//***************************************************************************** -extern INT32 wlan_ioctl_statusget(void); - - -//***************************************************************************** -// -//! wlan_ioctl_set_connection_policy -//! -//! @param should_connect_to_open_ap enable(1), disable(0) connect to any -//! available AP. This parameter corresponds to the configuration of -//! item # 3 in the brief description. -//! @param should_use_fast_connect enable(1), disable(0). if enabled, tries -//! to connect to the last connected AP. This parameter corresponds -//! to the configuration of item # 1 in the brief description. -//! @param auto_start enable(1), disable(0) auto connect -//! after reset and periodically reconnect if needed. This -//! configuration configures option 2 in the above description. -//! -//! @return On success, zero is returned. On error, -1 is returned -//! -//! @brief When auto is enabled, the device tries to connect according -//! the following policy: -//! 1) If fast connect is enabled and last connection is valid, -//! the device will try to connect to it without the scanning -//! procedure (fast). The last connection will be marked as -//! invalid, due to adding/removing profile. -//! 2) If profile exists, the device will try to connect it -//! (Up to seven profiles). -//! 3) If fast and profiles are not found, and open mode is -//! enabled, the device will try to connect to any AP. -//! * Note that the policy settings are stored in the CC3000 NVMEM. -//! -//! @sa wlan_add_profile , wlan_ioctl_del_profile -// -//***************************************************************************** -extern INT32 wlan_ioctl_set_connection_policy( - UINT32 should_connect_to_open_ap, - UINT32 should_use_fast_connect, - UINT32 ulUseProfiles); - -//***************************************************************************** -// -//! wlan_ioctl_get_scan_results -//! -//! @param[in] scan_timeout parameter not supported -//! @param[out] ucResults scan result (_wlan_full_scan_results_args_t) -//! -//! @return On success, zero is returned. On error, -1 is returned -//! -//! @brief Gets entry from scan result table. -//! The scan results are returned one by one, and each entry -//! represents a single AP found in the area. The following is a -//! format of the scan result: -//! - 4 Bytes: number of networks found -//! - 4 Bytes: The status of the scan: 0 - aged results, -//! 1 - results valid, 2 - no results -//! - 42 bytes: Result entry, where the bytes are arranged as follows: -//! -//! - 1 bit isValid - is result valid or not -//! - 7 bits rssi - RSSI value; -//! - 2 bits: securityMode - security mode of the AP: -//! 0 - Open, 1 - WEP, 2 WPA, 3 WPA2 -//! - 6 bits: SSID name length -//! - 2 bytes: the time at which the entry has entered into -//! scans result table -//! - 32 bytes: SSID name -//! - 6 bytes: BSSID -//! -//! @Note scan_timeout, is not supported on this version. -//! -//! @sa wlan_ioctl_set_scan_params -// -//***************************************************************************** - - -extern INT32 wlan_ioctl_get_scan_results(UINT32 ulScanTimeout, - UINT8 *ucResults); - -//***************************************************************************** -// -//! wlan_ioctl_set_scan_params -//! -//! @param uiEnable - start/stop application scan: -//! 1 = start scan with default interval value of 10 min. -//! in order to set a different scan interval value apply the value -//! in milliseconds. minimum 1 second. 0=stop). Wlan reset -//! (wlan_stop() wlan_start()) is needed when changing scan interval -//! value. Saved: No -//! @param uiMinDwellTime minimum dwell time value to be used for each -//! channel, in milliseconds. Saved: yes -//! Recommended Value: 100 (Default: 20) -//! @param uiMaxDwellTime maximum dwell time value to be used for each -//! channel, in milliseconds. Saved: yes -//! Recommended Value: 100 (Default: 30) -//! @param uiNumOfProbeRequests max probe request between dwell time. -//! Saved: yes. Recommended Value: 5 (Default:2) -//! @param uiChannelMask bitwise, up to 13 channels (0x1fff). -//! Saved: yes. Default: 0x7ff -//! @param uiRSSIThreshold RSSI threshold. Saved: yes (Default: -80) -//! @param uiSNRThreshold NSR threshold. Saved: yes (Default: 0) -//! @param uiDefaultTxPower probe Tx power. Saved: yes (Default: 205) -//! @param aiIntervalList pointer to array with 16 entries (16 channels) -//! each entry (UINT32) holds timeout between periodic scan -//! (connection scan) - in milliseconds. Saved: yes. Default 2000ms. -//! -//! @return On success, zero is returned. On error, -1 is returned -//! -//! @brief start and stop scan procedure. Set scan parameters. -//! -//! @Note uiDefaultTxPower, is not supported on this version. -//! -//! @sa wlan_ioctl_get_scan_results -// -//***************************************************************************** -extern INT32 wlan_ioctl_set_scan_params(UINT32 uiEnable, UINT32 - uiMinDwellTime,UINT32 uiMaxDwellTime, - UINT32 uiNumOfProbeRequests, - UINT32 uiChannelMask, - INT32 iRSSIThreshold,UINT32 uiSNRThreshold, - UINT32 uiDefaultTxPower, - UINT32 *aiIntervalList); - - -//***************************************************************************** -// -//! wlan_smart_config_start -//! -//! @param algoEncryptedFlag indicates whether the information is encrypted -//! -//! @return On success, zero is returned. On error, -1 is returned -//! -//! @brief Start to acquire device profile. The device acquire its own -//! profile, if profile message is found. The acquired AP information -//! is stored in CC3000 EEPROM only in case AES128 encryption is used. -//! In case AES128 encryption is not used, a profile is created by -//! CC3000 internally. -//! -//! @Note An asynchronous event - Smart Config Done will be generated as soon -//! as the process finishes successfully. -//! -//! @sa wlan_smart_config_set_prefix , wlan_smart_config_stop -// -//***************************************************************************** -extern INT32 wlan_smart_config_start(UINT32 algoEncryptedFlag); - - -//***************************************************************************** -// -//! wlan_smart_config_stop -//! -//! @param algoEncryptedFlag indicates whether the information is encrypted -//! -//! @return On success, zero is returned. On error, -1 is returned -//! -//! @brief Stop the acquire profile procedure -//! -//! @sa wlan_smart_config_start , wlan_smart_config_set_prefix -// -//***************************************************************************** -extern INT32 wlan_smart_config_stop(void); - -//***************************************************************************** -// -//! wlan_smart_config_set_prefix -//! -//! @param newPrefix 3 bytes identify the SSID prefix for the Smart Config. -//! -//! @return On success, zero is returned. On error, -1 is returned -//! -//! @brief Configure station ssid prefix. The prefix is used internally -//! in CC3000. It should always be TTT. -//! -//! @Note The prefix is stored in CC3000 NVMEM -//! -//! @sa wlan_smart_config_start , wlan_smart_config_stop -// -//***************************************************************************** -extern INT32 wlan_smart_config_set_prefix(CHAR* cNewPrefix); - -//***************************************************************************** -// -//! wlan_smart_config_process -//! -//! @param none -//! -//! @return On success, zero is returned. On error, -1 is returned -//! -//! @brief process the acquired data and store it as a profile. The acquired -//! AP information is stored in CC3000 EEPROM encrypted. -//! The encrypted data is decrypted and stored as a profile. -//! behavior is as defined by connection policy. -// -//***************************************************************************** -extern INT32 wlan_smart_config_process(void); - -//***************************************************************************** -// -// Close the Doxygen group. -//! @} -// -//***************************************************************************** - - - -//***************************************************************************** -// -// Mark the end of the C bindings section for C++ compilers. -// -//***************************************************************************** -#ifdef __cplusplus -} -#endif // __cplusplus - -#endif // __CC3000_WLAN_H__ diff --git a/drivers/cc3000/src/cc3000_common.c b/drivers/cc3000/src/cc3000_common.c deleted file mode 100644 index b4c87848cf..0000000000 --- a/drivers/cc3000/src/cc3000_common.c +++ /dev/null @@ -1,164 +0,0 @@ -/***************************************************************************** -* -* cc3000_common.c.c - CC3000 Host Driver Implementation. -* Copyright (C) 2011 Texas Instruments Incorporated - http://www.ti.com/ -* -* Redistribution and use in source and binary forms, with or without -* modification, are permitted provided that the following conditions -* are met: -* -* Redistributions of source code must retain the above copyright -* notice, this list of conditions and the following disclaimer. -* -* Redistributions in binary form must reproduce the above copyright -* notice, this list of conditions and the following disclaimer in the -* documentation and/or other materials provided with the -* distribution. -* -* Neither the name of Texas Instruments Incorporated nor the names of -* its contributors may be used to endorse or promote products derived -* from this software without specific prior written permission. -* -* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -* -*****************************************************************************/ -//***************************************************************************** -// -//! \addtogroup common_api -//! @{ -// -//***************************************************************************** -/****************************************************************************** -* -* Include files -* -*****************************************************************************/ - -#include "cc3000_common.h" -#include "socket.h" -#include "wlan.h" -#include "evnt_handler.h" - -//***************************************************************************** -// -//! __error__ -//! -//! @param pcFilename - file name, where error occurred -//! @param ulLine - line number, where error occurred -//! -//! @return none -//! -//! @brief stub function for ASSERT macro -// -//***************************************************************************** -void __error__(CHAR *pcFilename, UINT32 ulLine) -{ - //TODO full up function -} - - - -//***************************************************************************** -// -//! UINT32_TO_STREAM_f -//! -//! @param p pointer to the new stream -//! @param u32 pointer to the 32 bit -//! -//! @return pointer to the new stream -//! -//! @brief This function is used for copying 32 bit to stream -//! while converting to little endian format. -// -//***************************************************************************** - -UINT8* UINT32_TO_STREAM_f (UINT8 *p, UINT32 u32) -{ - *(p)++ = (UINT8)(u32); - *(p)++ = (UINT8)((u32) >> 8); - *(p)++ = (UINT8)((u32) >> 16); - *(p)++ = (UINT8)((u32) >> 24); - return p; -} - -//***************************************************************************** -// -//! UINT16_TO_STREAM_f -//! -//! @param p pointer to the new stream -//! @param u32 pointer to the 16 bit -//! -//! @return pointer to the new stream -//! -//! @brief This function is used for copying 16 bit to stream -//! while converting to little endian format. -// -//***************************************************************************** - -UINT8* UINT16_TO_STREAM_f (UINT8 *p, UINT16 u16) -{ - *(p)++ = (UINT8)(u16); - *(p)++ = (UINT8)((u16) >> 8); - return p; -} - -//***************************************************************************** -// -//! STREAM_TO_UINT16_f -//! -//! @param p pointer to the stream -//! @param offset offset in the stream -//! -//! @return pointer to the new 16 bit -//! -//! @brief This function is used for copying received stream to -//! 16 bit in little endian format. -// -//***************************************************************************** - -UINT16 STREAM_TO_UINT16_f(CHAR* p, UINT16 offset) -{ - return (UINT16)((UINT16)((UINT16) - (*(p + offset + 1)) << 8) + (UINT16)(*(p + offset))); -} - -//***************************************************************************** -// -//! STREAM_TO_UINT32_f -//! -//! @param p pointer to the stream -//! @param offset offset in the stream -//! -//! @return pointer to the new 32 bit -//! -//! @brief This function is used for copying received stream to -//! 32 bit in little endian format. -// -//***************************************************************************** - -UINT32 STREAM_TO_UINT32_f(CHAR* p, UINT16 offset) -{ - return (UINT32)((UINT32)((UINT32) - (*(p + offset + 3)) << 24) + (UINT32)((UINT32) - (*(p + offset + 2)) << 16) + (UINT32)((UINT32) - (*(p + offset + 1)) << 8) + (UINT32)(*(p + offset))); -} - - - -//***************************************************************************** -// -// Close the Doxygen group. -//! @} -// -//***************************************************************************** diff --git a/drivers/cc3000/src/ccspi.c b/drivers/cc3000/src/ccspi.c deleted file mode 100644 index 64900efe46..0000000000 --- a/drivers/cc3000/src/ccspi.c +++ /dev/null @@ -1,456 +0,0 @@ -/***************************************************************************** - * - * spi.c - CC3000 Host Driver Implementation. - * Copyright (C) 2011 Texas Instruments Incorporated - http://www.ti.com/ - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * - * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * Neither the name of Texas Instruments Incorporated nor the names of - * its contributors may be used to endorse or promote products derived - * from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - *****************************************************************************/ - -#include - -#include "py/nlr.h" -#include "py/obj.h" -#include "py/runtime.h" -#include "pin.h" -#include "led.h" -#include "extint.h" -#include "spi.h" -#include "ccspi.h" -#include "evnt_handler.h" - -#if 0 // print debugging info -#include -#define DEBUG_printf(args...) printf(args) -#else // don't print debugging info -#define DEBUG_printf(args...) (void)0 -#endif - -// these need to be set to valid values before anything in this file will work -STATIC SPI_HandleTypeDef *SPI_HANDLE = NULL; -STATIC const pin_obj_t *PIN_CS = NULL; -STATIC const pin_obj_t *PIN_EN = NULL; -STATIC const pin_obj_t *PIN_IRQ = NULL; - -#define CS_LOW() HAL_GPIO_WritePin(PIN_CS->gpio, PIN_CS->pin_mask, GPIO_PIN_RESET) -#define CS_HIGH() HAL_GPIO_WritePin(PIN_CS->gpio, PIN_CS->pin_mask, GPIO_PIN_SET) - -#define READ 3 -#define WRITE 1 - -#define HI(value) (((value) & 0xFF00) >> 8) -#define LO(value) ((value) & 0x00FF) - -#define SPI_TIMEOUT (1000) -#define HEADERS_SIZE_EVNT (SPI_HEADER_SIZE + 5) - -/* SPI bus states */ -#define eSPI_STATE_POWERUP (0) -#define eSPI_STATE_INITIALIZED (1) -#define eSPI_STATE_IDLE (2) -#define eSPI_STATE_WRITE_IRQ (3) -#define eSPI_STATE_WRITE_FIRST_PORTION (4) -#define eSPI_STATE_WRITE_EOT (5) -#define eSPI_STATE_READ_IRQ (6) -#define eSPI_STATE_READ_FIRST_PORTION (7) -#define eSPI_STATE_READ_EOT (8) - -// The magic number that resides at the end of the TX/RX buffer (1 byte after the allocated size) -// for the purpose of detection of the overrun. The location of the memory where the magic number -// resides shall never be written. In case it is written - the overrun occured and either recevie function -// or send function will stuck forever. -#define CC3000_BUFFER_MAGIC_NUMBER (0xDE) - -typedef struct { - gcSpiHandleRx SPIRxHandler; - unsigned short usTxPacketLength; - unsigned short usRxPacketLength; - unsigned long ulSpiState; - unsigned char *pTxPacket; - unsigned char *pRxPacket; -} tSpiInformation; -STATIC tSpiInformation sSpiInformation; - -STATIC char spi_buffer[CC3000_RX_BUFFER_SIZE]; -unsigned char wlan_tx_buffer[CC3000_TX_BUFFER_SIZE]; - -STATIC const mp_obj_fun_builtin_fixed_t irq_callback_obj; - -// set the pins to use to communicate with the CC3000 -// the arguments must be of type pin_obj_t* and SPI_HandleTypeDef* -void SpiInit(void *spi, const void *pin_cs, const void *pin_en, const void *pin_irq) { - SPI_HANDLE = spi; - PIN_CS = pin_cs; - PIN_EN = pin_en; - PIN_IRQ = pin_irq; -} - -void SpiClose(void) -{ - if (sSpiInformation.pRxPacket) { - sSpiInformation.pRxPacket = 0; - } - - tSLInformation.WlanInterruptDisable(); - - //HAL_SPI_DeInit(SPI_HANDLE); -} - -void SpiOpen(gcSpiHandleRx pfRxHandler) -{ - DEBUG_printf("SpiOpen\n"); - - /* initialize SPI state */ - sSpiInformation.ulSpiState = eSPI_STATE_POWERUP; - sSpiInformation.SPIRxHandler = pfRxHandler; - sSpiInformation.usTxPacketLength = 0; - sSpiInformation.pTxPacket = NULL; - sSpiInformation.pRxPacket = (unsigned char *)spi_buffer; - sSpiInformation.usRxPacketLength = 0; - spi_buffer[CC3000_RX_BUFFER_SIZE - 1] = CC3000_BUFFER_MAGIC_NUMBER; - wlan_tx_buffer[CC3000_TX_BUFFER_SIZE - 1] = CC3000_BUFFER_MAGIC_NUMBER; - - /* SPI configuration */ - SPI_HANDLE->Init.Mode = SPI_MODE_MASTER; - SPI_HANDLE->Init.Direction = SPI_DIRECTION_2LINES; - SPI_HANDLE->Init.DataSize = SPI_DATASIZE_8BIT; - SPI_HANDLE->Init.CLKPolarity = SPI_POLARITY_LOW; - SPI_HANDLE->Init.CLKPhase = SPI_PHASE_2EDGE; - SPI_HANDLE->Init.NSS = SPI_NSS_SOFT; - SPI_HANDLE->Init.BaudRatePrescaler = SPI_BAUDRATEPRESCALER_8; - SPI_HANDLE->Init.FirstBit = SPI_FIRSTBIT_MSB; - SPI_HANDLE->Init.TIMode = SPI_TIMODE_DISABLED; - SPI_HANDLE->Init.CRCCalculation = SPI_CRCCALCULATION_DISABLED; - SPI_HANDLE->Init.CRCPolynomial = 7; - spi_init(SPI_HANDLE, false); - - // configure wlan CS and EN pins - GPIO_InitTypeDef GPIO_InitStructure; - GPIO_InitStructure.Speed = GPIO_SPEED_FAST; - GPIO_InitStructure.Mode = GPIO_MODE_OUTPUT_PP; - GPIO_InitStructure.Pull = GPIO_NOPULL; - GPIO_InitStructure.Alternate = 0; - - GPIO_InitStructure.Pin = PIN_CS->pin_mask; - HAL_GPIO_Init(PIN_CS->gpio, &GPIO_InitStructure); - - GPIO_InitStructure.Pin = PIN_EN->pin_mask; - HAL_GPIO_Init(PIN_EN->gpio, &GPIO_InitStructure); - - HAL_GPIO_WritePin(PIN_CS->gpio, PIN_CS->pin_mask, GPIO_PIN_SET); - HAL_GPIO_WritePin(PIN_EN->gpio, PIN_EN->pin_mask, GPIO_PIN_RESET); - - /* do a dummy read, this ensures SCLK is low before - actual communications start, it might be required */ - CS_LOW(); - uint8_t buf[1]; - HAL_SPI_Receive(SPI_HANDLE, buf, sizeof(buf), SPI_TIMEOUT); - CS_HIGH(); - - // register EXTI - extint_register((mp_obj_t)PIN_IRQ, GPIO_MODE_IT_FALLING, GPIO_PULLUP, (mp_obj_t)&irq_callback_obj, true); - extint_enable(PIN_IRQ->pin); - - DEBUG_printf("SpiOpen finished; IRQ.pin=%d IRQ_LINE=%d\n", PIN_IRQ->pin, PIN_IRQ->pin); -} - -long ReadWlanInterruptPin(void) -{ - return HAL_GPIO_ReadPin(PIN_IRQ->gpio, PIN_IRQ->pin_mask); -} - -void WriteWlanPin(unsigned char val) -{ - HAL_GPIO_WritePin(PIN_EN->gpio, PIN_EN->pin_mask, - (WLAN_ENABLE)? GPIO_PIN_SET:GPIO_PIN_RESET); -} - -STATIC void SpiWriteDataSynchronous(unsigned char *data, unsigned short size) -{ - DEBUG_printf("SpiWriteDataSynchronous(data=%p [%x %x %x %x], size=%u)\n", data, data[0], data[1], data[2], data[3], size); - __disable_irq(); - if (HAL_SPI_TransmitReceive(SPI_HANDLE, data, data, size, SPI_TIMEOUT) != HAL_OK) { - //BREAK(); - } - __enable_irq(); - DEBUG_printf(" - rx data = [%x %x %x %x]\n", data[0], data[1], data[2], data[3]); -} - -STATIC void SpiReadDataSynchronous(unsigned char *data, unsigned short size) -{ - memset(data, READ, size); - __disable_irq(); - if (HAL_SPI_TransmitReceive(SPI_HANDLE, data, data, size, SPI_TIMEOUT) != HAL_OK) { - //BREAK(); - } - __enable_irq(); -} - -STATIC void __delay_cycles(volatile int x) -{ - x *= 6; // for 168 MHz CPU - while (x--); -} - -STATIC long SpiFirstWrite(unsigned char *ucBuf, unsigned short usLength) -{ - DEBUG_printf("SpiFirstWrite %lu\n", sSpiInformation.ulSpiState); - - CS_LOW(); - - // Assuming we are running on 24 MHz ~50 micro delay is 1200 cycles; - __delay_cycles(1200); - - // SPI writes first 4 bytes of data - SpiWriteDataSynchronous(ucBuf, 4); - - __delay_cycles(1200); - - SpiWriteDataSynchronous(ucBuf + 4, usLength - 4); - - // From this point on - operate in a regular way - sSpiInformation.ulSpiState = eSPI_STATE_IDLE; - - CS_HIGH(); - - return(0); -} - -long SpiWrite(unsigned char *pUserBuffer, unsigned short usLength) -{ - DEBUG_printf("SpiWrite %lu\n", sSpiInformation.ulSpiState); - - unsigned char ucPad = 0; - - // Figure out the total length of the packet in order to figure out if there - // is padding or not - if(!(usLength & 0x0001)) { - ucPad++; - } - - pUserBuffer[0] = WRITE; - pUserBuffer[1] = HI(usLength + ucPad); - pUserBuffer[2] = LO(usLength + ucPad); - pUserBuffer[3] = 0; - pUserBuffer[4] = 0; - - usLength += (SPI_HEADER_SIZE + ucPad); - - // The magic number that resides at the end of the TX/RX buffer (1 byte after the allocated size) - // for the purpose of detection of the overrun. If the magic number is overriten - buffer overrun - // occurred - and we will stuck here forever! - if (wlan_tx_buffer[CC3000_TX_BUFFER_SIZE - 1] != CC3000_BUFFER_MAGIC_NUMBER) { - while (1); - } - - if (sSpiInformation.ulSpiState == eSPI_STATE_POWERUP) { - while (sSpiInformation.ulSpiState != eSPI_STATE_INITIALIZED); - } - - if (sSpiInformation.ulSpiState == eSPI_STATE_INITIALIZED) { - // This is time for first TX/RX transactions over SPI: - // the IRQ is down - so need to send read buffer size command - SpiFirstWrite(pUserBuffer, usLength); - } else { - // - // We need to prevent here race that can occur in case 2 back to back packets are sent to the - // device, so the state will move to IDLE and once again to not IDLE due to IRQ - // - tSLInformation.WlanInterruptDisable(); - - while (sSpiInformation.ulSpiState != eSPI_STATE_IDLE); - - sSpiInformation.ulSpiState = eSPI_STATE_WRITE_IRQ; - sSpiInformation.pTxPacket = pUserBuffer; - sSpiInformation.usTxPacketLength = usLength; - - // Assert the CS line and wait till SSI IRQ line is active and then initialize write operation - CS_LOW(); - - // Re-enable IRQ - if it was not disabled - this is not a problem... - tSLInformation.WlanInterruptEnable(); - - // check for a missing interrupt between the CS assertion and enabling back the interrupts - if (tSLInformation.ReadWlanInterruptPin() == 0) { - SpiWriteDataSynchronous(sSpiInformation.pTxPacket, sSpiInformation.usTxPacketLength); - - sSpiInformation.ulSpiState = eSPI_STATE_IDLE; - - CS_HIGH(); - } - } - - // Due to the fact that we are currently implementing a blocking situation - // here we will wait till end of transaction - while (eSPI_STATE_IDLE != sSpiInformation.ulSpiState); - - return(0); -} - -#if 0 -unused -STATIC void SpiReadPacket(void) -{ - int length; - - /* read SPI header */ - SpiReadDataSynchronous(sSpiInformation.pRxPacket, SPI_HEADER_SIZE); - - /* parse data length */ - STREAM_TO_UINT8(sSpiInformation.pRxPacket, SPI_HEADER_SIZE-1, length); - - /* read the remainder of the packet */ - SpiReadDataSynchronous(sSpiInformation.pRxPacket + SPI_HEADER_SIZE, length); - - sSpiInformation.ulSpiState = eSPI_STATE_READ_EOT; -} -#endif - -STATIC void SpiReadHeader(void) -{ - SpiReadDataSynchronous(sSpiInformation.pRxPacket, 10); -} - -STATIC void SpiTriggerRxProcessing(void) -{ - SpiPauseSpi(); - CS_HIGH(); - - // The magic number that resides at the end of the TX/RX buffer (1 byte after the allocated size) - // for the purpose of detection of the overrun. If the magic number is overriten - buffer overrun - // occurred - and we will stuck here forever! - if (sSpiInformation.pRxPacket[CC3000_RX_BUFFER_SIZE - 1] != CC3000_BUFFER_MAGIC_NUMBER) { - while (1); - } - - sSpiInformation.ulSpiState = eSPI_STATE_IDLE; - sSpiInformation.SPIRxHandler(sSpiInformation.pRxPacket + SPI_HEADER_SIZE); -} - - -STATIC long SpiReadDataCont(void) -{ - long data_to_recv=0; - unsigned char *evnt_buff, type; - - //determine what type of packet we have - evnt_buff = sSpiInformation.pRxPacket; - STREAM_TO_UINT8((char *)(evnt_buff + SPI_HEADER_SIZE), HCI_PACKET_TYPE_OFFSET, type); - - switch (type) { - case HCI_TYPE_DATA:{ - // We need to read the rest of data.. - STREAM_TO_UINT16((char *)(evnt_buff + SPI_HEADER_SIZE), - HCI_DATA_LENGTH_OFFSET, data_to_recv); - if (!((HEADERS_SIZE_EVNT + data_to_recv) & 1)) { - data_to_recv++; - } - - if (data_to_recv) { - SpiReadDataSynchronous(evnt_buff + 10, data_to_recv); - } - break; - } - case HCI_TYPE_EVNT: { - // Calculate the rest length of the data - STREAM_TO_UINT8((char *)(evnt_buff + SPI_HEADER_SIZE), - HCI_EVENT_LENGTH_OFFSET, data_to_recv); - data_to_recv -= 1; - - // Add padding byte if needed - if ((HEADERS_SIZE_EVNT + data_to_recv) & 1) { - data_to_recv++; - } - - if (data_to_recv) { - SpiReadDataSynchronous(evnt_buff + 10, data_to_recv); - } - - sSpiInformation.ulSpiState = eSPI_STATE_READ_EOT; - break; - } - } - - return 0; -} - -STATIC void SSIContReadOperation(void) -{ - // The header was read - continue with the payload read - if (!SpiReadDataCont()) { - /* All the data was read - finalize handling by switching - to the task and calling from task Event Handler */ - SpiTriggerRxProcessing(); - } -} - -STATIC mp_obj_t irq_callback(mp_obj_t line) { - DEBUG_printf("<< IRQ; state=%lu >>\n", sSpiInformation.ulSpiState); - switch (sSpiInformation.ulSpiState) { - case eSPI_STATE_POWERUP: - /* This means IRQ line was low call a callback of HCI Layer to inform on event */ - DEBUG_printf(" - POWERUP\n"); - sSpiInformation.ulSpiState = eSPI_STATE_INITIALIZED; - break; - case eSPI_STATE_IDLE: - DEBUG_printf(" - IDLE\n"); - sSpiInformation.ulSpiState = eSPI_STATE_READ_IRQ; - - /* IRQ line goes down - we are start reception */ - CS_LOW(); - - // Wait for TX/RX Compete which will come as DMA interrupt - SpiReadHeader(); - - sSpiInformation.ulSpiState = eSPI_STATE_READ_EOT; - - SSIContReadOperation(); - break; - case eSPI_STATE_WRITE_IRQ: - DEBUG_printf(" - WRITE IRQ\n"); - SpiWriteDataSynchronous(sSpiInformation.pTxPacket, sSpiInformation.usTxPacketLength); - - sSpiInformation.ulSpiState = eSPI_STATE_IDLE; - - CS_HIGH(); - break; - } - return mp_const_none; -} - -STATIC MP_DEFINE_CONST_FUN_OBJ_1(irq_callback_obj, irq_callback); - -void SpiPauseSpi(void) { - DEBUG_printf("SpiPauseSpi\n"); - extint_disable(PIN_IRQ->pin); -} - -void SpiResumeSpi(void) { - DEBUG_printf("SpiResumeSpi\n"); - extint_enable(PIN_IRQ->pin); -} diff --git a/drivers/cc3000/src/evnt_handler.c b/drivers/cc3000/src/evnt_handler.c deleted file mode 100644 index 80f34e469b..0000000000 --- a/drivers/cc3000/src/evnt_handler.c +++ /dev/null @@ -1,849 +0,0 @@ -/***************************************************************************** -* -* evnt_handler.c - CC3000 Host Driver Implementation. -* Copyright (C) 2011 Texas Instruments Incorporated - http://www.ti.com/ -* -* Redistribution and use in source and binary forms, with or without -* modification, are permitted provided that the following conditions -* are met: -* -* Redistributions of source code must retain the above copyright -* notice, this list of conditions and the following disclaimer. -* -* Redistributions in binary form must reproduce the above copyright -* notice, this list of conditions and the following disclaimer in the -* documentation and/or other materials provided with the -* distribution. -* -* Neither the name of Texas Instruments Incorporated nor the names of -* its contributors may be used to endorse or promote products derived -* from this software without specific prior written permission. -* -* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -* -*****************************************************************************/ -//***************************************************************************** -// -//! \addtogroup evnt_handler_api -//! @{ -// -//****************************************************************************** - -//****************************************************************************** -// INCLUDE FILES -//****************************************************************************** - -#include "cc3000_common.h" -#include "string.h" -#include "hci.h" -#include "evnt_handler.h" -#include "wlan.h" -#include "socket.h" -#include "netapp.h" -#include "ccspi.h" - - - -//***************************************************************************** -// COMMON DEFINES -//***************************************************************************** - -#define FLOW_CONTROL_EVENT_HANDLE_OFFSET (0) -#define FLOW_CONTROL_EVENT_BLOCK_MODE_OFFSET (1) -#define FLOW_CONTROL_EVENT_FREE_BUFFS_OFFSET (2) -#define FLOW_CONTROL_EVENT_SIZE (4) - -#define BSD_RSP_PARAMS_SOCKET_OFFSET (0) -#define BSD_RSP_PARAMS_STATUS_OFFSET (4) - -#define GET_HOST_BY_NAME_RETVAL_OFFSET (0) -#define GET_HOST_BY_NAME_ADDR_OFFSET (4) - -#define ACCEPT_SD_OFFSET (0) -#define ACCEPT_RETURN_STATUS_OFFSET (4) -#define ACCEPT_ADDRESS__OFFSET (8) - -#define SL_RECEIVE_SD_OFFSET (0) -#define SL_RECEIVE_NUM_BYTES_OFFSET (4) -#define SL_RECEIVE__FLAGS__OFFSET (8) - - -#define SELECT_STATUS_OFFSET (0) -#define SELECT_READFD_OFFSET (4) -#define SELECT_WRITEFD_OFFSET (8) -#define SELECT_EXFD_OFFSET (12) - - -#define NETAPP_IPCONFIG_IP_OFFSET (0) -#define NETAPP_IPCONFIG_SUBNET_OFFSET (4) -#define NETAPP_IPCONFIG_GW_OFFSET (8) -#define NETAPP_IPCONFIG_DHCP_OFFSET (12) -#define NETAPP_IPCONFIG_DNS_OFFSET (16) -#define NETAPP_IPCONFIG_MAC_OFFSET (20) -#define NETAPP_IPCONFIG_SSID_OFFSET (26) - -#define NETAPP_IPCONFIG_IP_LENGTH (4) -#define NETAPP_IPCONFIG_MAC_LENGTH (6) -#define NETAPP_IPCONFIG_SSID_LENGTH (32) - - -#define NETAPP_PING_PACKETS_SENT_OFFSET (0) -#define NETAPP_PING_PACKETS_RCVD_OFFSET (4) -#define NETAPP_PING_MIN_RTT_OFFSET (8) -#define NETAPP_PING_MAX_RTT_OFFSET (12) -#define NETAPP_PING_AVG_RTT_OFFSET (16) - -#define GET_SCAN_RESULTS_TABlE_COUNT_OFFSET (0) -#define GET_SCAN_RESULTS_SCANRESULT_STATUS_OFFSET (4) -#define GET_SCAN_RESULTS_ISVALID_TO_SSIDLEN_OFFSET (8) -#define GET_SCAN_RESULTS_FRAME_TIME_OFFSET (10) -#define GET_SCAN_RESULTS_SSID_MAC_LENGTH (38) - -#define GET_MSS_VAL_RETVAL_OFFSET (0) - -//***************************************************************************** -// GLOBAL VARAIABLES -//***************************************************************************** - -UINT32 socket_active_status = SOCKET_STATUS_INIT_VAL; - - -//***************************************************************************** -// Prototypes for the static functions -//***************************************************************************** - -static INT32 hci_event_unsol_flowcontrol_handler(CHAR *pEvent); - -static void update_socket_active_status(CHAR *resp_params); - - -//***************************************************************************** -// -//! hci_unsol_handle_patch_request -//! -//! @param event_hdr event header -//! -//! @return none -//! -//! @brief Handle unsolicited event from type patch request -// -//***************************************************************************** -void hci_unsol_handle_patch_request(CHAR *event_hdr) -{ - CHAR *params = (CHAR *)(event_hdr) + HCI_EVENT_HEADER_SIZE; - UINT32 ucLength = 0; - CHAR *patch; - - switch (*params) - { - case HCI_EVENT_PATCHES_DRV_REQ: - - if (tSLInformation.sDriverPatches) - { - patch = tSLInformation.sDriverPatches(&ucLength); - - if (patch) - { - hci_patch_send(HCI_EVENT_PATCHES_DRV_REQ, - tSLInformation.pucTxCommandBuffer, patch, ucLength); - return; - } - } - - // Send 0 length Patches response event - hci_patch_send(HCI_EVENT_PATCHES_DRV_REQ, - tSLInformation.pucTxCommandBuffer, 0, 0); - break; - - case HCI_EVENT_PATCHES_FW_REQ: - - if (tSLInformation.sFWPatches) - { - patch = tSLInformation.sFWPatches(&ucLength); - - // Build and send a patch - if (patch) - { - hci_patch_send(HCI_EVENT_PATCHES_FW_REQ, - tSLInformation.pucTxCommandBuffer, patch, ucLength); - return; - } - } - - // Send 0 length Patches response event - hci_patch_send(HCI_EVENT_PATCHES_FW_REQ, - tSLInformation.pucTxCommandBuffer, 0, 0); - break; - - case HCI_EVENT_PATCHES_BOOTLOAD_REQ: - - if (tSLInformation.sBootLoaderPatches) - { - patch = tSLInformation.sBootLoaderPatches(&ucLength); - - if (patch) - { - hci_patch_send(HCI_EVENT_PATCHES_BOOTLOAD_REQ, - tSLInformation.pucTxCommandBuffer, patch, ucLength); - return; - } - } - - // Send 0 length Patches response event - hci_patch_send(HCI_EVENT_PATCHES_BOOTLOAD_REQ, - tSLInformation.pucTxCommandBuffer, 0, 0); - break; - } -} - - - -//***************************************************************************** -// -//! hci_event_handler -//! -//! @param pRetParams incoming data buffer -//! @param from from information (in case of data received) -//! @param fromlen from information length (in case of data received) -//! -//! @return none -//! -//! @brief Parse the incoming events packets and issues corresponding -//! event handler from global array of handlers pointers -// -//***************************************************************************** - - -UINT8 * hci_event_handler(void *pRetParams, UINT8 *from, UINT8 *fromlen) -{ - UINT8 *pucReceivedData, ucArgsize; - UINT16 usLength; - UINT8 *pucReceivedParams; - UINT16 usReceivedEventOpcode = 0; - UINT32 retValue32; - UINT8 * RecvParams; - UINT8 *RetParams; - - - while (1) - { - if (tSLInformation.usEventOrDataReceived != 0) - { - pucReceivedData = (tSLInformation.pucReceivedData); - - if (*pucReceivedData == HCI_TYPE_EVNT) - { - // Event Received - STREAM_TO_UINT16((CHAR *)pucReceivedData, HCI_EVENT_OPCODE_OFFSET, - usReceivedEventOpcode); - pucReceivedParams = pucReceivedData + HCI_EVENT_HEADER_SIZE; - RecvParams = pucReceivedParams; - RetParams = pRetParams; - - // In case unsolicited event received - here the handling finished - if (hci_unsol_event_handler((CHAR *)pucReceivedData) == 0) - { - STREAM_TO_UINT8(pucReceivedData, HCI_DATA_LENGTH_OFFSET, usLength); - - switch(usReceivedEventOpcode) - { - case HCI_CMND_READ_BUFFER_SIZE: - { - STREAM_TO_UINT8((CHAR *)pucReceivedParams, 0, - tSLInformation.usNumberOfFreeBuffers); - STREAM_TO_UINT16((CHAR *)pucReceivedParams, 1, - tSLInformation.usSlBufferLength); - } - break; - - case HCI_CMND_WLAN_CONFIGURE_PATCH: - case HCI_NETAPP_DHCP: - case HCI_NETAPP_PING_SEND: - case HCI_NETAPP_PING_STOP: - case HCI_NETAPP_ARP_FLUSH: - case HCI_NETAPP_SET_DEBUG_LEVEL: - case HCI_NETAPP_SET_TIMERS: - case HCI_EVNT_NVMEM_READ: - case HCI_EVNT_NVMEM_CREATE_ENTRY: - case HCI_CMND_NVMEM_WRITE_PATCH: - case HCI_NETAPP_PING_REPORT: - case HCI_EVNT_MDNS_ADVERTISE: - - STREAM_TO_UINT8(pucReceivedData, HCI_EVENT_STATUS_OFFSET - ,*(UINT8 *)pRetParams); - break; - - case HCI_CMND_SETSOCKOPT: - case HCI_CMND_WLAN_CONNECT: - case HCI_CMND_WLAN_IOCTL_STATUSGET: - case HCI_EVNT_WLAN_IOCTL_ADD_PROFILE: - case HCI_CMND_WLAN_IOCTL_DEL_PROFILE: - case HCI_CMND_WLAN_IOCTL_SET_CONNECTION_POLICY: - case HCI_CMND_WLAN_IOCTL_SET_SCANPARAM: - case HCI_CMND_WLAN_IOCTL_SIMPLE_CONFIG_START: - case HCI_CMND_WLAN_IOCTL_SIMPLE_CONFIG_STOP: - case HCI_CMND_WLAN_IOCTL_SIMPLE_CONFIG_SET_PREFIX: - case HCI_CMND_EVENT_MASK: - case HCI_EVNT_WLAN_DISCONNECT: - case HCI_EVNT_SOCKET: - case HCI_EVNT_BIND: - case HCI_CMND_LISTEN: - case HCI_EVNT_CLOSE_SOCKET: - case HCI_EVNT_CONNECT: - case HCI_EVNT_NVMEM_WRITE: - - STREAM_TO_UINT32((CHAR *)pucReceivedParams,0 - ,*(UINT32 *)pRetParams); - break; - - case HCI_EVNT_READ_SP_VERSION: - - STREAM_TO_UINT8(pucReceivedData, HCI_EVENT_STATUS_OFFSET - ,*(UINT8 *)pRetParams); - pRetParams = ((CHAR *)pRetParams) + 1; - STREAM_TO_UINT32((CHAR *)pucReceivedParams, 0, retValue32); - UINT32_TO_STREAM((UINT8 *)pRetParams, retValue32); - break; - - case HCI_EVNT_BSD_GETHOSTBYNAME: - - STREAM_TO_UINT32((CHAR *)pucReceivedParams - ,GET_HOST_BY_NAME_RETVAL_OFFSET,*(UINT32 *)pRetParams); - pRetParams = ((CHAR *)pRetParams) + 4; - STREAM_TO_UINT32((CHAR *)pucReceivedParams - ,GET_HOST_BY_NAME_ADDR_OFFSET,*(UINT32 *)pRetParams); - break; - - case HCI_EVNT_GETMSSVALUE: - - STREAM_TO_UINT16((CHAR *)pucReceivedParams - ,GET_MSS_VAL_RETVAL_OFFSET,*(UINT16 *)pRetParams); - - break; - - case HCI_EVNT_ACCEPT: - { - STREAM_TO_UINT32((CHAR *)pucReceivedParams,ACCEPT_SD_OFFSET - ,*(UINT32 *)pRetParams); - pRetParams = ((CHAR *)pRetParams) + 4; - STREAM_TO_UINT32((CHAR *)pucReceivedParams - ,ACCEPT_RETURN_STATUS_OFFSET,*(UINT32 *)pRetParams); - pRetParams = ((CHAR *)pRetParams) + 4; - - //This argument returns in network order - memcpy((UINT8 *)pRetParams, - pucReceivedParams + ACCEPT_ADDRESS__OFFSET, sizeof(sockaddr)); - break; - } - - case HCI_EVNT_RECV: - case HCI_EVNT_RECVFROM: - { - STREAM_TO_UINT32((CHAR *)pucReceivedParams,SL_RECEIVE_SD_OFFSET ,*(UINT32 *)pRetParams); - pRetParams = ((CHAR *)pRetParams) + 4; - STREAM_TO_UINT32((CHAR *)pucReceivedParams,SL_RECEIVE_NUM_BYTES_OFFSET,*(UINT32 *)pRetParams); - pRetParams = ((CHAR *)pRetParams) + 4; - STREAM_TO_UINT32((CHAR *)pucReceivedParams,SL_RECEIVE__FLAGS__OFFSET,*(UINT32 *)pRetParams); - - if(((tBsdReadReturnParams *)pRetParams)->iNumberOfBytes == ERROR_SOCKET_INACTIVE) - { - set_socket_active_status(((tBsdReadReturnParams *)pRetParams)->iSocketDescriptor,SOCKET_STATUS_INACTIVE); - } - break; - } - - case HCI_EVNT_SEND: - case HCI_EVNT_SENDTO: - { - STREAM_TO_UINT32((CHAR *)pucReceivedParams,SL_RECEIVE_SD_OFFSET ,*(UINT32 *)pRetParams); - pRetParams = ((CHAR *)pRetParams) + 4; - STREAM_TO_UINT32((CHAR *)pucReceivedParams,SL_RECEIVE_NUM_BYTES_OFFSET,*(UINT32 *)pRetParams); - pRetParams = ((CHAR *)pRetParams) + 4; - - break; - } - - case HCI_EVNT_SELECT: - { - STREAM_TO_UINT32((CHAR *)pucReceivedParams,SELECT_STATUS_OFFSET,*(UINT32 *)pRetParams); - pRetParams = ((CHAR *)pRetParams) + 4; - STREAM_TO_UINT32((CHAR *)pucReceivedParams,SELECT_READFD_OFFSET,*(UINT32 *)pRetParams); - pRetParams = ((CHAR *)pRetParams) + 4; - STREAM_TO_UINT32((CHAR *)pucReceivedParams,SELECT_WRITEFD_OFFSET,*(UINT32 *)pRetParams); - pRetParams = ((CHAR *)pRetParams) + 4; - STREAM_TO_UINT32((CHAR *)pucReceivedParams,SELECT_EXFD_OFFSET,*(UINT32 *)pRetParams); - break; - } - - case HCI_CMND_GETSOCKOPT: - - STREAM_TO_UINT8(pucReceivedData, HCI_EVENT_STATUS_OFFSET,((tBsdGetSockOptReturnParams *)pRetParams)->iStatus); - //This argument returns in network order - memcpy((UINT8 *)pRetParams, pucReceivedParams, 4); - break; - - case HCI_CMND_WLAN_IOCTL_GET_SCAN_RESULTS: - - STREAM_TO_UINT32((CHAR *)pucReceivedParams,GET_SCAN_RESULTS_TABlE_COUNT_OFFSET,*(UINT32 *)pRetParams); - pRetParams = ((CHAR *)pRetParams) + 4; - STREAM_TO_UINT32((CHAR *)pucReceivedParams,GET_SCAN_RESULTS_SCANRESULT_STATUS_OFFSET,*(UINT32 *)pRetParams); - pRetParams = ((CHAR *)pRetParams) + 4; - STREAM_TO_UINT16((CHAR *)pucReceivedParams,GET_SCAN_RESULTS_ISVALID_TO_SSIDLEN_OFFSET,*(UINT32 *)pRetParams); - pRetParams = ((CHAR *)pRetParams) + 2; - STREAM_TO_UINT16((CHAR *)pucReceivedParams,GET_SCAN_RESULTS_FRAME_TIME_OFFSET,*(UINT32 *)pRetParams); - pRetParams = ((CHAR *)pRetParams) + 2; - memcpy((UINT8 *)pRetParams, (CHAR *)(pucReceivedParams + GET_SCAN_RESULTS_FRAME_TIME_OFFSET + 2), GET_SCAN_RESULTS_SSID_MAC_LENGTH); - break; - - case HCI_CMND_SIMPLE_LINK_START: - break; - - case HCI_NETAPP_IPCONFIG: - - //Read IP address - STREAM_TO_STREAM(RecvParams,RetParams,NETAPP_IPCONFIG_IP_LENGTH); - RecvParams += 4; - - //Read subnet - STREAM_TO_STREAM(RecvParams,RetParams,NETAPP_IPCONFIG_IP_LENGTH); - RecvParams += 4; - - //Read default GW - STREAM_TO_STREAM(RecvParams,RetParams,NETAPP_IPCONFIG_IP_LENGTH); - RecvParams += 4; - - //Read DHCP server - STREAM_TO_STREAM(RecvParams,RetParams,NETAPP_IPCONFIG_IP_LENGTH); - RecvParams += 4; - - //Read DNS server - STREAM_TO_STREAM(RecvParams,RetParams,NETAPP_IPCONFIG_IP_LENGTH); - RecvParams += 4; - - //Read Mac address - STREAM_TO_STREAM(RecvParams,RetParams,NETAPP_IPCONFIG_MAC_LENGTH); - RecvParams += 6; - - //Read SSID - STREAM_TO_STREAM(RecvParams,RetParams,NETAPP_IPCONFIG_SSID_LENGTH); - - } - } - - if (usReceivedEventOpcode == tSLInformation.usRxEventOpcode) - { - tSLInformation.usRxEventOpcode = 0; - } - } - else - { - pucReceivedParams = pucReceivedData; - STREAM_TO_UINT8((CHAR *)pucReceivedData, HCI_PACKET_ARGSIZE_OFFSET, ucArgsize); - - STREAM_TO_UINT16((CHAR *)pucReceivedData, HCI_PACKET_LENGTH_OFFSET, usLength); - - // Data received: note that the only case where from and from length - // are not null is in recv from, so fill the args accordingly - if (from) - { - STREAM_TO_UINT32((CHAR *)(pucReceivedData + HCI_DATA_HEADER_SIZE), BSD_RECV_FROM_FROMLEN_OFFSET, *(UINT32 *)fromlen); - memcpy(from, (pucReceivedData + HCI_DATA_HEADER_SIZE + BSD_RECV_FROM_FROM_OFFSET) ,*fromlen); - } - - memcpy(pRetParams, pucReceivedParams + HCI_DATA_HEADER_SIZE + ucArgsize, - usLength - ucArgsize); - - tSLInformation.usRxDataPending = 0; - } - - tSLInformation.usEventOrDataReceived = 0; - - SpiResumeSpi(); - - // Since we are going to TX - we need to handle this event after the - // ResumeSPi since we need interrupts - if ((*pucReceivedData == HCI_TYPE_EVNT) && - (usReceivedEventOpcode == HCI_EVNT_PATCHES_REQ)) - { - hci_unsol_handle_patch_request((CHAR *)pucReceivedData); - } - - if ((tSLInformation.usRxEventOpcode == 0) && (tSLInformation.usRxDataPending == 0)) - { - return NULL; - } - } - } - -} - -//***************************************************************************** -// -//! hci_unsol_event_handler -//! -//! @param event_hdr event header -//! -//! @return 1 if event supported and handled -//! 0 if event is not supported -//! -//! @brief Handle unsolicited events -// -//***************************************************************************** -INT32 hci_unsol_event_handler(CHAR *event_hdr) -{ - CHAR * data = NULL; - INT32 event_type; - UINT32 NumberOfReleasedPackets; - UINT32 NumberOfSentPackets; - - STREAM_TO_UINT16(event_hdr, HCI_EVENT_OPCODE_OFFSET,event_type); - - if (event_type & HCI_EVNT_UNSOL_BASE) - { - switch(event_type) - { - - case HCI_EVNT_DATA_UNSOL_FREE_BUFF: - { - hci_event_unsol_flowcontrol_handler(event_hdr); - - NumberOfReleasedPackets = tSLInformation.NumberOfReleasedPackets; - NumberOfSentPackets = tSLInformation.NumberOfSentPackets; - - if (NumberOfReleasedPackets == NumberOfSentPackets) - { - if (tSLInformation.InformHostOnTxComplete) - { - tSLInformation.sWlanCB(HCI_EVENT_CC3000_CAN_SHUT_DOWN, NULL, 0); - } - } - return 1; - - } - } - } - - if(event_type & HCI_EVNT_WLAN_UNSOL_BASE) - { - switch(event_type) - { - case HCI_EVNT_WLAN_KEEPALIVE: - case HCI_EVNT_WLAN_UNSOL_CONNECT: - case HCI_EVNT_WLAN_UNSOL_DISCONNECT: - case HCI_EVNT_WLAN_UNSOL_INIT: - case HCI_EVNT_WLAN_ASYNC_SIMPLE_CONFIG_DONE: - - if( tSLInformation.sWlanCB ) - { - tSLInformation.sWlanCB(event_type, 0, 0); - } - break; - - case HCI_EVNT_WLAN_UNSOL_DHCP: - { - UINT8 params[NETAPP_IPCONFIG_MAC_OFFSET + 1]; // extra byte is for the status - UINT8 *recParams = params; - - data = (CHAR*)(event_hdr) + HCI_EVENT_HEADER_SIZE; - - //Read IP address - STREAM_TO_STREAM(data,recParams,NETAPP_IPCONFIG_IP_LENGTH); - data += 4; - //Read subnet - STREAM_TO_STREAM(data,recParams,NETAPP_IPCONFIG_IP_LENGTH); - data += 4; - //Read default GW - STREAM_TO_STREAM(data,recParams,NETAPP_IPCONFIG_IP_LENGTH); - data += 4; - //Read DHCP server - STREAM_TO_STREAM(data,recParams,NETAPP_IPCONFIG_IP_LENGTH); - data += 4; - //Read DNS server - STREAM_TO_STREAM(data,recParams,NETAPP_IPCONFIG_IP_LENGTH); - // read the status - STREAM_TO_UINT8(event_hdr, HCI_EVENT_STATUS_OFFSET, *recParams); - - - if( tSLInformation.sWlanCB ) - { - tSLInformation.sWlanCB(event_type, (CHAR *)params, sizeof(params)); - } - } - break; - - case HCI_EVNT_WLAN_ASYNC_PING_REPORT: - { - netapp_pingreport_args_t params; - data = (CHAR*)(event_hdr) + HCI_EVENT_HEADER_SIZE; - STREAM_TO_UINT32(data, NETAPP_PING_PACKETS_SENT_OFFSET, params.packets_sent); - STREAM_TO_UINT32(data, NETAPP_PING_PACKETS_RCVD_OFFSET, params.packets_received); - STREAM_TO_UINT32(data, NETAPP_PING_MIN_RTT_OFFSET, params.min_round_time); - STREAM_TO_UINT32(data, NETAPP_PING_MAX_RTT_OFFSET, params.max_round_time); - STREAM_TO_UINT32(data, NETAPP_PING_AVG_RTT_OFFSET, params.avg_round_time); - - if( tSLInformation.sWlanCB ) - { - tSLInformation.sWlanCB(event_type, (CHAR *)¶ms, sizeof(params)); - } - } - break; - case HCI_EVNT_BSD_TCP_CLOSE_WAIT: - { - data = (CHAR *)(event_hdr) + HCI_EVENT_HEADER_SIZE; - if( tSLInformation.sWlanCB ) - { - //data[0] represents the socket id, for which FIN was received by remote. - //Upon receiving this event, the user can close the socket, or else the - //socket will be closded after inacvitity timeout (by default 60 seconds) - tSLInformation.sWlanCB(event_type, data, 1); - } - } - break; - - //'default' case which means "event not supported" - default: - return (0); - } - return(1); - } - - if ((event_type == HCI_EVNT_SEND) || (event_type == HCI_EVNT_SENDTO) - || (event_type == HCI_EVNT_WRITE)) - { - CHAR *pArg; - INT32 status; - - pArg = M_BSD_RESP_PARAMS_OFFSET(event_hdr); - STREAM_TO_UINT32(pArg, BSD_RSP_PARAMS_STATUS_OFFSET,status); - - if (ERROR_SOCKET_INACTIVE == status) - { - // The only synchronous event that can come from SL device in form of - // command complete is "Command Complete" on data sent, in case SL device - // was unable to transmit - STREAM_TO_UINT8(event_hdr, HCI_EVENT_STATUS_OFFSET, tSLInformation.slTransmitDataError); - update_socket_active_status(M_BSD_RESP_PARAMS_OFFSET(event_hdr)); - - return (1); - } - else - return (0); - } - - //handle a case where unsolicited event arrived, but was not handled by any of the cases above - if ((event_type != tSLInformation.usRxEventOpcode) && (event_type != HCI_EVNT_PATCHES_REQ)) - { - return(1); - } - - return(0); -} - -//***************************************************************************** -// -//! hci_unsolicited_event_handler -//! -//! @param None -//! -//! @return ESUCCESS if successful, EFAIL if an error occurred -//! -//! @brief Parse the incoming unsolicited event packets and issues -//! corresponding event handler. -// -//***************************************************************************** -INT32 hci_unsolicited_event_handler(void) -{ - UINT32 res = 0; - UINT8 *pucReceivedData; - - if (tSLInformation.usEventOrDataReceived != 0) - { - pucReceivedData = (tSLInformation.pucReceivedData); - - if (*pucReceivedData == HCI_TYPE_EVNT) - { - - // In case unsolicited event received - here the handling finished - if (hci_unsol_event_handler((CHAR *)pucReceivedData) == 1) - { - - // There was an unsolicited event received - we can release the buffer - // and clean the event received - tSLInformation.usEventOrDataReceived = 0; - - res = 1; - SpiResumeSpi(); - } - } - } - - return res; -} - -//***************************************************************************** -// -//! set_socket_active_status -//! -//! @param Sd -//! @param Status -//! @return none -//! -//! @brief Check if the socket ID and status are valid and set -//! accordingly the global socket status -// -//***************************************************************************** -void set_socket_active_status(INT32 Sd, INT32 Status) -{ - if(M_IS_VALID_SD(Sd) && M_IS_VALID_STATUS(Status)) - { - socket_active_status &= ~(1 << Sd); /* clean socket's mask */ - socket_active_status |= (Status << Sd); /* set new socket's mask */ - } -} - - -//***************************************************************************** -// -//! hci_event_unsol_flowcontrol_handler -//! -//! @param pEvent pointer to the string contains parameters for IPERF -//! @return ESUCCESS if successful, EFAIL if an error occurred -//! -//! @brief Called in case unsolicited event from type -//! HCI_EVNT_DATA_UNSOL_FREE_BUFF has received. -//! Keep track on the number of packets transmitted and update the -//! number of free buffer in the SL device. -// -//***************************************************************************** -INT32 hci_event_unsol_flowcontrol_handler(CHAR *pEvent) -{ - - INT32 temp, value; - UINT16 i; - UINT16 pusNumberOfHandles=0; - CHAR *pReadPayload; - - STREAM_TO_UINT16((CHAR *)pEvent,HCI_EVENT_HEADER_SIZE,pusNumberOfHandles); - pReadPayload = ((CHAR *)pEvent + - HCI_EVENT_HEADER_SIZE + sizeof(pusNumberOfHandles)); - temp = 0; - - for(i = 0; i < pusNumberOfHandles ; i++) - { - STREAM_TO_UINT16(pReadPayload, FLOW_CONTROL_EVENT_FREE_BUFFS_OFFSET, value); - temp += value; - pReadPayload += FLOW_CONTROL_EVENT_SIZE; - } - - tSLInformation.usNumberOfFreeBuffers += temp; - tSLInformation.NumberOfReleasedPackets += temp; - - return(ESUCCESS); -} - -//***************************************************************************** -// -//! get_socket_active_status -//! -//! @param Sd Socket IS -//! @return Current status of the socket. -//! -//! @brief Retrieve socket status -// -//***************************************************************************** - -INT32 get_socket_active_status(INT32 Sd) -{ - if(M_IS_VALID_SD(Sd)) - { - return (socket_active_status & (1 << Sd)) ? SOCKET_STATUS_INACTIVE : SOCKET_STATUS_ACTIVE; - } - return SOCKET_STATUS_INACTIVE; -} - -//***************************************************************************** -// -//! update_socket_active_status -//! -//! @param resp_params Socket IS -//! @return Current status of the socket. -//! -//! @brief Retrieve socket status -// -//***************************************************************************** -void update_socket_active_status(CHAR *resp_params) -{ - INT32 status, sd; - - STREAM_TO_UINT32(resp_params, BSD_RSP_PARAMS_SOCKET_OFFSET,sd); - STREAM_TO_UINT32(resp_params, BSD_RSP_PARAMS_STATUS_OFFSET,status); - - if(ERROR_SOCKET_INACTIVE == status) - { - set_socket_active_status(sd, SOCKET_STATUS_INACTIVE); - } -} - - -//***************************************************************************** -// -//! SimpleLinkWaitEvent -//! -//! @param usOpcode command operation code -//! @param pRetParams command return parameters -//! -//! @return none -//! -//! @brief Wait for event, pass it to the hci_event_handler and -//! update the event opcode in a global variable. -// -//***************************************************************************** - -void SimpleLinkWaitEvent(UINT16 usOpcode, void *pRetParams) -{ - // In the blocking implementation the control to caller will be returned only - // after the end of current transaction - tSLInformation.usRxEventOpcode = usOpcode; - hci_event_handler(pRetParams, 0, 0); -} - -//***************************************************************************** -// -//! SimpleLinkWaitData -//! -//! @param pBuf data buffer -//! @param from from information -//! @param fromlen from information length -//! -//! @return none -//! -//! @brief Wait for data, pass it to the hci_event_handler -//! and update in a global variable that there is -//! data to read. -// -//***************************************************************************** - -void SimpleLinkWaitData(UINT8 *pBuf, UINT8 *from, UINT8 *fromlen) -{ - // In the blocking implementation the control to caller will be returned only - // after the end of current transaction, i.e. only after data will be received - tSLInformation.usRxDataPending = 1; - hci_event_handler(pBuf, from, fromlen); -} - -//***************************************************************************** -// -// Close the Doxygen group. -//! @} -// -//***************************************************************************** diff --git a/drivers/cc3000/src/hci.c b/drivers/cc3000/src/hci.c deleted file mode 100644 index 4391692b8b..0000000000 --- a/drivers/cc3000/src/hci.c +++ /dev/null @@ -1,225 +0,0 @@ -/***************************************************************************** -* -* hci.c - CC3000 Host Driver Implementation. -* Copyright (C) 2011 Texas Instruments Incorporated - http://www.ti.com/ -* -* Redistribution and use in source and binary forms, with or without -* modification, are permitted provided that the following conditions -* are met: -* -* Redistributions of source code must retain the above copyright -* notice, this list of conditions and the following disclaimer. -* -* Redistributions in binary form must reproduce the above copyright -* notice, this list of conditions and the following disclaimer in the -* documentation and/or other materials provided with the -* distribution. -* -* Neither the name of Texas Instruments Incorporated nor the names of -* its contributors may be used to endorse or promote products derived -* from this software without specific prior written permission. -* -* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -* -*****************************************************************************/ - -//***************************************************************************** -// -//! \addtogroup hci_app -//! @{ -// -//***************************************************************************** - -#include -#include "cc3000_common.h" -#include "hci.h" -#include "ccspi.h" -#include "evnt_handler.h" -#include "wlan.h" - -#define SL_PATCH_PORTION_SIZE (1000) - - -//***************************************************************************** -// -//! hci_command_send -//! -//! @param usOpcode command operation code -//! @param pucBuff pointer to the command's arguments buffer -//! @param ucArgsLength length of the arguments -//! -//! @return none -//! -//! @brief Initiate an HCI command. -// -//***************************************************************************** -UINT16 hci_command_send(UINT16 usOpcode, UINT8 *pucBuff, UINT8 ucArgsLength) -{ - UINT8 *stream; - - stream = (pucBuff + SPI_HEADER_SIZE); - - UINT8_TO_STREAM(stream, HCI_TYPE_CMND); - stream = UINT16_TO_STREAM(stream, usOpcode); - UINT8_TO_STREAM(stream, ucArgsLength); - - //Update the opcode of the event we will be waiting for - SpiWrite(pucBuff, ucArgsLength + SIMPLE_LINK_HCI_CMND_HEADER_SIZE); - - return(0); -} - -//***************************************************************************** -// -//! hci_data_send -//! -//! @param usOpcode command operation code -//! @param ucArgs pointer to the command's arguments buffer -//! @param usArgsLength length of the arguments -//! @param ucTail pointer to the data buffer -//! @param usTailLength buffer length -//! -//! @return none -//! -//! @brief Initiate an HCI data write operation -// -//***************************************************************************** -INT32 hci_data_send(UINT8 ucOpcode, - UINT8 *ucArgs, - UINT16 usArgsLength, - UINT16 usDataLength, - const UINT8 *ucTail, - UINT16 usTailLength) -{ - UINT8 *stream; - - stream = ((ucArgs) + SPI_HEADER_SIZE); - - UINT8_TO_STREAM(stream, HCI_TYPE_DATA); - UINT8_TO_STREAM(stream, ucOpcode); - UINT8_TO_STREAM(stream, usArgsLength); - stream = UINT16_TO_STREAM(stream, usArgsLength + usDataLength + usTailLength); - - // Send the packet over the SPI - SpiWrite(ucArgs, SIMPLE_LINK_HCI_DATA_HEADER_SIZE + usArgsLength + usDataLength + usTailLength); - - return(ESUCCESS); -} - - -//***************************************************************************** -// -//! hci_data_command_send -//! -//! @param usOpcode command operation code -//! @param pucBuff pointer to the data buffer -//! @param ucArgsLength arguments length -//! @param ucDataLength data length -//! -//! @return none -//! -//! @brief Prepeare HCI header and initiate an HCI data write operation -// -//***************************************************************************** -void hci_data_command_send(UINT16 usOpcode, UINT8 *pucBuff, UINT8 ucArgsLength,UINT16 ucDataLength) -{ - UINT8 *stream = (pucBuff + SPI_HEADER_SIZE); - - UINT8_TO_STREAM(stream, HCI_TYPE_DATA); - UINT8_TO_STREAM(stream, usOpcode); - UINT8_TO_STREAM(stream, ucArgsLength); - stream = UINT16_TO_STREAM(stream, ucArgsLength + ucDataLength); - - // Send the command over SPI on data channel - SpiWrite(pucBuff, ucArgsLength + ucDataLength + SIMPLE_LINK_HCI_DATA_CMND_HEADER_SIZE); - - return; -} - -//***************************************************************************** -// -//! hci_patch_send -//! -//! @param usOpcode command operation code -//! @param pucBuff pointer to the command's arguments buffer -//! @param patch pointer to patch content buffer -//! @param usDataLength data length -//! -//! @return none -//! -//! @brief Prepeare HCI header and initiate an HCI patch write operation -// -//***************************************************************************** -void hci_patch_send(UINT8 ucOpcode, UINT8 *pucBuff, CHAR *patch, UINT16 usDataLength) -{ - UINT8 *data_ptr = (pucBuff + SPI_HEADER_SIZE); - UINT16 usTransLength; - UINT8 *stream = (pucBuff + SPI_HEADER_SIZE); - - UINT8_TO_STREAM(stream, HCI_TYPE_PATCH); - UINT8_TO_STREAM(stream, ucOpcode); - stream = UINT16_TO_STREAM(stream, usDataLength + SIMPLE_LINK_HCI_PATCH_HEADER_SIZE); - - if (usDataLength <= SL_PATCH_PORTION_SIZE) - { - UINT16_TO_STREAM(stream, usDataLength); - stream = UINT16_TO_STREAM(stream, usDataLength); - memcpy((pucBuff + SPI_HEADER_SIZE) + HCI_PATCH_HEADER_SIZE, patch, usDataLength); - - // Update the opcode of the event we will be waiting for - SpiWrite(pucBuff, usDataLength + HCI_PATCH_HEADER_SIZE); - } - else - { - - usTransLength = (usDataLength/SL_PATCH_PORTION_SIZE); - UINT16_TO_STREAM(stream, usDataLength + SIMPLE_LINK_HCI_PATCH_HEADER_SIZE + usTransLength*SIMPLE_LINK_HCI_PATCH_HEADER_SIZE); - stream = UINT16_TO_STREAM(stream, SL_PATCH_PORTION_SIZE); - memcpy(pucBuff + SPI_HEADER_SIZE + HCI_PATCH_HEADER_SIZE, patch, SL_PATCH_PORTION_SIZE); - usDataLength -= SL_PATCH_PORTION_SIZE; - patch += SL_PATCH_PORTION_SIZE; - - // Update the opcode of the event we will be waiting for - SpiWrite(pucBuff, SL_PATCH_PORTION_SIZE + HCI_PATCH_HEADER_SIZE); - - while (usDataLength) - { - if (usDataLength <= SL_PATCH_PORTION_SIZE) - { - usTransLength = usDataLength; - usDataLength = 0; - - } - else - { - usTransLength = SL_PATCH_PORTION_SIZE; - usDataLength -= usTransLength; - } - - *(UINT16 *)data_ptr = usTransLength; - memcpy(data_ptr + SIMPLE_LINK_HCI_PATCH_HEADER_SIZE, patch, usTransLength); - patch += usTransLength; - - // Update the opcode of the event we will be waiting for - SpiWrite((UINT8 *)data_ptr, usTransLength + sizeof(usTransLength)); - } - } -} - -//***************************************************************************** -// -// Close the Doxygen group. -//! @} -// -// -//***************************************************************************** diff --git a/drivers/cc3000/src/inet_ntop.c b/drivers/cc3000/src/inet_ntop.c deleted file mode 100644 index 83242efa00..0000000000 --- a/drivers/cc3000/src/inet_ntop.c +++ /dev/null @@ -1,200 +0,0 @@ -/* - * Copyright (C) 1996-2001 Internet Software Consortium. - * - * Permission to use, copy, modify, and distribute this software for any - * purpose with or without fee is hereby granted, provided that the above - * copyright notice and this permission notice appear in all copies. - * - * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM - * DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL - * INTERNET SOFTWARE CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT, - * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING - * FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, - * NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION - * WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - */ - -#include -#include "cc3000_common.h" -#include "socket.h" -#include "inet_ntop.h" - -// We can't include stdio.h because it defines _types_fd_set, but we -// need to use the CC3000 version of this type. So we must provide -// our own declaration of snprintf. Grrr. -int snprintf(char *str, size_t size, const char *fmt, ...); - -#define IN6ADDRSZ 16 -#define INADDRSZ 4 -#define INT16SZ 2 - -#define ENOSPC (28) -#define EAFNOSUPPORT (106) -#define SET_ERRNO(err) (CC3000_EXPORT(errno)=-err) - -/* - * Format an IPv4 address, more or less like inet_ntoa(). - * - * Returns `dst' (as a const) - * Note: - * - uses no statics - * - takes a unsigned char* not an in_addr as input - */ -static char *inet_ntop4 (const unsigned char *src, char *dst, size_t size) -{ - size_t len; - char tmp[sizeof "255.255.255.255"]; - - tmp[0] = '\0'; - (void)snprintf(tmp, sizeof(tmp), "%d.%d.%d.%d", - ((int)((unsigned char)src[3])) & 0xff, - ((int)((unsigned char)src[2])) & 0xff, - ((int)((unsigned char)src[1])) & 0xff, - ((int)((unsigned char)src[0])) & 0xff); - - len = strlen(tmp); - if(len == 0 || len >= size) - { - SET_ERRNO(ENOSPC); - return (NULL); - } - strcpy(dst, tmp); - return dst; -} - -#ifdef ENABLE_IPV6 -/* - * Convert IPv6 binary address into presentation (printable) format. - */ -static char *inet_ntop6 (const unsigned char *src, char *dst, size_t size) -{ - /* - * Note that int32_t and int16_t need only be "at least" large enough - * to contain a value of the specified size. On some systems, like - * Crays, there is no such thing as an integer variable with 16 bits. - * Keep this in mind if you think this function should have been coded - * to use pointer overlays. All the world's not a VAX. - */ - char tmp[sizeof("ffff:ffff:ffff:ffff:ffff:ffff:255.255.255.255")]; - char *tp; - struct { - long base; - long len; - } best, cur; - unsigned long words[IN6ADDRSZ / INT16SZ]; - int i; - - /* Preprocess: - * Copy the input (bytewise) array into a wordwise array. - * Find the longest run of 0x00's in src[] for :: shorthanding. - */ - memset(words, '\0', sizeof(words)); - for (i = 0; i < IN6ADDRSZ; i++) - words[i/2] |= (src[i] << ((1 - (i % 2)) << 3)); - - best.base = -1; - cur.base = -1; - best.len = 0; - cur.len = 0; - - for (i = 0; i < (IN6ADDRSZ / INT16SZ); i++) - { - if(words[i] == 0) - { - if(cur.base == -1) - cur.base = i, cur.len = 1; - else - cur.len++; - } - else if(cur.base != -1) - { - if(best.base == -1 || cur.len > best.len) - best = cur; - cur.base = -1; - } - } - if((cur.base != -1) && (best.base == -1 || cur.len > best.len)) - best = cur; - if(best.base != -1 && best.len < 2) - best.base = -1; - - /* Format the result. - */ - tp = tmp; - for (i = 0; i < (IN6ADDRSZ / INT16SZ); i++) - { - /* Are we inside the best run of 0x00's? - */ - if(best.base != -1 && i >= best.base && i < (best.base + best.len)) - { - if(i == best.base) - *tp++ = ':'; - continue; - } - - /* Are we following an initial run of 0x00s or any real hex? - */ - if(i != 0) - *tp++ = ':'; - - /* Is this address an encapsulated IPv4? - */ - if(i == 6 && best.base == 0 && - (best.len == 6 || (best.len == 5 && words[5] == 0xffff))) - { - if(!inet_ntop4(src+12, tp, sizeof(tmp) - (tp - tmp))) - { - SET_ERRNO(ENOSPC); - return (NULL); - } - tp += strlen(tp); - break; - } - tp += snprintf(tp, 5, "%lx", words[i]); - } - - /* Was it a trailing run of 0x00's? - */ - if(best.base != -1 && (best.base + best.len) == (IN6ADDRSZ / INT16SZ)) - *tp++ = ':'; - *tp++ = '\0'; - - /* Check for overflow, copy, and we're done. - */ - if((size_t)(tp - tmp) > size) - { - SET_ERRNO(ENOSPC); - return (NULL); - } - strcpy(dst, tmp); - return dst; -} -#endif /* ENABLE_IPV6 */ - -/* - * Convert a network format address to presentation format. - * - * Returns pointer to presentation format address (`buf'). - * Returns NULL on error and errno set with the specific - * error, EAFNOSUPPORT or ENOSPC. - * - * On Windows we store the error in the thread errno, not - * in the winsock error code. This is to avoid loosing the - * actual last winsock error. So use macro ERRNO to fetch the - * errno this funtion sets when returning NULL, not SOCKERRNO. - */ -char *inet_ntop(int af, const void *src, char *buf, size_t size) -{ - switch (af) { - case AF_INET: - return inet_ntop4((const unsigned char*)src, buf, size); -#ifdef ENABLE_IPV6 - case AF_INET6: - return inet_ntop6((const unsigned char*)src, buf, size); -#endif - default: - SET_ERRNO(EAFNOSUPPORT); - return NULL; - } -} diff --git a/drivers/cc3000/src/inet_pton.c b/drivers/cc3000/src/inet_pton.c deleted file mode 100644 index 5f5ae5f9d7..0000000000 --- a/drivers/cc3000/src/inet_pton.c +++ /dev/null @@ -1,216 +0,0 @@ -/* This is from the BIND 4.9.4 release, modified to compile by itself */ - -/* Copyright (c) 1996 by Internet Software Consortium. - * - * Permission to use, copy, modify, and distribute this software for any - * purpose with or without fee is hereby granted, provided that the above - * copyright notice and this permission notice appear in all copies. - * - * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS - * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES - * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE - * CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL - * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR - * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS - * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS - * SOFTWARE. - */ - -#include -#include "cc3000_common.h" -#include "socket.h" -#include "inet_pton.h" - -#define IN6ADDRSZ 16 -#define INADDRSZ 4 -#define INT16SZ 2 - -static int inet_pton4(const char *src, unsigned char *dst); -#ifdef ENABLE_IPV6 -static int inet_pton6(const char *src, unsigned char *dst); -#endif - -#define EAFNOSUPPORT (106) -#define SET_ERRNO(err) (CC3000_EXPORT(errno)=-err) - -/* int - * inet_pton(af, src, dst) - * convert from presentation format (which usually means ASCII printable) - * to network format (which is usually some kind of binary format). - * return: - * 1 if the address was valid for the specified address family - * 0 if the address wasn't valid (`dst' is untouched in this case) - * -1 if some other error occurred (`dst' is untouched in this case, too) - * notice: - * On Windows we store the error in the thread errno, not - * in the winsock error code. This is to avoid loosing the - * actual last winsock error. So use macro ERRNO to fetch the - * errno this funtion sets when returning (-1), not SOCKERRNO. - * author: - * Paul Vixie, 1996. - */ -int inet_pton(int af, const char *src, void *dst) -{ - switch (af) { - case AF_INET: - return (inet_pton4(src, (unsigned char *)dst)); -#ifdef ENABLE_IPV6 - case AF_INET6: - return (inet_pton6(src, (unsigned char *)dst)); -#endif - default: - SET_ERRNO(EAFNOSUPPORT); - return (-1); - } - /* NOTREACHED */ -} - -/* int - * inet_pton4(src, dst) - * like inet_aton() but without all the hexadecimal and shorthand. - * return: - * 1 if `src' is a valid dotted quad, else 0. - * notice: - * does not touch `dst' unless it's returning 1. - * author: - * Paul Vixie, 1996. - */ -static int inet_pton4(const char *src, unsigned char *dst) -{ - static const char digits[] = "0123456789"; - int saw_digit, octets, ch; - unsigned char tmp[INADDRSZ], *tp; - - saw_digit = 0; - octets = 0; - tp = tmp; - *tp = 0; - while((ch = *src++) != '\0') { - const char *pch; - - if((pch = strchr(digits, ch)) != NULL) { - unsigned int val = *tp * 10 + (unsigned int)(pch - digits); - - if(saw_digit && *tp == 0) - return (0); - if(val > 255) - return (0); - *tp = (unsigned char)val; - if(! saw_digit) { - if(++octets > 4) - return (0); - saw_digit = 1; - } - } - else if(ch == '.' && saw_digit) { - if(octets == 4) - return (0); - *++tp = 0; - saw_digit = 0; - } - else - return (0); - } - if(octets < 4) - return (0); - memcpy(dst, tmp, INADDRSZ); - return (1); -} - -#ifdef ENABLE_IPV6 -/* int - * inet_pton6(src, dst) - * convert presentation level address to network order binary form. - * return: - * 1 if `src' is a valid [RFC1884 2.2] address, else 0. - * notice: - * (1) does not touch `dst' unless it's returning 1. - * (2) :: in a full address is silently ignored. - * credit: - * inspired by Mark Andrews. - * author: - * Paul Vixie, 1996. - */ -static int inet_pton6(const char *src, unsigned char *dst) -{ - static const char xdigits_l[] = "0123456789abcdef", - xdigits_u[] = "0123456789ABCDEF"; - unsigned char tmp[IN6ADDRSZ], *tp, *endp, *colonp; - const char *xdigits, *curtok; - int ch, saw_xdigit; - unsigned int val; - - memset((tp = tmp), 0, IN6ADDRSZ); - endp = tp + IN6ADDRSZ; - colonp = NULL; - /* Leading :: requires some special handling. */ - if(*src == ':') - if(*++src != ':') - return (0); - curtok = src; - saw_xdigit = 0; - val = 0; - while((ch = *src++) != '\0') { - const char *pch; - - if((pch = strchr((xdigits = xdigits_l), ch)) == NULL) - pch = strchr((xdigits = xdigits_u), ch); - if(pch != NULL) { - val <<= 4; - val |= (pch - xdigits); - if(++saw_xdigit > 4) - return (0); - continue; - } - if(ch == ':') { - curtok = src; - if(!saw_xdigit) { - if(colonp) - return (0); - colonp = tp; - continue; - } - if(tp + INT16SZ > endp) - return (0); - *tp++ = (unsigned char) (val >> 8) & 0xff; - *tp++ = (unsigned char) val & 0xff; - saw_xdigit = 0; - val = 0; - continue; - } - if(ch == '.' && ((tp + INADDRSZ) <= endp) && - inet_pton4(curtok, tp) > 0) { - tp += INADDRSZ; - saw_xdigit = 0; - break; /* '\0' was seen by inet_pton4(). */ - } - return (0); - } - if(saw_xdigit) { - if(tp + INT16SZ > endp) - return (0); - *tp++ = (unsigned char) (val >> 8) & 0xff; - *tp++ = (unsigned char) val & 0xff; - } - if(colonp != NULL) { - /* - * Since some memmove()'s erroneously fail to handle - * overlapping regions, we'll do the shift by hand. - */ - const long n = tp - colonp; - long i; - - if(tp == endp) - return (0); - for (i = 1; i <= n; i++) { - endp[- i] = colonp[n - i]; - colonp[n - i] = 0; - } - tp = endp; - } - if(tp != endp) - return (0); - memcpy(dst, tmp, IN6ADDRSZ); - return (1); -} -#endif /* ENABLE_IPV6 */ diff --git a/drivers/cc3000/src/netapp.c b/drivers/cc3000/src/netapp.c deleted file mode 100644 index a6f60feda0..0000000000 --- a/drivers/cc3000/src/netapp.c +++ /dev/null @@ -1,459 +0,0 @@ -/***************************************************************************** -* -* netapp.c - CC3000 Host Driver Implementation. -* Copyright (C) 2011 Texas Instruments Incorporated - http://www.ti.com/ -* -* Redistribution and use in source and binary forms, with or without -* modification, are permitted provided that the following conditions -* are met: -* -* Redistributions of source code must retain the above copyright -* notice, this list of conditions and the following disclaimer. -* -* Redistributions in binary form must reproduce the above copyright -* notice, this list of conditions and the following disclaimer in the -* documentation and/or other materials provided with the -* distribution. -* -* Neither the name of Texas Instruments Incorporated nor the names of -* its contributors may be used to endorse or promote products derived -* from this software without specific prior written permission. -* -* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -* -*****************************************************************************/ - -#include -#include "netapp.h" -#include "hci.h" -#include "socket.h" -#include "evnt_handler.h" -#include "nvmem.h" - -#define MIN_TIMER_VAL_SECONDS 10 -#define MIN_TIMER_SET(t) if ((0 != t) && (t < MIN_TIMER_VAL_SECONDS)) \ - { \ - t = MIN_TIMER_VAL_SECONDS; \ - } - - -#define NETAPP_DHCP_PARAMS_LEN (20) -#define NETAPP_SET_TIMER_PARAMS_LEN (20) -#define NETAPP_SET_DEBUG_LEVEL_PARAMS_LEN (4) -#define NETAPP_PING_SEND_PARAMS_LEN (16) - - -//***************************************************************************** -// -//! netapp_config_mac_adrress -//! -//! @param mac device mac address, 6 bytes. Saved: yes -//! -//! @return return on success 0, otherwise error. -//! -//! @brief Configure device MAC address and store it in NVMEM. -//! The value of the MAC address configured through the API will -//! be stored in CC3000 non volatile memory, thus preserved -//! over resets. -// -//***************************************************************************** -INT32 netapp_config_mac_adrress(UINT8 * mac) -{ - return nvmem_set_mac_address(mac); -} - -//***************************************************************************** -// -//! netapp_dhcp -//! -//! @param aucIP device mac address, 6 bytes. Saved: yes -//! @param aucSubnetMask device mac address, 6 bytes. Saved: yes -//! @param aucDefaultGateway device mac address, 6 bytes. Saved: yes -//! @param aucDNSServer device mac address, 6 bytes. Saved: yes -//! -//! @return return on success 0, otherwise error. -//! -//! @brief netapp_dhcp is used to configure the network interface, -//! static or dynamic (DHCP).\n In order to activate DHCP mode, -//! aucIP, aucSubnetMask, aucDefaultGateway must be 0. -//! The default mode of CC3000 is DHCP mode. -//! Note that the configuration is saved in non volatile memory -//! and thus preserved over resets. -//! -//! @note If the mode is altered a reset of CC3000 device is required -//! in order to apply changes.\nAlso note that asynchronous event -//! of DHCP_EVENT, which is generated when an IP address is -//! allocated either by the DHCP server or due to static -//! allocation is generated only upon a connection to the -//! AP was established. -//! -//***************************************************************************** -INT32 netapp_dhcp(UINT32 *aucIP, UINT32 *aucSubnetMask,UINT32 *aucDefaultGateway, UINT32 *aucDNSServer) -{ - INT8 scRet; - UINT8 *ptr; - UINT8 *args; - - scRet = EFAIL; - ptr = tSLInformation.pucTxCommandBuffer; - args = (ptr + HEADERS_SIZE_CMD); - - // Fill in temporary command buffer - ARRAY_TO_STREAM(args,aucIP,4); - ARRAY_TO_STREAM(args,aucSubnetMask,4); - ARRAY_TO_STREAM(args,aucDefaultGateway,4); - args = UINT32_TO_STREAM(args, 0); - ARRAY_TO_STREAM(args,aucDNSServer,4); - - // Initiate a HCI command - hci_command_send(HCI_NETAPP_DHCP, ptr, NETAPP_DHCP_PARAMS_LEN); - - // Wait for command complete event - SimpleLinkWaitEvent(HCI_NETAPP_DHCP, &scRet); - - return(scRet); -} - - -//***************************************************************************** -// -//! netapp_timeout_values -//! -//! @param aucDHCP DHCP lease time request, also impact -//! the DHCP renew timeout. Range: [0-0xffffffff] seconds, -//! 0 or 0xffffffff == infinity lease timeout. -//! Resolution:10 seconds. Influence: only after -//! reconnecting to the AP. -//! Minimal bound value: MIN_TIMER_VAL_SECONDS - 10 seconds. -//! The parameter is saved into the CC3000 NVMEM. -//! The default value on CC3000 is 14400 seconds. -//! -//! @param aucARP ARP refresh timeout, if ARP entry is not updated by -//! incoming packet, the ARP entry will be deleted by -//! the end of the timeout. -//! Range: [0-0xffffffff] seconds, 0 == infinity ARP timeout -//! Resolution: 10 seconds. Influence: on runtime. -//! Minimal bound value: MIN_TIMER_VAL_SECONDS - 10 seconds -//! The parameter is saved into the CC3000 NVMEM. -//! The default value on CC3000 is 3600 seconds. -//! -//! @param aucKeepalive Keepalive event sent by the end of keepalive timeout -//! Range: [0-0xffffffff] seconds, 0 == infinity timeout -//! Resolution: 10 seconds. -//! Influence: on runtime. -//! Minimal bound value: MIN_TIMER_VAL_SECONDS - 10 sec -//! The parameter is saved into the CC3000 NVMEM. -//! The default value on CC3000 is 10 seconds. -//! -//! @param aucInactivity Socket inactivity timeout, socket timeout is -//! refreshed by incoming or outgoing packet, by the -//! end of the socket timeout the socket will be closed -//! Range: [0-0xffffffff] sec, 0 == infinity timeout. -//! Resolution: 10 seconds. Influence: on runtime. -//! Minimal bound value: MIN_TIMER_VAL_SECONDS - 10 sec -//! The parameter is saved into the CC3000 NVMEM. -//! The default value on CC3000 is 60 seconds. -//! -//! @return return on success 0, otherwise error. -//! -//! @brief Set new timeout values. Function set new timeout values for: -//! DHCP lease timeout, ARP refresh timeout, keepalive event -//! timeout and socket inactivity timeout -//! -//! @note If a parameter set to non zero value which is less than 10s, -//! it will be set automatically to 10s. -//! -//***************************************************************************** - -#ifndef CC3000_TINY_DRIVER -INT32 netapp_timeout_values(UINT32 *aucDHCP, UINT32 *aucARP,UINT32 *aucKeepalive, UINT32 *aucInactivity) -{ - INT8 scRet; - UINT8 *ptr; - UINT8 *args; - - scRet = EFAIL; - ptr = tSLInformation.pucTxCommandBuffer; - args = (ptr + HEADERS_SIZE_CMD); - - // Set minimal values of timers - MIN_TIMER_SET(*aucDHCP) - MIN_TIMER_SET(*aucARP) - MIN_TIMER_SET(*aucKeepalive) - MIN_TIMER_SET(*aucInactivity) - - // Fill in temporary command buffer - args = UINT32_TO_STREAM(args, *aucDHCP); - args = UINT32_TO_STREAM(args, *aucARP); - args = UINT32_TO_STREAM(args, *aucKeepalive); - args = UINT32_TO_STREAM(args, *aucInactivity); - - // Initiate a HCI command - hci_command_send(HCI_NETAPP_SET_TIMERS, ptr, NETAPP_SET_TIMER_PARAMS_LEN); - - // Wait for command complete event - SimpleLinkWaitEvent(HCI_NETAPP_SET_TIMERS, &scRet); - - return(scRet); -} -#endif - - -//***************************************************************************** -// -//! netapp_ping_send -//! -//! @param ip destination IP address -//! @param pingAttempts number of echo requests to send -//! @param pingSize send buffer size which may be up to 1400 bytes -//! @param pingTimeout Time to wait for a response,in milliseconds. -//! -//! @return return on success 0, otherwise error. -//! -//! @brief send ICMP ECHO_REQUEST to network hosts -//! -//! @note If an operation finished successfully asynchronous ping report -//! event will be generated. The report structure is as defined -//! by structure netapp_pingreport_args_t. -//! -//! @warning Calling this function while a previous Ping Requests are in -//! progress will stop the previous ping request. -//***************************************************************************** - -#ifndef CC3000_TINY_DRIVER -INT32 - netapp_ping_send(UINT32 *ip, UINT32 ulPingAttempts, UINT32 ulPingSize, UINT32 ulPingTimeout) -{ - INT8 scRet; - UINT8 *ptr, *args; - - scRet = EFAIL; - ptr = tSLInformation.pucTxCommandBuffer; - args = (ptr + HEADERS_SIZE_CMD); - - // Fill in temporary command buffer - args = UINT32_TO_STREAM(args, *ip); - args = UINT32_TO_STREAM(args, ulPingAttempts); - args = UINT32_TO_STREAM(args, ulPingSize); - args = UINT32_TO_STREAM(args, ulPingTimeout); - - // Initiate a HCI command - hci_command_send(HCI_NETAPP_PING_SEND, ptr, NETAPP_PING_SEND_PARAMS_LEN); - - // Wait for command complete event - SimpleLinkWaitEvent(HCI_NETAPP_PING_SEND, &scRet); - - return(scRet); -} -#endif - -//***************************************************************************** -// -//! netapp_ping_report -//! -//! @param none -//! -//! @return none -//! -//! @brief Request for ping status. This API triggers the CC3000 to send -//! asynchronous events: HCI_EVNT_WLAN_ASYNC_PING_REPORT. -//! This event will carry the report structure: -//! netapp_pingreport_args_t. This structure is filled in with ping -//! results up till point of triggering API. -//! netapp_pingreport_args_t:\n packets_sent - echo sent, -//! packets_received - echo reply, min_round_time - minimum -//! round time, max_round_time - max round time, -//! avg_round_time - average round time -//! -//! @note When a ping operation is not active, the returned structure -//! fields are 0. -//! -//***************************************************************************** - - -#ifndef CC3000_TINY_DRIVER -void netapp_ping_report() -{ - UINT8 *ptr; - ptr = tSLInformation.pucTxCommandBuffer; - INT8 scRet; - - scRet = EFAIL; - - // Initiate a HCI command - hci_command_send(HCI_NETAPP_PING_REPORT, ptr, 0); - - // Wait for command complete event - SimpleLinkWaitEvent(HCI_NETAPP_PING_REPORT, &scRet); -} -#endif - -//***************************************************************************** -// -//! netapp_ping_stop -//! -//! @param none -//! -//! @return On success, zero is returned. On error, -1 is returned. -//! -//! @brief Stop any ping request. -//! -//! -//***************************************************************************** - -#ifndef CC3000_TINY_DRIVER -INT32 netapp_ping_stop() -{ - INT8 scRet; - UINT8 *ptr; - - scRet = EFAIL; - ptr = tSLInformation.pucTxCommandBuffer; - - // Initiate a HCI command - hci_command_send(HCI_NETAPP_PING_STOP, ptr, 0); - - // Wait for command complete event - SimpleLinkWaitEvent(HCI_NETAPP_PING_STOP, &scRet); - - return(scRet); -} -#endif - -//***************************************************************************** -// -//! netapp_ipconfig -//! -//! @param[out] ipconfig This argument is a pointer to a -//! tNetappIpconfigRetArgs structure. This structure is -//! filled in with the network interface configuration. -//! tNetappIpconfigRetArgs:\n aucIP - ip address, -//! aucSubnetMask - mask, aucDefaultGateway - default -//! gateway address, aucDHCPServer - dhcp server address -//! aucDNSServer - dns server address, uaMacAddr - mac -//! address, uaSSID - connected AP ssid -//! -//! @return none -//! -//! @brief Obtain the CC3000 Network interface information. -//! Note that the information is available only after the WLAN -//! connection was established. Calling this function before -//! associated, will cause non-defined values to be returned. -//! -//! @note The function is useful for figuring out the IP Configuration of -//! the device when DHCP is used and for figuring out the SSID of -//! the Wireless network the device is associated with. -//! -//***************************************************************************** - -#ifndef CC3000_TINY_DRIVER -void netapp_ipconfig( tNetappIpconfigRetArgs * ipconfig ) -{ - UINT8 *ptr; - - ptr = tSLInformation.pucTxCommandBuffer; - - // Initiate a HCI command - hci_command_send(HCI_NETAPP_IPCONFIG, ptr, 0); - - // Wait for command complete event - SimpleLinkWaitEvent(HCI_NETAPP_IPCONFIG, ipconfig ); - -} -#else -void netapp_ipconfig( tNetappIpconfigRetArgs * ipconfig ) -{ - -} -#endif - -//***************************************************************************** -// -//! netapp_arp_flush -//! -//! @param none -//! -//! @return none -//! -//! @brief Flushes ARP table -//! -//***************************************************************************** - -#ifndef CC3000_TINY_DRIVER -INT32 netapp_arp_flush(void) -{ - INT8 scRet; - UINT8 *ptr; - - scRet = EFAIL; - ptr = tSLInformation.pucTxCommandBuffer; - - // Initiate a HCI command - hci_command_send(HCI_NETAPP_ARP_FLUSH, ptr, 0); - - // Wait for command complete event - SimpleLinkWaitEvent(HCI_NETAPP_ARP_FLUSH, &scRet); - - return(scRet); -} -#endif - -//***************************************************************************** -// -//! netapp_set_debug_level -//! -//! @param[in] level debug level. Bitwise [0-8], -//! 0(disable)or 1(enable).\n Bitwise map: 0 - Critical -//! message, 1 information message, 2 - core messages, 3 - -//! HCI messages, 4 - Network stack messages, 5 - wlan -//! messages, 6 - wlan driver messages, 7 - epprom messages, -//! 8 - general messages. Default: 0x13f. Saved: no -//! -//! @return On success, zero is returned. On error, -1 is returned -//! -//! @brief Debug messages sent via the UART debug channel, this function -//! enable/disable the debug level -//! -//***************************************************************************** - - -#ifndef CC3000_TINY_DRIVER -INT32 netapp_set_debug_level(UINT32 ulLevel) -{ - INT8 scRet; - UINT8 *ptr, *args; - - scRet = EFAIL; - ptr = tSLInformation.pucTxCommandBuffer; - args = (ptr + HEADERS_SIZE_CMD); - - // - // Fill in temporary command buffer - // - args = UINT32_TO_STREAM(args, ulLevel); - - - // - // Initiate a HCI command - // - hci_command_send(HCI_NETAPP_SET_DEBUG_LEVEL, ptr, NETAPP_SET_DEBUG_LEVEL_PARAMS_LEN); - - // - // Wait for command complete event - // - SimpleLinkWaitEvent(HCI_NETAPP_SET_DEBUG_LEVEL, &scRet); - - return(scRet); - -} -#endif diff --git a/drivers/cc3000/src/nvmem.c b/drivers/cc3000/src/nvmem.c deleted file mode 100644 index c6e170a746..0000000000 --- a/drivers/cc3000/src/nvmem.c +++ /dev/null @@ -1,334 +0,0 @@ -/***************************************************************************** -* -* nvmem.c - CC3000 Host Driver Implementation. -* Copyright (C) 2011 Texas Instruments Incorporated - http://www.ti.com/ -* -* Redistribution and use in source and binary forms, with or without -* modification, are permitted provided that the following conditions -* are met: -* -* Redistributions of source code must retain the above copyright -* notice, this list of conditions and the following disclaimer. -* -* Redistributions in binary form must reproduce the above copyright -* notice, this list of conditions and the following disclaimer in the -* documentation and/or other materials provided with the -* distribution. -* -* Neither the name of Texas Instruments Incorporated nor the names of -* its contributors may be used to endorse or promote products derived -* from this software without specific prior written permission. -* -* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -* -*****************************************************************************/ - -//***************************************************************************** -// -//! \addtogroup nvmem_api -//! @{ -// -//***************************************************************************** - -#include -#include "nvmem.h" -#include "hci.h" -#include "socket.h" -#include "evnt_handler.h" - -//***************************************************************************** -// -// Prototypes for the structures for APIs. -// -//***************************************************************************** - -#define NVMEM_READ_PARAMS_LEN (12) -#define NVMEM_CREATE_PARAMS_LEN (8) -#define NVMEM_WRITE_PARAMS_LEN (16) - -//***************************************************************************** -// -//! nvmem_read -//! -//! @param ulFileId nvmem file id:\n -//! NVMEM_NVS_FILEID, NVMEM_NVS_SHADOW_FILEID, -//! NVMEM_WLAN_CONFIG_FILEID, NVMEM_WLAN_CONFIG_SHADOW_FILEID, -//! NVMEM_WLAN_DRIVER_SP_FILEID, NVMEM_WLAN_FW_SP_FILEID, -//! NVMEM_MAC_FILEID, NVMEM_FRONTEND_VARS_FILEID, -//! NVMEM_IP_CONFIG_FILEID, NVMEM_IP_CONFIG_SHADOW_FILEID, -//! NVMEM_BOOTLOADER_SP_FILEID, NVMEM_RM_FILEID, -//! and user files 12-15. -//! @param ulLength number of bytes to read -//! @param ulOffset ulOffset in file from where to read -//! @param buff output buffer pointer -//! -//! @return on success 0, error otherwise. -//! -//! @brief Reads data from the file referred by the ulFileId parameter. -//! Reads data from file ulOffset till length. Err if the file can't -//! be used, is invalid, or if the read is out of bounds. -//! -//***************************************************************************** - -INT32 nvmem_read(UINT32 ulFileId, UINT32 ulLength, UINT32 ulOffset, UINT8 *buff) -{ - UINT8 ucStatus = 0xFF; - UINT8 *ptr; - UINT8 *args; - - ptr = tSLInformation.pucTxCommandBuffer; - args = (ptr + HEADERS_SIZE_CMD); - - // Fill in HCI packet structure - args = UINT32_TO_STREAM(args, ulFileId); - args = UINT32_TO_STREAM(args, ulLength); - args = UINT32_TO_STREAM(args, ulOffset); - - // Initiate a HCI command - hci_command_send(HCI_CMND_NVMEM_READ, ptr, NVMEM_READ_PARAMS_LEN); - SimpleLinkWaitEvent(HCI_CMND_NVMEM_READ, &ucStatus); - - // In case there is data - read it - even if an error code is returned - // Note: It is the user responsibility to ignore the data in case of an error code - - // Wait for the data in a synchronous way. Here we assume that the buffer is - // big enough to store also parameters of nvmem - - SimpleLinkWaitData(buff, 0, 0); - - return(ucStatus); -} - -//***************************************************************************** -// -//! nvmem_write -//! -//! @param ulFileId nvmem file id:\n -//! NVMEM_WLAN_DRIVER_SP_FILEID, NVMEM_WLAN_FW_SP_FILEID, -//! NVMEM_MAC_FILEID, NVMEM_BOOTLOADER_SP_FILEID, -//! and user files 12-15. -//! @param ulLength number of bytes to write -//! @param ulEntryOffset offset in file to start write operation from -//! @param buff data to write -//! -//! @return on success 0, error otherwise. -//! -//! @brief Write data to nvmem. -//! writes data to file referred by the ulFileId parameter. -//! Writes data to file ulOffset till ulLength.The file id will be -//! marked invalid till the write is done. The file entry doesn't -//! need to be valid - only allocated. -//! -//***************************************************************************** - -INT32 nvmem_write(UINT32 ulFileId, UINT32 ulLength, UINT32 ulEntryOffset, UINT8 *buff) -{ - INT32 iRes; - UINT8 *ptr; - UINT8 *args; - - iRes = EFAIL; - - ptr = tSLInformation.pucTxCommandBuffer; - args = (ptr + SPI_HEADER_SIZE + HCI_DATA_CMD_HEADER_SIZE); - - // Fill in HCI packet structure - args = UINT32_TO_STREAM(args, ulFileId); - args = UINT32_TO_STREAM(args, 12); - args = UINT32_TO_STREAM(args, ulLength); - args = UINT32_TO_STREAM(args, ulEntryOffset); - - memcpy((ptr + SPI_HEADER_SIZE + HCI_DATA_CMD_HEADER_SIZE + - NVMEM_WRITE_PARAMS_LEN),buff,ulLength); - - // Initiate a HCI command but it will come on data channel - hci_data_command_send(HCI_CMND_NVMEM_WRITE, ptr, NVMEM_WRITE_PARAMS_LEN, - ulLength); - - SimpleLinkWaitEvent(HCI_EVNT_NVMEM_WRITE, &iRes); - - return(iRes); -} - - -//***************************************************************************** -// -//! nvmem_set_mac_address -//! -//! @param mac mac address to be set -//! -//! @return on success 0, error otherwise. -//! -//! @brief Write MAC address to EEPROM. -//! mac address as appears over the air (OUI first) -//! -//***************************************************************************** - -UINT8 nvmem_set_mac_address(UINT8 *mac) -{ - return nvmem_write(NVMEM_MAC_FILEID, MAC_ADDR_LEN, 0, mac); -} - -//***************************************************************************** -// -//! nvmem_get_mac_address -//! -//! @param[out] mac mac address -//! -//! @return on success 0, error otherwise. -//! -//! @brief Read MAC address from EEPROM. -//! mac address as appears over the air (OUI first) -//! -//***************************************************************************** - -UINT8 nvmem_get_mac_address(UINT8 *mac) -{ - return nvmem_read(NVMEM_MAC_FILEID, MAC_ADDR_LEN, 0, mac); -} - -//***************************************************************************** -// -//! nvmem_write_patch -//! -//! @param ulFileId nvmem file id:\n -//! NVMEM_WLAN_DRIVER_SP_FILEID, NVMEM_WLAN_FW_SP_FILEID, -//! @param spLength number of bytes to write -//! @param spData SP data to write -//! -//! @return on success 0, error otherwise. -//! -//! @brief program a patch to a specific file ID. -//! The SP data is assumed to be organized in 2-dimensional. -//! Each line is SP_PORTION_SIZE bytes long. Actual programming is -//! applied in SP_PORTION_SIZE bytes portions. -//! -//***************************************************************************** - -UINT8 nvmem_write_patch(UINT32 ulFileId, UINT32 spLength, const UINT8 *spData) -{ - UINT8 status = 0; - UINT16 offset = 0; - UINT8* spDataPtr = (UINT8*)spData; - - while ((status == 0) && (spLength >= SP_PORTION_SIZE)) - { - status = nvmem_write(ulFileId, SP_PORTION_SIZE, offset, spDataPtr); - offset += SP_PORTION_SIZE; - spLength -= SP_PORTION_SIZE; - spDataPtr += SP_PORTION_SIZE; - } - - if (status !=0) - { - // NVMEM error occurred - return status; - } - - if (spLength != 0) - { - // if reached here, a reminder is left - status = nvmem_write(ulFileId, spLength, offset, spDataPtr); - } - - return status; -} - -//***************************************************************************** -// -//! nvmem_read_sp_version -//! -//! @param[out] patchVer first number indicates package ID and the second -//! number indicates package build number -//! -//! @return on success 0, error otherwise. -//! -//! @brief Read patch version. read package version (WiFi FW patch, -//! driver-supplicant-NS patch, bootloader patch) -//! -//***************************************************************************** - -#ifndef CC3000_TINY_DRIVER -UINT8 nvmem_read_sp_version(UINT8* patchVer) -{ - UINT8 *ptr; - // 1st byte is the status and the rest is the SP version - UINT8 retBuf[5]; - - ptr = tSLInformation.pucTxCommandBuffer; - - // Initiate a HCI command, no args are required - hci_command_send(HCI_CMND_READ_SP_VERSION, ptr, 0); - SimpleLinkWaitEvent(HCI_CMND_READ_SP_VERSION, retBuf); - - // package ID - *patchVer = retBuf[3]; - // package build number - *(patchVer+1) = retBuf[4]; - - return(retBuf[0]); -} -#endif - -//***************************************************************************** -// -//! nvmem_create_entry -//! -//! @param ulFileId nvmem file Id:\n -//! * NVMEM_AES128_KEY_FILEID: 12 -//! * NVMEM_SHARED_MEM_FILEID: 13 -//! * and fileIDs 14 and 15 -//! @param ulNewLen entry ulLength -//! -//! @return on success 0, error otherwise. -//! -//! @brief Create new file entry and allocate space on the NVMEM. -//! Applies only to user files. -//! Modify the size of file. -//! If the entry is unallocated - allocate it to size -//! ulNewLen (marked invalid). -//! If it is allocated then deallocate it first. -//! To just mark the file as invalid without resizing - -//! set ulNewLen=0. -//! -//***************************************************************************** - -INT32 nvmem_create_entry(UINT32 ulFileId, UINT32 ulNewLen) -{ - UINT8 *ptr; - UINT8 *args; - UINT8 retval; - - ptr = tSLInformation.pucTxCommandBuffer; - args = (ptr + HEADERS_SIZE_CMD); - - // Fill in HCI packet structure - args = UINT32_TO_STREAM(args, ulFileId); - args = UINT32_TO_STREAM(args, ulNewLen); - - // Initiate a HCI command - hci_command_send(HCI_CMND_NVMEM_CREATE_ENTRY,ptr, NVMEM_CREATE_PARAMS_LEN); - - SimpleLinkWaitEvent(HCI_CMND_NVMEM_CREATE_ENTRY, &retval); - - return(retval); -} - - - -//***************************************************************************** -// -// Close the Doxygen group. -//! @} -// -//***************************************************************************** diff --git a/drivers/cc3000/src/patch.c b/drivers/cc3000/src/patch.c deleted file mode 100644 index 227be3c9f2..0000000000 --- a/drivers/cc3000/src/patch.c +++ /dev/null @@ -1,117 +0,0 @@ -/***************************************************************************** - * - * {PatchProgrammer_DR_Patch.c} - * - * Burn Patches to EEPROM - * - * Copyright (C) 2013 Texas Instruments Incorporated - http://www.ti.com/ - * ALL RIGHTS RESERVED - * - *****************************************************************************/ -// -// Service Pack version P1.13.7.15.28 - Driver patches -// This file contains the CC3K driver and firmware patches -// From CC3000-FRAM-PATCH V:1.13.7 15-MAY-2014 - -unsigned short fw_length = 5700; -unsigned short drv_length = 8024; - -const unsigned char wlan_drv_patch[8024] = { 0x00, 0x01, 0x00, 0x00, 0x50, 0x1F, 0x00, 0x00, 0xF0, 0x03, 0x18, 0x00, 0xE4, 0x62, 0x08, 0x00, 0x96, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 , -0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0x7A, 0x63, 0x08, 0x00, 0x96, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 , -0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0x10, 0x64, 0x08, 0x00, 0x96, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0x20, 0x0C, 0x49, 0x08, 0x60, 0x0C, 0x48, 0x19, 0x30, 0xF7, 0x46, 0x30, 0xB5, 0x05, 0x1C, 0xAC, 0x69, 0x68, 0x68, 0x5F, 0x30, 0x09, 0xD1, 0x60, 0x6B, 0x0C, 0x38, 0x01, 0x21, 0x8E, 0x46, 0x06, 0x49, 0xFE, 0x44, 0x08, 0x47, 0x00, 0x20, 0x60, 0x63, 0xAC, 0x69, 0x6C, 0x60, 0x04, 0x48, 0x5B, 0x30, 0x30, 0xBD, 0x40, 0x3B, 0x08, 0x00, 0x49, 0xD0, 0x01, 0x00, 0x09, 0xEA, 0x02, 0x00, 0x91, 0xE1, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 , -0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xA6, 0x64, 0x08, 0x00, 0x96, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 , -0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0x3C, 0x65, 0x08, 0x00, 0x96, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xF0, 0xB5, 0x85, 0xB0, 0x05, 0x1C, 0xA8, 0x88, 0x00, 0x90, 0x28, 0x89, 0x01, 0x90, 0xE9, 0x68, 0x02, 0x91, 0x28, 0x7C, 0x03, 0x90, 0x2A, 0x6A, 0x00, 0x20, 0x17, 0x56, 0x68, 0x60, 0x00, 0x29, 0x4C, 0xD0, 0x00, 0x2F, 0x4A, 0xDC , -0xCA, 0x49, 0x0C, 0x1C, 0x08, 0x26, 0x04, 0x90, 0x21, 0x88, 0x00, 0x98, 0x81, 0x42, 0x0C, 0xD1, 0x62, 0x88, 0x01, 0x98, 0x82, 0x42, 0x08, 0xD1, 0x46, 0x20, 0x02, 0x5D, 0x03, 0x98, 0x82, 0x42, 0x03, 0xD1, 0x0E, 0x20, 0x00, 0x57, 0xB8, 0x42, 0x0A, 0xD0, 0x46, 0x20, 0x00, 0x5D, 0x11, 0x28, 0x22, 0xD1, 0x00, 0x98, 0x81, 0x42, 0x1F, 0xD1, 0x0E, 0x20, 0x00, 0x57, 0xFF, 0xFF, 0xD2, 0x65, 0x08, 0x00, 0x96, 0x00, 0x00, 0x00, 0xB8, 0x42, 0x1B, 0xD1, 0x04, 0x20, 0x02, 0x1C, 0x02, 0x98, 0xB9, 0x49, 0x01, 0x23, 0x9E, 0x46, 0xEC, 0x4B, 0xFE, 0x44, 0x18, 0x47, 0x00, 0x28, 0x17, 0xD0, 0x20, 0x1D, 0x02, 0x99, 0x04, 0x22, 0x01, 0x23, 0x9E, 0x46, 0xE7, 0x4B, 0xFE, 0x44, 0x18, 0x47, 0x00, 0x28, 0x0D, 0xD0, 0x46, 0x20, 0x00, 0x5D, 0x11, 0x28, 0x09, 0xD0, 0xA0, 0x6D, 0x00, 0x28, 0x06, 0xD0, 0xAC, 0x34, 0x04, 0x98, 0x01, 0x30, 0x04, 0x90, 0x01, 0x3E, 0xC1, 0xD1, 0x07, 0xE0, 0x04, 0x98, 0x00, 0x06, 0x00, 0x0E , -0xAC, 0x21, 0x41, 0x43, 0xA6, 0x48, 0x40, 0x18, 0x68, 0x60, 0xA6, 0x48, 0xAD, 0x30, 0x05, 0xB0, 0xF0, 0xBD, 0x00, 0xB5, 0xC2, 0x68, 0x90, 0x69, 0x02, 0x21, 0x01, 0x23, 0x9E, 0x46, 0xA2, 0x4B, 0xFE, 0x44, 0x18, 0x47, 0xA2, 0x48, 0x61, 0x30, 0x00, 0xBD, 0x01, 0x79, 0x0B, 0x29, 0x03, 0xD0, 0x89, 0x00, 0x9F, 0x4A, 0x51, 0x5A, 0x01, 0xE0, 0x01, 0x21, 0x49, 0x02, 0x41, 0x60, 0x9D, 0x48, 0x0D, 0x30, 0xF7, 0x46, 0x01, 0x1C, 0xFF, 0xFF, 0x68, 0x66, 0x08, 0x00, 0x96, 0x00, 0x00, 0x00, 0x9C, 0x48, 0x02, 0x68, 0x9C, 0x48, 0x01, 0x2A, 0x01, 0xD1, 0x25, 0x30, 0xF7, 0x46, 0x9B, 0x4A, 0x12, 0x68, 0x4A, 0x60, 0x19, 0x30, 0xF7, 0x46, 0x00, 0x21, 0x41, 0x60, 0x99, 0x48, 0x98, 0x49, 0x08, 0x18, 0xF7, 0x46, 0x00, 0x21, 0x41, 0x60, 0x97, 0x48, 0xE7, 0x49, 0x08, 0x18, 0xF7, 0x46, 0xFF, 0xB5, 0x46, 0x69, 0x40, 0x68, 0x01, 0x90, 0x94, 0x49, 0x0A, 0x7C, 0x9A, 0x4F, 0x01, 0x2A, 0x63, 0xD0, 0x09, 0x7C, 0x03, 0x29 , -0x60, 0xD0, 0x91, 0x4A, 0x92, 0x4B, 0x00, 0x21, 0x02, 0x91, 0x59, 0x56, 0x24, 0x23, 0x59, 0x43, 0x53, 0x18, 0x03, 0x93, 0x01, 0x28, 0x17, 0xD1, 0x8A, 0x18, 0x04, 0x23, 0x6C, 0x46, 0x8C, 0x49, 0x15, 0x79, 0x08, 0x78, 0xC0, 0x43, 0x28, 0x43, 0x20, 0x70, 0x01, 0x32, 0x01, 0x31, 0x01, 0x34, 0x01, 0x3B, 0xF5, 0xD1, 0x31, 0x1D, 0x68, 0x46, 0x04, 0x22, 0x01, 0x23, 0x9E, 0x46, 0xA9, 0x4B, 0xFE, 0x44, 0x18, 0x47, 0x00, 0x28, 0x40, 0xD0, 0x35, 0x1D, 0x82, 0x48, 0x00, 0x78, 0xFF, 0x28, 0xFF, 0xFF, 0xFE, 0x66, 0x08, 0x00, 0x96, 0x00, 0x00, 0x00, 0x11, 0xD0, 0x00, 0x28, 0x0F, 0xD0, 0x03, 0x98, 0x01, 0x1D, 0x28, 0x1C, 0x01, 0x24, 0xA6, 0x46, 0x7E, 0x4A, 0xFE, 0x44, 0x10, 0x47, 0x00, 0x28, 0x05, 0xD1, 0x7A, 0x48, 0xA6, 0x46, 0x7B, 0x49, 0xFE, 0x44, 0x08, 0x47, 0x05, 0xE0, 0x28, 0x1C, 0x01, 0x21, 0x8E, 0x46, 0x78, 0x49, 0xFE, 0x44, 0x08, 0x47, 0x01, 0x99, 0x01, 0x29, 0x01, 0xD1, 0x00, 0x28, 0x1E, 0xD1 , -0x01, 0x99, 0x5F, 0x31, 0x01, 0xD0, 0x00, 0x28, 0x0F, 0xD1, 0xA8, 0x20, 0x81, 0x5D, 0x00, 0x29, 0x08, 0xD0, 0x49, 0x1E, 0x81, 0x55, 0x80, 0x5D, 0x00, 0x28, 0x09, 0xD1, 0x38, 0x1C, 0xFF, 0x30, 0x08, 0x30, 0x11, 0xE0, 0x03, 0x21, 0x02, 0x91, 0x00, 0xE0, 0xA8, 0x20, 0x02, 0x99, 0x81, 0x55, 0x38, 0x1C, 0xFF, 0x30, 0x16, 0x30, 0x07, 0xE0, 0x01, 0x98, 0x01, 0x28, 0x02, 0xD1, 0x38, 0x1C, 0xA3, 0x30, 0x01, 0xE0, 0x38, 0x1C, 0x9F, 0x30, 0x00, 0x90, 0xFF, 0xBD, 0x00, 0xB5, 0x02, 0x1C, 0x10, 0x6A, 0xD1, 0x69, 0x52, 0x69, 0xC3, 0x69, 0x5A, 0x60, 0xFF, 0xFF, 0x94, 0x67, 0x08, 0x00, 0x96, 0x00, 0x00, 0x00, 0x01, 0x22, 0x96, 0x46, 0x5E, 0x4A, 0xFE, 0x44, 0x10, 0x47, 0x5E, 0x48, 0xFF, 0x30, 0x6E, 0x30, 0x00, 0xBD, 0x10, 0xB5, 0x0A, 0x1C, 0x41, 0x69, 0x00, 0x6A, 0x93, 0x69, 0xDB, 0x69, 0x58, 0x60, 0x90, 0x69, 0x01, 0x24, 0xA6, 0x46, 0x56, 0x4A, 0xFE, 0x44, 0x10, 0x47, 0xA6, 0x46, 0x56, 0x48, 0xFE, 0x44 , -0x00, 0x47, 0x55, 0x48, 0xFF, 0x30, 0xB6, 0x30, 0x10, 0xBD, 0x70, 0xB5, 0x05, 0x1C, 0x6E, 0x69, 0x53, 0x48, 0x02, 0x68, 0x5C, 0x21, 0x88, 0x5D, 0x04, 0x28, 0x15, 0xD1, 0x07, 0x20, 0x88, 0x55, 0x10, 0x0B, 0x11, 0xD2, 0x01, 0x24, 0xA6, 0x46, 0x4E, 0x48, 0xFE, 0x44, 0x00, 0x47, 0x00, 0x28, 0x0A, 0xD0, 0x47, 0x21, 0x89, 0x57, 0xC1, 0x60, 0x11, 0x21, 0xC9, 0x02, 0x00, 0x22, 0x04, 0x23, 0xA6, 0x46, 0xE8, 0x4C, 0xFE, 0x44, 0x20, 0x47, 0x01, 0x20, 0x68, 0x60, 0x43, 0x48, 0xED, 0x49, 0x08, 0x18, 0x70, 0xBD, 0x70, 0xB5, 0x05, 0x1C, 0xAE, 0x69, 0x9C, 0x20, 0x80, 0x19, 0x4B, 0x21, 0x89, 0x00, 0x01, 0x24, 0xFF, 0xFF, 0x2A, 0x68, 0x08, 0x00, 0x96, 0x00, 0x00, 0x00, 0xA6, 0x46, 0xE8, 0x4A, 0xFE, 0x44, 0x10, 0x47, 0x5C, 0x21, 0x88, 0x5D, 0x07, 0x28, 0x01, 0xD1, 0x09, 0x20, 0x00, 0xE0, 0x05, 0x20, 0xAA, 0x69, 0x88, 0x54, 0x30, 0x1C, 0xA6, 0x46, 0xE9, 0x49, 0xFE, 0x44, 0x08, 0x47, 0x68, 0x60, 0xE8, 0x48 , -0x4D, 0x30, 0x70, 0xBD, 0xF0, 0xB5, 0x41, 0x68, 0x82, 0x68, 0x88, 0x23, 0x5E, 0x18, 0x37, 0x88, 0x0B, 0x6F, 0x00, 0x2B, 0x01, 0xD1, 0x00, 0x2F, 0x10, 0xD1, 0x06, 0x2F, 0x02, 0xDD, 0x00, 0x21, 0xC9, 0x43, 0x07, 0xE0, 0x33, 0x88, 0x9B, 0x00, 0xC9, 0x18, 0x0A, 0x67, 0x31, 0x88, 0x01, 0x31, 0x31, 0x80, 0x01, 0x21, 0x81, 0x60, 0xE1, 0x48, 0x1D, 0x30, 0xF0, 0xBD, 0x0B, 0x1C, 0x01, 0x24, 0x5D, 0x6F, 0x1D, 0x67, 0x04, 0x33, 0x01, 0x34, 0x06, 0x2C, 0xE1, 0xDA, 0xF8, 0xE7, 0x00, 0xB5, 0x00, 0x21, 0xC1, 0x60, 0xE9, 0x48, 0x01, 0x68, 0x10, 0x31, 0xE6, 0x48, 0x20, 0x22, 0x01, 0x23, 0x9E, 0x46, 0xE7, 0x4B, 0xFE, 0x44, 0x18, 0x47, 0xE5, 0x48, 0xFB, 0x30, 0x00, 0xBD, 0xFF, 0xFF, 0xC0, 0x68, 0x08, 0x00, 0x96, 0x00, 0x00, 0x00, 0x14, 0x0D, 0x1B, 0x00, 0x54, 0x19, 0x1B, 0x00, 0x91, 0x1A, 0x01, 0x00, 0x4B, 0xAD, 0x03, 0x00, 0x61, 0x4E, 0x01, 0x00, 0x06, 0x32, 0x08, 0x00, 0x1F, 0x0B, 0x02, 0x00, 0x54, 0x3F , -0x08, 0x00, 0x45, 0xC1, 0x00, 0x00, 0x84, 0x3C, 0x08, 0x00, 0x1B, 0x02, 0x00, 0x00, 0xED, 0x17, 0x00, 0x00, 0xF3, 0xC1, 0x01, 0x00, 0x34, 0x19, 0x1B, 0x00, 0x08, 0x19, 0x1B, 0x00, 0xA6, 0x44, 0x08, 0x00, 0x1C, 0x17, 0x1B, 0x00, 0x18, 0x17, 0x1B, 0x00, 0xCB, 0x67, 0x03, 0x00, 0x0D, 0x47, 0x02, 0x00, 0x39, 0x42, 0x03, 0x00, 0xBD, 0xE7, 0x02, 0x00, 0xB1, 0x40, 0x03, 0x00, 0xB9, 0xEA, 0x01, 0x00, 0x45, 0xDA, 0x00, 0x00, 0x24, 0x41, 0x08, 0x00, 0x71, 0xC0, 0x02, 0x00, 0xF0, 0xB5, 0x88, 0xB0, 0x06, 0x91, 0x07, 0x90, 0x86, 0x69, 0xF0, 0x1C, 0xD9, 0xA1, 0x04, 0x22, 0x01, 0x24, 0xA6, 0x46, 0x14, 0x4B, 0xFE, 0x44, 0x18, 0x47, 0x00, 0x28, 0x32, 0xD1, 0xF2, 0x79, 0xD7, 0x48, 0x02, 0x70, 0x35, 0x7A, 0x77, 0x7A, 0x78, 0x1B, 0xFF, 0xFF, 0x56, 0x69, 0x08, 0x00, 0x96, 0x00, 0x00, 0x00, 0x43, 0x1C, 0x93, 0x42, 0x1D, 0xD0, 0x16, 0x2A, 0x0C, 0xDB, 0x00, 0x2D, 0x0A, 0xD1, 0xD6, 0x48, 0x04, 0x70, 0x0A, 0x20 , -0x81, 0x19, 0xD0, 0x48, 0x1A, 0x1C, 0xA6, 0x46, 0xB8, 0x4B, 0xFE, 0x44, 0x18, 0x47, 0x74, 0xE0, 0xD2, 0x48, 0x04, 0x70, 0xCC, 0x48, 0x40, 0x19, 0x0A, 0x21, 0x89, 0x19, 0x7A, 0x1B, 0x52, 0x1C, 0xA6, 0x46, 0xB1, 0x4B, 0xFE, 0x44, 0x18, 0x47, 0x67, 0xE0, 0x8F, 0xC6, 0x03, 0x00, 0xC9, 0x48, 0x04, 0x70, 0xC9, 0x48, 0x04, 0x70, 0x0A, 0x20, 0x81, 0x19, 0xC2, 0x48, 0xA6, 0x46, 0xAA, 0x4B, 0xFE, 0x44, 0x18, 0x47, 0x59, 0xE0, 0xF0, 0x1C, 0x03, 0x21, 0x0A, 0x1C, 0xBC, 0xA1, 0xA6, 0x46, 0xC6, 0x4B, 0xFE, 0x44, 0x18, 0x47, 0x00, 0x28, 0x4F, 0xD1, 0xF1, 0x79, 0xBB, 0x48, 0x01, 0x70, 0xBB, 0x4D, 0xB2, 0x79, 0x2A, 0x70, 0x03, 0x20, 0x17, 0x49, 0xF4, 0x31, 0xA6, 0x46, 0xB8, 0x4B, 0xFE, 0x44, 0x18, 0x47, 0x28, 0x78, 0x00, 0x28, 0x0B, 0xD1, 0xFF, 0xE7, 0xB8, 0x49, 0x0C, 0x70, 0xB8, 0x49, 0xFF, 0xFF, 0xEC, 0x69, 0x08, 0x00, 0x96, 0x00, 0x00, 0x00, 0x0C, 0x70, 0x03, 0x20, 0x0F, 0x49, 0xF5, 0x31, 0xA6, 0x46 , -0xB6, 0x4A, 0xFE, 0x44, 0x10, 0x47, 0x20, 0x1C, 0xF2, 0x79, 0x35, 0x7A, 0x77, 0x7A, 0x79, 0x1B, 0x4B, 0x1C, 0x93, 0x42, 0x20, 0xD0, 0xA9, 0x49, 0x09, 0x78, 0x16, 0x29, 0x0F, 0xDB, 0x00, 0x2D, 0x0D, 0xD1, 0xAB, 0x49, 0x08, 0x70, 0x0A, 0x20, 0x81, 0x19, 0xE9, 0x48, 0x1A, 0x1C, 0xA6, 0x46, 0x8B, 0x4B, 0xFE, 0x44, 0x18, 0x47, 0x1A, 0xE0, 0xC0, 0x46, 0xC7, 0x04, 0x00, 0x00, 0xA5, 0x49, 0x08, 0x70, 0xE3, 0x48, 0x40, 0x19, 0x0A, 0x21, 0x89, 0x19, 0x7A, 0x1B, 0x52, 0x1C, 0xA6, 0x46, 0x83, 0x4B, 0xFE, 0x44, 0x18, 0x47, 0x0A, 0xE0, 0x9E, 0x49, 0x08, 0x70, 0x9E, 0x49, 0x08, 0x70, 0x0A, 0x20, 0x81, 0x19, 0xDB, 0x48, 0xA6, 0x46, 0x7D, 0x4B, 0xFE, 0x44, 0x18, 0x47, 0x96, 0x48, 0x00, 0x78, 0x00, 0x28, 0x0A, 0xD0, 0x95, 0x48, 0x00, 0x78, 0x00, 0x28, 0x06, 0xD0, 0x94, 0x48, 0x00, 0x78, 0x00, 0x28, 0x02, 0xD0, 0x93, 0x48, 0x00, 0x78, 0x00, 0x28, 0xFF, 0xFF, 0x82, 0x6A, 0x08, 0x00, 0x96, 0x00, 0x00, 0x00 , -0x00, 0xD1, 0x8C, 0xE0, 0x03, 0x20, 0x17, 0x21, 0x89, 0x01, 0xA6, 0x46, 0x90, 0x4A, 0xFE, 0x44, 0x10, 0x47, 0x87, 0x48, 0x01, 0x78, 0x87, 0x48, 0x07, 0x78, 0x84, 0x4E, 0x83, 0x4D, 0xE0, 0x48, 0x00, 0x68, 0x00, 0x28, 0x2E, 0xD1, 0x07, 0x98, 0x41, 0x61, 0x06, 0x62, 0xC6, 0x48, 0x06, 0x9A, 0x10, 0x64, 0x02, 0x2F, 0x01, 0xD0, 0x03, 0x2F, 0x01, 0xD1, 0x03, 0x22, 0x00, 0xE0, 0x3A, 0x1C, 0x06, 0x9B, 0xDA, 0x63, 0x2A, 0x78, 0x9A, 0x63, 0x01, 0x2F, 0x03, 0xD1, 0x05, 0x29, 0x04, 0xD0, 0x0D, 0x29, 0x02, 0xD0, 0xEC, 0x48, 0xDB, 0x30, 0x64, 0xE0, 0x00, 0x25, 0x00, 0x95, 0x01, 0x91, 0x02, 0x96, 0x03, 0x95, 0x04, 0x90, 0x2B, 0x1C, 0x20, 0x1C, 0x01, 0x1C, 0x8E, 0x46, 0xE6, 0x4E, 0xFE, 0x44, 0x30, 0x47, 0xE6, 0x48, 0x04, 0x60, 0x28, 0x1C, 0xA6, 0x46, 0xE5, 0x49, 0xFE, 0x44, 0x08, 0x47, 0x4C, 0xE0, 0x0D, 0x27, 0x00, 0x20, 0x39, 0x1C, 0x05, 0xAA, 0xA6, 0x46, 0xE3, 0x4B, 0xFE, 0x44, 0x18, 0x47, 0x68, 0x46 , -0xFF, 0xFF, 0x18, 0x6B, 0x08, 0x00, 0x96, 0x00, 0x00, 0x00, 0x80, 0x8A, 0x40, 0x08, 0x05, 0xD2, 0x38, 0x1C, 0x50, 0x21, 0xA6, 0x46, 0xDC, 0x4A, 0xFE, 0x44, 0x10, 0x47, 0x38, 0x1C, 0x21, 0x1C, 0x0B, 0x1C, 0x29, 0x1C, 0x00, 0x22, 0xA6, 0x46, 0xD9, 0x4F, 0xFE, 0x44, 0x38, 0x47, 0x2B, 0x78, 0x0D, 0x20, 0x31, 0x1C, 0x22, 0x1C, 0xA6, 0x46, 0xD5, 0x4E, 0xFE, 0x44, 0x30, 0x47, 0x28, 0x78, 0x01, 0x30, 0x02, 0x1C, 0x0D, 0x20, 0x57, 0x49, 0x23, 0x1C, 0xA6, 0x46, 0xD0, 0x4E, 0xFE, 0x44, 0x30, 0x47, 0x55, 0x4E, 0x28, 0x78, 0x02, 0x30, 0x02, 0x1C, 0x0D, 0x20, 0x31, 0x1C, 0x23, 0x1C, 0xA6, 0x46, 0xCA, 0x4F, 0xFE, 0x44, 0x38, 0x47, 0x30, 0x78, 0x00, 0x28, 0x0A, 0xD0, 0x28, 0x78, 0x03, 0x30, 0x02, 0x1C, 0x4C, 0x48, 0x03, 0x78, 0x0D, 0x20, 0x8F, 0x49, 0xA6, 0x46, 0xC3, 0x4D, 0xFE, 0x44, 0x28, 0x47, 0xBF, 0x48, 0x04, 0x60, 0x00, 0x20, 0xA6, 0x46, 0xBE, 0x49, 0xFE, 0x44, 0x08, 0x47, 0xB9, 0x48, 0xEC, 0x49 , -0x08, 0x18, 0x08, 0xB0, 0xF0, 0xBD, 0xC0, 0x46, 0x7B, 0xC0, 0xFF, 0xFF, 0xAE, 0x6B, 0x08, 0x00, 0x96, 0x00, 0x00, 0x00, 0x02, 0x00, 0x01, 0x1C, 0xE9, 0x48, 0x02, 0x68, 0xE9, 0x48, 0x00, 0x2A, 0x04, 0xD0, 0x00, 0x22, 0x0A, 0x62, 0x8A, 0x61, 0x1D, 0x30, 0xF7, 0x46, 0xD7, 0x30, 0xF7, 0x46, 0xC0, 0x46, 0x9F, 0x03, 0x00, 0x00, 0x7D, 0xB8, 0x03, 0x00, 0x01, 0x1C, 0xE2, 0x48, 0x02, 0x68, 0xE2, 0x48, 0x00, 0x2A, 0x02, 0xD0, 0xFF, 0x30, 0xB4, 0x30, 0xF7, 0x46, 0x00, 0x22, 0xCA, 0x61, 0x8A, 0x61, 0x4F, 0x30, 0xF7, 0x46, 0xC9, 0x21, 0x01, 0x00, 0x91, 0xE1, 0x00, 0x00, 0xDB, 0x48, 0x01, 0x68, 0x8A, 0x69, 0x01, 0x20, 0xC0, 0x03, 0x10, 0x43, 0x88, 0x61, 0x00, 0x20, 0x08, 0x61, 0xD8, 0x48, 0x23, 0x30, 0xF7, 0x46, 0x89, 0x17, 0x02, 0x00, 0x70, 0xB5, 0x05, 0x1C, 0xD5, 0x4E, 0x29, 0x6A, 0xEA, 0x69, 0x30, 0x1C, 0x01, 0x24, 0xA6, 0x46, 0x0B, 0x4B, 0xFE, 0x44, 0x18, 0x47, 0x68, 0x69, 0xA6, 0x46, 0xD1, 0x49 , -0xFE, 0x44, 0x08, 0x47, 0xA8, 0x69, 0x06, 0x30, 0xA8, 0x60, 0xCF, 0x48, 0x00, 0x68, 0x68, 0x60, 0xEE, 0x60, 0xCE, 0x48, 0xFF, 0xFF, 0x44, 0x6C, 0x08, 0x00, 0x96, 0x00, 0x00, 0x00, 0x6D, 0x30, 0x70, 0xBD, 0x46, 0x17, 0x1B, 0x00, 0x30, 0x3F, 0x08, 0x00, 0x41, 0xEB, 0x00, 0x00, 0x09, 0xB4, 0x03, 0x00, 0x30, 0xB5, 0xEE, 0x48, 0x01, 0x6D, 0x80, 0x6C, 0x08, 0x43, 0x18, 0xD0, 0xEC, 0x49, 0x08, 0x1C, 0x07, 0x22, 0xFF, 0x23, 0x09, 0x33, 0x1B, 0x58, 0x00, 0x2B, 0x04, 0xD0, 0xFF, 0x30, 0x1D, 0x30, 0x01, 0x3A, 0xF6, 0xD1, 0x0B, 0xE0, 0x02, 0x20, 0xF0, 0x4A, 0xF1, 0x4B, 0x01, 0x24, 0xA6, 0x46, 0xF0, 0x4D, 0xFE, 0x44, 0x28, 0x47, 0xA6, 0x46, 0xEF, 0x48, 0xFE, 0x44, 0x00, 0x47, 0xEF, 0x48, 0xFF, 0x30, 0x5C, 0x30, 0x30, 0xBD, 0xC0, 0x46, 0x53, 0x53, 0x49, 0x44, 0x00, 0xC0, 0x46, 0xC0, 0x4B, 0x45, 0x59, 0x00, 0xEE, 0x62, 0x08, 0x00, 0xF0, 0x62, 0x08, 0x00, 0xEC, 0x62, 0x08, 0x00, 0xED, 0x62, 0x08, 0x00 , -0xE7, 0x7E, 0x03, 0x00, 0xE8, 0x62, 0x08, 0x00, 0xE9, 0x62, 0x08, 0x00, 0xEA, 0x62, 0x08, 0x00, 0xEB, 0x62, 0x08, 0x00, 0xDD, 0x7E, 0x03, 0x00, 0x8F, 0xC6, 0x03, 0x00, 0xF0, 0xB5, 0xFF, 0xFF, 0xDA, 0x6C, 0x08, 0x00, 0x96, 0x00, 0x00, 0x00, 0x87, 0xB0, 0x00, 0x91, 0x01, 0x90, 0x6B, 0x48, 0x01, 0x68, 0xCC, 0x4A, 0x14, 0x1C, 0x02, 0x94, 0x07, 0x26, 0x00, 0x25, 0x03, 0x95, 0x04, 0x94, 0x05, 0x95, 0xDF, 0x48, 0x00, 0x68, 0x08, 0x43, 0x27, 0xD0, 0xE0, 0x68, 0x03, 0x99, 0x88, 0x42, 0x0A, 0xDD, 0x03, 0x90, 0x40, 0x1C, 0x00, 0x99, 0x88, 0x60, 0xC2, 0x49, 0xFF, 0x20, 0x1D, 0x30, 0x68, 0x43, 0x0C, 0x18, 0xE0, 0x68, 0x04, 0x91, 0x02, 0x99, 0xC9, 0x68, 0x88, 0x42, 0x10, 0xDB, 0x88, 0x42, 0x10, 0xD1, 0x02, 0x98, 0x01, 0x27, 0xBE, 0x46, 0xCE, 0x49, 0xFE, 0x44, 0x08, 0x47, 0x06, 0x90, 0x20, 0x1C, 0xBE, 0x46, 0xCB, 0x49, 0xFE, 0x44, 0x08, 0x47, 0x06, 0x99, 0x88, 0x42, 0x01, 0xDA, 0x05, 0x95, 0x02, 0x94 , -0x51, 0x48, 0x01, 0x68, 0xFF, 0x27, 0x09, 0x37, 0x38, 0x59, 0x00, 0x28, 0x06, 0xD0, 0xC7, 0x48, 0x00, 0x68, 0x07, 0x2E, 0x00, 0xD1, 0x2E, 0x1C, 0x08, 0x43, 0x04, 0xD0, 0xFF, 0x34, 0x1D, 0x34, 0x01, 0x35, 0x07, 0x2D, 0xC2, 0xDB, 0x07, 0x2E, 0xFF, 0xFF, 0x70, 0x6D, 0x08, 0x00, 0x96, 0x00, 0x00, 0x00, 0x0A, 0xD1, 0xC0, 0x48, 0x00, 0x68, 0x08, 0x43, 0x06, 0xD0, 0x05, 0x9E, 0x30, 0x1C, 0x01, 0x21, 0x8E, 0x46, 0xBA, 0x49, 0xFE, 0x44, 0x08, 0x47, 0x01, 0x98, 0x47, 0x61, 0x00, 0x21, 0x81, 0x61, 0xFF, 0x22, 0x1D, 0x32, 0x72, 0x43, 0x04, 0x99, 0x89, 0x18, 0xC1, 0x61, 0x06, 0x62, 0xB4, 0x48, 0x39, 0x30, 0x07, 0xB0, 0xF0, 0xBD, 0x10, 0xB5, 0x04, 0x1C, 0x00, 0x20, 0x01, 0x21, 0x8E, 0x46, 0xB1, 0x49, 0xFE, 0x44, 0x08, 0x47, 0x40, 0x1E, 0x00, 0xD5, 0x00, 0x20, 0x60, 0x60, 0xE0, 0x61, 0xAE, 0x48, 0x21, 0x30, 0x10, 0xBD, 0xC0, 0x46, 0x10, 0x63, 0x08, 0x00, 0x70, 0xB5, 0x04, 0x1C, 0xE5, 0x69, 0x66, 0x69 , -0x00, 0x20, 0x01, 0x21, 0x8E, 0x46, 0xA7, 0x49, 0xFE, 0x44, 0x08, 0x47, 0x60, 0x60, 0xAB, 0x19, 0xA6, 0x4A, 0xA5, 0x49, 0x93, 0x42, 0x02, 0xD3, 0x9A, 0x1A, 0x82, 0x42, 0x02, 0xD9, 0x08, 0x1C, 0x99, 0x30, 0x70, 0xBD, 0x08, 0x1C, 0xAB, 0x30, 0x70, 0xBD, 0x08, 0x6B, 0x41, 0x7D, 0x02, 0x88, 0x92, 0x00, 0xFF, 0xFF, 0x06, 0x6E, 0x08, 0x00, 0x96, 0x00, 0x00, 0x00, 0x51, 0x1A, 0x3C, 0x39, 0xFF, 0x22, 0x5F, 0x32, 0x91, 0x42, 0x03, 0xD9, 0x65, 0x21, 0x01, 0x80, 0x02, 0x21, 0x81, 0x73, 0x9B, 0x48, 0x99, 0x49, 0x08, 0x18, 0xF7, 0x46, 0xC0, 0x46, 0x30, 0x63, 0x08, 0x00, 0xF8, 0xB5, 0x40, 0x68, 0x24, 0x21, 0x41, 0x43, 0x97, 0x48, 0x45, 0x18, 0x28, 0x1D, 0x0C, 0x21, 0x49, 0x19, 0x04, 0x22, 0x01, 0x23, 0x9E, 0x46, 0x94, 0x4B, 0xFE, 0x44, 0x18, 0x47, 0x91, 0x4C, 0x00, 0x28, 0x1B, 0xD0, 0x2B, 0x1C, 0x04, 0x22, 0x6E, 0x46, 0x91, 0x49, 0x1F, 0x7B, 0x08, 0x78, 0xC0, 0x43, 0x38, 0x43, 0x30, 0x70, 0x01, 0x33 , -0x01, 0x31, 0x01, 0x36, 0x01, 0x3A, 0xF5, 0xD1, 0x0C, 0x20, 0x41, 0x19, 0x68, 0x46, 0x04, 0x22, 0x01, 0x23, 0x9E, 0x46, 0x87, 0x4B, 0xFE, 0x44, 0x18, 0x47, 0x00, 0x28, 0x02, 0xD0, 0x20, 0x1C, 0x4A, 0x30, 0xF8, 0xBD, 0x20, 0x1C, 0xF8, 0xBD, 0xB1, 0xBD, 0x00, 0x00, 0x15, 0x95, 0x00, 0x00, 0x58, 0x3F, 0x08, 0x00, 0xF3, 0xF8, 0x00, 0x00, 0xE9, 0x09, 0x02, 0x00, 0xFF, 0xFF, 0x9C, 0x6E, 0x08, 0x00, 0x96, 0x00, 0x00, 0x00, 0x2B, 0x09, 0x02, 0x00, 0xDD, 0x0A, 0x02, 0x00, 0xF8, 0xB5, 0x05, 0x1C, 0xAA, 0x69, 0x7D, 0x49, 0x00, 0x20, 0x08, 0x56, 0x24, 0x21, 0x41, 0x43, 0x76, 0x48, 0x43, 0x18, 0x04, 0x24, 0x6E, 0x46, 0x76, 0x49, 0x1F, 0x79, 0x08, 0x78, 0xC0, 0x43, 0x38, 0x43, 0x30, 0x70, 0x01, 0x33, 0x01, 0x31, 0x01, 0x36, 0x01, 0x3C, 0xF5, 0xD1, 0x11, 0x1D, 0x68, 0x46, 0x04, 0x22, 0x01, 0x24, 0xA6, 0x46, 0x6D, 0x4B, 0xFE, 0x44, 0x18, 0x47, 0x01, 0x1C, 0x6D, 0x48, 0x04, 0xD0, 0x6E, 0x49, 0x09, 0x78 , -0x69, 0x60, 0x45, 0x30, 0xF8, 0xBD, 0xEC, 0x61, 0xAF, 0x30, 0xF8, 0xBD, 0x70, 0xB5, 0xC5, 0x68, 0x81, 0x68, 0x0A, 0x89, 0x6D, 0x4E, 0x00, 0x2A, 0x22, 0xD0, 0x01, 0x24, 0xC2, 0x6D, 0xA2, 0x18, 0xC2, 0x65, 0x08, 0x89, 0x0D, 0x28, 0x1B, 0xD1, 0x68, 0x6B, 0x21, 0x1C, 0xA6, 0x46, 0x63, 0x4A, 0xFE, 0x44, 0x10, 0x47, 0x22, 0x1C, 0x28, 0x1C, 0x00, 0x21, 0xA6, 0x46, 0x60, 0x4B, 0xFE, 0x44, 0x18, 0x47, 0x2C, 0x60, 0xE9, 0x6B, 0xFF, 0xFF, 0x32, 0x6F, 0x08, 0x00, 0x96, 0x00, 0x00, 0x00, 0x28, 0x1C, 0xA6, 0x46, 0x5E, 0x4A, 0xFE, 0x44, 0x10, 0x47, 0x28, 0x1C, 0xA6, 0x46, 0x5C, 0x49, 0xFE, 0x44, 0x08, 0x47, 0x30, 0x1C, 0x3D, 0x30, 0x70, 0xBD, 0x30, 0x1C, 0x23, 0x30, 0x70, 0xBD, 0xC0, 0x46, 0xB1, 0x02, 0x00, 0x00, 0x74, 0x3F, 0x08, 0x00, 0x19, 0xC6, 0x00, 0x00, 0x5C, 0x3F, 0x08, 0x00, 0x1D, 0xC2, 0x00, 0x00, 0x68, 0x44, 0x08, 0x00, 0x43, 0x12, 0x03, 0x00, 0x34, 0x63, 0x08, 0x00, 0x2F, 0x7A, 0x02, 0x00 , -0xB4, 0x36, 0x08, 0x00, 0x8F, 0xF4, 0x01, 0x00, 0xF0, 0xB5, 0x05, 0x1C, 0xAB, 0x69, 0xEC, 0x69, 0x60, 0x68, 0x00, 0x68, 0x2A, 0x30, 0x01, 0x78, 0x0A, 0x06, 0x41, 0x78, 0x09, 0x04, 0x8A, 0x18, 0x81, 0x78, 0x09, 0x02, 0x8A, 0x18, 0xC1, 0x78, 0x8A, 0x18, 0x8E, 0x26, 0xF1, 0x5A, 0x09, 0x0A, 0x01, 0x70, 0xF0, 0x5C, 0x61, 0x68, 0x09, 0x68, 0x2B, 0x26, 0x70, 0x54, 0x8C, 0x20, 0xC0, 0x18, 0x61, 0x68, 0x0E, 0x68, 0x01, 0x88, 0x09, 0x0A, 0x2C, 0x27, 0xB9, 0x55, 0x61, 0x68, 0x09, 0x68, 0xFF, 0xFF, 0xC8, 0x6F, 0x08, 0x00, 0x96, 0x00, 0x00, 0x00, 0x2D, 0x26, 0x00, 0x78, 0x70, 0x54, 0x60, 0x68, 0x01, 0x68, 0x32, 0x31, 0x08, 0x78, 0x00, 0x02, 0x49, 0x78, 0x08, 0x18, 0x00, 0x04, 0x00, 0x0C, 0x8C, 0x21, 0xCB, 0x58, 0x35, 0x49, 0x41, 0x40, 0x08, 0x04, 0x00, 0x0C, 0xC0, 0x18, 0x80, 0x1A, 0x01, 0x21, 0x8E, 0x46, 0x32, 0x49, 0xFE, 0x44, 0x08, 0x47, 0x61, 0x68, 0x0A, 0x68, 0x32, 0x23, 0x01, 0x0A, 0x99, 0x54 , -0x61, 0x68, 0x09, 0x68, 0x33, 0x22, 0x50, 0x54, 0x60, 0x68, 0x68, 0x60, 0x2C, 0x48, 0xF0, 0xBD, 0x00, 0x00, 0x1B, 0x00, 0x34, 0x04, 0x1B, 0x00, 0x02, 0x6A, 0x8B, 0x69, 0xDB, 0x69, 0x1B, 0x68, 0x83, 0x60, 0x88, 0x69, 0xC0, 0x69, 0x41, 0x68, 0x8A, 0x42, 0x00, 0xDA, 0x42, 0x60, 0x25, 0x48, 0x79, 0x30, 0xF7, 0x46, 0x24, 0x48, 0x57, 0x30, 0xF7, 0x46, 0x24, 0x48, 0x91, 0x30, 0xF7, 0x46, 0x32, 0x04, 0x00, 0x00, 0xC4, 0x07, 0x00, 0x00, 0x15, 0x09, 0x02, 0x00, 0xC5, 0x93, 0x00, 0x00, 0x0D, 0x91, 0x00, 0x00, 0x40, 0x1E, 0x80, 0x00, 0x1E, 0x4B, 0xFF, 0xFF, 0x5E, 0x70, 0x08, 0x00, 0x96, 0x00, 0x00, 0x00, 0x19, 0x50, 0x1C, 0x49, 0x0A, 0x50, 0xF7, 0x46, 0xC0, 0x46, 0xBD, 0xB5, 0x00, 0x00, 0x95, 0x92, 0x00, 0x00, 0xFD, 0x93, 0x00, 0x00, 0x54, 0x3F, 0x08, 0x00, 0x29, 0x4F, 0x03, 0x00, 0xDF, 0xE8, 0x02, 0x00, 0x36, 0x89, 0x41, 0x00, 0x81, 0x06, 0x00, 0x00, 0xB1, 0x78, 0x00, 0x00, 0x94, 0xEC, 0x01, 0x00 , -0x08, 0x19, 0x1B, 0x00, 0x8F, 0xC6, 0x03, 0x00, 0x1C, 0x17, 0x1B, 0x00, 0x67, 0x66, 0x03, 0x00, 0xA6, 0x44, 0x08, 0x00, 0x18, 0x17, 0x1B, 0x00, 0xA7, 0x2F, 0x02, 0x00, 0x91, 0x44, 0x03, 0x00, 0x91, 0x63, 0x03, 0x00, 0x5B, 0x44, 0x03, 0x00, 0xE7, 0x44, 0x03, 0x00, 0xFF, 0xFF, 0x00, 0x00, 0x61, 0xA2, 0x03, 0x00, 0x6A, 0x1E, 0x01, 0x00, 0x45, 0xDA, 0x00, 0x00, 0xD7, 0xE8, 0x01, 0x00, 0xE9, 0x78, 0x02, 0x00, 0x04, 0xF3, 0x1A, 0x00, 0x80, 0x7B, 0x08, 0x00, 0xFC, 0xB5, 0x04, 0x1C, 0xA5, 0x69, 0x60, 0x6A, 0x01, 0x90, 0x20, 0x69, 0x00, 0x28, 0x35, 0xD4, 0x08, 0x28, 0x33, 0xDA, 0xE1, 0x69, 0x09, 0x68, 0xFF, 0xFF, 0xF4, 0x70, 0x08, 0x00, 0x96, 0x00, 0x00, 0x00, 0x10, 0x29, 0x2F, 0xD1, 0xAC, 0x21, 0x41, 0x43, 0x9E, 0x4A, 0x51, 0x5C, 0x49, 0x08, 0x27, 0xD3, 0x00, 0x06, 0x00, 0x16, 0xA2, 0x68, 0x69, 0x46, 0x01, 0x23, 0x9E, 0x46, 0x9A, 0x4B, 0xFE, 0x44, 0x18, 0x47, 0x06, 0x1C, 0x39, 0x30, 0x1F, 0xD0 , -0x00, 0x2E, 0x1D, 0xD0, 0x00, 0x98, 0x07, 0x68, 0x00, 0x99, 0x0C, 0x39, 0x01, 0x98, 0x01, 0x60, 0x28, 0x1D, 0x10, 0x21, 0x79, 0x1A, 0x04, 0x22, 0x01, 0x23, 0x9E, 0x46, 0x91, 0x4B, 0xFE, 0x44, 0x18, 0x47, 0x02, 0x22, 0x2A, 0x80, 0xA8, 0x1C, 0x08, 0x21, 0x79, 0x1A, 0x01, 0x23, 0x9E, 0x46, 0x8C, 0x4B, 0xFE, 0x44, 0x18, 0x47, 0x03, 0xE0, 0x38, 0x20, 0x00, 0xE0, 0x00, 0x20, 0xC6, 0x43, 0x26, 0x60, 0x89, 0x48, 0x7C, 0x30, 0x20, 0x62, 0xFC, 0xBD, 0x30, 0xB5, 0x05, 0x1C, 0x28, 0x69, 0xA9, 0x69, 0x90, 0x29, 0x1D, 0xD1, 0x69, 0x69, 0x09, 0x78, 0x04, 0x29, 0x19, 0xD0, 0x05, 0x29, 0x17, 0xD0, 0x0A, 0x29, 0x15, 0xD0, 0x06, 0x29, 0x13, 0xD0, 0x0C, 0x29, 0x01, 0xDB, 0xFF, 0xFF, 0x8A, 0x71, 0x08, 0x00, 0x96, 0x00, 0x00, 0x00, 0x10, 0x29, 0x0F, 0xD1, 0x01, 0x24, 0xA6, 0x46, 0x7D, 0x49, 0xFE, 0x44, 0x08, 0x47, 0x7C, 0x48, 0x7D, 0x49, 0x00, 0x22, 0xA6, 0x46, 0x7C, 0x4B, 0xFE, 0x44, 0x18, 0x47, 0x7C, 0x48 , -0xFF, 0x30, 0x5F, 0x30, 0x28, 0x62, 0x30, 0xBD, 0xF0, 0xB5, 0x89, 0xB0, 0x05, 0x90, 0x41, 0x69, 0x02, 0x69, 0x75, 0x48, 0x79, 0x4E, 0x82, 0x42, 0x3A, 0xD0, 0x04, 0x30, 0x82, 0x42, 0x25, 0xD0, 0x74, 0x4D, 0xAA, 0x42, 0x00, 0xD0, 0xCC, 0xE0, 0x08, 0x68, 0x06, 0x1C, 0x0C, 0x22, 0x8F, 0x1A, 0x4A, 0x68, 0x89, 0x18, 0x09, 0x1D, 0x10, 0x22, 0x01, 0x24, 0xA6, 0x46, 0x6E, 0x4B, 0xFE, 0x44, 0x18, 0x47, 0x01, 0x1C, 0x09, 0xD1, 0xAC, 0x22, 0x72, 0x43, 0xCB, 0x48, 0x80, 0x18, 0x46, 0x22, 0x12, 0x5C, 0x11, 0x2A, 0x01, 0xD1, 0x44, 0x22, 0x14, 0x54, 0x28, 0x1C, 0x3A, 0x1C, 0xA6, 0x46, 0x62, 0x4B, 0xFE, 0x44, 0x18, 0x47, 0x69, 0x48, 0xEC, 0x30, 0xAB, 0xE0, 0x08, 0x68, 0xC0, 0x00, 0x30, 0x18, 0x8A, 0x68, 0x02, 0x2A, 0x02, 0xD0, 0xFF, 0xFF, 0x20, 0x72, 0x08, 0x00, 0x96, 0x00, 0x00, 0x00, 0xE7, 0x20, 0x80, 0x00, 0xA2, 0xE0, 0xCA, 0x68, 0x89, 0x18, 0x09, 0x7B, 0x41, 0x60, 0x80, 0x21, 0x01, 0x60, 0x3B, 0x20 , -0x00, 0x01, 0x99, 0xE0, 0x08, 0x68, 0x06, 0x90, 0xC0, 0x00, 0x34, 0x58, 0x10, 0x20, 0x04, 0x90, 0x01, 0x25, 0xAE, 0x46, 0x57, 0x48, 0xFE, 0x44, 0x00, 0x47, 0x07, 0x90, 0x00, 0x28, 0x00, 0xD1, 0x89, 0xE0, 0x0C, 0x21, 0x07, 0x98, 0x0F, 0x18, 0xB0, 0x49, 0xAC, 0x20, 0x06, 0x9A, 0x50, 0x43, 0x08, 0x18, 0x48, 0x22, 0x13, 0x5C, 0x5B, 0x06, 0x5B, 0x0E, 0x13, 0x54, 0x06, 0x9A, 0xD2, 0x00, 0xB6, 0x18, 0x71, 0x68, 0x00, 0x29, 0x47, 0xD1, 0x00, 0x2C, 0x01, 0xDD, 0x08, 0x2C, 0x21, 0xDB, 0x00, 0x22, 0x69, 0x46, 0x0A, 0x70, 0x01, 0x92, 0x0A, 0x81, 0x8A, 0x72, 0xCD, 0x72, 0x0D, 0x73, 0x4D, 0x73, 0x01, 0x88, 0x44, 0x48, 0x06, 0x23, 0xAE, 0x46, 0x44, 0x4C, 0xFE, 0x44, 0x20, 0x47, 0x04, 0x1C, 0x02, 0xDC, 0x00, 0x20, 0xC0, 0x43, 0x36, 0xE0, 0x34, 0x60, 0xAC, 0x20, 0x60, 0x43, 0x9A, 0x49, 0xFF, 0xFF, 0xB6, 0x72, 0x08, 0x00, 0x96, 0x00, 0x00, 0x00, 0x09, 0x18, 0x5C, 0x22, 0x28, 0x1C, 0x50, 0x54, 0x48, 0x20 , -0x42, 0x5C, 0x52, 0x06, 0x52, 0x0E, 0x42, 0x54, 0xAC, 0x20, 0x60, 0x43, 0x94, 0x49, 0x08, 0x18, 0x5C, 0x21, 0x09, 0x5C, 0x49, 0x1E, 0x02, 0x29, 0x16, 0xD9, 0x03, 0x39, 0x08, 0xD0, 0x00, 0x20, 0x30, 0x56, 0xAE, 0x46, 0xEA, 0x49, 0xFE, 0x44, 0x08, 0x47, 0x80, 0x20, 0x30, 0x60, 0xDB, 0xE7, 0x08, 0x94, 0x80, 0x21, 0x31, 0x60, 0x48, 0x22, 0x13, 0x5C, 0x19, 0x43, 0x11, 0x54, 0xAE, 0x46, 0xE4, 0x49, 0xFE, 0x44, 0x08, 0x47, 0x0A, 0xE0, 0x01, 0x20, 0xCE, 0xE7, 0x06, 0x98, 0x39, 0x1C, 0x04, 0xAA, 0xAE, 0x46, 0xE0, 0x4B, 0xFE, 0x44, 0x18, 0x47, 0x04, 0x1C, 0x08, 0x90, 0x06, 0x98, 0x38, 0x60, 0x08, 0x98, 0x78, 0x60, 0x00, 0x28, 0x15, 0xD0, 0xAC, 0x20, 0x60, 0x43, 0x7C, 0x49, 0x09, 0x18, 0x48, 0x88, 0x02, 0x04, 0x02, 0x20, 0x10, 0x43, 0xB8, 0x60, 0x48, 0x68, 0x02, 0x0E, 0x01, 0x02, 0x09, 0x0E, 0x09, 0x02, 0x11, 0x43, 0x02, 0x04, 0x12, 0x0E, 0xFF, 0xFF, 0x4C, 0x73, 0x08, 0x00, 0x96, 0x00, 0x00, 0x00 , -0x12, 0x04, 0x0A, 0x43, 0x00, 0x06, 0x10, 0x43, 0xF8, 0x60, 0x07, 0x98, 0x0D, 0x49, 0x00, 0x22, 0x10, 0x23, 0xAE, 0x46, 0xCE, 0x4C, 0xFE, 0x44, 0x20, 0x47, 0x13, 0x48, 0x00, 0xE0, 0x16, 0x20, 0xCC, 0x49, 0x09, 0x18, 0x05, 0x98, 0x01, 0x62, 0x09, 0xB0, 0xF0, 0xBD, 0x5D, 0x0D, 0x1B, 0x00, 0x81, 0xE7, 0x02, 0x00, 0x09, 0xB4, 0x03, 0x00, 0x27, 0x1A, 0x02, 0x00, 0x2F, 0x7A, 0x02, 0x00, 0x02, 0x02, 0x00, 0x00, 0x05, 0x10, 0x00, 0x00, 0xCF, 0xF6, 0x00, 0x00, 0xD5, 0xF4, 0x00, 0x00, 0x02, 0x10, 0x00, 0x00, 0x91, 0x19, 0x02, 0x00, 0x50, 0x65, 0x08, 0x00, 0x71, 0xC0, 0x02, 0x00, 0x50, 0x19, 0x1B, 0x00, 0x29, 0x16, 0x01, 0x00, 0x2A, 0x03, 0x00, 0x00, 0xF0, 0xB5, 0x8B, 0xB0, 0x07, 0x90, 0x05, 0x69, 0x47, 0x69, 0x0C, 0x20, 0x38, 0x1A, 0x08, 0x90, 0xB6, 0x49, 0x8D, 0x42, 0x16, 0xD1, 0x78, 0x68, 0x0F, 0x30, 0x00, 0x11, 0x00, 0x01, 0x78, 0x60, 0x38, 0x68, 0x0B, 0x28, 0x0E, 0xD8, 0x00, 0x23, 0x68, 0x46 , -0xFF, 0xFF, 0xE2, 0x73, 0x08, 0x00, 0x96, 0x00, 0x00, 0x00, 0x03, 0x70, 0x08, 0x98, 0x05, 0x22, 0x01, 0x24, 0xA6, 0x46, 0xAE, 0x4C, 0xFE, 0x44, 0x20, 0x47, 0xAE, 0x48, 0xFF, 0x30, 0x95, 0x30, 0x07, 0x99, 0x08, 0x62, 0xAC, 0x48, 0x85, 0x42, 0x23, 0xD1, 0xAC, 0x48, 0x02, 0x78, 0x6C, 0x46, 0x22, 0x72, 0x43, 0x78, 0x63, 0x72, 0x81, 0x78, 0xA1, 0x72, 0xC0, 0x78, 0xE0, 0x72, 0x00, 0x91, 0x01, 0x90, 0x03, 0x20, 0xA6, 0x49, 0x01, 0x39, 0x01, 0x26, 0xB6, 0x46, 0xF3, 0x4E, 0xFE, 0x44, 0x30, 0x47, 0x04, 0x20, 0x20, 0x70, 0x08, 0x98, 0x9F, 0x49, 0x00, 0x22, 0x02, 0xAB, 0x01, 0x24, 0xA6, 0x46, 0x9B, 0x4C, 0xFE, 0x44, 0x20, 0x47, 0x9A, 0x48, 0xFF, 0x30, 0x95, 0x30, 0x07, 0x99, 0x08, 0x62, 0xEB, 0x49, 0x8D, 0x42, 0x14, 0xD1, 0x02, 0x22, 0x68, 0x46, 0x02, 0x70, 0x3A, 0x68, 0xAC, 0x20, 0x42, 0x43, 0x30, 0x48, 0x68, 0x30, 0x83, 0x18, 0x08, 0x98, 0x00, 0x22, 0x01, 0x24, 0xA6, 0x46, 0x8F, 0x4C, 0xFE, 0x44 , -0x20, 0x47, 0x8E, 0x48, 0xFF, 0x30, 0x95, 0x30, 0x07, 0x99, 0xFF, 0xFF, 0x78, 0x74, 0x08, 0x00, 0x96, 0x00, 0x00, 0x00, 0x08, 0x62, 0xEF, 0x48, 0x85, 0x42, 0x00, 0xD0, 0x04, 0xE1, 0x03, 0x20, 0x8C, 0x49, 0x01, 0x22, 0x96, 0x46, 0xEC, 0x4A, 0xFE, 0x44, 0x10, 0x47, 0x86, 0x48, 0xFF, 0x30, 0x95, 0x30, 0x09, 0x90, 0x38, 0x68, 0xEA, 0x4D, 0x00, 0x28, 0x00, 0xD1, 0xE2, 0xE0, 0x01, 0x24, 0xA6, 0x46, 0xE6, 0x48, 0xFE, 0x44, 0x00, 0x47, 0x00, 0x28, 0x00, 0xD1, 0xD6, 0xE0, 0xE4, 0x48, 0x02, 0x68, 0x03, 0x20, 0x7F, 0x49, 0x01, 0x31, 0xA6, 0x46, 0xE2, 0x4B, 0xFE, 0x44, 0x18, 0x47, 0xDF, 0x48, 0x00, 0x68, 0x00, 0x28, 0x5A, 0xD1, 0xDF, 0x4D, 0x2E, 0x20, 0x41, 0x19, 0xB8, 0x68, 0x03, 0x30, 0x08, 0x70, 0x38, 0x7A, 0x48, 0x70, 0x2E, 0x1C, 0x30, 0x36, 0xB8, 0x68, 0x28, 0x18, 0x30, 0x30, 0xDA, 0x49, 0x0A, 0x68, 0x30, 0x3A, 0x31, 0x1C, 0xA6, 0x46, 0xD8, 0x4B, 0xFE, 0x44, 0x18, 0x47, 0x78, 0x68, 0x38, 0x18 , -0x01, 0x1D, 0xBA, 0x68, 0x30, 0x1C, 0xA6, 0x46, 0xD9, 0x4B, 0xFE, 0x44, 0x18, 0x47, 0xB8, 0x68, 0x41, 0x19, 0x97, 0x22, 0xFF, 0xFF, 0x0E, 0x75, 0x08, 0x00, 0x96, 0x00, 0x00, 0x00, 0x09, 0x30, 0x50, 0x54, 0xB8, 0x68, 0x46, 0x19, 0x9E, 0x36, 0x30, 0x70, 0x01, 0x36, 0xB8, 0x68, 0x01, 0xE0, 0x14, 0x0D, 0x1B, 0x00, 0x30, 0x18, 0xCA, 0x49, 0x0A, 0x68, 0x9E, 0x3A, 0x31, 0x1C, 0xA6, 0x46, 0xC8, 0x4B, 0xFE, 0x44, 0x18, 0x47, 0x78, 0x68, 0x38, 0x18, 0x01, 0x1D, 0xBA, 0x68, 0x30, 0x1C, 0xA6, 0x46, 0xC9, 0x4B, 0xFE, 0x44, 0x18, 0x47, 0xB8, 0x68, 0x40, 0x00, 0xC0, 0x49, 0x09, 0x68, 0x08, 0x18, 0x28, 0x18, 0xC0, 0x49, 0x0A, 0x79, 0x02, 0x70, 0x4A, 0x79, 0x42, 0x70, 0x8A, 0x79, 0x82, 0x70, 0xC9, 0x79, 0xC1, 0x70, 0x04, 0x30, 0x0F, 0x21, 0x41, 0x1A, 0x0A, 0x78, 0xBB, 0x68, 0x9A, 0x18, 0x0A, 0x70, 0x40, 0x1B, 0x00, 0x04, 0x00, 0x0C, 0xB5, 0x49, 0x08, 0x60, 0xB1, 0x48, 0x04, 0x60, 0x02, 0x20, 0x01, 0x1C , -0x11, 0x22, 0xA6, 0x46, 0xB4, 0x4B, 0xFE, 0x44, 0x18, 0x47, 0x06, 0x1C, 0x63, 0xD4, 0x03, 0x20, 0xA6, 0x46, 0xB1, 0x49, 0xFE, 0x44, 0x08, 0x47, 0x0A, 0x90, 0x00, 0x25, 0x01, 0x1C, 0xFF, 0xFF, 0xA4, 0x75, 0x08, 0x00, 0x96, 0x00, 0x00, 0x00, 0x8D, 0x42, 0x50, 0xD0, 0x29, 0x1C, 0x2B, 0x22, 0xA6, 0x46, 0xAD, 0x4B, 0xFE, 0x44, 0x18, 0x47, 0x0C, 0x20, 0x0A, 0x99, 0x40, 0x18, 0xAC, 0x22, 0x72, 0x43, 0xAB, 0x49, 0x8F, 0x18, 0x78, 0x63, 0x29, 0x1C, 0x18, 0x22, 0xA6, 0x46, 0xA6, 0x4B, 0xFE, 0x44, 0x18, 0x47, 0x9F, 0x48, 0x02, 0x68, 0x79, 0x6B, 0x4A, 0x60, 0x0A, 0x98, 0xAC, 0x30, 0x08, 0x60, 0x08, 0x68, 0x9A, 0x49, 0xA6, 0x46, 0xA0, 0x4B, 0xFE, 0x44, 0x18, 0x47, 0x29, 0x1C, 0x03, 0xA8, 0x10, 0x22, 0xA6, 0x46, 0x9C, 0x4B, 0xFE, 0x44, 0x18, 0x47, 0xE0, 0x21, 0x68, 0x46, 0x01, 0x74, 0x45, 0x74, 0x85, 0x74, 0xFB, 0x21, 0xC1, 0x74, 0xEE, 0x49, 0xC1, 0x81, 0x02, 0x21, 0x81, 0x81, 0x79, 0x6B, 0xCA, 0x68 , -0x01, 0x20, 0xC0, 0x03, 0x10, 0x43, 0xC8, 0x60, 0x48, 0x68, 0x00, 0x90, 0x2A, 0x1C, 0x30, 0x1C, 0x0A, 0x9D, 0x29, 0x1C, 0x03, 0xAB, 0xA6, 0x46, 0xE6, 0x4F, 0xFE, 0x44, 0x38, 0x47, 0x07, 0x1C, 0x30, 0x06, 0x00, 0x16, 0xA6, 0x46, 0xEF, 0x49, 0xFF, 0xFF, 0x3A, 0x76, 0x08, 0x00, 0x96, 0x00, 0x00, 0x00, 0xFE, 0x44, 0x08, 0x47, 0x28, 0x1C, 0xA6, 0x46, 0xEE, 0x49, 0xFE, 0x44, 0x08, 0x47, 0x11, 0xE0, 0x30, 0x06, 0x00, 0x16, 0xA6, 0x46, 0xE9, 0x49, 0xFE, 0x44, 0x08, 0x47, 0x01, 0x20, 0xC7, 0x43, 0x08, 0xE0, 0x07, 0x1C, 0x06, 0xE0, 0x00, 0x20, 0x00, 0x21, 0xCF, 0x43, 0x01, 0xE0, 0x00, 0x20, 0x07, 0x1C, 0x28, 0x60, 0x00, 0x23, 0x68, 0x46, 0x03, 0x70, 0x3A, 0x06, 0x12, 0x0E, 0x08, 0x98, 0x6F, 0x49, 0x01, 0x24, 0xA6, 0x46, 0x09, 0x4C, 0xFE, 0x44, 0x20, 0x47, 0x07, 0x98, 0x09, 0x99, 0x01, 0x62, 0x0B, 0xB0, 0xF0, 0xBD, 0xC1, 0x18, 0x01, 0x00, 0xF1, 0x1B, 0x01, 0x00, 0xF3, 0x1C, 0x02, 0x00, 0x7B, 0xC0 , -0x02, 0x00, 0x91, 0xF0, 0x00, 0x00, 0x03, 0x02, 0x00, 0x00, 0xA3, 0xC0, 0x02, 0x00, 0xA9, 0xE9, 0x00, 0x00, 0x07, 0x02, 0x00, 0x00, 0xE4, 0x62, 0x08, 0x00, 0xAC, 0x05, 0x00, 0x00, 0xFE, 0xB5, 0x07, 0x1C, 0x7D, 0x69, 0xBE, 0x69, 0x0C, 0x20, 0x30, 0x1A, 0x01, 0x90, 0xDF, 0x4C, 0x0A, 0x2D, 0x13, 0xD1, 0xFF, 0xFF, 0xD0, 0x76, 0x08, 0x00, 0x96, 0x00, 0x00, 0x00, 0x30, 0x68, 0xDB, 0x49, 0x08, 0x60, 0x01, 0x20, 0x86, 0x46, 0xDA, 0x48, 0xFE, 0x44, 0x00, 0x47, 0x0A, 0x20, 0x00, 0x21, 0x01, 0x9A, 0x01, 0x23, 0x9E, 0x46, 0xE6, 0x4B, 0xFE, 0x44, 0x18, 0x47, 0xF5, 0x20, 0x80, 0x00, 0x00, 0x19, 0x38, 0x62, 0x03, 0x2D, 0x79, 0xD1, 0xF5, 0x20, 0x80, 0x00, 0x00, 0x19, 0x02, 0x90, 0x70, 0x68, 0x00, 0x28, 0x0C, 0xD1, 0x00, 0x21, 0xCF, 0x48, 0x01, 0x60, 0xCF, 0x48, 0x00, 0x68, 0x00, 0x28, 0x61, 0xD0, 0x01, 0x21, 0x8E, 0x46, 0xCD, 0x49, 0xFE, 0x44, 0x08, 0x47, 0x5B, 0xE0, 0xCC, 0x48, 0xB1, 0x68, 0x01, 0x60 , -0xF1, 0x68, 0x41, 0x60, 0x31, 0x69, 0x81, 0x60, 0x71, 0x69, 0xC1, 0x60, 0xB1, 0x69, 0xC1, 0x63, 0xF1, 0x69, 0x01, 0x64, 0x31, 0x6A, 0xC1, 0x64, 0x01, 0x24, 0xA6, 0x46, 0xC5, 0x48, 0xFE, 0x44, 0x00, 0x47, 0xA6, 0x46, 0xC4, 0x48, 0xFE, 0x44, 0x00, 0x47, 0x70, 0x68, 0x7D, 0x25, 0xED, 0x00, 0xA8, 0x42, 0x21, 0xD8, 0x01, 0x28, 0x18, 0xD0, 0x02, 0x28, 0x05, 0xD0, 0xFF, 0xFF, 0x66, 0x77, 0x08, 0x00, 0x96, 0x00, 0x00, 0x00, 0x28, 0x1C, 0xA6, 0x46, 0xBE, 0x49, 0xFE, 0x44, 0x08, 0x47, 0x1C, 0xE0, 0xB9, 0x48, 0x00, 0x23, 0x19, 0x1C, 0x59, 0x43, 0x3E, 0x22, 0x4A, 0x43, 0x82, 0x83, 0x02, 0x30, 0x01, 0x33, 0x10, 0x2B, 0xF6, 0xDB, 0xA6, 0x46, 0xB4, 0x48, 0xFE, 0x44, 0x00, 0x47, 0xB5, 0x48, 0x0D, 0xE0, 0xB5, 0x4D, 0x28, 0x1C, 0xA6, 0x46, 0xB2, 0x49, 0xFE, 0x44, 0x08, 0x47, 0x04, 0xE0, 0xA6, 0x46, 0xAF, 0x49, 0xFE, 0x44, 0x08, 0x47, 0x75, 0x68, 0xAE, 0x48, 0x05, 0x60, 0x05, 0x1C, 0xA7, 0x4E, 0x30, 0x68 , -0x00, 0x28, 0x06, 0xD1, 0xAD, 0x48, 0x00, 0x68, 0xA6, 0x46, 0xAC, 0x49, 0xFE, 0x44, 0x08, 0x47, 0x30, 0x60, 0x00, 0x94, 0x2B, 0x68, 0xAA, 0x49, 0xAB, 0x4A, 0xA6, 0x46, 0xAB, 0x4D, 0xFE, 0x44, 0x28, 0x47, 0x9C, 0x48, 0x04, 0x60, 0x03, 0x20, 0x00, 0x21, 0x01, 0x9A, 0x01, 0x23, 0x9E, 0x46, 0xA7, 0x4B, 0xFE, 0x44, 0x18, 0x47, 0x02, 0x98, 0x38, 0x62, 0xFE, 0xBD, 0xC0, 0x46, 0x13, 0x7F, 0x03, 0x00, 0x12, 0x10, 0x00, 0x00, 0xFF, 0xFF, 0xFC, 0x77, 0x08, 0x00, 0x96, 0x00, 0x00, 0x00, 0x30, 0xB5, 0x05, 0x1C, 0x00, 0x20, 0x01, 0x24, 0xA6, 0x46, 0xA0, 0x49, 0xFE, 0x44, 0x08, 0x47, 0xA6, 0x46, 0x9F, 0x49, 0xFE, 0x44, 0x08, 0x47, 0xA6, 0x46, 0x9E, 0x48, 0xFE, 0x44, 0x00, 0x47, 0x7D, 0x21, 0xC9, 0x00, 0xA6, 0x46, 0x9E, 0x4A, 0xFE, 0x44, 0x10, 0x47, 0x9B, 0x49, 0x08, 0x18, 0x99, 0x49, 0x08, 0x80, 0x9B, 0x48, 0x0A, 0x30, 0x28, 0x62, 0x30, 0xBD, 0x11, 0x10, 0x00, 0x00, 0xDD, 0x7E, 0x03, 0x00, 0xB9, 0x90 , -0x00, 0x00, 0x6C, 0x64, 0x08, 0x00, 0xE7, 0x7E, 0x03, 0x00, 0x74, 0x64, 0x08, 0x00, 0x70, 0x64, 0x08, 0x00, 0x6D, 0xC6, 0x03, 0x00, 0x08, 0x19, 0x1B, 0x00, 0x11, 0x18, 0x02, 0x00, 0xD1, 0x78, 0x02, 0x00, 0xC9, 0xBA, 0x03, 0x00, 0x09, 0xB4, 0x03, 0x00, 0x14, 0x0D, 0x1B, 0x00, 0xFE, 0xB5, 0x02, 0x90, 0x45, 0x69, 0x68, 0x46, 0x01, 0x21, 0x8E, 0x46, 0x89, 0x49, 0xFE, 0x44, 0x08, 0x47, 0x89, 0x48, 0x04, 0x1C, 0x68, 0x68, 0x01, 0x69, 0x4A, 0x78, 0x00, 0x27, 0x3E, 0x1C, 0x20, 0x88, 0xFF, 0xFF, 0x92, 0x78, 0x08, 0x00, 0x96, 0x00, 0x00, 0x00, 0x40, 0x08, 0x22, 0xD3, 0x20, 0x1D, 0x89, 0x1C, 0x01, 0x23, 0x9E, 0x46, 0x83, 0x4B, 0xFE, 0x44, 0x18, 0x47, 0x00, 0x28, 0x07, 0xD1, 0x68, 0x68, 0x00, 0x69, 0x40, 0x78, 0x21, 0x88, 0x09, 0x04, 0x89, 0x16, 0x81, 0x42, 0x3D, 0xD0, 0x02, 0x20, 0x00, 0x5F, 0x00, 0x99, 0x08, 0x1A, 0x00, 0x04, 0x00, 0x14, 0x3C, 0x28, 0x03, 0xDD, 0x20, 0x88, 0x40, 0x10, 0x40, 0x00 , -0x20, 0x80, 0x78, 0x1C, 0x07, 0x06, 0x3F, 0x0E, 0x68, 0x68, 0x01, 0x69, 0x4A, 0x78, 0x2A, 0x34, 0x01, 0x36, 0x14, 0x2E, 0xD5, 0xDB, 0x00, 0x2A, 0x02, 0xD1, 0xAB, 0x20, 0x40, 0x00, 0x50, 0xE0, 0x00, 0x9B, 0x6D, 0x48, 0x14, 0x21, 0x00, 0x22, 0x04, 0x88, 0x64, 0x08, 0x03, 0xD3, 0x2A, 0x30, 0x01, 0x32, 0x01, 0x39, 0xF8, 0xD1, 0x12, 0x06, 0x12, 0x0E, 0x14, 0x2F, 0x16, 0xD1, 0x66, 0x48, 0x00, 0x88, 0x00, 0x06, 0x44, 0x16, 0x64, 0x49, 0x00, 0x22, 0x01, 0x20, 0x4E, 0x8D, 0x36, 0x06, 0x76, 0x16, 0xA6, 0x42, 0x02, 0xDD, 0x34, 0x1C, 0x02, 0x06, 0xFF, 0xFF, 0x28, 0x79, 0x08, 0x00, 0x96, 0x00, 0x00, 0x00, 0x12, 0x0E, 0x2A, 0x31, 0x01, 0x30, 0x14, 0x28, 0xF3, 0xDB, 0x02, 0xE0, 0x32, 0x06, 0x12, 0x0E, 0x00, 0x9B, 0x2A, 0x20, 0x42, 0x43, 0x5A, 0x48, 0x11, 0x18, 0x0C, 0x88, 0x01, 0x20, 0x20, 0x43, 0x00, 0x04, 0x00, 0x0C, 0x08, 0x80, 0xFE, 0x24, 0xA0, 0x43, 0x14, 0x24, 0x64, 0x57, 0x64, 0x06, 0x24, 0x0E , -0x04, 0x43, 0x52, 0x48, 0x14, 0x52, 0x14, 0x18, 0x63, 0x80, 0x08, 0x88, 0x80, 0x05, 0x82, 0x0D, 0x68, 0x68, 0x00, 0x69, 0x40, 0x78, 0x80, 0x02, 0x10, 0x43, 0x08, 0x80, 0x68, 0x68, 0x02, 0x69, 0x20, 0x1D, 0x91, 0x1C, 0x52, 0x78, 0x01, 0x23, 0x9E, 0x46, 0x4B, 0x4B, 0xFE, 0x44, 0x18, 0x47, 0x02, 0x98, 0x04, 0x61, 0xFE, 0x20, 0x47, 0x49, 0x09, 0x18, 0x02, 0x98, 0x01, 0x62, 0xFE, 0xBD, 0x82, 0x69, 0x41, 0x69, 0x03, 0x69, 0x02, 0x2B, 0x0A, 0xD1, 0x01, 0x2A, 0x01, 0xD1, 0x00, 0x29, 0x05, 0xD0, 0x02, 0x2A, 0x04, 0xD1, 0x00, 0x29, 0x02, 0xD1, 0x11, 0x21, 0x00, 0xE0, 0x06, 0x21, 0x41, 0x61, 0xF7, 0x46, 0xFF, 0xFF, 0xBE, 0x79, 0x08, 0x00, 0x96, 0x00, 0x00, 0x00, 0xC0, 0x46, 0x14, 0xE9, 0x00, 0x00, 0xC9, 0x18, 0x02, 0x00, 0x30, 0xB5, 0x05, 0x1C, 0x3A, 0x48, 0x00, 0x78, 0x00, 0x28, 0x04, 0xD0, 0x01, 0x20, 0x86, 0x46, 0x38, 0x48, 0xFE, 0x44, 0x00, 0x47, 0x01, 0x24, 0xA6, 0x46, 0x37, 0x48, 0xFE, 0x44 , -0x00, 0x47, 0xA6, 0x46, 0x36, 0x48, 0xFE, 0x44, 0x00, 0x47, 0x35, 0x48, 0x0E, 0x30, 0x28, 0x62, 0x30, 0xBD, 0x49, 0x19, 0x01, 0x00, 0x2F, 0x7A, 0x02, 0x00, 0x18, 0xB5, 0x43, 0x69, 0x81, 0x69, 0x31, 0x48, 0x81, 0x29, 0x00, 0xD1, 0x0B, 0x38, 0x00, 0x21, 0x00, 0x91, 0x1A, 0x68, 0x9B, 0x68, 0x01, 0x24, 0xA6, 0x46, 0x2D, 0x4C, 0xFE, 0x44, 0x20, 0x47, 0x18, 0xBD, 0x18, 0xB5, 0x40, 0x69, 0x00, 0x21, 0x00, 0x91, 0x02, 0x68, 0x83, 0x68, 0x27, 0x48, 0x01, 0x30, 0x01, 0x24, 0xA6, 0x46, 0x26, 0x4C, 0xFE, 0x44, 0x20, 0x47, 0x18, 0xBD, 0xC0, 0x46, 0x30, 0x63, 0x08, 0x00, 0x19, 0x9E, 0x00, 0x00, 0xB9, 0xEC, 0x00, 0x00, 0x74, 0x3F, 0x08, 0x00, 0x80, 0x3F, 0x08, 0x00, 0xFF, 0xFF, 0x54, 0x7A, 0x08, 0x00, 0x96, 0x00, 0x00, 0x00, 0xB7, 0x5D, 0x03, 0x00, 0x00, 0x00, 0x1B, 0x00, 0xD3, 0x8E, 0x00, 0x00, 0xF7, 0xC6, 0x00, 0x00, 0xE5, 0x90, 0x00, 0x00, 0x68, 0x64, 0x08, 0x00, 0xC0, 0x27, 0x09, 0x00, 0xA0, 0x3B , -0x08, 0x00, 0x3D, 0x5D, 0x03, 0x00, 0x19, 0xC6, 0x00, 0x00, 0xE8, 0x3A, 0x08, 0x00, 0x81, 0x5D, 0x03, 0x00, 0xCF, 0xF6, 0x00, 0x00, 0x4B, 0x4F, 0x03, 0x00, 0x6B, 0xC0, 0x03, 0x00, 0x95, 0x1E, 0x01, 0x00, 0xDA, 0x40, 0x08, 0x00, 0xDC, 0x05, 0x00, 0x00, 0x55, 0xAA, 0x03, 0x00, 0x0D, 0x91, 0x00, 0x00, 0xD7, 0x56, 0x03, 0x00, 0x08, 0x51, 0x08, 0x00, 0x8F, 0xC6, 0x03, 0x00, 0x65, 0xB8, 0x00, 0x00, 0x09, 0xB4, 0x03, 0x00, 0x84, 0x17, 0x1B, 0x00, 0xB5, 0x86, 0x01, 0x00, 0x3D, 0x47, 0x02, 0x00, 0x73, 0x49, 0x02, 0x00, 0x5F, 0x90, 0x00, 0x00, 0x0E, 0x10, 0x00, 0x00, 0xF7, 0xF6, 0x00, 0x00, 0xFF, 0xB5, 0x68, 0x46, 0xFF, 0xF7, 0x76, 0xFF, 0xFF, 0xBD, 0xFF, 0xB5, 0x68, 0x46, 0xFF, 0xF7, 0x5A, 0xFF, 0xFF, 0xBD, 0xFF, 0xB5, 0xFF, 0xFF, 0xEA, 0x7A, 0x08, 0x00, 0x58, 0x00, 0x00, 0x00, 0x68, 0x46, 0xFF, 0xF7, 0x99, 0xFF, 0xFF, 0xBD, 0xFF, 0xB5, 0x68, 0x46, 0xFF, 0xF7, 0x83, 0xFF, 0xFF, 0xBD, 0xFF, 0xB5 , -0x68, 0x46, 0xFF, 0xF7, 0xB6, 0xFE, 0xFF, 0xBD, 0xFF, 0xB5, 0x68, 0x46, 0xFF, 0xF7, 0x55, 0xFC, 0xFF, 0xBD, 0xFF, 0xB5, 0x68, 0x46, 0xFF, 0xF7, 0x27, 0xFB, 0xFF, 0xBD, 0xFF, 0xB5, 0x68, 0x46, 0xFF, 0xF7, 0xDD, 0xFA, 0xFF, 0xBD, 0xFF, 0xB5, 0x68, 0x46, 0xFF, 0xF7, 0x68, 0xFE, 0xFF, 0xBD, 0xFF, 0xB5, 0x68, 0x46, 0xFF, 0xF7, 0x3D, 0xFB, 0xFF, 0xBD, 0xFF, 0xB5, 0x68, 0x46, 0xFF, 0xF7, 0xBE, 0xFD, 0xFF, 0xBD, 0x78, 0x7B, 0x08, 0x00, 0x88, 0x00, 0x00, 0x00, 0x00, 0xB5, 0xF8, 0xF0, 0x43, 0xFA, 0x00, 0xBD, 0x35, 0x66, 0x08, 0x00, 0x67, 0x66, 0x08, 0x00, 0x71, 0x65, 0x08, 0x00, 0x4D, 0x66, 0x08, 0x00, 0x25, 0x64, 0x08, 0x00, 0x81, 0x66, 0x08, 0x00, 0x8D, 0x66, 0x08, 0x00, 0x99, 0x66, 0x08, 0x00, 0x87, 0x67, 0x08, 0x00, 0xA7, 0x67, 0x08, 0x00, 0xD1, 0x67, 0x08, 0x00, 0x1B, 0x68, 0x08, 0x00, 0x57, 0x68, 0x08, 0x00, 0x2D, 0x69, 0x08, 0x00, 0xB1, 0x6B, 0x08, 0x00, 0xD5, 0x6B, 0x08, 0x00, 0xF9, 0x6B , -0x08, 0x00, 0x15, 0x6C, 0x08, 0x00, 0xA1, 0x68, 0x08, 0x00, 0x59, 0x6C, 0x08, 0x00, 0xA7, 0x6D, 0x08, 0x00, 0xFF, 0x6D, 0x08, 0x00, 0x29, 0x6E, 0x08, 0x00, 0xF9, 0x6E, 0x08, 0x00, 0xD9, 0x6C, 0x08, 0x00, 0xA5, 0x6E, 0x08, 0x00, 0xCD, 0x6D, 0x08, 0x00, 0x81, 0x6F, 0x08, 0x00, 0x1D, 0x70, 0x08, 0x00, 0x31, 0x64, 0x08, 0x00, 0x39, 0x70, 0x08, 0x00, 0x3F, 0x70, 0x08, 0x00, 0x04, 0xF3, 0x1A, 0x00, 0x80, 0x00, 0x00, 0x00, 0xB2, 0x4E, 0x01, 0x00, 0x5A, 0xC1, 0x00, 0x00, 0x96, 0x1A, 0x01, 0x00, 0x22, 0x0B, 0x02, 0x00, 0x60, 0xD0, 0x01, 0x00, 0x06, 0x1A, 0x00, 0x00, 0xB8, 0xC6, 0x01, 0x00, 0xD8, 0x42, 0x03, 0x00, 0x16, 0x42, 0x03, 0x00, 0xEE, 0xDB, 0x00, 0x00, 0x62, 0xDC, 0x00, 0x00, 0xC8, 0xE1, 0x00, 0x00, 0x8A, 0x17, 0x02, 0x00, 0x38, 0xBE, 0x00, 0x00, 0x26, 0xC6, 0x00, 0x00, 0x56, 0xC2, 0x00, 0x00, 0x62, 0x12, 0x03, 0x00, 0xE4, 0xF4, 0x01, 0x00, 0x3A, 0xEC, 0x00, 0x00, 0x5E, 0x92, 0x00, 0x00 , -0xFE, 0xE8, 0x02, 0x00, 0x18, 0x7F, 0x00, 0x00, 0x64, 0xEC, 0x01, 0x00, 0xFE, 0x44, 0x03, 0x00, 0x1C, 0x94, 0x00, 0x00, 0xA8, 0x66, 0x03, 0x00, 0x74, 0xE9, 0x02, 0x00, 0x68, 0x1E, 0x01, 0x00, 0xBC, 0xDA, 0x00, 0x00, 0xEA, 0xE1, 0x00, 0x00, 0x24, 0xE9, 0x01, 0x00, 0x70, 0x79, 0x02, 0x00, 0x00, 0x00, 0x18, 0x00, 0x96, 0x00, 0x00, 0x00, 0x00, 0x06, 0x01, 0x1C, 0xF0, 0xB5, 0x88, 0xB0, 0xCA, 0x4C, 0x03, 0x20, 0x22, 0x78, 0x63, 0x78, 0xCA, 0x4E, 0x31, 0x1C, 0x01, 0x39, 0x01, 0x25, 0xAE, 0x46, 0xC7, 0x4F, 0xFE, 0x44, 0x38, 0x47, 0xA2, 0x78, 0xE3, 0x78, 0x03, 0x20, 0x31, 0x1C, 0xAE, 0x46, 0xC3, 0x4F, 0xFE, 0x44, 0x38, 0x47, 0x03, 0x20, 0x31, 0x1C, 0x01, 0x31, 0xAE, 0x46, 0xC1, 0x4A, 0xFE, 0x44, 0x10, 0x47, 0xC1, 0x48, 0x21, 0x78, 0x01, 0x70, 0x61, 0x78, 0x41, 0x70, 0xE1, 0x78, 0xC1, 0x70, 0xA1, 0x78, 0x81, 0x70, 0xBF, 0x48, 0x04, 0x1C, 0x33, 0x3C, 0x20, 0x1C, 0x00, 0x21, 0xDC, 0x22, 0xAE, 0x46 , -0xBA, 0x4B, 0xFE, 0x44, 0x18, 0x47, 0x84, 0x20, 0xA0, 0x70, 0x05, 0x27, 0xE7, 0x71, 0x0C, 0x26, 0x26, 0x73, 0x0D, 0x20, 0x00, 0x19, 0x98, 0xA1, 0x32, 0x1C, 0xAE, 0x46, 0xB4, 0x4B, 0xFE, 0x44, 0x18, 0x47, 0x04, 0x20, 0x60, 0x76, 0x1A, 0x20, 0x00, 0x19, 0x97, 0xA1, 0x06, 0x91, 0x04, 0x22, 0xAE, 0x46, 0xAE, 0x4B, 0xFE, 0x44, 0x18, 0x47, 0xFF, 0xFF, 0x96, 0x00, 0x18, 0x00, 0x96, 0x00, 0x00, 0x00, 0xA7, 0x77, 0x1F, 0x34, 0x95, 0xA1, 0x07, 0x91, 0x20, 0x1C, 0x3A, 0x1C, 0xAE, 0x46, 0xA9, 0x4B, 0xFE, 0x44, 0x18, 0x47, 0xE6, 0x71, 0x28, 0x1C, 0x60, 0x72, 0x11, 0x20, 0x20, 0x73, 0x94, 0x20, 0x60, 0x73, 0xC0, 0x25, 0x65, 0x74, 0xA6, 0x74, 0x09, 0x22, 0xE2, 0x74, 0xA3, 0x4C, 0x20, 0x1C, 0x8C, 0xA1, 0x01, 0x23, 0x9E, 0x46, 0x9F, 0x4B, 0xFE, 0x44, 0x18, 0x47, 0x07, 0x22, 0x62, 0x72, 0x9E, 0x4C, 0x0A, 0x34, 0x20, 0x1C, 0x89, 0xA1, 0x01, 0x23, 0x9E, 0x46, 0x9A, 0x4B, 0xFE, 0x44, 0x18, 0x47, 0x04, 0x20 , -0xE0, 0x71, 0x98, 0x4C, 0x12, 0x34, 0x20, 0x1C, 0x06, 0x99, 0x04, 0x22, 0x01, 0x23, 0x9E, 0x46, 0x94, 0x4B, 0xFE, 0x44, 0x18, 0x47, 0x27, 0x71, 0x93, 0x4C, 0x17, 0x34, 0x20, 0x1C, 0x07, 0x99, 0x3A, 0x1C, 0x01, 0x23, 0x9E, 0x46, 0x8E, 0x4B, 0xFE, 0x44, 0x18, 0x47, 0xE6, 0x71, 0x01, 0x20, 0x60, 0x72, 0x11, 0x20, 0x20, 0x73, 0x94, 0x20, 0x60, 0x73, 0x02, 0x20, 0xE0, 0x73, 0x25, 0x74, 0x66, 0x74, 0xFF, 0xFF, 0x2C, 0x01, 0x18, 0x00, 0x96, 0x00, 0x00, 0x00, 0xA5, 0x74, 0x2F, 0x27, 0xE7, 0x74, 0x10, 0x20, 0x60, 0x75, 0x80, 0x26, 0xA6, 0x75, 0x01, 0x20, 0xE0, 0x75, 0x11, 0x20, 0xA0, 0x76, 0x94, 0x20, 0xE0, 0x76, 0x24, 0x20, 0x60, 0x77, 0x0A, 0x22, 0xA2, 0x77, 0x80, 0x4C, 0x36, 0x34, 0x20, 0x1C, 0x6D, 0xA1, 0x01, 0x23, 0x9E, 0x46, 0x7C, 0x4B, 0xFE, 0x44, 0x18, 0x47, 0x18, 0x22, 0xA2, 0x72, 0x7A, 0x4C, 0x41, 0x34, 0x20, 0x1C, 0x6B, 0xA1, 0x01, 0x23, 0x9E, 0x46, 0x76, 0x4B, 0xFE, 0x44, 0x18, 0x47 , -0x25, 0x76, 0x67, 0x76, 0x21, 0x20, 0xE0, 0x76, 0x26, 0x77, 0x01, 0x20, 0x60, 0x77, 0x72, 0x48, 0x61, 0x30, 0x11, 0x21, 0x01, 0x70, 0x94, 0x21, 0x41, 0x70, 0x04, 0x21, 0x01, 0x72, 0xD2, 0x21, 0x41, 0x72, 0xC5, 0x72, 0x1E, 0x21, 0x01, 0x73, 0x45, 0x73, 0x9E, 0x21, 0x81, 0x73, 0x01, 0x21, 0x01, 0x74, 0x46, 0x74, 0x81, 0x74, 0x11, 0x21, 0x41, 0x75, 0x94, 0x21, 0x81, 0x75, 0x04, 0x21, 0x01, 0x76, 0xAD, 0x20, 0x66, 0x49, 0x08, 0x60, 0x00, 0x24, 0x0F, 0x25, 0xFF, 0xFF, 0xC2, 0x01, 0x18, 0x00, 0x96, 0x00, 0x00, 0x00, 0x29, 0x06, 0x09, 0x0E, 0x00, 0x20, 0x6A, 0x46, 0x01, 0x23, 0x9E, 0x46, 0x62, 0x4B, 0xFE, 0x44, 0x18, 0x47, 0x6B, 0x46, 0x18, 0x88, 0x40, 0x08, 0x0E, 0xD3, 0xA0, 0x00, 0x0F, 0x21, 0xCA, 0x43, 0x69, 0x46, 0x0E, 0x88, 0x16, 0x40, 0x01, 0xAF, 0x3E, 0x52, 0x49, 0x88, 0x11, 0x40, 0x68, 0x44, 0xC1, 0x80, 0x60, 0x1C, 0x04, 0x04, 0x24, 0x0C, 0x01, 0x3D, 0x0B, 0x2D, 0xE0, 0xDA, 0x60, 0x1E , -0x00, 0x04, 0x00, 0x0C, 0x1D, 0xD0, 0x86, 0x46, 0x01, 0x1C, 0x01, 0xAD, 0x01, 0x22, 0xAE, 0x88, 0x90, 0x00, 0xC7, 0x5A, 0xB7, 0x42, 0x0A, 0xDA, 0xBC, 0x46, 0x07, 0x1C, 0x6F, 0x44, 0x7F, 0x88, 0x68, 0x44, 0x06, 0x80, 0xEE, 0x88, 0x46, 0x80, 0x60, 0x46, 0xA8, 0x80, 0xEF, 0x80, 0x04, 0x35, 0x50, 0x1C, 0x02, 0x04, 0x12, 0x0C, 0x01, 0x39, 0xE9, 0xD1, 0x70, 0x46, 0x01, 0x38, 0x86, 0x46, 0xE2, 0xD1, 0x99, 0x88, 0x68, 0x46, 0xC0, 0x88, 0x40, 0x18, 0x00, 0x04, 0x00, 0x0C, 0x42, 0x4B, 0x18, 0x80, 0x42, 0x49, 0x08, 0x1A, 0xFF, 0xFF, 0x58, 0x02, 0x18, 0x00, 0x96, 0x00, 0x00, 0x00, 0x58, 0x80, 0x02, 0x2C, 0x1E, 0xDB, 0x65, 0x1E, 0x01, 0xAA, 0x01, 0x20, 0x01, 0x1C, 0x8C, 0x00, 0x6B, 0x46, 0xE6, 0x5A, 0x93, 0x88, 0xD4, 0x88, 0xE7, 0x18, 0xB7, 0x42, 0x0C, 0xDA, 0x06, 0x24, 0x44, 0x43, 0x38, 0x4B, 0x1B, 0x19, 0x1F, 0x80, 0x1C, 0x88, 0x34, 0x1B, 0x5C, 0x80, 0x01, 0x24, 0x1C, 0x71, 0x40, 0x1C, 0x00, 0x04 , -0x00, 0x0C, 0x04, 0x32, 0x49, 0x1C, 0x09, 0x06, 0x09, 0x0E, 0x01, 0x3D, 0xE4, 0xD1, 0x00, 0x24, 0x31, 0x48, 0x04, 0x70, 0x31, 0x48, 0x04, 0x70, 0x31, 0x48, 0x04, 0x70, 0x31, 0x48, 0x04, 0x70, 0x01, 0x20, 0x86, 0x46, 0x30, 0x48, 0xFE, 0x44, 0x00, 0x47, 0x2F, 0x49, 0x22, 0x1C, 0x08, 0x68, 0x00, 0x28, 0x02, 0xD0, 0x01, 0x20, 0x90, 0x40, 0x04, 0x43, 0x04, 0x31, 0x01, 0x32, 0x20, 0x2A, 0xF5, 0xD3, 0x2A, 0x48, 0x04, 0x60, 0x08, 0xB0, 0xF0, 0xBD, 0x5F, 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, 0x2D, 0x69, 0x6E, 0x66, 0x6F, 0x00, 0xC0, 0x46, 0xC0, 0x5F, 0x75, 0x64, 0x70, 0x00, 0xC0, 0xFF, 0xFF, 0xEE, 0x02, 0x18, 0x00, 0x96, 0x00, 0x00, 0x00, 0x46, 0xC0, 0x6C, 0x6F, 0x63, 0x61, 0x6C, 0x00, 0xC0, 0x46, 0x5F, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x73, 0x00, 0xC0, 0x46, 0x5F, 0x64, 0x6E, 0x73, 0x2D, 0x73, 0x64, 0x00, 0x64, 0x65, 0x76, 0x3D, 0x43, 0x43, 0x33, 0x30, 0x30, 0x30, 0x00, 0xC0, 0x76, 0x65 , -0x6E, 0x64, 0x6F, 0x72, 0x3D, 0x54, 0x65, 0x78, 0x61, 0x73, 0x2D, 0x49, 0x6E, 0x73, 0x74, 0x72, 0x75, 0x6D, 0x65, 0x6E, 0x74, 0x73, 0x00, 0xC0, 0x46, 0xC0, 0x00, 0x00, 0x18, 0x00, 0xF3, 0x7E, 0x03, 0x00, 0xC6, 0x05, 0x00, 0x00, 0xDD, 0x7E, 0x03, 0x00, 0xE4, 0x62, 0x08, 0x00, 0xC9, 0xBA, 0x03, 0x00, 0x09, 0xB4, 0x03, 0x00, 0xA7, 0x64, 0x08, 0x00, 0x70, 0x64, 0x08, 0x00, 0xDD, 0x0A, 0x02, 0x00, 0x48, 0x32, 0x08, 0x00, 0x00, 0x80, 0xFF, 0xFF, 0xE8, 0x62, 0x08, 0x00, 0xE9, 0x62, 0x08, 0x00, 0xEA, 0x62, 0x08, 0x00, 0xEB, 0x62, 0x08, 0x00, 0x81, 0x03, 0x18, 0x00, 0x80, 0x7B, 0x08, 0x00, 0x84, 0xF3, 0x1A, 0x00, 0x0D, 0x49, 0x0E, 0x48, 0xFF, 0xFF, 0x84, 0x03, 0x18, 0x00, 0x6C, 0x00, 0x00, 0x00, 0x88, 0x67, 0x0E, 0x48, 0x88, 0x64, 0x0E, 0x48, 0x48, 0x64, 0x0E, 0x48, 0xC8, 0x64, 0x0E, 0x48, 0x08, 0x65, 0x11, 0x48, 0x02, 0x1C, 0x04, 0x32, 0x0C, 0x4B, 0x13, 0x60, 0x0C, 0x4B, 0x93, 0x62, 0x0C, 0x4A , -0x8A, 0x66, 0x0D, 0x49, 0x01, 0x60, 0x0D, 0x48, 0x0E, 0x49, 0x01, 0x60, 0x0E, 0x49, 0x41, 0x60, 0xF7, 0x46, 0x1C, 0x21, 0x08, 0x00, 0x1B, 0x7B, 0x08, 0x00, 0x11, 0x7B, 0x08, 0x00, 0x07, 0x7B, 0x08, 0x00, 0x39, 0x7B, 0x08, 0x00, 0x2F, 0x7B, 0x08, 0x00, 0x25, 0x7B, 0x08, 0x00, 0xFD, 0x7A, 0x08, 0x00, 0xDF, 0x7A, 0x08, 0x00, 0x50, 0x23, 0x08, 0x00, 0xD5, 0x7A, 0x08, 0x00, 0x58, 0x26, 0x08, 0x00, 0xF3, 0x7A, 0x08, 0x00, 0xE9, 0x7A, 0x08, 0x00 }; - - -const unsigned char cRMdefaultParams[128] = { 0x03, 0x00, 0x01, 0x01, 0x14, 0x14, 0x00, 0x27, 0x27, 0x27, 0x27, 0x27, 0x27, 0x27, 0x27, 0x27, 0x27, 0x27, 0x27, 0x27, 0x27, 0x23, 0x25, 0x25, 0x25, 0x25, 0x25, 0x25, 0x25, 0x25, 0x25, 0x23, 0x23, 0x23, 0x23, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x50, 0x50, 0x50, 0x50, 0x50, 0x50, 0x50, 0x50, 0x50, 0x50, 0x50, 0x50, 0x50, 0x50, 0x50, 0x50, 0x50, 0x50, 0x50, 0x50, 0x50, 0x50, 0x50, 0x50, 0x50, 0x50, 0x50, 0x50, 0x50, 0x50, 0x50, 0x50, 0x50, 0x50, 0x50, 0x01, 0x77, 0x80, 0x1D, 0x1F, 0x22, 0x26, 0x28, 0x29, 0x1A, 0x1F, 0x22, 0x24, 0x26, 0x28, 0x16, 0x1D, 0x1E, 0x20, 0x24, 0x25, 0x1E, 0x2D, 0x01, 0x02, 0x02, 0x02, 0x02, 0x00, 0x15, 0x15, 0x15, 0x11, 0x15, 0x15, 0x0E, 0x00}; - -// -//Service Pack version P1.13.7.15.15 - FW patches -// -const unsigned char fw_patch[5700] = { 0x00, 0x01, 0x00, 0x00, 0x3C, 0x16, 0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0x14, 0x03, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x68, 0x46, 0x25, 0xF0, 0x95, 0xFB, 0xE0, 0x6B, 0xD0, 0x03, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x25, 0xF0, 0x38, 0xFB, 0x2C, 0x04, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x25, 0xF0, 0x0A, 0xFB, 0x04, 0x15, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0xB8, 0xF1, 0x90, 0x0F, 0xA4, 0x16, 0x00, 0x00, 0xC8, 0x00, 0x00, 0x00, 0x66, 0xE0, 0x04, 0xA8, 0x35, 0x1D, 0x21, 0xF0, 0x99, 0xFC, 0x68, 0x46, 0x23, 0xF0, 0x28, 0xFB, 0x9A, 0xF8, 0x00, 0x00, 0x01, 0x28, 0x07, 0xD1, 0x28, 0x46, 0x05, 0xF0, 0xC3, 0xFE, 0x01, 0x46, 0x01, 0xAA, 0x00, 0x20, 0x21, 0xF0, 0x50, 0xF9, 0x28, 0x46, 0x05, 0xF0, 0xBB, 0xFE, 0x01, 0xA9, 0x21, 0xF0, 0x2A, 0xFA, 0xE9, 0x79, 0x4F, 0xEA, 0xE0, 0x00, 0x40, 0xB2, 0x11, 0xB1, 0x00, 0xF1, 0x06, 0x00, 0x40, 0xB2, 0xA8, 0x71, 0x1F, 0x38, 0x40, 0x00, 0xE8, 0x71, 0x30, 0x46 , -0x01, 0xF0, 0x0D, 0xFF, 0x10, 0xF1, 0x00, 0x09, 0x4F, 0xF0, 0x00, 0x01, 0x09, 0xD0, 0x28, 0x68, 0x40, 0x0C, 0x09, 0xD3, 0xE8, 0x68, 0xC0, 0x0B, 0x03, 0xD2, 0x48, 0x46, 0xFF, 0xF7, 0xDD, 0xFE, 0x01, 0x21, 0x28, 0x68, 0x40, 0x0C, 0x0A, 0xD2, 0x38, 0x68, 0x40, 0x1C, 0x38, 0x60, 0x20, 0x68, 0x6F, 0xF3, 0x0F, 0x00, 0x20, 0x60, 0x22, 0x68, 0x38, 0x68, 0x10, 0x43, 0x20, 0x60, 0xE8, 0x68, 0xC0, 0x0B, 0x0F, 0xD3, 0xD8, 0xF8, 0x00, 0x00, 0x00, 0xF1, 0x01, 0x00, 0xC8, 0xF8, 0x00, 0x00, 0x20, 0x68, 0x6F, 0xF3, 0x1F, 0x40, 0x20, 0x60, 0xD8, 0xF8, 0x00, 0x20, 0x20, 0x68, 0x40, 0xEA, 0x02, 0x40, 0x20, 0x60, 0x49, 0xB9, 0xB9, 0xF1, 0x00, 0x0F, 0x03, 0xD1, 0x30, 0x46, 0x07, 0xF0, 0xBE, 0xF9, 0x02, 0xE0, 0x48, 0x46, 0x07, 0xF0, 0x06, 0xFA, 0x6C, 0x17, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x68, 0x46, 0x0E, 0xF0, 0x85, 0xFB, 0x00, 0x9E, 0x00, 0x2E, 0x96, 0xD1, 0x05, 0xB0, 0xBD, 0xE8, 0xF0, 0x87, 0xC0, 0x46 , -0x9C, 0x20, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x23, 0xF0, 0x2A, 0xFE, 0x74, 0x47, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x0B, 0x21, 0x21, 0xF0, 0x41, 0xFA, 0x20, 0x68, 0x18, 0x4B, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x21, 0xF0, 0x1C, 0xF9, 0x0A, 0xE0, 0x20, 0x68, 0x00, 0x68, 0x0C, 0x21, 0x40, 0xF0, 0x20, 0x00, 0x21, 0xF0, 0x14, 0xF9, 0x10, 0x57, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x01, 0xA8, 0x20, 0xF0, 0x97, 0xF9, 0x01, 0x98, 0x5C, 0x57, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x02, 0xA8, 0x20, 0xF0, 0x71, 0xF9, 0x03, 0x98, 0x00, 0x58, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x20, 0xF0, 0x20, 0xF9, 0x1C, 0x58, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x20, 0xF0, 0x12, 0xF9, 0x54, 0x58, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x09, 0xA8, 0x20, 0xF0, 0xF5, 0xF8, 0x04, 0xAB, 0x04, 0x62, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x20, 0x79, 0x1F, 0xF0, 0x1B, 0xFD, 0x69, 0xE0, 0x60, 0x93, 0x00, 0x00, 0x40, 0x00 , -0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x48, 0xA6, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x78, 0x1B, 0xF0, 0x39, 0xFB, 0x28, 0x46, 0x90, 0xA8, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x78, 0x1B, 0xF0, 0x69, 0xF9, 0x1E, 0x48, 0x34, 0xAD, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x09, 0x68, 0xFF, 0x29, 0x98, 0xAD, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x10, 0xD4, 0x21, 0xD4, 0xB2, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x09, 0xD0, 0x1A, 0xF0, 0x47, 0xFC, 0x20, 0x98, 0xAC, 0xC5, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x78, 0x19, 0xF0 , -0xDB, 0xFA, 0x09, 0x49, 0x28, 0xC6, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x19, 0xF0, 0x9E, 0xFA, 0xDC, 0xD3, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0xB5, 0x18, 0xF0, 0xAB, 0xFC, 0x00, 0xF0, 0x03, 0xF8, 0x00, 0xBD, 0x00, 0x00, 0x00, 0x00, 0xC0, 0xDF, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x17, 0xF0, 0xA8, 0xFD, 0xCC, 0xEB, 0x00, 0x00, 0x0C, 0x00, 0x00, 0x00, 0x38, 0x78, 0x17, 0xF0, 0x77, 0xF8, 0x38, 0x78, 0x16, 0xF0, 0xF0, 0xFF, 0xA8, 0xF7, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x0E, 0x49, 0x09, 0x68, 0x23, 0x22, 0x41, 0x61, 0xC8, 0xF7, 0x00, 0x00, 0x28, 0x00, 0x00, 0x00, 0x31, 0x2E, 0x31, 0x39, 0x2E, 0x33, 0x31, 0x34, 0x5F, 0x4E, 0x65, 0x77, 0x5F, 0x43, 0x43, 0x41, 0x5F, 0x61, 0x6C, 0x67, 0x6F, 0x72, 0x69, 0x74, 0x68, 0x6D, 0x00, 0xC0, 0x74, 0x56, 0x30, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x4C, 0xF9, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x02, 0xA8, 0x16, 0xF0, 0x79, 0xF8 , -0x12, 0xE0, 0x38, 0xFA, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x01, 0xA8, 0x16, 0xF0, 0x03, 0xF8, 0x32, 0x20, 0x94, 0xFB, 0x00, 0x00, 0x50, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x34, 0x0C, 0x01, 0x00, 0x08, 0x00, 0x00, 0x00, 0x05, 0xA8, 0x14, 0xF0, 0x05, 0xFF, 0x01, 0xF0, 0x10, 0x1B, 0x01, 0x00, 0x44, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 , -0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x1E, 0x01, 0x00, 0x04, 0x00, 0x00, 0x00, 0x13, 0xF0, 0x46, 0xBF, 0x18, 0x30, 0x01, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x90, 0x30, 0x01, 0x00, 0x04, 0x00, 0x00, 0x00, 0x12, 0xF0, 0xD8, 0xFC, 0x9C, 0x31, 0x01, 0x00, 0x08, 0x00 , -0x00, 0x00, 0x68, 0x46, 0x12, 0xF0, 0x51, 0xFC, 0xFE, 0xF7, 0xF0, 0x35, 0x01, 0x00, 0x08, 0x00, 0x00, 0x00, 0x68, 0x46, 0x12, 0xF0, 0x27, 0xFA, 0xFE, 0xF7, 0xF0, 0x3D, 0x01, 0x00, 0x08, 0x00, 0x00, 0x00, 0x05, 0xA9, 0x11, 0xF0, 0x27, 0xFE, 0x20, 0x6F, 0xD0, 0x62, 0x01, 0x00, 0x04, 0x00, 0x00, 0x00, 0x0F, 0xF0, 0xB8, 0xFB, 0x80, 0x7E, 0x01, 0x00, 0x04, 0x00, 0x00, 0x00, 0xDF, 0xF8, 0x58, 0x82, 0xE0, 0x7E, 0x01, 0x00, 0x18, 0x00, 0x00, 0x00, 0x0D, 0xF0, 0x6A, 0xFE, 0x0B, 0xF0, 0x9A, 0xF9, 0x03, 0x20, 0xA8, 0xF5, 0x88, 0x71, 0x08, 0x60, 0xF2, 0xF7, 0x16, 0xF9, 0x7A, 0x48, 0x6B, 0x49, 0x9C, 0x7F, 0x01, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x70, 0x51, 0x4D, 0xC4, 0x7F, 0x01, 0x00, 0x3C, 0x00, 0x00, 0x00, 0x40, 0x49, 0x00, 0xF1, 0x52, 0x00, 0x3A, 0x4A, 0xA8, 0x81, 0x28, 0x83, 0xE8, 0x83, 0xE8, 0x84, 0xA8, 0x85, 0x2A, 0x60, 0x39, 0x48, 0x41, 0xF2, 0x11, 0x12, 0x2A, 0x85, 0x18, 0x90, 0x19, 0x91 , -0x39, 0x49, 0x1A, 0x91, 0x39, 0x49, 0x1B, 0x91, 0x39, 0x49, 0x20, 0x46, 0xDF, 0xF8, 0xC4, 0x90, 0x1C, 0x91, 0x38, 0x49, 0xDF, 0xF8, 0xC0, 0xB0, 0x31, 0x4E, 0x1D, 0x91, 0x48, 0x80, 0x01, 0x00, 0x04, 0x00, 0x00, 0x00, 0x0D, 0xF0, 0x7C, 0xFA, 0xB4, 0x80, 0x01, 0x00, 0x34, 0x00, 0x00, 0x00, 0x34, 0x12, 0x66, 0x09, 0x84, 0x6B, 0x00, 0x20, 0x94, 0x70, 0x00, 0x20, 0xB4, 0x70, 0x00, 0x20, 0xC4, 0x78, 0x00, 0x20, 0x50, 0x7A, 0x00, 0x20, 0xFE, 0xFF, 0x03, 0x00, 0xA4, 0x70, 0x00, 0x20, 0xB0, 0x70, 0x00, 0x20, 0xB8, 0x70, 0x00, 0x20, 0x60, 0x55, 0x30, 0x80, 0x3C, 0x5C, 0x00, 0x20, 0x04, 0x74, 0x00, 0x20, 0xB8, 0xE4, 0x01, 0x00, 0x0C, 0x00, 0x00, 0x00, 0x20, 0x78, 0x07, 0xF0, 0x01, 0xFC, 0x20, 0x78, 0x07, 0xF0, 0x7A, 0xFB, 0x04, 0x4D, 0x02, 0x00, 0xC8, 0x00, 0x00, 0x00, 0x2D, 0xE9, 0xF0, 0x4F, 0xAD, 0xF1, 0x8C, 0x0D, 0x04, 0x68, 0x0F, 0x30, 0x03, 0x94, 0xFE, 0xF7, 0xDB, 0xFA, 0x04, 0xF1, 0x14, 0x00 , -0x04, 0x90, 0x21, 0x7D, 0x00, 0x20, 0x21, 0xF0, 0x73, 0x01, 0x88, 0x29, 0x08, 0xBF, 0x01, 0x20, 0x05, 0x90, 0x03, 0x98, 0x00, 0x1D, 0x06, 0x90, 0x5D, 0x48, 0x00, 0x68, 0x01, 0x28, 0x40, 0xF0, 0xFA, 0x83, 0x5B, 0x4D, 0x5C, 0x48, 0xDF, 0xF8, 0x70, 0x91, 0x29, 0x68, 0xDF, 0xF8, 0x70, 0x81, 0xDF, 0xF8, 0x74, 0xA1, 0x88, 0x42, 0x21, 0xD1, 0x10, 0x22, 0x00, 0x21, 0x48, 0x46, 0x4F, 0x46, 0xFB, 0xF7, 0xB7, 0xFE, 0x10, 0x22, 0x00, 0x21, 0x40, 0x46, 0xFB, 0xF7, 0xB2, 0xFE, 0x54, 0x49, 0x08, 0x68, 0x40, 0xF4, 0x80, 0x10, 0x08, 0x60, 0x01, 0x20, 0x51, 0x46, 0x08, 0x60, 0x00, 0x21, 0x29, 0x60, 0x39, 0x78, 0x46, 0x46, 0x00, 0x91, 0x31, 0x78, 0x41, 0xF2, 0x11, 0x13, 0x04, 0x22, 0x01, 0x91, 0x07, 0x21, 0x02, 0x90, 0x03, 0x20, 0xF3, 0xF7, 0x41, 0xFC, 0x51, 0x46, 0x07, 0x91, 0x08, 0x68, 0x56, 0x49, 0xDF, 0xF8, 0x5C, 0xB1, 0x01, 0x28, 0x08, 0x91, 0x56, 0x49, 0xDF, 0xF8, 0x48, 0xA1, 0x09, 0x91, 0x55, 0x49 , -0x0A, 0x91, 0x44, 0x49, 0x0B, 0x91, 0x44, 0x49, 0x0C, 0x91, 0x44, 0x49, 0x0D, 0x91, 0x44, 0x49, 0x0E, 0x91, 0x44, 0x49, 0x0F, 0x91, 0x44, 0x49, 0x10, 0x91, 0x44, 0x49, 0xCC, 0x4D, 0x02, 0x00, 0xC8, 0x00, 0x00, 0x00, 0x11, 0x91, 0x44, 0x49, 0x12, 0x91, 0x44, 0x49, 0x13, 0x91, 0x44, 0x49, 0x14, 0x91, 0x44, 0x49, 0x15, 0x91, 0x44, 0x49, 0x16, 0x91, 0x9F, 0x49, 0x17, 0x91, 0x9F, 0x49, 0x18, 0x91, 0x9F, 0x49, 0x19, 0x91, 0x9F, 0x49, 0x1A, 0x91, 0x9F, 0x49, 0x1B, 0x91, 0x9F, 0x49, 0x1C, 0x91, 0x9F, 0x49, 0x1D, 0x91, 0x9F, 0x49, 0x1E, 0x91, 0x9F, 0x49, 0x1F, 0x91, 0x40, 0xF0, 0x00, 0x81, 0x04, 0x98, 0x40, 0x78, 0x00, 0xF0, 0x03, 0x01, 0x01, 0x29, 0x40, 0xF0, 0xF9, 0x80, 0x04, 0x99, 0x09, 0x78, 0x01, 0xF0, 0x0C, 0x01, 0x08, 0x29, 0x40, 0xF0, 0xF2, 0x80, 0x06, 0x99, 0x09, 0x88, 0xA1, 0xF1, 0x3C, 0x01, 0x0E, 0xB2, 0x05, 0x99, 0x11, 0xB1, 0xA6, 0xF1, 0x02, 0x06, 0x36, 0xB2, 0xC0, 0x09, 0x4F, 0xF0 , -0x00, 0x07, 0x15, 0xD3, 0x08, 0x3E, 0x36, 0xB2, 0x03, 0x2E, 0x10, 0xD0, 0x17, 0x2E, 0x0E, 0xD0, 0x08, 0x3E, 0x36, 0xB2, 0x03, 0x2E, 0x08, 0xD0, 0x17, 0x2E, 0x06, 0xD0, 0x36, 0x1F, 0x36, 0xB2, 0x03, 0x2E, 0x14, 0xBF, 0x17, 0x2E, 0x02, 0x27, 0x02, 0xE0, 0x03, 0x27, 0x00, 0xE0, 0x01, 0x27, 0x03, 0x2E, 0x18, 0xBF, 0x17, 0x2E, 0x04, 0x9A, 0x40, 0xF0, 0xC8, 0x80, 0x0A, 0x32, 0x12, 0xF8, 0x01, 0x1B, 0x05, 0x24, 0x12, 0xF8, 0x01, 0x3B, 0x4B, 0x40, 0x64, 0x1E, 0xD9, 0xB2, 0xF9, 0xD1, 0x81, 0xEA, 0x21, 0x11, 0x03, 0x2E, 0x94, 0x4E, 0x02, 0x00, 0xC8, 0x00, 0x00, 0x00, 0x01, 0xF0, 0x0F, 0x01, 0x48, 0x46, 0x35, 0xD0, 0x43, 0x46, 0xCA, 0x5C, 0x52, 0x1C, 0xCA, 0x54, 0x0C, 0x18, 0x33, 0xE0, 0x50, 0x57, 0x02, 0x00, 0x04, 0x74, 0x00, 0x20, 0x34, 0x12, 0x66, 0x09, 0x60, 0x57, 0x02, 0x00, 0x70, 0x57, 0x02, 0x00, 0xC8, 0x48, 0x30, 0x80, 0x4C, 0x57, 0x02, 0x00, 0x88, 0x57, 0x02, 0x00, 0x80, 0x57, 0x02, 0x00 , -0x18, 0x58, 0x02, 0x00, 0x20, 0x58, 0x02, 0x00, 0x28, 0x58, 0x02, 0x00, 0x30, 0x58, 0x02, 0x00, 0x38, 0x58, 0x02, 0x00, 0x40, 0x58, 0x02, 0x00, 0xE4, 0x58, 0x02, 0x00, 0xE2, 0x58, 0x02, 0x00, 0x14, 0x58, 0x02, 0x00, 0xEF, 0x58, 0x02, 0x00, 0xE0, 0x58, 0x02, 0x00, 0xEE, 0x58, 0x02, 0x00, 0x5C, 0x57, 0x02, 0x00, 0xE6, 0x58, 0x02, 0x00, 0xE8, 0x58, 0x02, 0x00, 0x0C, 0x18, 0x20, 0x78, 0x40, 0x1C, 0x20, 0x70, 0x20, 0x78, 0x43, 0x46, 0x03, 0xEB, 0x01, 0x08, 0x0A, 0x28, 0x76, 0xDB, 0x98, 0xF8, 0x00, 0x00, 0x0A, 0x28, 0x72, 0xDB, 0x94, 0x48, 0x00, 0x25, 0x01, 0x60, 0x04, 0x98, 0x00, 0xF1, 0x0A, 0x09, 0x40, 0x78, 0x41, 0x08, 0x24, 0xBF, 0x04, 0x99, 0x09, 0x1D, 0x04, 0xD2, 0x80, 0x08, 0x2E, 0xBF, 0x49, 0x46, 0x04, 0x99, 0x10, 0x31, 0x0B, 0x98, 0x06, 0x22, 0xFA, 0xF7, 0xB9, 0xFC, 0x0C, 0x98, 0x06, 0x22, 0x49, 0x46, 0xFA, 0xF7, 0xB4, 0xFC, 0x9B, 0x48, 0x9A, 0x49, 0x5C, 0x4F, 0x02, 0x00, 0xC8, 0x00 , -0x00, 0x00, 0x00, 0x78, 0x08, 0x22, 0x08, 0x60, 0x58, 0x46, 0x07, 0x60, 0x0D, 0x98, 0x29, 0x46, 0xFB, 0xF7, 0xAF, 0xFD, 0x08, 0x22, 0x0E, 0x98, 0x29, 0x46, 0xFB, 0xF7, 0xAA, 0xFD, 0x08, 0x22, 0x0F, 0x98, 0x29, 0x46, 0xFB, 0xF7, 0xA5, 0xFD, 0x08, 0x22, 0x10, 0x98, 0x29, 0x46, 0xFB, 0xF7, 0xA0, 0xFD, 0x08, 0x22, 0x11, 0x98, 0x29, 0x46, 0xFB, 0xF7, 0x9B, 0xFD, 0x08, 0x22, 0x12, 0x98, 0x29, 0x46, 0xFB, 0xF7, 0x96, 0xFD, 0x07, 0x99, 0x02, 0x20, 0x08, 0x60, 0x13, 0x99, 0x28, 0x46, 0x08, 0x80, 0x08, 0x99, 0x08, 0x70, 0x14, 0x99, 0x08, 0x70, 0x15, 0x99, 0x08, 0x60, 0x16, 0x99, 0x08, 0x70, 0x17, 0x99, 0x08, 0x60, 0x18, 0x99, 0x08, 0x60, 0x19, 0x99, 0x08, 0x60, 0x09, 0x99, 0x08, 0x80, 0x0A, 0x99, 0x08, 0x80, 0x1A, 0x99, 0x08, 0x80, 0x7D, 0x49, 0x0D, 0x60, 0x1B, 0x99, 0x08, 0x70, 0x1C, 0x99, 0x08, 0x70, 0x1D, 0x99, 0x08, 0x70, 0x1E, 0x99, 0x08, 0x80, 0x1F, 0x99, 0x08, 0x80, 0x51, 0x46, 0x08, 0x80 , -0x20, 0x78, 0x00, 0x96, 0x04, 0x22, 0x01, 0x90, 0x98, 0xF8, 0x00, 0x00, 0x41, 0xF2, 0x14, 0x13, 0x07, 0x21, 0x02, 0x90, 0x03, 0x20, 0xF3, 0xF7, 0x07, 0xFB, 0x07, 0x98, 0xA2, 0x49, 0x00, 0x68, 0x20, 0x91, 0xA2, 0x49, 0x05, 0x28, 0x21, 0x91, 0x9E, 0x49, 0x22, 0x91, 0x40, 0xF0, 0x37, 0x82, 0x04, 0x98, 0x40, 0x78, 0x24, 0x50, 0x02, 0x00, 0xC8, 0x00, 0x00, 0x00, 0x41, 0x08, 0x24, 0xBF, 0x04, 0x99, 0x09, 0x1D, 0x05, 0xD2, 0x80, 0x08, 0x27, 0xBF, 0x04, 0x99, 0x0A, 0x31, 0x04, 0x99, 0x10, 0x31, 0x0B, 0x98, 0xF8, 0xF7, 0x2D, 0xFC, 0x01, 0x28, 0x04, 0x98, 0x40, 0xF0, 0x23, 0x82, 0x40, 0x78, 0x00, 0xF0, 0x03, 0x00, 0x03, 0x28, 0x18, 0xD0, 0x02, 0x28, 0x07, 0xBF, 0x04, 0x99, 0x10, 0x31, 0x04, 0x99, 0x0A, 0x31, 0x13, 0xE0, 0x48, 0x58, 0x02, 0x00, 0x4C, 0x58, 0x02, 0x00, 0x50, 0x58, 0x02, 0x00, 0xF0, 0x58, 0x02, 0x00, 0xF2, 0x58, 0x02, 0x00, 0xF3, 0x58, 0x02, 0x00, 0xF4, 0x58, 0x02, 0x00, 0xEA, 0x58 , -0x02, 0x00, 0xEC, 0x58, 0x02, 0x00, 0x04, 0x99, 0x18, 0x31, 0x0C, 0x98, 0xF8, 0xF7, 0x06, 0xFC, 0x04, 0x99, 0x01, 0x28, 0x40, 0xF0, 0xFC, 0x81, 0x49, 0x78, 0x01, 0xF0, 0x03, 0x01, 0x01, 0x29, 0x40, 0xF0, 0xF6, 0x81, 0x59, 0x46, 0x09, 0x68, 0x04, 0x9A, 0x8E, 0x46, 0x51, 0x46, 0xD2, 0x8A, 0x0B, 0x88, 0x12, 0x11, 0x93, 0x42, 0x00, 0xF0, 0x37, 0x82, 0x0A, 0x80, 0x06, 0x99, 0x09, 0x88, 0x3C, 0x39, 0x0B, 0xB2, 0x71, 0x46, 0x49, 0x1E, 0x09, 0xD0, 0x49, 0x1E, 0x04, 0xD0, 0x49, 0x1E, 0x08, 0xD1, 0xA3, 0xF1, 0x10, 0x03, 0x04, 0xE0, 0xA3, 0xF1, 0x14, 0x03, 0x01, 0xE0, 0xA3, 0xF1, 0x08, 0x03, 0x1B, 0xB2, 0x05, 0x98, 0x10, 0xB1, 0xA3, 0xF1, 0x02, 0x03, 0x1B, 0xB2, 0xEC, 0x50, 0x02, 0x00, 0xC8, 0x00, 0x00, 0x00, 0x00, 0x2B, 0x00, 0xF1, 0xCE, 0x81, 0x16, 0x98, 0x40, 0xF2, 0x77, 0x51, 0x99, 0x42, 0x0B, 0x90, 0x14, 0x98, 0x05, 0x90, 0x00, 0xF0, 0xA3, 0x81, 0x08, 0x46, 0x00, 0xF1, 0x3C, 0x00, 0x98, 0x42 , -0x05, 0x9A, 0x00, 0xF0, 0x9A, 0x81, 0xDF, 0xF8, 0x48, 0x82, 0x14, 0x78, 0x0B, 0x9A, 0xBB, 0x2C, 0x12, 0x78, 0x0C, 0x92, 0x63, 0xD1, 0xDD, 0xF8, 0x68, 0xC0, 0xBC, 0xF9, 0x00, 0x20, 0x91, 0x42, 0x18, 0xBF, 0x90, 0x42, 0x5B, 0xD1, 0x1C, 0x2B, 0x4F, 0xF0, 0x00, 0x00, 0xC0, 0xF2, 0x82, 0x81, 0x3D, 0x2B, 0x13, 0x9D, 0x80, 0xF2, 0x7E, 0x81, 0xA3, 0xF1, 0x1C, 0x01, 0x09, 0xB2, 0x29, 0x80, 0x1E, 0x9A, 0xDD, 0xF8, 0x30, 0x90, 0xB2, 0xF9, 0x00, 0x60, 0xB9, 0xF1, 0x01, 0x0F, 0x15, 0xD1, 0xDD, 0xF8, 0x24, 0x90, 0x03, 0x2E, 0x0D, 0xDA, 0xB9, 0xF9, 0x00, 0x70, 0xB9, 0x42, 0x07, 0xD0, 0x01, 0x26, 0x16, 0x80, 0x4A, 0x46, 0x0E, 0x46, 0x03, 0xE0, 0xC0, 0x46, 0x90, 0x57, 0x02, 0x00, 0x76, 0x1C, 0x16, 0x80, 0x1B, 0x9A, 0x16, 0x78, 0x1D, 0x9A, 0x16, 0x70, 0x0C, 0x9A, 0x1F, 0x9E, 0x02, 0x2A, 0x28, 0xD1, 0xB6, 0xF9, 0x00, 0x20, 0xBE, 0xF1, 0x00, 0x0F, 0x1A, 0xD0, 0x03, 0x2A, 0x35, 0x46, 0x0B, 0xDA, 0x0A, 0x9E , -0xB6, 0xF9, 0x00, 0x70, 0xB9, 0x42, 0x04, 0xD0, 0x01, 0x22, 0x2A, 0x80, 0x0A, 0x46, 0x35, 0x46, 0x00, 0xE0, 0xB4, 0x51, 0x02, 0x00, 0xC8, 0x00, 0x00, 0x00, 0x52, 0x1C, 0x2A, 0x80, 0x1C, 0x99, 0x0A, 0x78, 0x1D, 0x99, 0x0A, 0x70, 0x0F, 0xE0, 0xC0, 0x46, 0x58, 0x57, 0x02, 0x00, 0xA6, 0x64, 0x00, 0x20, 0x54, 0x57, 0x02, 0x00, 0x28, 0x80, 0x05, 0x99, 0x08, 0x70, 0x08, 0x9A, 0x11, 0x78, 0x41, 0xF0, 0x04, 0x01, 0x11, 0x70, 0x04, 0x46, 0x45, 0x46, 0xAC, 0xF8, 0x00, 0x00, 0x28, 0x70, 0xCC, 0x2C, 0x09, 0x9A, 0x40, 0xF0, 0x00, 0x81, 0xDD, 0xF8, 0x7C, 0xC0, 0x0A, 0x99, 0x1E, 0x9F, 0x45, 0x46, 0xB1, 0xF9, 0x00, 0x60, 0xB2, 0xF9, 0x00, 0x90, 0x28, 0x78, 0xCD, 0xF8, 0x50, 0xC0, 0x16, 0x91, 0x0A, 0x97, 0x13, 0x92, 0x09, 0x95, 0x0C, 0x99, 0x01, 0x29, 0x05, 0xD1, 0x05, 0x9A, 0xB0, 0xEB, 0x49, 0x0F, 0x01, 0xD1, 0x00, 0x21, 0x11, 0x70, 0x0C, 0x99, 0x02, 0x29, 0x05, 0xD1, 0x05, 0x9A, 0xB0, 0xEB, 0x46, 0x0F , -0x01, 0xD1, 0x00, 0x21, 0x11, 0x70, 0xB3, 0xF5, 0x14, 0x7F, 0x40, 0xF3, 0xBA, 0x80, 0x40, 0xF2, 0x51, 0x31, 0x99, 0x42, 0x08, 0x99, 0x40, 0xF3, 0xB4, 0x80, 0x09, 0x78, 0x06, 0x29, 0x00, 0xF0, 0xB0, 0x80, 0xA3, 0xF2, 0x51, 0x21, 0x0B, 0xB2, 0x4F, 0xEA, 0xE3, 0x01, 0x03, 0xEB, 0x11, 0x71, 0x4F, 0xEA, 0x21, 0x11, 0xCA, 0xB2, 0x4F, 0xEA, 0xE3, 0x01, 0x03, 0xEB, 0x11, 0x71, 0x15, 0x9D, 0x21, 0xF0, 0x0F, 0x01, 0xA3, 0xEB, 0x01, 0x03, 0x1D, 0x99, 0x2E, 0x68, 0x7C, 0x52, 0x02, 0x00, 0xC8, 0x00, 0x00, 0x00, 0x91, 0xF8, 0x00, 0xE0, 0x5F, 0xFA, 0x83, 0xF8, 0x60, 0xB1, 0x31, 0x18, 0x11, 0xF8, 0x01, 0x1C, 0x51, 0x40, 0xCB, 0xB2, 0x07, 0xE0, 0xC0, 0x46, 0x58, 0x58, 0x02, 0x00, 0x54, 0x58, 0x02, 0x00, 0xDC, 0x58, 0x02, 0x00, 0x13, 0x46, 0x19, 0x99, 0xDD, 0xF8, 0x6C, 0xA0, 0xDD, 0xF8, 0x70, 0xB0, 0xD1, 0xF8, 0x00, 0xC0, 0x00, 0xF0, 0x0F, 0x01, 0x99, 0x42, 0x22, 0xD0, 0x0A, 0x9B, 0x86, 0x45, 0x9A, 0xF8 , -0x00, 0x10, 0xB3, 0xF9, 0x00, 0x30, 0x9B, 0xF8, 0x00, 0x50, 0x15, 0xDD, 0x37, 0x5C, 0x44, 0x1C, 0x82, 0xEA, 0x07, 0x0C, 0x04, 0xF0, 0x0F, 0x07, 0x67, 0x45, 0x0B, 0xD0, 0xA6, 0x45, 0x06, 0x44, 0x0A, 0xDD, 0x76, 0x78, 0x72, 0x40, 0x86, 0x1C, 0x06, 0xF0, 0x0F, 0x06, 0x96, 0x42, 0x03, 0xD1, 0xC0, 0x1C, 0x4D, 0xE0, 0x80, 0x1C, 0x4B, 0xE0, 0x05, 0x9E, 0x00, 0x22, 0x32, 0x70, 0x4A, 0xE0, 0x00, 0xF0, 0x1F, 0x01, 0x01, 0x22, 0x8A, 0x40, 0x17, 0x99, 0xC4, 0x10, 0x0B, 0x68, 0x24, 0xF0, 0x03, 0x01, 0x5C, 0xF8, 0x01, 0x70, 0x3A, 0x42, 0x32, 0xD1, 0x5F, 0x58, 0x3A, 0x42, 0x06, 0x44, 0x1F, 0xD0, 0x18, 0x9B, 0x37, 0x78, 0x1B, 0x68, 0xB8, 0x45, 0x04, 0xD1, 0x58, 0x58, 0x02, 0x42, 0x19, 0xD0, 0x63, 0x46, 0x15, 0xE0, 0xA1, 0x10, 0x8C, 0x00, 0x19, 0x59, 0x91, 0x43, 0x19, 0x51, 0x00, 0x90, 0x30, 0x78, 0x01, 0x90, 0x44, 0x53, 0x02, 0x00, 0xC8, 0x00, 0x00, 0x00, 0x03, 0x20, 0x06, 0x21, 0x02, 0x46, 0x4D, 0xF6 , -0x80, 0x53, 0xF3, 0xF7, 0x63, 0xF9, 0x09, 0x99, 0x28, 0x68, 0x0E, 0x78, 0x36, 0x18, 0x06, 0xE0, 0xE3, 0x58, 0x02, 0x00, 0xA0, 0x10, 0x81, 0x00, 0x58, 0x58, 0x02, 0x43, 0x5A, 0x50, 0x86, 0xF8, 0x00, 0x80, 0x0B, 0x98, 0x00, 0x78, 0x0C, 0x90, 0x13, 0x98, 0xB0, 0xF9, 0x00, 0x90, 0x09, 0x98, 0x00, 0x78, 0x0A, 0x9A, 0x40, 0x1C, 0x9B, 0xF8, 0x00, 0x50, 0x9A, 0xF8, 0x00, 0x10, 0xB2, 0xF9, 0x00, 0x30, 0x09, 0x9A, 0xC0, 0xB2, 0x10, 0x70, 0x0C, 0x9A, 0x01, 0x2A, 0x03, 0xD1, 0x88, 0x42, 0xC8, 0xBF, 0x8A, 0xF8, 0x00, 0x00, 0x0C, 0x99, 0x02, 0x29, 0x07, 0xD1, 0xA8, 0x42, 0xC8, 0xBF, 0x8B, 0xF8, 0x00, 0x00, 0x02, 0xE0, 0x0A, 0x98, 0xB0, 0xF9, 0x00, 0x30, 0xB9, 0xF1, 0x00, 0x0F, 0x06, 0xDD, 0x03, 0x2B, 0x04, 0xD1, 0x11, 0x98, 0x01, 0x22, 0x49, 0x46, 0x00, 0xF0, 0x72, 0xFB, 0x16, 0x98, 0xB0, 0xF9, 0x00, 0x10, 0x14, 0x98, 0x00, 0x29, 0xB0, 0xF9, 0x00, 0x00, 0x05, 0xDD, 0x03, 0x28, 0x03, 0xD1, 0x12, 0x98 , -0x02, 0x22, 0x00, 0xF0, 0x64, 0xFB, 0x05, 0x98, 0x04, 0x78, 0x0B, 0x98, 0x00, 0x78, 0x0C, 0x90, 0x08, 0x98, 0xBB, 0x2C, 0x01, 0x78, 0x02, 0xD0, 0xAA, 0x2C, 0x2F, 0xD0, 0x31, 0xE0, 0x0C, 0x98, 0x01, 0x28, 0x0B, 0xD1, 0x0D, 0x98, 0x17, 0x9A, 0x10, 0x60, 0x0C, 0x54, 0x02, 0x00, 0xC8, 0x00, 0x00, 0x00, 0x0F, 0x98, 0x18, 0x9A, 0x10, 0x60, 0x19, 0x9A, 0x11, 0x98, 0x10, 0x60, 0x47, 0x4A, 0x15, 0x98, 0x02, 0x60, 0x0C, 0x98, 0x02, 0x28, 0x0B, 0xD1, 0x0E, 0x98, 0x17, 0x9A, 0x10, 0x60, 0x10, 0x98, 0x18, 0x9A, 0x10, 0x60, 0x19, 0x9A, 0x12, 0x98, 0x10, 0x60, 0x41, 0x4A, 0x15, 0x98, 0x02, 0x60, 0xCC, 0x20, 0x0F, 0xE0, 0x08, 0x99, 0x09, 0x78, 0x0C, 0xE0, 0x02, 0x20, 0x00, 0xE0, 0x01, 0x20, 0x0B, 0x99, 0x08, 0x70, 0x1A, 0x99, 0x0B, 0x80, 0x13, 0x99, 0x00, 0x20, 0x08, 0x80, 0x08, 0x98, 0x01, 0x78, 0xBB, 0x20, 0x05, 0x9A, 0x10, 0x70, 0x06, 0x29, 0x07, 0x99, 0x11, 0xD1, 0x06, 0x20, 0x08, 0x60, 0x20, 0x98 , -0x00, 0x25, 0x05, 0x70, 0x21, 0x98, 0x29, 0x46, 0x04, 0x22, 0xFB, 0xF7, 0x27, 0xFB, 0x01, 0x20, 0x00, 0xF0, 0x3A, 0xFA, 0x02, 0x20, 0x00, 0xF0, 0x37, 0xFA, 0x22, 0x98, 0x05, 0x60, 0x07, 0x98, 0x04, 0x99, 0x00, 0x68, 0x07, 0x28, 0x44, 0xD1, 0x09, 0x78, 0x03, 0x9C, 0x80, 0x29, 0x40, 0xD1, 0x38, 0x34, 0x21, 0x78, 0x64, 0x1C, 0x22, 0x46, 0x00, 0x29, 0x3A, 0xD1, 0x20, 0x98, 0x90, 0xF8, 0x00, 0xA0, 0x22, 0x98, 0x05, 0x90, 0xD0, 0xF8, 0x00, 0x90, 0x51, 0x46, 0x48, 0x46, 0xFD, 0xF7, 0x79, 0xF9, 0x5F, 0xFA, 0x80, 0xF8, 0x21, 0x9F, 0x15, 0x78, 0x51, 0x46, 0x48, 0x46, 0x17, 0xF8, 0x08, 0x30, 0xFD, 0xF7, 0xD4, 0x54, 0x02, 0x00, 0xC8, 0x00, 0x00, 0x00, 0x6F, 0xF9, 0x1E, 0x46, 0x1B, 0x1D, 0xC0, 0xB2, 0x38, 0x5C, 0x00, 0x1D, 0xA8, 0x42, 0x28, 0x46, 0x07, 0xDD, 0x80, 0x18, 0x82, 0x1C, 0x10, 0x78, 0x2D, 0x18, 0xAD, 0x1C, 0xAD, 0xB2, 0xAB, 0x42, 0xF7, 0xDC, 0x04, 0xF8, 0x01, 0x6B, 0x11, 0x49, 0x32, 0x46 , -0x20, 0x46, 0x01, 0xEB, 0x48, 0x11, 0xFA, 0xF7, 0xDC, 0xF9, 0xAD, 0x1B, 0xFF, 0x20, 0x34, 0x19, 0xAD, 0x1E, 0x04, 0xF8, 0x01, 0x0B, 0x25, 0x70, 0x05, 0x98, 0x01, 0x68, 0x49, 0x1C, 0x01, 0x60, 0x07, 0x98, 0x00, 0x68, 0x07, 0x28, 0x04, 0xD0, 0x06, 0x99, 0x08, 0x68, 0x20, 0xF4, 0x80, 0x30, 0x08, 0x60, 0x23, 0xB0, 0xBD, 0xE8, 0xF0, 0x8F, 0xC0, 0x46, 0x94, 0x57, 0x02, 0x00, 0xD4, 0x57, 0x02, 0x00, 0x5C, 0x58, 0x02, 0x00, 0x6E, 0x48, 0x2D, 0xE9, 0xF0, 0x47, 0x6E, 0x4D, 0x82, 0x89, 0x4A, 0xF6, 0x55, 0x21, 0xAD, 0xF5, 0xFE, 0x7D, 0x91, 0x42, 0x4F, 0xF0, 0x00, 0x01, 0xAD, 0xF1, 0x38, 0x0D, 0x12, 0xD1, 0x29, 0x60, 0x68, 0x4A, 0x11, 0x70, 0x41, 0xF2, 0x10, 0x41, 0x81, 0x81, 0x4F, 0xF6, 0xFF, 0x70, 0x66, 0x49, 0x08, 0x60, 0x28, 0x68, 0x00, 0x90, 0x02, 0x22, 0x05, 0x21, 0x03, 0x20, 0x41, 0xF2, 0x34, 0x23, 0xF3, 0xF7, 0x48, 0xF8, 0x29, 0x68, 0x61, 0x4C, 0x01, 0x29, 0x20, 0x68, 0x40, 0xF0, 0xAF, 0x80 , -0x5F, 0x4D, 0x02, 0x28, 0x29, 0x68, 0x23, 0xD1, 0x9C, 0x55, 0x02, 0x00, 0xC8, 0x00, 0x00, 0x00, 0x5E, 0x48, 0x00, 0x68, 0x5F, 0x4A, 0x12, 0x5C, 0x00, 0x92, 0x01, 0x91, 0x5E, 0x49, 0x09, 0x68, 0x02, 0x91, 0x5B, 0x49, 0x0B, 0x5C, 0x03, 0x20, 0x07, 0x21, 0x04, 0x22, 0xF3, 0xF7, 0x2E, 0xF8, 0x5B, 0x49, 0x4A, 0x79, 0x59, 0x48, 0x00, 0x92, 0x02, 0x79, 0x01, 0x92, 0x40, 0x79, 0x04, 0x22, 0x02, 0x90, 0x03, 0x20, 0x0B, 0x79, 0x07, 0x21, 0xF3, 0xF7, 0x20, 0xF8, 0x03, 0x20, 0x20, 0x60, 0xEC, 0xF7, 0x1A, 0xFF, 0x20, 0x68, 0x29, 0x68, 0x04, 0x28, 0x15, 0xD1, 0x0D, 0x20, 0x8D, 0xF8, 0x10, 0x00, 0x00, 0x25, 0x8D, 0xF8, 0x14, 0x50, 0x8D, 0xF8, 0x15, 0x10, 0x28, 0x46, 0x63, 0x21, 0x00, 0xF0, 0xAA, 0xFB, 0x63, 0x21, 0x28, 0x46, 0x00, 0xF0, 0xFA, 0xFA, 0x03, 0xA9, 0x04, 0xA8, 0xE0, 0xF7, 0xCA, 0xFC, 0x05, 0x20, 0x20, 0x60, 0x46, 0x4D, 0x05, 0x28, 0x29, 0x68, 0x01, 0xF1, 0x01, 0x01, 0x29, 0x60, 0x1D, 0xD1 , -0x44, 0x4A, 0x8A, 0x42, 0x1A, 0xD1, 0x43, 0x48, 0x01, 0x68, 0x00, 0x91, 0x40, 0x68, 0x01, 0x90, 0x03, 0x20, 0x02, 0x46, 0x06, 0x21, 0x41, 0x4E, 0x33, 0x46, 0x22, 0x3B, 0xF2, 0xF7, 0xEB, 0xFF, 0x3E, 0x48, 0x01, 0x68, 0x00, 0x91, 0x40, 0x68, 0x33, 0x46, 0x06, 0x21, 0x01, 0x90, 0x03, 0x20, 0x02, 0x46, 0xF2, 0xF7, 0xE0, 0xFF, 0x00, 0x20, 0x28, 0x60, 0x20, 0x68, 0x06, 0x28, 0x47, 0xD1, 0x4F, 0xF0, 0x64, 0x56, 0x02, 0x00, 0xC8, 0x00, 0x00, 0x00, 0x07, 0x0A, 0xC4, 0xF8, 0x00, 0xA0, 0x03, 0x20, 0x48, 0xF2, 0x70, 0x53, 0x01, 0x22, 0x04, 0x21, 0xF2, 0xF7, 0xD0, 0xFF, 0xDF, 0xF8, 0xCC, 0x80, 0x31, 0x4F, 0x48, 0xF2, 0x70, 0x59, 0x01, 0x25, 0x49, 0xEA, 0x05, 0x03, 0x01, 0x22, 0x04, 0x21, 0x03, 0x20, 0xF2, 0xF7, 0xC3, 0xFF, 0x00, 0x24, 0x17, 0xF8, 0x02, 0x0F, 0x20, 0xE0, 0x69, 0x01, 0x04, 0xEB, 0x08, 0x02, 0x88, 0x18, 0xC6, 0x1C, 0x43, 0x78, 0x00, 0x93, 0x80, 0x78, 0x01, 0x90, 0x30, 0x78, 0x02, 0x90 , -0x53, 0x5C, 0x51, 0x46, 0x04, 0x22, 0x03, 0x20, 0xF2, 0xF7, 0xAE, 0xFF, 0x38, 0x78, 0x01, 0x1B, 0xB1, 0xF1, 0xFF, 0x3F, 0x08, 0xD1, 0xF0, 0x78, 0x00, 0x90, 0xB3, 0x78, 0x03, 0x20, 0x02, 0x22, 0x05, 0x21, 0xF2, 0xF7, 0xA1, 0xFF, 0x38, 0x78, 0x24, 0x1D, 0xE4, 0xB2, 0xA0, 0x42, 0xDC, 0xDC, 0xAD, 0x1C, 0xED, 0xB2, 0x04, 0x2D, 0xCD, 0xDB, 0x63, 0x21, 0x4F, 0xF4, 0x05, 0x70, 0xF1, 0xF7, 0xA3, 0xFC, 0xE1, 0xF7, 0x85, 0xFD, 0x7F, 0xB0, 0x0E, 0xB0, 0xBD, 0xE8, 0xF0, 0x87, 0xC0, 0x46, 0x04, 0x74, 0x00, 0x20, 0x50, 0x57, 0x02, 0x00, 0x6C, 0x5D, 0x02, 0x00, 0x40, 0x00, 0x3D, 0x80, 0x4C, 0x57, 0x02, 0x00, 0x58, 0x57, 0x02, 0x00, 0x90, 0x57, 0x02, 0x00, 0x60, 0x57, 0x02, 0x00, 0x70, 0x57, 0x02, 0x00, 0x5C, 0x57, 0x02, 0x00, 0x80, 0x57, 0x02, 0x00, 0x2C, 0x57, 0x02, 0x00, 0xC8, 0x00, 0x00, 0x00, 0x88, 0x57, 0x02, 0x00, 0x54, 0x57, 0x02, 0x00, 0xFF, 0xFF, 0x03, 0x00, 0x38, 0x58, 0x02, 0x00, 0x40, 0x58 , -0x02, 0x00, 0x66, 0x55, 0xDD, 0xEE, 0xDB, 0x58, 0x02, 0x00, 0x5C, 0x58, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 , -0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xF4, 0x57, 0x02, 0x00, 0xC8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 , -0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xBC, 0x58, 0x02, 0x00, 0xC8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 , -0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x2D, 0xE9, 0xFE, 0x4F, 0x4A, 0x4A, 0x49, 0x4D, 0x00, 0x90, 0xB2, 0xF9, 0x00, 0x20, 0x43, 0xA3, 0x29, 0x78, 0x01, 0x93, 0x43, 0xA3, 0x01, 0x28, 0x02, 0x93, 0x47, 0x4E, 0xDF, 0xF8, 0x1C, 0x81, 0xDF, 0xF8, 0x1C, 0x91, 0x1E, 0xD0, 0x43, 0x48, 0x04, 0x78, 0x48, 0x01, 0x87, 0x19, 0x30, 0x18, 0x01, 0x99, 0x06, 0x22, 0xF9, 0xF7, 0xC8, 0xFF, 0x40, 0x46, 0x01, 0x78, 0x00, 0x68, 0x07, 0xF1, 0x06, 0x07, 0x07, 0xF8, 0x01, 0x1B, 0x07, 0xF8, 0x01, 0x4B, 0x4F, 0xF0, 0x00, 0x01, 0x07, 0xF8, 0x01, 0x1B, 0x20, 0xB9, 0x39, 0x70, 0x28, 0x78, 0x4E, 0x46, 0x0A, 0x21, 0x58, 0xE0, 0xDF, 0xF8, 0xE4, 0xB0, 0x0F, 0xE0, 0xD4, 0xB2, 0x48, 0x01, 0x87, 0x19, 0x30, 0x18, 0x02, 0x99, 0x07, 0x22, 0xF9, 0xF7, 0xAA, 0xFF, 0xFF, 0x1D, 0x00, 0x20, 0xDF, 0xF8, 0xCC, 0xB0, 0x07, 0xF8, 0x01, 0x4B, 0x07, 0xF8, 0x01, 0x0B, 0x16, 0x2C, 0xB2, 0x46, 0xAE, 0xBF, 0x14, 0x20, 0x84, 0x59 , -0x02, 0x00, 0xC8, 0x00, 0x00, 0x00, 0x60, 0x1E, 0xC0, 0xB2, 0x38, 0x70, 0x4E, 0x46, 0x7F, 0x1C, 0x40, 0x1C, 0xC2, 0xB2, 0x28, 0x78, 0x5B, 0x46, 0x00, 0x21, 0x32, 0x54, 0x38, 0x46, 0x00, 0xF0, 0xBC, 0xF9, 0x28, 0x78, 0x16, 0x2C, 0x31, 0x5C, 0x01, 0xF1, 0x0A, 0x01, 0x31, 0x54, 0x00, 0xF1, 0x01, 0x00, 0xC0, 0xB2, 0x28, 0x70, 0x2B, 0xDB, 0x00, 0x99, 0x0A, 0xEB, 0x40, 0x10, 0x07, 0x46, 0x01, 0x29, 0xA4, 0xF1, 0x01, 0x09, 0x09, 0xD0, 0x01, 0x99, 0x06, 0x22, 0xF9, 0xF7, 0x79, 0xFF, 0x40, 0x46, 0x00, 0x78, 0xBF, 0x1D, 0x07, 0xF8, 0x01, 0x0B, 0x04, 0xE0, 0x02, 0x99, 0x07, 0x22, 0xF9, 0xF7, 0x6F, 0xFF, 0xFF, 0x1D, 0x07, 0xF8, 0x01, 0x4B, 0x15, 0x3C, 0x15, 0x21, 0x28, 0x78, 0xE2, 0xB2, 0x5B, 0x46, 0x07, 0xF8, 0x01, 0x1B, 0x32, 0x54, 0x07, 0xF8, 0x01, 0x9B, 0x38, 0x46, 0x00, 0xF0, 0x8B, 0xF9, 0x28, 0x78, 0x31, 0x5C, 0x0A, 0x31, 0x31, 0x54, 0x40, 0x1C, 0x28, 0x70, 0xBD, 0xE8, 0xFE, 0x8F, 0xC0, 0x46 , -0x54, 0x54, 0x54, 0x4B, 0x45, 0x59, 0x00, 0xC0, 0x54, 0x54, 0x54, 0x53, 0x53, 0x49, 0x44, 0x00, 0x54, 0x58, 0x02, 0x00, 0xE6, 0x58, 0x02, 0x00, 0xE8, 0x58, 0x02, 0x00, 0x5C, 0x58, 0x02, 0x00, 0x5C, 0x57, 0x02, 0x00, 0xDC, 0x58, 0x02, 0x00, 0xD4, 0x57, 0x02, 0x00, 0x94, 0x57, 0x02, 0x00, 0xFF, 0xB5, 0x0C, 0x46, 0x06, 0x46, 0xF7, 0xF7, 0x4C, 0x5A, 0x02, 0x00, 0xC8, 0x00, 0x00, 0x00, 0xE3, 0xFE, 0x15, 0x49, 0x15, 0x4A, 0x0D, 0x68, 0x01, 0xA9, 0x92, 0xE8, 0x8C, 0x00, 0x81, 0xE8, 0x8C, 0x00, 0xF7, 0xF7, 0xFD, 0xFE, 0x01, 0x98, 0x11, 0x49, 0x28, 0x1A, 0x03, 0x9D, 0x25, 0x60, 0x02, 0x9A, 0x80, 0x18, 0x82, 0x42, 0x30, 0x60, 0x0E, 0xD8, 0x08, 0x46, 0x00, 0x68, 0x22, 0x68, 0x82, 0x42, 0x0E, 0xD2, 0x68, 0x46, 0xE8, 0xF7, 0xB9, 0xFF, 0x9D, 0xF8, 0x00, 0x00, 0x05, 0xF1, 0x01, 0x05, 0x30, 0xB9, 0x03, 0x95, 0x03, 0xE0, 0x25, 0x68, 0x6D, 0x1C, 0x25, 0x60, 0x0C, 0x46, 0x25, 0x60, 0x00, 0x20, 0x00, 0x90 , -0xFF, 0xBD, 0x60, 0x55, 0x30, 0x80, 0x24, 0x5D, 0x00, 0x20, 0x6C, 0x5D, 0x02, 0x00, 0x70, 0xB5, 0x4D, 0x00, 0x20, 0x2D, 0x4F, 0xF0, 0x00, 0x01, 0x0C, 0x46, 0x4F, 0xEA, 0x55, 0x13, 0x09, 0xD3, 0x50, 0xF8, 0x21, 0x60, 0xB6, 0xF1, 0xFF, 0x3F, 0x04, 0xD1, 0x49, 0x1C, 0xC9, 0xB2, 0x20, 0x3D, 0x5B, 0x1E, 0xF5, 0xD1, 0x4D, 0xB1, 0x20, 0x2D, 0x09, 0xD2, 0x01, 0x23, 0xAB, 0x40, 0x5B, 0x1E, 0x50, 0xF8, 0x21, 0x00, 0x18, 0x40, 0x83, 0x42, 0x01, 0xD1, 0x4F, 0xF0, 0x01, 0x04, 0x07, 0x48, 0x03, 0x78, 0x2C, 0xB9, 0x01, 0x21, 0x91, 0x40, 0xC9, 0x43, 0xC9, 0xB2, 0x0B, 0x40, 0x03, 0xE0, 0x01, 0x21, 0x91, 0x40, 0xC9, 0xB2, 0x0B, 0x43, 0x03, 0x70, 0x70, 0xBD, 0xC0, 0x46, 0xEE, 0x58, 0x02, 0x00, 0x14, 0x5B, 0x02, 0x00, 0xC8, 0x00, 0x00, 0x00, 0x7E, 0xB5, 0x05, 0x46, 0x95, 0xF8, 0x36, 0x20, 0x0E, 0x46, 0x0F, 0x49, 0x07, 0x2A, 0x12, 0xBF, 0x08, 0x68, 0x01, 0x20, 0x08, 0x60, 0x0D, 0x4C, 0x00, 0x92, 0x21, 0x68 , -0x41, 0xF2, 0x12, 0x13, 0x04, 0x22, 0x01, 0x91, 0x07, 0x21, 0x02, 0x90, 0x03, 0x20, 0xF2, 0xF7, 0x6B, 0xFD, 0x31, 0x46, 0x28, 0x46, 0xE7, 0xF7, 0x21, 0xFC, 0x21, 0x68, 0x00, 0x22, 0x05, 0x29, 0x02, 0xD1, 0x04, 0x49, 0x08, 0x31, 0x0A, 0x60, 0x7E, 0xBD, 0xC0, 0x46, 0x50, 0x57, 0x02, 0x00, 0x4C, 0x57, 0x02, 0x00, 0x00, 0x7C, 0x00, 0x20, 0x0E, 0x49, 0x09, 0x68, 0x49, 0x08, 0x15, 0xD2, 0x0D, 0x49, 0x09, 0x78, 0x91, 0xB1, 0x44, 0xF2, 0xE9, 0x21, 0x68, 0xB9, 0x0B, 0x48, 0x01, 0x78, 0x07, 0x48, 0x01, 0x29, 0x03, 0xD1, 0x0A, 0x49, 0x09, 0x78, 0x0E, 0x29, 0x02, 0xD0, 0x44, 0xF2, 0xDE, 0x21, 0x41, 0x60, 0x01, 0x21, 0x00, 0xE0, 0x06, 0x48, 0x01, 0x60, 0x70, 0x47, 0xC0, 0x46, 0x00, 0x97, 0x3C, 0x80, 0x10, 0x0C, 0x30, 0x80, 0xDD, 0x6A, 0x00, 0x20, 0xE0, 0x7C, 0x00, 0x20, 0xA6, 0x64, 0x00, 0x20, 0x04, 0x97, 0x3C, 0x80, 0x00, 0xB5, 0xAD, 0xF1, 0x18, 0x0D, 0x4F, 0xF0, 0x09, 0x00, 0x00, 0x90, 0x4F, 0xF4 , -0x0C, 0x60, 0x03, 0x90, 0x4F, 0xF0, 0x00, 0x00, 0x01, 0x90, 0x02, 0x90, 0x08, 0x48, 0x08, 0x49, 0x05, 0x90, 0x08, 0x68, 0x20, 0xB9, 0xDC, 0x5B, 0x02, 0x00, 0xC8, 0x00, 0x00, 0x00, 0x68, 0x46, 0x03, 0x22, 0xED, 0xF7, 0x3A, 0xFA, 0x03, 0xE0, 0x68, 0x46, 0x03, 0x22, 0xED, 0xF7, 0xC1, 0xFC, 0x06, 0xB0, 0x00, 0xBD, 0xC0, 0x46, 0x81, 0x5C, 0x02, 0x00, 0xDC, 0x7C, 0x00, 0x20, 0x1C, 0xB5, 0x0F, 0x4C, 0x22, 0x68, 0x01, 0x2A, 0x15, 0xD1, 0x0C, 0x48, 0x00, 0x68, 0x07, 0x28, 0x14, 0xBF, 0x40, 0x20, 0x4F, 0xF4, 0x05, 0x70, 0x63, 0x21, 0xF1, 0xF7, 0x0F, 0xFA, 0x20, 0x68, 0x00, 0x90, 0x43, 0xF2, 0x33, 0x33, 0x06, 0x21, 0x40, 0x20, 0x01, 0x90, 0x03, 0x20, 0x02, 0x46, 0xF2, 0xF7, 0xF4, 0xFC, 0x1C, 0xBD, 0xF1, 0xF7, 0x01, 0xFA, 0x1C, 0xBD, 0x4C, 0x57, 0x02, 0x00, 0x50, 0x57, 0x02, 0x00, 0x1E, 0xB5, 0x04, 0x46, 0x0A, 0x49, 0x00, 0x20, 0x0A, 0x4A, 0x08, 0x60, 0x0A, 0x49, 0x00, 0x90, 0x01, 0x90, 0x11, 0x60 , -0x09, 0x4A, 0x45, 0xF2, 0x55, 0x53, 0x02, 0x91, 0x10, 0x60, 0x07, 0x21, 0x04, 0x22, 0x03, 0x20, 0xF2, 0xF7, 0xD8, 0xFC, 0x20, 0x46, 0xE7, 0xF7, 0x59, 0xFD, 0x1E, 0xBD, 0x50, 0x57, 0x02, 0x00, 0x04, 0x74, 0x00, 0x20, 0x34, 0x12, 0x66, 0x09, 0x4C, 0x57, 0x02, 0x00, 0x00, 0xB5, 0x0B, 0x49, 0x00, 0x20, 0x08, 0x60, 0xE0, 0x20, 0xF7, 0xF7, 0xAA, 0xFD, 0x09, 0x49, 0x09, 0x78, 0x49, 0xB1, 0x08, 0x49, 0x0A, 0x78, 0x08, 0x49, 0x00, 0x2A, 0x06, 0xBF, 0x01, 0x22, 0x09, 0x1F, 0x44, 0xF2, 0xA4, 0x5C, 0x02, 0x00, 0xC8, 0x00, 0x00, 0x00, 0xE9, 0x22, 0x0A, 0x60, 0xF7, 0xF7, 0xA1, 0xFD, 0x00, 0xBD, 0xC0, 0x46, 0xDC, 0x7C, 0x00, 0x20, 0xDD, 0x6A, 0x00, 0x20, 0xA7, 0x64, 0x00, 0x20, 0x04, 0x97, 0x3C, 0x80, 0x50, 0xB9, 0x09, 0x48, 0x00, 0x78, 0x01, 0x28, 0x06, 0xD1, 0x08, 0x48, 0x00, 0x78, 0x0E, 0x28, 0x08, 0xBF, 0x44, 0xF2, 0xCB, 0x20, 0x01, 0xD0, 0x44, 0xF2, 0xDE, 0x20, 0x04, 0x49, 0x08, 0x60, 0x01, 0x20 , -0x41, 0xF8, 0x04, 0x0C, 0x70, 0x47, 0xE0, 0x7C, 0x00, 0x20, 0xA6, 0x64, 0x00, 0x20, 0x04, 0x97, 0x3C, 0x80, 0x30, 0xB5, 0x0D, 0x46, 0x84, 0x69, 0xDC, 0xF7, 0x97, 0xFB, 0x24, 0x1D, 0x01, 0x28, 0x04, 0xEB, 0x45, 0x01, 0x06, 0xD1, 0x89, 0x8E, 0x04, 0xEB, 0x85, 0x04, 0x11, 0xB9, 0x21, 0x69, 0x01, 0xB9, 0x00, 0x20, 0x30, 0xBD, 0x30, 0xB5, 0x05, 0x46, 0x5A, 0xB1, 0x03, 0xEB, 0x41, 0x03, 0x1C, 0x78, 0x59, 0x78, 0x41, 0xEA, 0x04, 0x11, 0x52, 0x1E, 0x03, 0xF1, 0x02, 0x03, 0x05, 0xF8, 0x01, 0x1B, 0xF5, 0xD1, 0x30, 0xBD, 0x00, 0xB5, 0x00, 0x20, 0xE7, 0xF7, 0xD6, 0xFE, 0x03, 0x48, 0x01, 0x68, 0x03, 0x29, 0x04, 0xBF, 0x04, 0x21, 0x01, 0x60, 0x00, 0xBD, 0xC0, 0x46, 0x4C, 0x57, 0x02, 0x00, 0x03, 0x4A, 0x12, 0x68, 0x01, 0x2A, 0x04, 0xBF, 0x02, 0x48, 0x63, 0x21, 0xF1, 0xF7, 0x76, 0xB9, 0x50, 0x57, 0x02, 0x00, 0x02, 0x20, 0x01, 0x00, 0x6C, 0x5D, 0x02, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; diff --git a/drivers/cc3000/src/patch_prog.c b/drivers/cc3000/src/patch_prog.c deleted file mode 100644 index fd128928fb..0000000000 --- a/drivers/cc3000/src/patch_prog.c +++ /dev/null @@ -1,414 +0,0 @@ -#include -#include -#include "cc3000_common.h" -#include "nvmem.h" -#include "ccspi.h" -#include "hci.h" -#include "wlan.h" -#include "patch_prog.h" -#define BIT0 0x1 -#define BIT1 0x2 -#define BIT2 0x4 -#define BIT3 0x8 -#define BIT4 0x10 -#define BIT5 0x20 -#define BIT6 0x40 -#define BIT7 0x80 - -static unsigned char ucStatus_Dr; -static unsigned char ucStatus_FW; -static unsigned char return_status = 0xFF; - -static signed char mac_status = -1; -static unsigned char counter = 0; - -// Array to store RM parameters from EEPROM. -static unsigned char cRMParamsFromEeprom[128]; -// Array to store MAC address from EEPROM. -static unsigned char cMacFromEeprom[MAC_ADDR_LEN]; -// Smart Config Prefix -static const char aucCC3000_prefix[] = {'T', 'T', 'T'}; - -static void systick_sleep(unsigned long ms) { - extern void HAL_Delay(volatile uint32_t Delay); - HAL_Delay(ms); -} - -// 2 dim array to store address and length of new FAT -static const unsigned short aFATEntries[2][NVMEM_RM_FILEID + 1] = -/* address */ {{0x50, 0x1f0, 0x390, 0x1390, 0x2390, 0x4390, 0x6390, 0x63a0, 0x63b0, 0x63f0, 0x6430, 0x6830}, -/* length */ {0x1a0, 0x1a0, 0x1000, 0x1000, 0x2000, 0x2000, 0x10, 0x10, 0x40, 0x40, 0x400, 0x200}}; -/* 0. NVS */ -/* 1. NVS Shadow */ -/* 2. Wireless Conf */ -/* 3. Wireless Conf Shadow */ -/* 4. BT (WLAN driver) Patches */ -/* 5. WiLink (Firmware) Patches */ -/* 6. MAC addr */ -/* 7. Frontend Vars */ -/* 8. IP config */ -/* 9. IP config Shadow */ -/* 10. Bootloader Patches */ -/* 11. Radio Module params */ -/* 12. AES128 for smart config */ -/* 13. user file */ -/* 14. user file */ -/* 15. user file */ - -//***************************************************************************** -// -//! sendDriverPatch -//! -//! \param pointer to the length -//! -//! \return none -//! -//! \brief The function returns a pointer to the driver patch: -//! since there is no patch yet - it returns 0 -// -//***************************************************************************** - -static char *sendDriverPatch(unsigned long *Length) -{ - *Length = 0; - return NULL; -} - - -//***************************************************************************** -// -//! sendBootLoaderPatch -//! -//! \param pointer to the length -//! -//! \return none -//! -//! \brief The function returns a pointer to the boot loader patch: -//! since there is no patch yet - it returns 0 -// -//***************************************************************************** - -static char *sendBootLoaderPatch(unsigned long *Length) -{ - *Length = 0; - return NULL; -} - -//***************************************************************************** -// -//! sendWLFWPatch -//! -//! \param pointer to the length -//! -//! \return none -//! -//! \brief The function returns a pointer to the FW patch: -//! since there is no patch yet - it returns 0 -// -//***************************************************************************** - -static char *sendWLFWPatch(unsigned long *Length) -{ - *Length = 0; - return NULL; -} - -//***************************************************************************** -// -//! CC3000_UsynchCallback -//! -//! \param Event type -//! -//! \return none -//! -//! \brief The function handles asynchronous events that come from CC3000 -//! device and operates a LED4 to have an on-board indication -// -//***************************************************************************** - -static void CC3000_UsynchCallback(long lEventType, char * data, unsigned char length) -{ - -} - -//***************************************************************************** -// -//! initDriver -//! -//! \param[in] cRequestPatch 0 to load with EEPROM patches -//! and 1 to load with no patches -//! -//! \return none -//! -//! \brief The function initializes a CC3000 device -//! and triggers it to start operation -// -//***************************************************************************** -static int initDriver(unsigned short cRequestPatch) -{ - // WLAN On API Implementation - wlan_init(CC3000_UsynchCallback, sendWLFWPatch, sendDriverPatch, sendBootLoaderPatch, - ReadWlanInterruptPin, SpiResumeSpi, SpiPauseSpi, WriteWlanPin); - - // Trigger a WLAN device - wlan_start(cRequestPatch); - wlan_smart_config_set_prefix((char*)aucCC3000_prefix); - wlan_ioctl_set_connection_policy(0, 0, 0); - wlan_ioctl_del_profile(255); - - // Mask out all non-required events from CC3000 - wlan_set_event_mask(HCI_EVNT_WLAN_KEEPALIVE| - HCI_EVNT_WLAN_UNSOL_INIT| - HCI_EVNT_WLAN_ASYNC_PING_REPORT); - - //unsolicicted_events_timer_init(); - systick_sleep(100); - return(0); -} - - -//***************************************************************************** -// -//! fat_read_content -//! -//! \param[out] is_allocated array of is_allocated in FAT table:\n -//! an allocated entry implies the address and length of the -//! file are valid. -//! 0: not allocated; 1: allocated. -//! \param[out] is_valid array of is_valid in FAT table:\n -//! a valid entry implies the content of the file is relevant. -//! 0: not valid; 1: valid. -//! \param[out] write_protected array of write_protected in FAT table:\n -//! a write protected entry implies it is not possible to write -//! into this entry. -//! 0: not protected; 1: protected. -//! \param[out] file_address array of file address in FAT table:\n -//! this is the absolute address of the file in the EEPROM. -//! \param[out] file_length array of file length in FAT table:\n -//! this is the upper limit of the file size in the EEPROM. -//! -//! \return on succes 0, error otherwise -//! -//! \brief parse the FAT table from eeprom -// -//***************************************************************************** -static unsigned char __attribute__ ((unused)) -fat_read_content(unsigned char *is_allocated, unsigned char *is_valid, - unsigned char *write_protected, unsigned short *file_address, unsigned short *file_length) -{ - unsigned short index; - unsigned char ucStatus; - unsigned char fatTable[48]; - unsigned char* fatTablePtr = fatTable; - - // - // Read in 6 parts to work with tiny driver - // - for (index = 0; index < 6; index++) - { - ucStatus = nvmem_read(16, 8, 4 + 8*index, fatTablePtr); - fatTablePtr += 8; - } - - fatTablePtr = fatTable; - - for (index = 0; index <= NVMEM_RM_FILEID; index++) - { - *is_allocated++ = (*fatTablePtr) & BIT0; - *is_valid++ = ((*fatTablePtr) & BIT1) >> 1; - *write_protected++ = ((*fatTablePtr) & BIT2) >> 2; - *file_address++ = ((*(fatTablePtr+1)<<8) | (*fatTablePtr)) & (BIT4|BIT5|BIT6|BIT7); - *file_length++ = ((*(fatTablePtr+3)<<8) | (*(fatTablePtr+2))) & (BIT4|BIT5|BIT6|BIT7); - - // - // Move to next file ID - // - fatTablePtr += 4; - } - - return ucStatus; -} - -//***************************************************************************** -// -//! fat_write_content -//! -//! \param[in] file_address array of file address in FAT table:\n -//! this is the absolute address of the file in the EEPROM. -//! \param[in] file_length array of file length in FAT table:\n -//! this is the upper limit of the file size in the EEPROM. -//! -//! \return on succes 0, error otherwise -//! -//! \brief parse the FAT table from eeprom -// -//***************************************************************************** -static unsigned char fat_write_content(unsigned short const *file_address, - unsigned short const *file_length) -{ - unsigned short index = 0; - unsigned char ucStatus; - unsigned char fatTable[48]; - unsigned char* fatTablePtr = fatTable; - - // - // First, write the magic number. - // - ucStatus = nvmem_write(16, 2, 0, (unsigned char*)"LS"); - - for (; index <= NVMEM_RM_FILEID; index++) - { - // - // Write address low char and mark as allocated. - // - *fatTablePtr++ = (unsigned char)(file_address[index] & 0xff) | BIT0; - - // - // Write address high char. - // - *fatTablePtr++ = (unsigned char)((file_address[index]>>8) & 0xff); - - // - // Write length low char. - // - *fatTablePtr++ = (unsigned char)(file_length[index] & 0xff); - - // - // Write length high char. - // - *fatTablePtr++ = (unsigned char)((file_length[index]>>8) & 0xff); - } - - // - // Second, write the FAT. - // Write in two parts to work with tiny driver. - // - ucStatus = nvmem_write(16, 24, 4, fatTable); - ucStatus = nvmem_write(16, 24, 24+4, &fatTable[24]); - - // - // Third, we want to erase any user files. - // - memset(fatTable, 0, sizeof(fatTable)); - ucStatus = nvmem_write(16, 16, 52, fatTable); - - return ucStatus; -} - -void patch_prog_start() -{ - unsigned short index; - unsigned char *pRMParams; - - printf("Initializing module...\n"); - - // Init module and request to load with no patches. - // This is in order to overwrite restrictions to - // write to specific places in EEPROM. - initDriver(1); - - // Read MAC address. - mac_status = nvmem_get_mac_address(cMacFromEeprom); - - return_status = 1; - - printf("Reading RM parameters...\n"); - while ((return_status) && (counter < 3)) { - // Read RM parameters. - // Read in 16 parts to work with tiny driver. - return_status = 0; - pRMParams = cRMParamsFromEeprom; - for (index = 0; index < 16; index++) { - return_status |= nvmem_read(NVMEM_RM_FILEID, 8, 8*index, pRMParams); - pRMParams += 8; - } - counter++; - } - - // If RM file is not valid, load the default one. - if (counter == 3) { - printf("RM is not valid, loading default one...\n"); - pRMParams = (unsigned char *)cRMdefaultParams; - } else { - printf("RM is valid.\n"); - pRMParams = cRMParamsFromEeprom; - } - - return_status = 1; - - printf("Writing new FAT\n"); - while (return_status) { - // Write new FAT. - return_status = fat_write_content(aFATEntries[0], aFATEntries[1]); - } - - return_status = 1; - - printf("Writing RM parameters...\n"); - while (return_status) { - // Write RM parameters. - // Write in 4 parts to work with tiny driver. - return_status = 0; - - for (index = 0; index < 4; index++) { - return_status |= nvmem_write(NVMEM_RM_FILEID, - 32, - 32*index, - (pRMParams + 32*index)); - } - } - - return_status = 1; - - // Write back the MAC address, only if exists. - if (mac_status == 0) { - // Zero out MCAST bit if set. - cMacFromEeprom[0] &= 0xfe; - printf("Writing back MAC address..\n"); - while (return_status) { - return_status = nvmem_set_mac_address(cMacFromEeprom); - } - } - - // Update driver - ucStatus_Dr = 1; - printf("Updating driver patch...\n"); - while (ucStatus_Dr) { - // Writing driver patch to EEPRROM - PROTABLE CODE - // Note that the array itself is changing between the - // different Service Packs. - ucStatus_Dr = nvmem_write_patch(NVMEM_WLAN_DRIVER_SP_FILEID, - drv_length, - wlan_drv_patch); - } - - // Update firmware - ucStatus_FW = 1; - printf("Updating firmware patch...\n"); - while (ucStatus_FW) { - // Writing FW patch to EEPRROM - PROTABLE CODE - // Note that the array itself is changing between the - // different Service Packs. - ucStatus_FW = nvmem_write_patch(NVMEM_WLAN_FW_SP_FILEID, - fw_length, - fw_patch); - } - - printf("Update complete, resetting module\n"\ - "If this doesn't work, reset manually...\n"); - - wlan_stop(); - systick_sleep(500); - - // Re-Init module and request to load with patches. - initDriver(0); - - // If MAC does not exist, it is recommended - // that the user will write a valid mac address. - if (mac_status != 0) { - printf("MAC address is not valid, please write a new one\n"); - } - - // Patch update done - printf("All done, call wlan.patch_version()\n"); -} diff --git a/drivers/cc3000/src/security.c b/drivers/cc3000/src/security.c deleted file mode 100644 index 62b4f88134..0000000000 --- a/drivers/cc3000/src/security.c +++ /dev/null @@ -1,530 +0,0 @@ -/***************************************************************************** -* -* security.c - CC3000 Host Driver Implementation. -* Copyright (C) 2011 Texas Instruments Incorporated - http://www.ti.com/ -* -* Redistribution and use in source and binary forms, with or without -* modification, are permitted provided that the following conditions -* are met: -* -* Redistributions of source code must retain the above copyright -* notice, this list of conditions and the following disclaimer. -* -* Redistributions in binary form must reproduce the above copyright -* notice, this list of conditions and the following disclaimer in the -* documentation and/or other materials provided with the -* distribution. -* -* Neither the name of Texas Instruments Incorporated nor the names of -* its contributors may be used to endorse or promote products derived -* from this software without specific prior written permission. -* -* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -* -*****************************************************************************/ - -//***************************************************************************** -// -//! \addtogroup security_api -//! @{ -// -//***************************************************************************** - -#include "security.h" - -#ifndef CC3000_UNENCRYPTED_SMART_CONFIG -// foreward sbox -const UINT8 sbox[256] = { -//0 1 2 3 4 5 6 7 8 9 A B C D E F -0x63, 0x7c, 0x77, 0x7b, 0xf2, 0x6b, 0x6f, 0xc5, 0x30, 0x01, 0x67, 0x2b, 0xfe, 0xd7, 0xab, 0x76, //0 -0xca, 0x82, 0xc9, 0x7d, 0xfa, 0x59, 0x47, 0xf0, 0xad, 0xd4, 0xa2, 0xaf, 0x9c, 0xa4, 0x72, 0xc0, //1 -0xb7, 0xfd, 0x93, 0x26, 0x36, 0x3f, 0xf7, 0xcc, 0x34, 0xa5, 0xe5, 0xf1, 0x71, 0xd8, 0x31, 0x15, //2 -0x04, 0xc7, 0x23, 0xc3, 0x18, 0x96, 0x05, 0x9a, 0x07, 0x12, 0x80, 0xe2, 0xeb, 0x27, 0xb2, 0x75, //3 -0x09, 0x83, 0x2c, 0x1a, 0x1b, 0x6e, 0x5a, 0xa0, 0x52, 0x3b, 0xd6, 0xb3, 0x29, 0xe3, 0x2f, 0x84, //4 -0x53, 0xd1, 0x00, 0xed, 0x20, 0xfc, 0xb1, 0x5b, 0x6a, 0xcb, 0xbe, 0x39, 0x4a, 0x4c, 0x58, 0xcf, //5 -0xd0, 0xef, 0xaa, 0xfb, 0x43, 0x4d, 0x33, 0x85, 0x45, 0xf9, 0x02, 0x7f, 0x50, 0x3c, 0x9f, 0xa8, //6 -0x51, 0xa3, 0x40, 0x8f, 0x92, 0x9d, 0x38, 0xf5, 0xbc, 0xb6, 0xda, 0x21, 0x10, 0xff, 0xf3, 0xd2, //7 -0xcd, 0x0c, 0x13, 0xec, 0x5f, 0x97, 0x44, 0x17, 0xc4, 0xa7, 0x7e, 0x3d, 0x64, 0x5d, 0x19, 0x73, //8 -0x60, 0x81, 0x4f, 0xdc, 0x22, 0x2a, 0x90, 0x88, 0x46, 0xee, 0xb8, 0x14, 0xde, 0x5e, 0x0b, 0xdb, //9 -0xe0, 0x32, 0x3a, 0x0a, 0x49, 0x06, 0x24, 0x5c, 0xc2, 0xd3, 0xac, 0x62, 0x91, 0x95, 0xe4, 0x79, //A -0xe7, 0xc8, 0x37, 0x6d, 0x8d, 0xd5, 0x4e, 0xa9, 0x6c, 0x56, 0xf4, 0xea, 0x65, 0x7a, 0xae, 0x08, //B -0xba, 0x78, 0x25, 0x2e, 0x1c, 0xa6, 0xb4, 0xc6, 0xe8, 0xdd, 0x74, 0x1f, 0x4b, 0xbd, 0x8b, 0x8a, //C -0x70, 0x3e, 0xb5, 0x66, 0x48, 0x03, 0xf6, 0x0e, 0x61, 0x35, 0x57, 0xb9, 0x86, 0xc1, 0x1d, 0x9e, //D -0xe1, 0xf8, 0x98, 0x11, 0x69, 0xd9, 0x8e, 0x94, 0x9b, 0x1e, 0x87, 0xe9, 0xce, 0x55, 0x28, 0xdf, //E -0x8c, 0xa1, 0x89, 0x0d, 0xbf, 0xe6, 0x42, 0x68, 0x41, 0x99, 0x2d, 0x0f, 0xb0, 0x54, 0xbb, 0x16 }; //F -// inverse sbox -const UINT8 rsbox[256] = -{ 0x52, 0x09, 0x6a, 0xd5, 0x30, 0x36, 0xa5, 0x38, 0xbf, 0x40, 0xa3, 0x9e, 0x81, 0xf3, 0xd7, 0xfb -, 0x7c, 0xe3, 0x39, 0x82, 0x9b, 0x2f, 0xff, 0x87, 0x34, 0x8e, 0x43, 0x44, 0xc4, 0xde, 0xe9, 0xcb -, 0x54, 0x7b, 0x94, 0x32, 0xa6, 0xc2, 0x23, 0x3d, 0xee, 0x4c, 0x95, 0x0b, 0x42, 0xfa, 0xc3, 0x4e -, 0x08, 0x2e, 0xa1, 0x66, 0x28, 0xd9, 0x24, 0xb2, 0x76, 0x5b, 0xa2, 0x49, 0x6d, 0x8b, 0xd1, 0x25 -, 0x72, 0xf8, 0xf6, 0x64, 0x86, 0x68, 0x98, 0x16, 0xd4, 0xa4, 0x5c, 0xcc, 0x5d, 0x65, 0xb6, 0x92 -, 0x6c, 0x70, 0x48, 0x50, 0xfd, 0xed, 0xb9, 0xda, 0x5e, 0x15, 0x46, 0x57, 0xa7, 0x8d, 0x9d, 0x84 -, 0x90, 0xd8, 0xab, 0x00, 0x8c, 0xbc, 0xd3, 0x0a, 0xf7, 0xe4, 0x58, 0x05, 0xb8, 0xb3, 0x45, 0x06 -, 0xd0, 0x2c, 0x1e, 0x8f, 0xca, 0x3f, 0x0f, 0x02, 0xc1, 0xaf, 0xbd, 0x03, 0x01, 0x13, 0x8a, 0x6b -, 0x3a, 0x91, 0x11, 0x41, 0x4f, 0x67, 0xdc, 0xea, 0x97, 0xf2, 0xcf, 0xce, 0xf0, 0xb4, 0xe6, 0x73 -, 0x96, 0xac, 0x74, 0x22, 0xe7, 0xad, 0x35, 0x85, 0xe2, 0xf9, 0x37, 0xe8, 0x1c, 0x75, 0xdf, 0x6e -, 0x47, 0xf1, 0x1a, 0x71, 0x1d, 0x29, 0xc5, 0x89, 0x6f, 0xb7, 0x62, 0x0e, 0xaa, 0x18, 0xbe, 0x1b -, 0xfc, 0x56, 0x3e, 0x4b, 0xc6, 0xd2, 0x79, 0x20, 0x9a, 0xdb, 0xc0, 0xfe, 0x78, 0xcd, 0x5a, 0xf4 -, 0x1f, 0xdd, 0xa8, 0x33, 0x88, 0x07, 0xc7, 0x31, 0xb1, 0x12, 0x10, 0x59, 0x27, 0x80, 0xec, 0x5f -, 0x60, 0x51, 0x7f, 0xa9, 0x19, 0xb5, 0x4a, 0x0d, 0x2d, 0xe5, 0x7a, 0x9f, 0x93, 0xc9, 0x9c, 0xef -, 0xa0, 0xe0, 0x3b, 0x4d, 0xae, 0x2a, 0xf5, 0xb0, 0xc8, 0xeb, 0xbb, 0x3c, 0x83, 0x53, 0x99, 0x61 -, 0x17, 0x2b, 0x04, 0x7e, 0xba, 0x77, 0xd6, 0x26, 0xe1, 0x69, 0x14, 0x63, 0x55, 0x21, 0x0c, 0x7d }; -// round constant -const UINT8 Rcon[11] = { - 0x8d, 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80, 0x1b, 0x36}; - - -UINT8 expandedKey[176]; - -//***************************************************************************** -// -//! expandKey -//! -//! @param key AES128 key - 16 bytes -//! @param expandedKey expanded AES128 key -//! -//! @return none -//! -//! @brief expend a 16 bytes key for AES128 implementation -//! -//***************************************************************************** - -void expandKey(UINT8 *expandedKey, UINT8 *key) -{ - UINT16 ii, buf1; - for (ii=0;ii<16;ii++) - expandedKey[ii] = key[ii]; - for (ii=1;ii<11;ii++){ - buf1 = expandedKey[ii*16 - 4]; - expandedKey[ii*16 + 0] = sbox[expandedKey[ii*16 - 3]]^expandedKey[(ii-1)*16 + 0]^Rcon[ii]; - expandedKey[ii*16 + 1] = sbox[expandedKey[ii*16 - 2]]^expandedKey[(ii-1)*16 + 1]; - expandedKey[ii*16 + 2] = sbox[expandedKey[ii*16 - 1]]^expandedKey[(ii-1)*16 + 2]; - expandedKey[ii*16 + 3] = sbox[buf1 ]^expandedKey[(ii-1)*16 + 3]; - expandedKey[ii*16 + 4] = expandedKey[(ii-1)*16 + 4]^expandedKey[ii*16 + 0]; - expandedKey[ii*16 + 5] = expandedKey[(ii-1)*16 + 5]^expandedKey[ii*16 + 1]; - expandedKey[ii*16 + 6] = expandedKey[(ii-1)*16 + 6]^expandedKey[ii*16 + 2]; - expandedKey[ii*16 + 7] = expandedKey[(ii-1)*16 + 7]^expandedKey[ii*16 + 3]; - expandedKey[ii*16 + 8] = expandedKey[(ii-1)*16 + 8]^expandedKey[ii*16 + 4]; - expandedKey[ii*16 + 9] = expandedKey[(ii-1)*16 + 9]^expandedKey[ii*16 + 5]; - expandedKey[ii*16 +10] = expandedKey[(ii-1)*16 +10]^expandedKey[ii*16 + 6]; - expandedKey[ii*16 +11] = expandedKey[(ii-1)*16 +11]^expandedKey[ii*16 + 7]; - expandedKey[ii*16 +12] = expandedKey[(ii-1)*16 +12]^expandedKey[ii*16 + 8]; - expandedKey[ii*16 +13] = expandedKey[(ii-1)*16 +13]^expandedKey[ii*16 + 9]; - expandedKey[ii*16 +14] = expandedKey[(ii-1)*16 +14]^expandedKey[ii*16 +10]; - expandedKey[ii*16 +15] = expandedKey[(ii-1)*16 +15]^expandedKey[ii*16 +11]; - } - -} - -//***************************************************************************** -// -//! galois_mul2 -//! -//! @param value argument to multiply -//! -//! @return multiplied argument -//! -//! @brief multiply by 2 in the galois field -//! -//***************************************************************************** - -UINT8 galois_mul2(UINT8 value) -{ - if (value>>7) - { - value = value << 1; - return (value^0x1b); - } else - return value<<1; -} - -//***************************************************************************** -// -//! aes_encr -//! -//! @param[in] expandedKey expanded AES128 key -//! @param[in/out] state 16 bytes of plain text and cipher text -//! -//! @return none -//! -//! @brief internal implementation of AES128 encryption. -//! straight forward aes encryption implementation -//! first the group of operations -//! - addRoundKey -//! - subbytes -//! - shiftrows -//! - mixcolums -//! is executed 9 times, after this addroundkey to finish the 9th -//! round, after that the 10th round without mixcolums -//! no further subfunctions to save cycles for function calls -//! no structuring with "for (....)" to save cycles. -//! -//! -//***************************************************************************** - -void aes_encr(UINT8 *state, UINT8 *expandedKey) -{ - UINT8 buf1, buf2, buf3, round; - - for (round = 0; round < 9; round ++){ - // addroundkey, sbox and shiftrows - // row 0 - state[ 0] = sbox[(state[ 0] ^ expandedKey[(round*16) ])]; - state[ 4] = sbox[(state[ 4] ^ expandedKey[(round*16) + 4])]; - state[ 8] = sbox[(state[ 8] ^ expandedKey[(round*16) + 8])]; - state[12] = sbox[(state[12] ^ expandedKey[(round*16) + 12])]; - // row 1 - buf1 = state[1] ^ expandedKey[(round*16) + 1]; - state[ 1] = sbox[(state[ 5] ^ expandedKey[(round*16) + 5])]; - state[ 5] = sbox[(state[ 9] ^ expandedKey[(round*16) + 9])]; - state[ 9] = sbox[(state[13] ^ expandedKey[(round*16) + 13])]; - state[13] = sbox[buf1]; - // row 2 - buf1 = state[2] ^ expandedKey[(round*16) + 2]; - buf2 = state[6] ^ expandedKey[(round*16) + 6]; - state[ 2] = sbox[(state[10] ^ expandedKey[(round*16) + 10])]; - state[ 6] = sbox[(state[14] ^ expandedKey[(round*16) + 14])]; - state[10] = sbox[buf1]; - state[14] = sbox[buf2]; - // row 3 - buf1 = state[15] ^ expandedKey[(round*16) + 15]; - state[15] = sbox[(state[11] ^ expandedKey[(round*16) + 11])]; - state[11] = sbox[(state[ 7] ^ expandedKey[(round*16) + 7])]; - state[ 7] = sbox[(state[ 3] ^ expandedKey[(round*16) + 3])]; - state[ 3] = sbox[buf1]; - - // mixcolums ////////// - // col1 - buf1 = state[0] ^ state[1] ^ state[2] ^ state[3]; - buf2 = state[0]; - buf3 = state[0]^state[1]; buf3=galois_mul2(buf3); state[0] = state[0] ^ buf3 ^ buf1; - buf3 = state[1]^state[2]; buf3=galois_mul2(buf3); state[1] = state[1] ^ buf3 ^ buf1; - buf3 = state[2]^state[3]; buf3=galois_mul2(buf3); state[2] = state[2] ^ buf3 ^ buf1; - buf3 = state[3]^buf2; buf3=galois_mul2(buf3); state[3] = state[3] ^ buf3 ^ buf1; - // col2 - buf1 = state[4] ^ state[5] ^ state[6] ^ state[7]; - buf2 = state[4]; - buf3 = state[4]^state[5]; buf3=galois_mul2(buf3); state[4] = state[4] ^ buf3 ^ buf1; - buf3 = state[5]^state[6]; buf3=galois_mul2(buf3); state[5] = state[5] ^ buf3 ^ buf1; - buf3 = state[6]^state[7]; buf3=galois_mul2(buf3); state[6] = state[6] ^ buf3 ^ buf1; - buf3 = state[7]^buf2; buf3=galois_mul2(buf3); state[7] = state[7] ^ buf3 ^ buf1; - // col3 - buf1 = state[8] ^ state[9] ^ state[10] ^ state[11]; - buf2 = state[8]; - buf3 = state[8]^state[9]; buf3=galois_mul2(buf3); state[8] = state[8] ^ buf3 ^ buf1; - buf3 = state[9]^state[10]; buf3=galois_mul2(buf3); state[9] = state[9] ^ buf3 ^ buf1; - buf3 = state[10]^state[11]; buf3=galois_mul2(buf3); state[10] = state[10] ^ buf3 ^ buf1; - buf3 = state[11]^buf2; buf3=galois_mul2(buf3); state[11] = state[11] ^ buf3 ^ buf1; - // col4 - buf1 = state[12] ^ state[13] ^ state[14] ^ state[15]; - buf2 = state[12]; - buf3 = state[12]^state[13]; buf3=galois_mul2(buf3); state[12] = state[12] ^ buf3 ^ buf1; - buf3 = state[13]^state[14]; buf3=galois_mul2(buf3); state[13] = state[13] ^ buf3 ^ buf1; - buf3 = state[14]^state[15]; buf3=galois_mul2(buf3); state[14] = state[14] ^ buf3 ^ buf1; - buf3 = state[15]^buf2; buf3=galois_mul2(buf3); state[15] = state[15] ^ buf3 ^ buf1; - - } - // 10th round without mixcols - state[ 0] = sbox[(state[ 0] ^ expandedKey[(round*16) ])]; - state[ 4] = sbox[(state[ 4] ^ expandedKey[(round*16) + 4])]; - state[ 8] = sbox[(state[ 8] ^ expandedKey[(round*16) + 8])]; - state[12] = sbox[(state[12] ^ expandedKey[(round*16) + 12])]; - // row 1 - buf1 = state[1] ^ expandedKey[(round*16) + 1]; - state[ 1] = sbox[(state[ 5] ^ expandedKey[(round*16) + 5])]; - state[ 5] = sbox[(state[ 9] ^ expandedKey[(round*16) + 9])]; - state[ 9] = sbox[(state[13] ^ expandedKey[(round*16) + 13])]; - state[13] = sbox[buf1]; - // row 2 - buf1 = state[2] ^ expandedKey[(round*16) + 2]; - buf2 = state[6] ^ expandedKey[(round*16) + 6]; - state[ 2] = sbox[(state[10] ^ expandedKey[(round*16) + 10])]; - state[ 6] = sbox[(state[14] ^ expandedKey[(round*16) + 14])]; - state[10] = sbox[buf1]; - state[14] = sbox[buf2]; - // row 3 - buf1 = state[15] ^ expandedKey[(round*16) + 15]; - state[15] = sbox[(state[11] ^ expandedKey[(round*16) + 11])]; - state[11] = sbox[(state[ 7] ^ expandedKey[(round*16) + 7])]; - state[ 7] = sbox[(state[ 3] ^ expandedKey[(round*16) + 3])]; - state[ 3] = sbox[buf1]; - // last addroundkey - state[ 0]^=expandedKey[160]; - state[ 1]^=expandedKey[161]; - state[ 2]^=expandedKey[162]; - state[ 3]^=expandedKey[163]; - state[ 4]^=expandedKey[164]; - state[ 5]^=expandedKey[165]; - state[ 6]^=expandedKey[166]; - state[ 7]^=expandedKey[167]; - state[ 8]^=expandedKey[168]; - state[ 9]^=expandedKey[169]; - state[10]^=expandedKey[170]; - state[11]^=expandedKey[171]; - state[12]^=expandedKey[172]; - state[13]^=expandedKey[173]; - state[14]^=expandedKey[174]; - state[15]^=expandedKey[175]; -} - -//***************************************************************************** -// -//! aes_decr -//! -//! @param[in] expandedKey expanded AES128 key -//! @param[in\out] state 16 bytes of cipher text and plain text -//! -//! @return none -//! -//! @brief internal implementation of AES128 decryption. -//! straight forward aes decryption implementation -//! the order of substeps is the exact reverse of decryption -//! inverse functions: -//! - addRoundKey is its own inverse -//! - rsbox is inverse of sbox -//! - rightshift instead of leftshift -//! - invMixColumns = barreto + mixColumns -//! no further subfunctions to save cycles for function calls -//! no structuring with "for (....)" to save cycles -//! -//***************************************************************************** - -void aes_decr(UINT8 *state, UINT8 *expandedKey) -{ - UINT8 buf1, buf2, buf3; - INT8 round; - round = 9; - - // initial addroundkey - state[ 0]^=expandedKey[160]; - state[ 1]^=expandedKey[161]; - state[ 2]^=expandedKey[162]; - state[ 3]^=expandedKey[163]; - state[ 4]^=expandedKey[164]; - state[ 5]^=expandedKey[165]; - state[ 6]^=expandedKey[166]; - state[ 7]^=expandedKey[167]; - state[ 8]^=expandedKey[168]; - state[ 9]^=expandedKey[169]; - state[10]^=expandedKey[170]; - state[11]^=expandedKey[171]; - state[12]^=expandedKey[172]; - state[13]^=expandedKey[173]; - state[14]^=expandedKey[174]; - state[15]^=expandedKey[175]; - - // 10th round without mixcols - state[ 0] = rsbox[state[ 0]] ^ expandedKey[(round*16) ]; - state[ 4] = rsbox[state[ 4]] ^ expandedKey[(round*16) + 4]; - state[ 8] = rsbox[state[ 8]] ^ expandedKey[(round*16) + 8]; - state[12] = rsbox[state[12]] ^ expandedKey[(round*16) + 12]; - // row 1 - buf1 = rsbox[state[13]] ^ expandedKey[(round*16) + 1]; - state[13] = rsbox[state[ 9]] ^ expandedKey[(round*16) + 13]; - state[ 9] = rsbox[state[ 5]] ^ expandedKey[(round*16) + 9]; - state[ 5] = rsbox[state[ 1]] ^ expandedKey[(round*16) + 5]; - state[ 1] = buf1; - // row 2 - buf1 = rsbox[state[ 2]] ^ expandedKey[(round*16) + 10]; - buf2 = rsbox[state[ 6]] ^ expandedKey[(round*16) + 14]; - state[ 2] = rsbox[state[10]] ^ expandedKey[(round*16) + 2]; - state[ 6] = rsbox[state[14]] ^ expandedKey[(round*16) + 6]; - state[10] = buf1; - state[14] = buf2; - // row 3 - buf1 = rsbox[state[ 3]] ^ expandedKey[(round*16) + 15]; - state[ 3] = rsbox[state[ 7]] ^ expandedKey[(round*16) + 3]; - state[ 7] = rsbox[state[11]] ^ expandedKey[(round*16) + 7]; - state[11] = rsbox[state[15]] ^ expandedKey[(round*16) + 11]; - state[15] = buf1; - - for (round = 8; round >= 0; round--){ - // barreto - //col1 - buf1 = galois_mul2(galois_mul2(state[0]^state[2])); - buf2 = galois_mul2(galois_mul2(state[1]^state[3])); - state[0] ^= buf1; state[1] ^= buf2; state[2] ^= buf1; state[3] ^= buf2; - //col2 - buf1 = galois_mul2(galois_mul2(state[4]^state[6])); - buf2 = galois_mul2(galois_mul2(state[5]^state[7])); - state[4] ^= buf1; state[5] ^= buf2; state[6] ^= buf1; state[7] ^= buf2; - //col3 - buf1 = galois_mul2(galois_mul2(state[8]^state[10])); - buf2 = galois_mul2(galois_mul2(state[9]^state[11])); - state[8] ^= buf1; state[9] ^= buf2; state[10] ^= buf1; state[11] ^= buf2; - //col4 - buf1 = galois_mul2(galois_mul2(state[12]^state[14])); - buf2 = galois_mul2(galois_mul2(state[13]^state[15])); - state[12] ^= buf1; state[13] ^= buf2; state[14] ^= buf1; state[15] ^= buf2; - // mixcolums ////////// - // col1 - buf1 = state[0] ^ state[1] ^ state[2] ^ state[3]; - buf2 = state[0]; - buf3 = state[0]^state[1]; buf3=galois_mul2(buf3); state[0] = state[0] ^ buf3 ^ buf1; - buf3 = state[1]^state[2]; buf3=galois_mul2(buf3); state[1] = state[1] ^ buf3 ^ buf1; - buf3 = state[2]^state[3]; buf3=galois_mul2(buf3); state[2] = state[2] ^ buf3 ^ buf1; - buf3 = state[3]^buf2; buf3=galois_mul2(buf3); state[3] = state[3] ^ buf3 ^ buf1; - // col2 - buf1 = state[4] ^ state[5] ^ state[6] ^ state[7]; - buf2 = state[4]; - buf3 = state[4]^state[5]; buf3=galois_mul2(buf3); state[4] = state[4] ^ buf3 ^ buf1; - buf3 = state[5]^state[6]; buf3=galois_mul2(buf3); state[5] = state[5] ^ buf3 ^ buf1; - buf3 = state[6]^state[7]; buf3=galois_mul2(buf3); state[6] = state[6] ^ buf3 ^ buf1; - buf3 = state[7]^buf2; buf3=galois_mul2(buf3); state[7] = state[7] ^ buf3 ^ buf1; - // col3 - buf1 = state[8] ^ state[9] ^ state[10] ^ state[11]; - buf2 = state[8]; - buf3 = state[8]^state[9]; buf3=galois_mul2(buf3); state[8] = state[8] ^ buf3 ^ buf1; - buf3 = state[9]^state[10]; buf3=galois_mul2(buf3); state[9] = state[9] ^ buf3 ^ buf1; - buf3 = state[10]^state[11]; buf3=galois_mul2(buf3); state[10] = state[10] ^ buf3 ^ buf1; - buf3 = state[11]^buf2; buf3=galois_mul2(buf3); state[11] = state[11] ^ buf3 ^ buf1; - // col4 - buf1 = state[12] ^ state[13] ^ state[14] ^ state[15]; - buf2 = state[12]; - buf3 = state[12]^state[13]; buf3=galois_mul2(buf3); state[12] = state[12] ^ buf3 ^ buf1; - buf3 = state[13]^state[14]; buf3=galois_mul2(buf3); state[13] = state[13] ^ buf3 ^ buf1; - buf3 = state[14]^state[15]; buf3=galois_mul2(buf3); state[14] = state[14] ^ buf3 ^ buf1; - buf3 = state[15]^buf2; buf3=galois_mul2(buf3); state[15] = state[15] ^ buf3 ^ buf1; - - // addroundkey, rsbox and shiftrows - // row 0 - state[ 0] = rsbox[state[ 0]] ^ expandedKey[(round*16) ]; - state[ 4] = rsbox[state[ 4]] ^ expandedKey[(round*16) + 4]; - state[ 8] = rsbox[state[ 8]] ^ expandedKey[(round*16) + 8]; - state[12] = rsbox[state[12]] ^ expandedKey[(round*16) + 12]; - // row 1 - buf1 = rsbox[state[13]] ^ expandedKey[(round*16) + 1]; - state[13] = rsbox[state[ 9]] ^ expandedKey[(round*16) + 13]; - state[ 9] = rsbox[state[ 5]] ^ expandedKey[(round*16) + 9]; - state[ 5] = rsbox[state[ 1]] ^ expandedKey[(round*16) + 5]; - state[ 1] = buf1; - // row 2 - buf1 = rsbox[state[ 2]] ^ expandedKey[(round*16) + 10]; - buf2 = rsbox[state[ 6]] ^ expandedKey[(round*16) + 14]; - state[ 2] = rsbox[state[10]] ^ expandedKey[(round*16) + 2]; - state[ 6] = rsbox[state[14]] ^ expandedKey[(round*16) + 6]; - state[10] = buf1; - state[14] = buf2; - // row 3 - buf1 = rsbox[state[ 3]] ^ expandedKey[(round*16) + 15]; - state[ 3] = rsbox[state[ 7]] ^ expandedKey[(round*16) + 3]; - state[ 7] = rsbox[state[11]] ^ expandedKey[(round*16) + 7]; - state[11] = rsbox[state[15]] ^ expandedKey[(round*16) + 11]; - state[15] = buf1; - } - -} - -//***************************************************************************** -// -//! aes_encrypt -//! -//! @param[in] key AES128 key of size 16 bytes -//! @param[in\out] state 16 bytes of plain text and cipher text -//! -//! @return none -//! -//! @brief AES128 encryption: -//! Given AES128 key and 16 bytes plain text, cipher text of 16 bytes -//! is computed. The AES implementation is in mode ECB (Electronic -//! Code Book). -//! -//! -//***************************************************************************** - -void aes_encrypt(UINT8 *state, UINT8 *key) -{ - // expand the key into 176 bytes - expandKey(expandedKey, key); - aes_encr(state, expandedKey); -} - -//***************************************************************************** -// -//! aes_decrypt -//! -//! @param[in] key AES128 key of size 16 bytes -//! @param[in\out] state 16 bytes of cipher text and plain text -//! -//! @return none -//! -//! @brief AES128 decryption: -//! Given AES128 key and 16 bytes cipher text, plain text of 16 bytes -//! is computed The AES implementation is in mode ECB -//! (Electronic Code Book). -//! -//! -//***************************************************************************** - -void aes_decrypt(UINT8 *state, UINT8 *key) -{ - expandKey(expandedKey, key); // expand the key into 176 bytes - aes_decr(state, expandedKey); -} - -//***************************************************************************** -// -//! aes_read_key -//! -//! @param[out] key AES128 key of size 16 bytes -//! -//! @return on success 0, error otherwise. -//! -//! @brief Reads AES128 key from EEPROM -//! Reads the AES128 key from fileID #12 in EEPROM -//! returns an error if the key does not exist. -//! -//! -//***************************************************************************** - -INT32 aes_read_key(UINT8 *key) -{ - INT32 returnValue; - - returnValue = nvmem_read(NVMEM_AES128_KEY_FILEID, AES128_KEY_SIZE, 0, key); - - return returnValue; -} - -//***************************************************************************** -// -//! aes_write_key -//! -//! @param[out] key AES128 key of size 16 bytes -//! -//! @return on success 0, error otherwise. -//! -//! @brief writes AES128 key from EEPROM -//! Writes the AES128 key to fileID #12 in EEPROM -//! -//! -//***************************************************************************** - -INT32 aes_write_key(UINT8 *key) -{ - INT32 returnValue; - - returnValue = nvmem_write(NVMEM_AES128_KEY_FILEID, AES128_KEY_SIZE, 0, key); - - return returnValue; -} - -#endif //CC3000_UNENCRYPTED_SMART_CONFIG - -//***************************************************************************** -// -// Close the Doxygen group. -//! @} -// -//***************************************************************************** diff --git a/drivers/cc3000/src/socket.c b/drivers/cc3000/src/socket.c deleted file mode 100644 index ddd7e56e80..0000000000 --- a/drivers/cc3000/src/socket.c +++ /dev/null @@ -1,1182 +0,0 @@ -/***************************************************************************** -* -* socket.c - CC3000 Host Driver Implementation. -* Copyright (C) 2011 Texas Instruments Incorporated - http://www.ti.com/ -* -* Redistribution and use in source and binary forms, with or without -* modification, are permitted provided that the following conditions -* are met: -* -* Redistributions of source code must retain the above copyright -* notice, this list of conditions and the following disclaimer. -* -* Redistributions in binary form must reproduce the above copyright -* notice, this list of conditions and the following disclaimer in the -* documentation and/or other materials provided with the -* distribution. -* -* Neither the name of Texas Instruments Incorporated nor the names of -* its contributors may be used to endorse or promote products derived -* from this software without specific prior written permission. -* -* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -* -*****************************************************************************/ - -//***************************************************************************** -// -//! \addtogroup socket_api -//! @{ -// -//***************************************************************************** - -#include -#include -#include "hci.h" -#include "socket.h" -#include "evnt_handler.h" -#include "netapp.h" - - - -//Enable this flag if and only if you must comply with BSD socket -//close() function -#ifdef _API_USE_BSD_CLOSE -#define close(sd) closesocket(sd) -#endif - -//Enable this flag if and only if you must comply with BSD socket read() and -//write() functions -#ifdef _API_USE_BSD_READ_WRITE -#define read(sd, buf, len, flags) recv(sd, buf, len, flags) -#define write(sd, buf, len, flags) send(sd, buf, len, flags) -#endif - -#define SOCKET_OPEN_PARAMS_LEN (12) -#define SOCKET_CLOSE_PARAMS_LEN (4) -#define SOCKET_ACCEPT_PARAMS_LEN (4) -#define SOCKET_BIND_PARAMS_LEN (20) -#define SOCKET_LISTEN_PARAMS_LEN (8) -#define SOCKET_GET_HOST_BY_NAME_PARAMS_LEN (9) -#define SOCKET_CONNECT_PARAMS_LEN (20) -#define SOCKET_SELECT_PARAMS_LEN (44) -#define SOCKET_SET_SOCK_OPT_PARAMS_LEN (20) -#define SOCKET_GET_SOCK_OPT_PARAMS_LEN (12) -#define SOCKET_RECV_FROM_PARAMS_LEN (12) -#define SOCKET_SENDTO_PARAMS_LEN (24) -#define SOCKET_MDNS_ADVERTISE_PARAMS_LEN (12) -#define SOCKET_GET_MSS_VALUE_PARAMS_LEN (4) - -// The legnth of arguments for the SEND command: sd + buff_offset + len + flags, -// while size of each parameter is 32 bit - so the total length is 16 bytes; - -#define HCI_CMND_SEND_ARG_LENGTH (16) - - -#define SELECT_TIMEOUT_MIN_MICRO_SECONDS 5000 - -#define HEADERS_SIZE_DATA (SPI_HEADER_SIZE + 5) - -#define SIMPLE_LINK_HCI_CMND_TRANSPORT_HEADER_SIZE (SPI_HEADER_SIZE + SIMPLE_LINK_HCI_CMND_HEADER_SIZE) - -#define MDNS_DEVICE_SERVICE_MAX_LENGTH (32) - - -//***************************************************************************** -// -//! HostFlowControlConsumeBuff -//! -//! @param sd socket descriptor -//! -//! @return 0 in case there are buffers available, -//! -1 in case of bad socket -//! -2 if there are no free buffers present (only when -//! SEND_NON_BLOCKING is enabled) -//! -//! @brief if SEND_NON_BLOCKING not define - block until have free buffer -//! becomes available, else return immediately with correct status -//! regarding the buffers available. -// -//***************************************************************************** -static INT16 HostFlowControlConsumeBuff(INT16 sd) -{ -#ifndef SEND_NON_BLOCKING - /* wait in busy loop */ - do - { - // In case last transmission failed then we will return the last failure - // reason here. - // Note that the buffer will not be allocated in this case - if (tSLInformation.slTransmitDataError != 0) - { - CC3000_EXPORT(errno) = tSLInformation.slTransmitDataError; - tSLInformation.slTransmitDataError = 0; - return CC3000_EXPORT(errno); - } - - if(SOCKET_STATUS_ACTIVE != get_socket_active_status(sd)) - return -1; - } while(0 == tSLInformation.usNumberOfFreeBuffers); - - tSLInformation.usNumberOfFreeBuffers--; - - return 0; -#else - - // In case last transmission failed then we will return the last failure - // reason here. - // Note that the buffer will not be allocated in this case - if (tSLInformation.slTransmitDataError != 0) - { - CC3000_EXPORT(errno) = tSLInformation.slTransmitDataError; - tSLInformation.slTransmitDataError = 0; - return CC3000_EXPORT(errno); - } - if(SOCKET_STATUS_ACTIVE != get_socket_active_status(sd)) - return -1; - - //If there are no available buffers, return -2. It is recommended to use - // select or receive to see if there is any buffer occupied with received data - // If so, call receive() to release the buffer. - if(0 == tSLInformation.usNumberOfFreeBuffers) - { - return -2; - } - else - { - tSLInformation.usNumberOfFreeBuffers--; - return 0; - } -#endif -} - -//***************************************************************************** -// -//! socket -//! -//! @param domain selects the protocol family which will be used for -//! communication. On this version only AF_INET is supported -//! @param type specifies the communication semantics. On this version -//! only SOCK_STREAM, SOCK_DGRAM, SOCK_RAW are supported -//! @param protocol specifies a particular protocol to be used with the -//! socket IPPROTO_TCP, IPPROTO_UDP or IPPROTO_RAW are -//! supported. -//! -//! @return On success, socket handle that is used for consequent socket -//! operations. On error, -1 is returned. -//! -//! @brief create an endpoint for communication -//! The socket function creates a socket that is bound to a specific -//! transport service provider. This function is called by the -//! application layer to obtain a socket handle. -// -//***************************************************************************** - -INT16 CC3000_EXPORT(socket)(INT32 domain, INT32 type, INT32 protocol) -{ - INT32 ret; - UINT8 *ptr, *args; - - ret = EFAIL; - ptr = tSLInformation.pucTxCommandBuffer; - args = (ptr + HEADERS_SIZE_CMD); - - // Fill in HCI packet structure - args = UINT32_TO_STREAM(args, domain); - args = UINT32_TO_STREAM(args, type); - args = UINT32_TO_STREAM(args, protocol); - - // Initiate a HCI command - hci_command_send(HCI_CMND_SOCKET, ptr, SOCKET_OPEN_PARAMS_LEN); - - // Since we are in blocking state - wait for event complete - SimpleLinkWaitEvent(HCI_CMND_SOCKET, &ret); - - // Process the event - CC3000_EXPORT(errno) = ret; - - set_socket_active_status(ret, SOCKET_STATUS_ACTIVE); - - return(ret); -} - -//***************************************************************************** -// -//! closesocket -//! -//! @param sd socket handle. -//! -//! @return On success, zero is returned. On error, -1 is returned. -//! -//! @brief The socket function closes a created socket. -// -//***************************************************************************** - -INT32 CC3000_EXPORT(closesocket)(INT32 sd) -{ - INT32 ret; - UINT8 *ptr, *args; - - ret = EFAIL; - ptr = tSLInformation.pucTxCommandBuffer; - args = (ptr + HEADERS_SIZE_CMD); - - // Fill in HCI packet structure - args = UINT32_TO_STREAM(args, sd); - - // Initiate a HCI command - hci_command_send(HCI_CMND_CLOSE_SOCKET, - ptr, SOCKET_CLOSE_PARAMS_LEN); - - // Since we are in blocking state - wait for event complete - SimpleLinkWaitEvent(HCI_CMND_CLOSE_SOCKET, &ret); - CC3000_EXPORT(errno) = ret; - - // since 'close' call may result in either OK (and then it closed) or error - // mark this socket as invalid - set_socket_active_status(sd, SOCKET_STATUS_INACTIVE); - - return(ret); -} - -//***************************************************************************** -// -//! accept -//! -//! @param[in] sd socket descriptor (handle) -//! @param[out] addr the argument addr is a pointer to a sockaddr structure -//! This structure is filled in with the address of the -//! peer socket, as known to the communications layer. -//! determined. The exact format of the address returned -//! addr is by the socket's address sockaddr. -//! On this version only AF_INET is supported. -//! This argument returns in network order. -//! @param[out] addrlen the addrlen argument is a value-result argument: -//! it should initially contain the size of the structure -//! pointed to by addr. -//! -//! @return For socket in blocking mode: -//! On success, socket handle. on failure negative -//! For socket in non-blocking mode: -//! - On connection establishment, socket handle -//! - On connection pending, SOC_IN_PROGRESS (-2) -//! - On failure, SOC_ERROR (-1) -//! -//! @brief accept a connection on a socket: -//! This function is used with connection-based socket types -//! (SOCK_STREAM). It extracts the first connection request on the -//! queue of pending connections, creates a new connected socket, and -//! returns a new file descriptor referring to that socket. -//! The newly created socket is not in the listening state. -//! The original socket sd is unaffected by this call. -//! The argument sd is a socket that has been created with socket(), -//! bound to a local address with bind(), and is listening for -//! connections after a listen(). The argument addr is a pointer -//! to a sockaddr structure. This structure is filled in with the -//! address of the peer socket, as known to the communications layer. -//! The exact format of the address returned addr is determined by the -//! socket's address family. The addrlen argument is a value-result -//! argument: it should initially contain the size of the structure -//! pointed to by addr, on return it will contain the actual -//! length (in bytes) of the address returned. -//! -//! @sa socket ; bind ; listen -// -//***************************************************************************** - -INT32 CC3000_EXPORT(accept)(INT32 sd, sockaddr *addr, socklen_t *addrlen) -{ - INT32 ret; - UINT8 *ptr, *args; - tBsdReturnParams tAcceptReturnArguments; - - ret = EFAIL; - ptr = tSLInformation.pucTxCommandBuffer; - args = (ptr + HEADERS_SIZE_CMD); - - // Fill in temporary command buffer - args = UINT32_TO_STREAM(args, sd); - - // Initiate a HCI command - hci_command_send(HCI_CMND_ACCEPT, - ptr, SOCKET_ACCEPT_PARAMS_LEN); - - // Since we are in blocking state - wait for event complete - SimpleLinkWaitEvent(HCI_CMND_ACCEPT, &tAcceptReturnArguments); - - - // need specify return parameters!!! - memcpy(addr, &tAcceptReturnArguments.tSocketAddress, ASIC_ADDR_LEN); - *addrlen = ASIC_ADDR_LEN; - CC3000_EXPORT(errno) = tAcceptReturnArguments.iStatus; - ret = CC3000_EXPORT(errno); - - // if succeeded, iStatus = new socket descriptor. otherwise - error number - if(M_IS_VALID_SD(ret)) - { - set_socket_active_status(ret, SOCKET_STATUS_ACTIVE); - } - else - { - set_socket_active_status(sd, SOCKET_STATUS_INACTIVE); - } - - return(ret); -} - -//***************************************************************************** -// -//! bind -//! -//! @param[in] sd socket descriptor (handle) -//! @param[out] addr specifies the destination address. On this version -//! only AF_INET is supported. -//! @param[out] addrlen contains the size of the structure pointed to by addr. -//! -//! @return On success, zero is returned. On error, -1 is returned. -//! -//! @brief assign a name to a socket -//! This function gives the socket the local address addr. -//! addr is addrlen bytes long. Traditionally, this is called when a -//! socket is created with socket, it exists in a name space (address -//! family) but has no name assigned. -//! It is necessary to assign a local address before a SOCK_STREAM -//! socket may receive connections. -//! -//! @sa socket ; accept ; listen -// -//***************************************************************************** - -INT32 CC3000_EXPORT(bind)(INT32 sd, const sockaddr *addr, INT32 addrlen) -{ - INT32 ret; - UINT8 *ptr, *args; - - ret = EFAIL; - ptr = tSLInformation.pucTxCommandBuffer; - args = (ptr + HEADERS_SIZE_CMD); - - addrlen = ASIC_ADDR_LEN; - - // Fill in temporary command buffer - args = UINT32_TO_STREAM(args, sd); - args = UINT32_TO_STREAM(args, 0x00000008); - args = UINT32_TO_STREAM(args, addrlen); - ARRAY_TO_STREAM(args, ((UINT8 *)addr), addrlen); - - // Initiate a HCI command - hci_command_send(HCI_CMND_BIND, - ptr, SOCKET_BIND_PARAMS_LEN); - - // Since we are in blocking state - wait for event complete - SimpleLinkWaitEvent(HCI_CMND_BIND, &ret); - - CC3000_EXPORT(errno) = ret; - - return(ret); -} - -//***************************************************************************** -// -//! listen -//! -//! @param[in] sd socket descriptor (handle) -//! @param[in] backlog specifies the listen queue depth. On this version -//! backlog is not supported. -//! @return On success, zero is returned. On error, -1 is returned. -//! -//! @brief listen for connections on a socket -//! The willingness to accept incoming connections and a queue -//! limit for incoming connections are specified with listen(), -//! and then the connections are accepted with accept. -//! The listen() call applies only to sockets of type SOCK_STREAM -//! The backlog parameter defines the maximum length the queue of -//! pending connections may grow to. -//! -//! @sa socket ; accept ; bind -//! -//! @note On this version, backlog is not supported -// -//***************************************************************************** - -INT32 CC3000_EXPORT(listen)(INT32 sd, INT32 backlog) -{ - INT32 ret; - UINT8 *ptr, *args; - - ret = EFAIL; - ptr = tSLInformation.pucTxCommandBuffer; - args = (ptr + HEADERS_SIZE_CMD); - - // Fill in temporary command buffer - args = UINT32_TO_STREAM(args, sd); - args = UINT32_TO_STREAM(args, backlog); - - // Initiate a HCI command - hci_command_send(HCI_CMND_LISTEN, - ptr, SOCKET_LISTEN_PARAMS_LEN); - - // Since we are in blocking state - wait for event complete - SimpleLinkWaitEvent(HCI_CMND_LISTEN, &ret); - CC3000_EXPORT(errno) = ret; - - return(ret); -} - -//***************************************************************************** -// -//! gethostbyname -//! -//! @param[in] hostname host name -//! @param[in] usNameLen name length -//! @param[out] out_ip_addr This parameter is filled in with host IP address. -//! In case that host name is not resolved, -//! out_ip_addr is zero. -//! @return On success, positive is returned. On error, negative is returned -//! -//! @brief Get host IP by name. Obtain the IP Address of machine on network, -//! by its name. -//! -//! @note On this version, only blocking mode is supported. Also note that -//! the function requires DNS server to be configured prior to its usage. -// -//***************************************************************************** - -#ifndef CC3000_TINY_DRIVER -INT16 CC3000_EXPORT(gethostbyname)(CHAR * hostname, UINT16 usNameLen, - UINT32* out_ip_addr) -{ - tBsdGethostbynameParams ret; - UINT8 *ptr, *args; - - CC3000_EXPORT(errno) = EFAIL; - - if (usNameLen > HOSTNAME_MAX_LENGTH) - { - return CC3000_EXPORT(errno); - } - - ptr = tSLInformation.pucTxCommandBuffer; - args = (ptr + SIMPLE_LINK_HCI_CMND_TRANSPORT_HEADER_SIZE); - - // Fill in HCI packet structure - args = UINT32_TO_STREAM(args, 8); - args = UINT32_TO_STREAM(args, usNameLen); - ARRAY_TO_STREAM(args, hostname, usNameLen); - - // Initiate a HCI command - hci_command_send(HCI_CMND_GETHOSTNAME, ptr, SOCKET_GET_HOST_BY_NAME_PARAMS_LEN - + usNameLen - 1); - - // Since we are in blocking state - wait for event complete - SimpleLinkWaitEvent(HCI_EVNT_BSD_GETHOSTBYNAME, &ret); - - CC3000_EXPORT(errno) = ret.retVal; - - (*((INT32*)out_ip_addr)) = ret.outputAddress; - - return CC3000_EXPORT(errno); - -} -#endif - -//***************************************************************************** -// -//! connect -//! -//! @param[in] sd socket descriptor (handle) -//! @param[in] addr specifies the destination addr. On this version -//! only AF_INET is supported. -//! @param[out] addrlen contains the size of the structure pointed to by addr -//! @return On success, zero is returned. On error, -1 is returned -//! -//! @brief initiate a connection on a socket -//! Function connects the socket referred to by the socket descriptor -//! sd, to the address specified by addr. The addrlen argument -//! specifies the size of addr. The format of the address in addr is -//! determined by the address space of the socket. If it is of type -//! SOCK_DGRAM, this call specifies the peer with which the socket is -//! to be associated; this address is that to which datagrams are to be -//! sent, and the only address from which datagrams are to be received. -//! If the socket is of type SOCK_STREAM, this call attempts to make a -//! connection to another socket. The other socket is specified by -//! address, which is an address in the communications space of the -//! socket. Note that the function implements only blocking behavior -//! thus the caller will be waiting either for the connection -//! establishment or for the connection establishment failure. -//! -//! @sa socket -// -//***************************************************************************** - -INT32 CC3000_EXPORT(connect)(INT32 sd, const sockaddr *addr, INT32 addrlen) -{ - INT32 ret; - UINT8 *ptr, *args; - - ret = EFAIL; - ptr = tSLInformation.pucTxCommandBuffer; - args = (ptr + SIMPLE_LINK_HCI_CMND_TRANSPORT_HEADER_SIZE); - addrlen = 8; - - // Fill in temporary command buffer - args = UINT32_TO_STREAM(args, sd); - args = UINT32_TO_STREAM(args, 0x00000008); - args = UINT32_TO_STREAM(args, addrlen); - ARRAY_TO_STREAM(args, ((UINT8 *)addr), addrlen); - - // Initiate a HCI command - hci_command_send(HCI_CMND_CONNECT, - ptr, SOCKET_CONNECT_PARAMS_LEN); - - // Since we are in blocking state - wait for event complete - SimpleLinkWaitEvent(HCI_CMND_CONNECT, &ret); - - CC3000_EXPORT(errno) = ret; - - return((INT32)ret); -} - - -//***************************************************************************** -// -//! select -//! -//! @param[in] nfds the highest-numbered file descriptor in any of the -//! three sets, plus 1. -//! @param[out] writesds socket descriptors list for write monitoring -//! @param[out] readsds socket descriptors list for read monitoring -//! @param[out] exceptsds socket descriptors list for exception monitoring -//! @param[in] timeout is an upper bound on the amount of time elapsed -//! before select() returns. Null means infinity -//! timeout. The minimum timeout is 5 milliseconds, -//! less than 5 milliseconds will be set -//! automatically to 5 milliseconds. -//! @return On success, select() returns the number of file descriptors -//! contained in the three returned descriptor sets (that is, the -//! total number of bits that are set in readfds, writefds, -//! exceptfds) which may be zero if the timeout expires before -//! anything interesting happens. -//! On error, -1 is returned. -//! *readsds - return the sockets on which Read request will -//! return without delay with valid data. -//! *writesds - return the sockets on which Write request -//! will return without delay. -//! *exceptsds - return the sockets which closed recently. -//! -//! @brief Monitor socket activity -//! Select allow a program to monitor multiple file descriptors, -//! waiting until one or more of the file descriptors become -//! "ready" for some class of I/O operation -//! -//! @Note If the timeout value set to less than 5ms it will automatically set -//! to 5ms to prevent overload of the system -//! -//! @sa socket -// -//***************************************************************************** - -INT16 CC3000_EXPORT(select)(INT32 nfds, fd_set *readsds, fd_set *writesds, fd_set *exceptsds, -struct cc3000_timeval *timeout) -{ - UINT8 *ptr, *args; - tBsdSelectRecvParams tParams; - UINT32 is_blocking; - - if( timeout == NULL) - { - is_blocking = 1; /* blocking , infinity timeout */ - } - else - { - is_blocking = 0; /* no blocking, timeout */ - } - - // Fill in HCI packet structure - ptr = tSLInformation.pucTxCommandBuffer; - args = (ptr + HEADERS_SIZE_CMD); - - // Fill in temporary command buffer - args = UINT32_TO_STREAM(args, nfds); - args = UINT32_TO_STREAM(args, 0x00000014); - args = UINT32_TO_STREAM(args, 0x00000014); - args = UINT32_TO_STREAM(args, 0x00000014); - args = UINT32_TO_STREAM(args, 0x00000014); - args = UINT32_TO_STREAM(args, is_blocking); - args = UINT32_TO_STREAM(args, ((readsds) ? *(UINT32*)readsds : 0)); - args = UINT32_TO_STREAM(args, ((writesds) ? *(UINT32*)writesds : 0)); - args = UINT32_TO_STREAM(args, ((exceptsds) ? *(UINT32*)exceptsds : 0)); - - if (timeout) - { - if ( 0 == timeout->tv_sec && timeout->tv_usec < - SELECT_TIMEOUT_MIN_MICRO_SECONDS) - { - timeout->tv_usec = SELECT_TIMEOUT_MIN_MICRO_SECONDS; - } - args = UINT32_TO_STREAM(args, timeout->tv_sec); - args = UINT32_TO_STREAM(args, timeout->tv_usec); - } - - // Initiate a HCI command - hci_command_send(HCI_CMND_BSD_SELECT, ptr, SOCKET_SELECT_PARAMS_LEN); - - // Since we are in blocking state - wait for event complete - SimpleLinkWaitEvent(HCI_EVNT_SELECT, &tParams); - - // Update actually read FD - if (tParams.iStatus >= 0) - { - if (readsds) - { - memcpy(readsds, &tParams.uiRdfd, sizeof(tParams.uiRdfd)); - } - - if (writesds) - { - memcpy(writesds, &tParams.uiWrfd, sizeof(tParams.uiWrfd)); - } - - if (exceptsds) - { - memcpy(exceptsds, &tParams.uiExfd, sizeof(tParams.uiExfd)); - } - - return(tParams.iStatus); - - } - else - { - CC3000_EXPORT(errno) = tParams.iStatus; - return(-1); - } -} - -//***************************************************************************** -// -//! setsockopt -//! -//! @param[in] sd socket handle -//! @param[in] level defines the protocol level for this option -//! @param[in] optname defines the option name to Interrogate -//! @param[in] optval specifies a value for the option -//! @param[in] optlen specifies the length of the option value -//! @return On success, zero is returned. On error, -1 is returned -//! -//! @brief set socket options -//! This function manipulate the options associated with a socket. -//! Options may exist at multiple protocol levels; they are always -//! present at the uppermost socket level. -//! When manipulating socket options the level at which the option -//! resides and the name of the option must be specified. -//! To manipulate options at the socket level, level is specified as -//! SOL_SOCKET. To manipulate options at any other level the protocol -//! number of the appropriate protocol controlling the option is -//! supplied. For example, to indicate that an option is to be -//! interpreted by the TCP protocol, level should be set to the -//! protocol number of TCP; -//! The parameters optval and optlen are used to access optval - -//! use for setsockopt(). For getsockopt() they identify a buffer -//! in which the value for the requested option(s) are to -//! be returned. For getsockopt(), optlen is a value-result -//! parameter, initially containing the size of the buffer -//! pointed to by option_value, and modified on return to -//! indicate the actual size of the value returned. If no option -//! value is to be supplied or returned, option_value may be NULL. -//! -//! @Note On this version the following two socket options are enabled: -//! The only protocol level supported in this version -//! is SOL_SOCKET (level). -//! 1. SOCKOPT_RECV_TIMEOUT (optname) -//! SOCKOPT_RECV_TIMEOUT configures recv and recvfrom timeout -//! in milliseconds. -//! In that case optval should be pointer to UINT32. -//! 2. SOCKOPT_NONBLOCK (optname). sets the socket non-blocking mode on -//! or off. -//! In that case optval should be SOCK_ON or SOCK_OFF (optval). -//! -//! @sa getsockopt -// -//***************************************************************************** - -#ifndef CC3000_TINY_DRIVER -INT16 CC3000_EXPORT(setsockopt)(INT32 sd, INT32 level, INT32 optname, const void *optval, - socklen_t optlen) -{ - INT32 ret; - UINT8 *ptr, *args; - - ptr = tSLInformation.pucTxCommandBuffer; - args = (ptr + HEADERS_SIZE_CMD); - - // Fill in temporary command buffer - args = UINT32_TO_STREAM(args, sd); - args = UINT32_TO_STREAM(args, level); - args = UINT32_TO_STREAM(args, optname); - args = UINT32_TO_STREAM(args, 0x00000008); - args = UINT32_TO_STREAM(args, optlen); - ARRAY_TO_STREAM(args, ((UINT8 *)optval), optlen); - - // Initiate a HCI command - hci_command_send(HCI_CMND_SETSOCKOPT, - ptr, SOCKET_SET_SOCK_OPT_PARAMS_LEN + optlen); - - // Since we are in blocking state - wait for event complete - SimpleLinkWaitEvent(HCI_CMND_SETSOCKOPT, &ret); - - if (ret >= 0) - { - return (0); - } - else - { - CC3000_EXPORT(errno) = ret; - return ret; - } -} -#endif - -//***************************************************************************** -// -//! getsockopt -//! -//! @param[in] sd socket handle -//! @param[in] level defines the protocol level for this option -//! @param[in] optname defines the option name to Interrogate -//! @param[out] optval specifies a value for the option -//! @param[out] optlen specifies the length of the option value -//! @return On success, zero is returned. On error, -1 is returned -//! -//! @brief set socket options -//! This function manipulate the options associated with a socket. -//! Options may exist at multiple protocol levels; they are always -//! present at the uppermost socket level. -//! When manipulating socket options the level at which the option -//! resides and the name of the option must be specified. -//! To manipulate options at the socket level, level is specified as -//! SOL_SOCKET. To manipulate options at any other level the protocol -//! number of the appropriate protocol controlling the option is -//! supplied. For example, to indicate that an option is to be -//! interpreted by the TCP protocol, level should be set to the -//! protocol number of TCP; -//! The parameters optval and optlen are used to access optval - -//! use for setsockopt(). For getsockopt() they identify a buffer -//! in which the value for the requested option(s) are to -//! be returned. For getsockopt(), optlen is a value-result -//! parameter, initially containing the size of the buffer -//! pointed to by option_value, and modified on return to -//! indicate the actual size of the value returned. If no option -//! value is to be supplied or returned, option_value may be NULL. -//! -//! @Note On this version the following two socket options are enabled: -//! The only protocol level supported in this version -//! is SOL_SOCKET (level). -//! 1. SOCKOPT_RECV_TIMEOUT (optname) -//! SOCKOPT_RECV_TIMEOUT configures recv and recvfrom timeout -//! in milliseconds. -//! In that case optval should be pointer to UINT32. -//! 2. SOCKOPT_NONBLOCK (optname). sets the socket non-blocking mode on -//! or off. -//! In that case optval should be SOCK_ON or SOCK_OFF (optval). -//! -//! @sa setsockopt -// -//***************************************************************************** - -INT16 CC3000_EXPORT(getsockopt) (INT32 sd, INT32 level, INT32 optname, void *optval, socklen_t *optlen) -{ - UINT8 *ptr, *args; - tBsdGetSockOptReturnParams tRetParams; - - ptr = tSLInformation.pucTxCommandBuffer; - args = (ptr + HEADERS_SIZE_CMD); - - // Fill in temporary command buffer - args = UINT32_TO_STREAM(args, sd); - args = UINT32_TO_STREAM(args, level); - args = UINT32_TO_STREAM(args, optname); - - // Initiate a HCI command - hci_command_send(HCI_CMND_GETSOCKOPT, - ptr, SOCKET_GET_SOCK_OPT_PARAMS_LEN); - - // Since we are in blocking state - wait for event complete - SimpleLinkWaitEvent(HCI_CMND_GETSOCKOPT, &tRetParams); - - if (((INT8)tRetParams.iStatus) >= 0) - { - *optlen = 4; - memcpy(optval, tRetParams.ucOptValue, 4); - return (0); - } - else - { - CC3000_EXPORT(errno) = tRetParams.iStatus; - return CC3000_EXPORT(errno); - } -} - -//***************************************************************************** -// -//! simple_link_recv -//! -//! @param sd socket handle -//! @param buf read buffer -//! @param len buffer length -//! @param flags indicates blocking or non-blocking operation -//! @param from pointer to an address structure indicating source address -//! @param fromlen source address structure size -//! -//! @return Return the number of bytes received, or -1 if an error -//! occurred -//! -//! @brief Read data from socket -//! Return the length of the message on successful completion. -//! If a message is too long to fit in the supplied buffer, -//! excess bytes may be discarded depending on the type of -//! socket the message is received from -// -//***************************************************************************** -static INT16 simple_link_recv(INT32 sd, void *buf, INT32 len, INT32 flags, sockaddr *from, - socklen_t *fromlen, INT32 opcode) -{ - UINT8 *ptr, *args; - tBsdReadReturnParams tSocketReadEvent; - - ptr = tSLInformation.pucTxCommandBuffer; - args = (ptr + HEADERS_SIZE_CMD); - - // Fill in HCI packet structure - args = UINT32_TO_STREAM(args, sd); - args = UINT32_TO_STREAM(args, len); - args = UINT32_TO_STREAM(args, flags); - - // Generate the read command, and wait for the - hci_command_send(opcode, ptr, SOCKET_RECV_FROM_PARAMS_LEN); - - // Since we are in blocking state - wait for event complete - SimpleLinkWaitEvent(opcode, &tSocketReadEvent); - - // In case the number of bytes is more then zero - read data - if (tSocketReadEvent.iNumberOfBytes > 0) - { - // Wait for the data in a synchronous way. Here we assume that the bug is - // big enough to store also parameters of receive from too.... - SimpleLinkWaitData(buf, (UINT8 *)from, (UINT8 *)fromlen); - } - - CC3000_EXPORT(errno) = tSocketReadEvent.iNumberOfBytes; - - return(tSocketReadEvent.iNumberOfBytes); -} - -//***************************************************************************** -// -//! recv -//! -//! @param[in] sd socket handle -//! @param[out] buf Points to the buffer where the message should be stored -//! @param[in] len Specifies the length in bytes of the buffer pointed to -//! by the buffer argument. -//! @param[in] flags Specifies the type of message reception. -//! On this version, this parameter is not supported. -//! -//! @return Return the number of bytes received, or -1 if an error -//! occurred -//! -//! @brief function receives a message from a connection-mode socket -//! -//! @sa recvfrom -//! -//! @Note On this version, only blocking mode is supported. -// -//***************************************************************************** - -INT16 CC3000_EXPORT(recv)(INT32 sd, void *buf, INT32 len, INT32 flags) -{ - return(simple_link_recv(sd, buf, len, flags, NULL, NULL, HCI_CMND_RECV)); -} - -//***************************************************************************** -// -//! recvfrom -//! -//! @param[in] sd socket handle -//! @param[out] buf Points to the buffer where the message should be stored -//! @param[in] len Specifies the length in bytes of the buffer pointed to -//! by the buffer argument. -//! @param[in] flags Specifies the type of message reception. -//! On this version, this parameter is not supported. -//! @param[in] from pointer to an address structure indicating the source -//! address: sockaddr. On this version only AF_INET is -//! supported. -//! @param[in] fromlen source address tructure size -//! -//! @return Return the number of bytes received, or -1 if an error -//! occurred -//! -//! @brief read data from socket -//! function receives a message from a connection-mode or -//! connectionless-mode socket. Note that raw sockets are not -//! supported. -//! -//! @sa recv -//! -//! @Note On this version, only blocking mode is supported. -// -//***************************************************************************** -INT16 CC3000_EXPORT(recvfrom)(INT32 sd, void *buf, INT32 len, INT32 flags, sockaddr *from, - socklen_t *fromlen) -{ - return(simple_link_recv(sd, buf, len, flags, from, fromlen, - HCI_CMND_RECVFROM)); -} - -//***************************************************************************** -// -//! simple_link_send -//! -//! @param sd socket handle -//! @param buf write buffer -//! @param len buffer length -//! @param flags On this version, this parameter is not supported -//! @param to pointer to an address structure indicating destination -//! address -//! @param tolen destination address structure size -//! -//! @return Return the number of bytes transmitted, or -1 if an error -//! occurred, or -2 in case there are no free buffers available -//! (only when SEND_NON_BLOCKING is enabled) -//! -//! @brief This function is used to transmit a message to another -//! socket -// -//***************************************************************************** -static INT16 simple_link_send(INT32 sd, const void *buf, INT32 len, INT32 flags, - const sockaddr *to, INT32 tolen, INT32 opcode) -{ - UINT8 uArgSize=0, addrlen; - UINT8 *ptr, *pDataPtr=0, *args; - UINT32 addr_offset=0; - INT16 res; - tBsdReadReturnParams tSocketSendEvent; - - // Check the bsd_arguments - if (0 != (res = HostFlowControlConsumeBuff(sd))) - { - return res; - } - - //Update the number of sent packets - tSLInformation.NumberOfSentPackets++; - - // Allocate a buffer and construct a packet and send it over spi - ptr = tSLInformation.pucTxCommandBuffer; - args = (ptr + HEADERS_SIZE_DATA); - - // Update the offset of data and parameters according to the command - switch(opcode) - { - case HCI_CMND_SENDTO: - { - addr_offset = len + sizeof(len) + sizeof(len); - addrlen = 8; - uArgSize = SOCKET_SENDTO_PARAMS_LEN; - pDataPtr = ptr + HEADERS_SIZE_DATA + SOCKET_SENDTO_PARAMS_LEN; - break; - } - - case HCI_CMND_SEND: - { - tolen = 0; - to = NULL; - uArgSize = HCI_CMND_SEND_ARG_LENGTH; - pDataPtr = ptr + HEADERS_SIZE_DATA + HCI_CMND_SEND_ARG_LENGTH; - break; - } - - default: - { - break; - } - } - - // Fill in temporary command buffer - args = UINT32_TO_STREAM(args, sd); - args = UINT32_TO_STREAM(args, uArgSize - sizeof(sd)); - args = UINT32_TO_STREAM(args, len); - args = UINT32_TO_STREAM(args, flags); - - if (opcode == HCI_CMND_SENDTO) - { - args = UINT32_TO_STREAM(args, addr_offset); - args = UINT32_TO_STREAM(args, addrlen); - } - - // Copy the data received from user into the TX Buffer - ARRAY_TO_STREAM(pDataPtr, ((UINT8 *)buf), len); - - // In case we are using SendTo, copy the to parameters - if (opcode == HCI_CMND_SENDTO) - { - ARRAY_TO_STREAM(pDataPtr, ((UINT8 *)to), tolen); - } - - // Initiate a HCI command - hci_data_send(opcode, ptr, uArgSize, len,(UINT8*)to, tolen); - - if (opcode == HCI_CMND_SENDTO) - SimpleLinkWaitEvent(HCI_EVNT_SENDTO, &tSocketSendEvent); - else - SimpleLinkWaitEvent(HCI_EVNT_SEND, &tSocketSendEvent); - - return (len); -} - - -//***************************************************************************** -// -//! send -//! -//! @param sd socket handle -//! @param buf Points to a buffer containing the message to be sent -//! @param len message size in bytes -//! @param flags On this version, this parameter is not supported -//! -//! @return Return the number of bytes transmitted, or -1 if an -//! error occurred -//! -//! @brief Write data to TCP socket -//! This function is used to transmit a message to another -//! socket. -//! -//! @Note On this version, only blocking mode is supported. -//! -//! @sa sendto -// -//***************************************************************************** - -INT16 CC3000_EXPORT(send)(INT32 sd, const void *buf, INT32 len, INT32 flags) -{ - return(simple_link_send(sd, buf, len, flags, NULL, 0, HCI_CMND_SEND)); -} - -//***************************************************************************** -// -//! sendto -//! -//! @param sd socket handle -//! @param buf Points to a buffer containing the message to be sent -//! @param len message size in bytes -//! @param flags On this version, this parameter is not supported -//! @param to pointer to an address structure indicating the destination -//! address: sockaddr. On this version only AF_INET is -//! supported. -//! @param tolen destination address structure size -//! -//! @return Return the number of bytes transmitted, or -1 if an -//! error occurred -//! -//! @brief Write data to TCP socket -//! This function is used to transmit a message to another -//! socket. -//! -//! @Note On this version, only blocking mode is supported. -//! -//! @sa send -// -//***************************************************************************** - -INT16 CC3000_EXPORT(sendto)(INT32 sd, const void *buf, INT32 len, INT32 flags, const sockaddr *to, - socklen_t tolen) -{ - return(simple_link_send(sd, buf, len, flags, to, tolen, HCI_CMND_SENDTO)); -} - -//***************************************************************************** -// -//! mdnsAdvertiser -//! -//! @param[in] mdnsEnabled flag to enable/disable the mDNS feature -//! @param[in] deviceServiceName Service name as part of the published -//! canonical domain name -//! @param[in] deviceServiceNameLength Length of the service name - up to 32 chars -//! -//! -//! @return On success, zero is returned, return SOC_ERROR if socket was not -//! opened successfully, or if an error occurred. -//! -//! @brief Set CC3000 in mDNS advertiser mode in order to advertise itself. -// -//***************************************************************************** - -INT16 CC3000_EXPORT(mdnsAdvertiser)(UINT16 mdnsEnabled, CHAR * deviceServiceName, UINT16 deviceServiceNameLength) -{ - INT8 ret; - UINT8 *pTxBuffer, *pArgs; - - if (deviceServiceNameLength > MDNS_DEVICE_SERVICE_MAX_LENGTH) - { - return EFAIL; - } - - pTxBuffer = tSLInformation.pucTxCommandBuffer; - pArgs = (pTxBuffer + SIMPLE_LINK_HCI_CMND_TRANSPORT_HEADER_SIZE); - - // Fill in HCI packet structure - pArgs = UINT32_TO_STREAM(pArgs, mdnsEnabled); - pArgs = UINT32_TO_STREAM(pArgs, 8); - pArgs = UINT32_TO_STREAM(pArgs, deviceServiceNameLength); - ARRAY_TO_STREAM(pArgs, deviceServiceName, deviceServiceNameLength); - - // Initiate a HCI command - hci_command_send(HCI_CMND_MDNS_ADVERTISE, pTxBuffer, SOCKET_MDNS_ADVERTISE_PARAMS_LEN + deviceServiceNameLength); - - // Since we are in blocking state - wait for event complete - SimpleLinkWaitEvent(HCI_EVNT_MDNS_ADVERTISE, &ret); - - return ret; - -} - - -//***************************************************************************** -// -//! getmssvalue -//! -//! @param[in] sd socket descriptor -//! -//! @return On success, returns the MSS value of a TCP connection -//! -//! @brief Returns the MSS value of a TCP connection according to the socket descriptor -// -//***************************************************************************** -UINT16 CC3000_EXPORT(getmssvalue) (INT32 sd) -{ - UINT8 *ptr, *args; - UINT16 ret; - - ptr = tSLInformation.pucTxCommandBuffer; - args = (ptr + HEADERS_SIZE_CMD); - - // Fill in temporary command buffer - args = UINT32_TO_STREAM(args, sd); - - // Initiate a HCI command - hci_command_send(HCI_CMND_GETMSSVALUE, ptr, SOCKET_GET_MSS_VALUE_PARAMS_LEN); - - // Since we are in blocking state - wait for event complete - SimpleLinkWaitEvent(HCI_EVNT_GETMSSVALUE, &ret); - - return ret; -} diff --git a/drivers/cc3000/src/wlan.c b/drivers/cc3000/src/wlan.c deleted file mode 100644 index 6385937778..0000000000 --- a/drivers/cc3000/src/wlan.c +++ /dev/null @@ -1,1252 +0,0 @@ -/***************************************************************************** -* -* wlan.c - CC3000 Host Driver Implementation. -* Copyright (C) 2011 Texas Instruments Incorporated - http://www.ti.com/ -* -* Redistribution and use in source and binary forms, with or without -* modification, are permitted provided that the following conditions -* are met: -* -* Redistributions of source code must retain the above copyright -* notice, this list of conditions and the following disclaimer. -* -* Redistributions in binary form must reproduce the above copyright -* notice, this list of conditions and the following disclaimer in the -* documentation and/or other materials provided with the -* distribution. -* -* Neither the name of Texas Instruments Incorporated nor the names of -* its contributors may be used to endorse or promote products derived -* from this software without specific prior written permission. -* -* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -* -*****************************************************************************/ - -//***************************************************************************** -// -//! \addtogroup wlan_api -//! @{ -// -//***************************************************************************** - -#include -#include "wlan.h" -#include "hci.h" -#include "ccspi.h" -#include "socket.h" -#include "nvmem.h" -#include "security.h" -#include "evnt_handler.h" - - -volatile sSimplLinkInformation tSLInformation; - -#define SMART_CONFIG_PROFILE_SIZE 67 // 67 = 32 (max ssid) + 32 (max key) + 1 (SSID length) + 1 (security type) + 1 (key length) - -#ifndef CC3000_UNENCRYPTED_SMART_CONFIG -UINT8 key[AES128_KEY_SIZE]; -UINT8 profileArray[SMART_CONFIG_PROFILE_SIZE]; -#endif //CC3000_UNENCRYPTED_SMART_CONFIG - -/* patches type */ -#define PATCHES_HOST_TYPE_WLAN_DRIVER 0x01 -#define PATCHES_HOST_TYPE_WLAN_FW 0x02 -#define PATCHES_HOST_TYPE_BOOTLOADER 0x03 - -#define SL_SET_SCAN_PARAMS_INTERVAL_LIST_SIZE (16) -#define SL_SIMPLE_CONFIG_PREFIX_LENGTH (3) -#define ETH_ALEN (6) -#define MAXIMAL_SSID_LENGTH (32) - -#define SL_PATCHES_REQUEST_DEFAULT (0) -#define SL_PATCHES_REQUEST_FORCE_HOST (1) -#define SL_PATCHES_REQUEST_FORCE_NONE (2) - - -#define WLAN_SEC_UNSEC (0) -#define WLAN_SEC_WEP (1) -#define WLAN_SEC_WPA (2) -#define WLAN_SEC_WPA2 (3) - - -#define WLAN_SL_INIT_START_PARAMS_LEN (1) -#define WLAN_PATCH_PARAMS_LENGTH (8) -#define WLAN_SET_CONNECTION_POLICY_PARAMS_LEN (12) -#define WLAN_DEL_PROFILE_PARAMS_LEN (4) -#define WLAN_SET_MASK_PARAMS_LEN (4) -#define WLAN_SET_SCAN_PARAMS_LEN (100) -#define WLAN_GET_SCAN_RESULTS_PARAMS_LEN (4) -#define WLAN_ADD_PROFILE_NOSEC_PARAM_LEN (24) -#define WLAN_ADD_PROFILE_WEP_PARAM_LEN (36) -#define WLAN_ADD_PROFILE_WPA_PARAM_LEN (44) -#define WLAN_CONNECT_PARAM_LEN (29) -#define WLAN_SMART_CONFIG_START_PARAMS_LEN (4) - - - - -//***************************************************************************** -// -//! SimpleLink_Init_Start -//! -//! @param usPatchesAvailableAtHost flag to indicate if patches available -//! from host or from EEPROM. Due to the -//! fact the patches are burn to the EEPROM -//! using the patch programmer utility, the -//! patches will be available from the EEPROM -//! and not from the host. -//! -//! @return none -//! -//! @brief Send HCI_CMND_SIMPLE_LINK_START to CC3000 -// -//***************************************************************************** -static void SimpleLink_Init_Start(UINT16 usPatchesAvailableAtHost) -{ - UINT8 *ptr; - UINT8 *args; - - ptr = tSLInformation.pucTxCommandBuffer; - args = (UINT8 *)(ptr + HEADERS_SIZE_CMD); - - UINT8_TO_STREAM(args, ((usPatchesAvailableAtHost) ? SL_PATCHES_REQUEST_FORCE_NONE : SL_PATCHES_REQUEST_DEFAULT)); - - // IRQ Line asserted - send HCI_CMND_SIMPLE_LINK_START to CC3000 - hci_command_send(HCI_CMND_SIMPLE_LINK_START, ptr, WLAN_SL_INIT_START_PARAMS_LEN); - - SimpleLinkWaitEvent(HCI_CMND_SIMPLE_LINK_START, 0); -} - - - -//***************************************************************************** -// -//! wlan_init -//! -//! @param sWlanCB Asynchronous events callback. -//! 0 no event call back. -//! -call back parameters: -//! 1) event_type: HCI_EVNT_WLAN_UNSOL_CONNECT connect event, -//! HCI_EVNT_WLAN_UNSOL_DISCONNECT disconnect event, -//! HCI_EVNT_WLAN_ASYNC_SIMPLE_CONFIG_DONE config done, -//! HCI_EVNT_WLAN_UNSOL_DHCP dhcp report, -//! HCI_EVNT_WLAN_ASYNC_PING_REPORT ping report OR -//! HCI_EVNT_WLAN_KEEPALIVE keepalive. -//! 2) data: pointer to extra data that received by the event -//! (NULL no data). -//! 3) length: data length. -//! -Events with extra data: -//! HCI_EVNT_WLAN_UNSOL_DHCP: 4 bytes IP, 4 bytes Mask, -//! 4 bytes default gateway, 4 bytes DHCP server and 4 bytes -//! for DNS server. -//! HCI_EVNT_WLAN_ASYNC_PING_REPORT: 4 bytes Packets sent, -//! 4 bytes Packets received, 4 bytes Min round time, -//! 4 bytes Max round time and 4 bytes for Avg round time. -//! -//! @param sFWPatches 0 no patch or pointer to FW patches -//! @param sDriverPatches 0 no patch or pointer to driver patches -//! @param sBootLoaderPatches 0 no patch or pointer to bootloader patches -//! @param sReadWlanInterruptPin init callback. the callback read wlan -//! interrupt status. -//! @param sWlanInterruptEnable init callback. the callback enable wlan -//! interrupt. -//! @param sWlanInterruptDisable init callback. the callback disable wlan -//! interrupt. -//! @param sWriteWlanPin init callback. the callback write value -//! to device pin. -//! -//! @return none -//! -//! @sa wlan_set_event_mask , wlan_start , wlan_stop -//! -//! @brief Initialize wlan driver -//! -//! @warning This function must be called before ANY other wlan driver function -// -//***************************************************************************** - -void wlan_init( tWlanCB sWlanCB, - tFWPatches sFWPatches, - tDriverPatches sDriverPatches, - tBootLoaderPatches sBootLoaderPatches, - tWlanReadInteruptPin sReadWlanInterruptPin, - tWlanInterruptEnable sWlanInterruptEnable, - tWlanInterruptDisable sWlanInterruptDisable, - tWriteWlanPin sWriteWlanPin) -{ - - tSLInformation.sFWPatches = sFWPatches; - tSLInformation.sDriverPatches = sDriverPatches; - tSLInformation.sBootLoaderPatches = sBootLoaderPatches; - - // init io callback - tSLInformation.ReadWlanInterruptPin = sReadWlanInterruptPin; - tSLInformation.WlanInterruptEnable = sWlanInterruptEnable; - tSLInformation.WlanInterruptDisable = sWlanInterruptDisable; - tSLInformation.WriteWlanPin = sWriteWlanPin; - - //init asynchronous events callback - tSLInformation.sWlanCB= sWlanCB; - - // By default TX Complete events are routed to host too - tSLInformation.InformHostOnTxComplete = 1; -} - -//***************************************************************************** -// -//! SpiReceiveHandler -//! -//! @param pvBuffer - pointer to the received data buffer -//! The function triggers Received event/data processing -//! -//! @param Pointer to the received data -//! @return none -//! -//! @brief The function triggers Received event/data processing. It is -//! called from the SPI library to receive the data -// -//***************************************************************************** -void SpiReceiveHandler(void *pvBuffer) -{ - tSLInformation.usEventOrDataReceived = 1; - tSLInformation.pucReceivedData = (UINT8 *)pvBuffer; - - hci_unsolicited_event_handler(); -} - - -//***************************************************************************** -// -//! wlan_start -//! -//! @param usPatchesAvailableAtHost - flag to indicate if patches available -//! from host or from EEPROM. Due to the -//! fact the patches are burn to the EEPROM -//! using the patch programmer utility, the -//! patches will be available from the EEPROM -//! and not from the host. -//! -//! @return none -//! -//! @brief Start WLAN device. This function asserts the enable pin of -//! the device (WLAN_EN), starting the HW initialization process. -//! The function blocked until device Initialization is completed. -//! Function also configure patches (FW, driver or bootloader) -//! and calls appropriate device callbacks. -//! -//! @Note Prior calling the function wlan_init shall be called. -//! @Warning This function must be called after wlan_init and before any -//! other wlan API -//! @sa wlan_init , wlan_stop -//! -// -//***************************************************************************** -#define TIMEOUT (500000) - -int wlan_start(UINT16 usPatchesAvailableAtHost) -{ - - UINT32 ulSpiIRQState; - UINT32 wlan_timeout; - - tSLInformation.NumberOfSentPackets = 0; - tSLInformation.NumberOfReleasedPackets = 0; - tSLInformation.usRxEventOpcode = 0; - tSLInformation.usNumberOfFreeBuffers = 0; - tSLInformation.usSlBufferLength = 0; - tSLInformation.usBufferSize = 0; - tSLInformation.usRxDataPending = 0; - tSLInformation.slTransmitDataError = 0; - tSLInformation.usEventOrDataReceived = 0; - tSLInformation.pucReceivedData = 0; - - // Allocate the memory for the RX/TX data transactions - tSLInformation.pucTxCommandBuffer = (UINT8 *)wlan_tx_buffer; - - // init spi - SpiOpen(SpiReceiveHandler); - - // Check the IRQ line - ulSpiIRQState = tSLInformation.ReadWlanInterruptPin(); - - // Chip enable: toggle WLAN EN line - tSLInformation.WriteWlanPin( WLAN_ENABLE ); - - wlan_timeout = TIMEOUT; - if (ulSpiIRQState) { - // wait till the IRQ line goes low - while(tSLInformation.ReadWlanInterruptPin() != 0 && --wlan_timeout) - { - } - } - else - { - // wait till the IRQ line goes high and than low - while(tSLInformation.ReadWlanInterruptPin() == 0 && --wlan_timeout) - { - } - - if (wlan_timeout == 0) { - return -1; - } - - wlan_timeout = TIMEOUT; - while(tSLInformation.ReadWlanInterruptPin() != 0 && --wlan_timeout) - { - } - } - - if (wlan_timeout ==0) { - return -1; - } - - SimpleLink_Init_Start(usPatchesAvailableAtHost); - - // Read Buffer's size and finish - hci_command_send(HCI_CMND_READ_BUFFER_SIZE, tSLInformation.pucTxCommandBuffer, 0); - SimpleLinkWaitEvent(HCI_CMND_READ_BUFFER_SIZE, 0); - - return 0; -} - - -//***************************************************************************** -// -//! wlan_stop -//! -//! @param none -//! -//! @return none -//! -//! @brief Stop WLAN device by putting it into reset state. -//! -//! @sa wlan_start -// -//***************************************************************************** - -void wlan_stop(void) -{ - // Chip disable - tSLInformation.WriteWlanPin( WLAN_DISABLE ); - - // Wait till IRQ line goes high... - while(tSLInformation.ReadWlanInterruptPin() == 0) - { - } - - // Free the used by WLAN Driver memory - if (tSLInformation.pucTxCommandBuffer) - { - tSLInformation.pucTxCommandBuffer = 0; - } - - SpiClose(); -} - - -//***************************************************************************** -// -//! wlan_connect -//! -//! @param sec_type security options: -//! WLAN_SEC_UNSEC, -//! WLAN_SEC_WEP (ASCII support only), -//! WLAN_SEC_WPA or WLAN_SEC_WPA2 -//! @param ssid up to 32 bytes and is ASCII SSID of the AP -//! @param ssid_len length of the SSID -//! @param bssid 6 bytes specified the AP bssid -//! @param key up to 32 bytes specified the AP security key -//! @param key_len key length -//! -//! @return On success, zero is returned. On error, negative is returned. -//! Note that even though a zero is returned on success to trigger -//! connection operation, it does not mean that CCC3000 is already -//! connected. An asynchronous "Connected" event is generated when -//! actual association process finishes and CC3000 is connected to -//! the AP. If DHCP is set, An asynchronous "DHCP" event is -//! generated when DHCP process is finish. -//! -//! -//! @brief Connect to AP -//! @warning Please Note that when connection to AP configured with security -//! type WEP, please confirm that the key is set as ASCII and not -//! as HEX. -//! @sa wlan_disconnect -// -//***************************************************************************** - -#ifndef CC3000_TINY_DRIVER -INT32 wlan_connect(UINT32 ulSecType, CHAR *ssid, INT32 ssid_len, - UINT8 *bssid, UINT8 *key, INT32 key_len) -{ - INT32 ret; - UINT8 *ptr; - UINT8 *args; - UINT8 bssid_zero[] = {0, 0, 0, 0, 0, 0}; - - ret = EFAIL; - ptr = tSLInformation.pucTxCommandBuffer; - args = (ptr + HEADERS_SIZE_CMD); - - // Fill in command buffer - args = UINT32_TO_STREAM(args, 0x0000001c); - args = UINT32_TO_STREAM(args, ssid_len); - args = UINT32_TO_STREAM(args, ulSecType); - args = UINT32_TO_STREAM(args, 0x00000010 + ssid_len); - args = UINT32_TO_STREAM(args, key_len); - args = UINT16_TO_STREAM(args, 0); - - // padding shall be zeroed - if(bssid) - { - ARRAY_TO_STREAM(args, bssid, ETH_ALEN); - } - else - { - ARRAY_TO_STREAM(args, bssid_zero, ETH_ALEN); - } - - ARRAY_TO_STREAM(args, ssid, ssid_len); - - if(key_len && key) - { - ARRAY_TO_STREAM(args, key, key_len); - } - - // Initiate a HCI command - hci_command_send(HCI_CMND_WLAN_CONNECT, ptr, WLAN_CONNECT_PARAM_LEN + - ssid_len + key_len - 1); - - // Wait for command complete event - SimpleLinkWaitEvent(HCI_CMND_WLAN_CONNECT, &ret); - CC3000_EXPORT(errno) = ret; - - return(ret); -} -#else -INT32 wlan_connect(CHAR *ssid, INT32 ssid_len) -{ - INT32 ret; - UINT8 *ptr; - UINT8 *args; - UINT8 bssid_zero[] = {0, 0, 0, 0, 0, 0}; - - ret = EFAIL; - ptr = tSLInformation.pucTxCommandBuffer; - args = (ptr + HEADERS_SIZE_CMD); - - // Fill in command buffer - args = UINT32_TO_STREAM(args, 0x0000001c); - args = UINT32_TO_STREAM(args, ssid_len); - args = UINT32_TO_STREAM(args, 0); - args = UINT32_TO_STREAM(args, 0x00000010 + ssid_len); - args = UINT32_TO_STREAM(args, 0); - args = UINT16_TO_STREAM(args, 0); - - // padding shall be zeroed - ARRAY_TO_STREAM(args, bssid_zero, ETH_ALEN); - ARRAY_TO_STREAM(args, ssid, ssid_len); - - // Initiate a HCI command - hci_command_send(HCI_CMND_WLAN_CONNECT, ptr, WLAN_CONNECT_PARAM_LEN + - ssid_len - 1); - - // Wait for command complete event - SimpleLinkWaitEvent(HCI_CMND_WLAN_CONNECT, &ret); - CC3000_EXPORT(errno) = ret; - - return(ret); -} -#endif - -//***************************************************************************** -// -//! wlan_disconnect -//! -//! @return 0 disconnected done, other CC3000 already disconnected -//! -//! @brief Disconnect connection from AP. -//! -//! @sa wlan_connect -// -//***************************************************************************** - -INT32 wlan_disconnect() -{ - INT32 ret; - UINT8 *ptr; - - ret = EFAIL; - ptr = tSLInformation.pucTxCommandBuffer; - - hci_command_send(HCI_CMND_WLAN_DISCONNECT, ptr, 0); - - // Wait for command complete event - SimpleLinkWaitEvent(HCI_CMND_WLAN_DISCONNECT, &ret); - CC3000_EXPORT(errno) = ret; - - return(ret); -} - -//***************************************************************************** -// -//! wlan_ioctl_set_connection_policy -//! -//! @param should_connect_to_open_ap enable(1), disable(0) connect to any -//! available AP. This parameter corresponds to the configuration of -//! item # 3 in the brief description. -//! @param should_use_fast_connect enable(1), disable(0). if enabled, tries -//! to connect to the last connected AP. This parameter corresponds -//! to the configuration of item # 1 in the brief description. -//! @param auto_start enable(1), disable(0) auto connect -//! after reset and periodically reconnect if needed. This -//! configuration configures option 2 in the above description. -//! -//! @return On success, zero is returned. On error, -1 is returned -//! -//! @brief When auto is enabled, the device tries to connect according -//! the following policy: -//! 1) If fast connect is enabled and last connection is valid, -//! the device will try to connect to it without the scanning -//! procedure (fast). The last connection will be marked as -//! invalid, due to adding/removing profile. -//! 2) If profile exists, the device will try to connect it -//! (Up to seven profiles). -//! 3) If fast and profiles are not found, and open mode is -//! enabled, the device will try to connect to any AP. -//! * Note that the policy settings are stored in the CC3000 NVMEM. -//! -//! @sa wlan_add_profile , wlan_ioctl_del_profile -// -//***************************************************************************** - -INT32 wlan_ioctl_set_connection_policy(UINT32 should_connect_to_open_ap, - UINT32 ulShouldUseFastConnect, - UINT32 ulUseProfiles) -{ - INT32 ret; - UINT8 *ptr; - UINT8 *args; - - ret = EFAIL; - ptr = tSLInformation.pucTxCommandBuffer; - args = (UINT8 *)(ptr + HEADERS_SIZE_CMD); - - // Fill in HCI packet structure - args = UINT32_TO_STREAM(args, should_connect_to_open_ap); - args = UINT32_TO_STREAM(args, ulShouldUseFastConnect); - args = UINT32_TO_STREAM(args, ulUseProfiles); - - // Initiate a HCI command - hci_command_send(HCI_CMND_WLAN_IOCTL_SET_CONNECTION_POLICY, - ptr, WLAN_SET_CONNECTION_POLICY_PARAMS_LEN); - - // Wait for command complete event - SimpleLinkWaitEvent(HCI_CMND_WLAN_IOCTL_SET_CONNECTION_POLICY, &ret); - - return(ret); -} - -//***************************************************************************** -// -//! wlan_add_profile -//! -//! @param ulSecType WLAN_SEC_UNSEC,WLAN_SEC_WEP,WLAN_SEC_WPA,WLAN_SEC_WPA2 -//! @param ucSsid ssid SSID up to 32 bytes -//! @param ulSsidLen ssid length -//! @param ucBssid bssid 6 bytes -//! @param ulPriority ulPriority profile priority. Lowest priority:0. -//! Important Note: Smartconfig process (in unencrypted mode) -//! stores the profile internally with priority 1, so changing -//! priorities when adding new profiles should be done with extra care -//! @param ulPairwiseCipher_Or_TxKeyLen key length for WEP security -//! @param ulGroupCipher_TxKeyIndex key index -//! @param ulKeyMgmt KEY management -//! @param ucPf_OrKey security key -//! @param ulPassPhraseLen security key length for WPA\WPA2 -//! -//! @return On success, index (1-7) of the stored profile is returned. -//! On error, -1 is returned. -//! -//! @brief When auto start is enabled, the device connects to -//! station from the profiles table. Up to 7 profiles are supported. -//! If several profiles configured the device choose the highest -//! priority profile, within each priority group, device will choose -//! profile based on security policy, signal strength, etc -//! parameters. All the profiles are stored in CC3000 NVMEM. -//! -//! @sa wlan_ioctl_del_profile -// -//***************************************************************************** - -#ifndef CC3000_TINY_DRIVER -INT32 wlan_add_profile(UINT32 ulSecType, - UINT8* ucSsid, - UINT32 ulSsidLen, - UINT8 *ucBssid, - UINT32 ulPriority, - UINT32 ulPairwiseCipher_Or_TxKeyLen, - UINT32 ulGroupCipher_TxKeyIndex, - UINT32 ulKeyMgmt, - UINT8* ucPf_OrKey, - UINT32 ulPassPhraseLen) -{ - UINT16 arg_len=0; - INT32 ret; - UINT8 *ptr; - INT32 i = 0; - UINT8 *args; - UINT8 bssid_zero[] = {0, 0, 0, 0, 0, 0}; - - ptr = tSLInformation.pucTxCommandBuffer; - args = (ptr + HEADERS_SIZE_CMD); - - args = UINT32_TO_STREAM(args, ulSecType); - - // Setup arguments in accordance with the security type - switch (ulSecType) - { - //OPEN - case WLAN_SEC_UNSEC: - { - args = UINT32_TO_STREAM(args, 0x00000014); - args = UINT32_TO_STREAM(args, ulSsidLen); - args = UINT16_TO_STREAM(args, 0); - if(ucBssid) - { - ARRAY_TO_STREAM(args, ucBssid, ETH_ALEN); - } - else - { - ARRAY_TO_STREAM(args, bssid_zero, ETH_ALEN); - } - args = UINT32_TO_STREAM(args, ulPriority); - ARRAY_TO_STREAM(args, ucSsid, ulSsidLen); - - arg_len = WLAN_ADD_PROFILE_NOSEC_PARAM_LEN + ulSsidLen; - } - break; - - //WEP - case WLAN_SEC_WEP: - { - args = UINT32_TO_STREAM(args, 0x00000020); - args = UINT32_TO_STREAM(args, ulSsidLen); - args = UINT16_TO_STREAM(args, 0); - if(ucBssid) - { - ARRAY_TO_STREAM(args, ucBssid, ETH_ALEN); - } - else - { - ARRAY_TO_STREAM(args, bssid_zero, ETH_ALEN); - } - args = UINT32_TO_STREAM(args, ulPriority); - args = UINT32_TO_STREAM(args, 0x0000000C + ulSsidLen); - args = UINT32_TO_STREAM(args, ulPairwiseCipher_Or_TxKeyLen); - args = UINT32_TO_STREAM(args, ulGroupCipher_TxKeyIndex); - ARRAY_TO_STREAM(args, ucSsid, ulSsidLen); - - for(i = 0; i < 4; i++) - { - UINT8 *p = &ucPf_OrKey[i * ulPairwiseCipher_Or_TxKeyLen]; - - ARRAY_TO_STREAM(args, p, ulPairwiseCipher_Or_TxKeyLen); - } - - arg_len = WLAN_ADD_PROFILE_WEP_PARAM_LEN + ulSsidLen + - ulPairwiseCipher_Or_TxKeyLen * 4; - - } - break; - - //WPA - //WPA2 - case WLAN_SEC_WPA: - case WLAN_SEC_WPA2: - { - args = UINT32_TO_STREAM(args, 0x00000028); - args = UINT32_TO_STREAM(args, ulSsidLen); - args = UINT16_TO_STREAM(args, 0); - if(ucBssid) - { - ARRAY_TO_STREAM(args, ucBssid, ETH_ALEN); - } - else - { - ARRAY_TO_STREAM(args, bssid_zero, ETH_ALEN); - } - args = UINT32_TO_STREAM(args, ulPriority); - args = UINT32_TO_STREAM(args, ulPairwiseCipher_Or_TxKeyLen); - args = UINT32_TO_STREAM(args, ulGroupCipher_TxKeyIndex); - args = UINT32_TO_STREAM(args, ulKeyMgmt); - args = UINT32_TO_STREAM(args, 0x00000008 + ulSsidLen); - args = UINT32_TO_STREAM(args, ulPassPhraseLen); - ARRAY_TO_STREAM(args, ucSsid, ulSsidLen); - ARRAY_TO_STREAM(args, ucPf_OrKey, ulPassPhraseLen); - - arg_len = WLAN_ADD_PROFILE_WPA_PARAM_LEN + ulSsidLen + ulPassPhraseLen; - } - - break; - } - - // Initiate a HCI command - hci_command_send(HCI_CMND_WLAN_IOCTL_ADD_PROFILE, - ptr, arg_len); - - // Wait for command complete event - SimpleLinkWaitEvent(HCI_CMND_WLAN_IOCTL_ADD_PROFILE, &ret); - - return(ret); -} -#else -INT32 wlan_add_profile(UINT32 ulSecType, - UINT8* ucSsid, - UINT32 ulSsidLen, - UINT8 *ucBssid, - UINT32 ulPriority, - UINT32 ulPairwiseCipher_Or_TxKeyLen, - UINT32 ulGroupCipher_TxKeyIndex, - UINT32 ulKeyMgmt, - UINT8* ucPf_OrKey, - UINT32 ulPassPhraseLen) -{ - return -1; -} -#endif - -//***************************************************************************** -// -//! wlan_ioctl_del_profile -//! -//! @param index number of profile to delete -//! -//! @return On success, zero is returned. On error, -1 is returned -//! -//! @brief Delete WLAN profile -//! -//! @Note In order to delete all stored profile, set index to 255. -//! -//! @sa wlan_add_profile -// -//***************************************************************************** - -INT32 wlan_ioctl_del_profile(UINT32 ulIndex) -{ - INT32 ret; - UINT8 *ptr; - UINT8 *args; - - ptr = tSLInformation.pucTxCommandBuffer; - args = (UINT8 *)(ptr + HEADERS_SIZE_CMD); - - // Fill in HCI packet structure - args = UINT32_TO_STREAM(args, ulIndex); - ret = EFAIL; - - // Initiate a HCI command - hci_command_send(HCI_CMND_WLAN_IOCTL_DEL_PROFILE, - ptr, WLAN_DEL_PROFILE_PARAMS_LEN); - - // Wait for command complete event - SimpleLinkWaitEvent(HCI_CMND_WLAN_IOCTL_DEL_PROFILE, &ret); - - return(ret); -} - -//***************************************************************************** -// -//! wlan_ioctl_get_scan_results -//! -//! @param[in] scan_timeout parameter not supported -//! @param[out] ucResults scan results (_wlan_full_scan_results_args_t) -//! -//! @return On success, zero is returned. On error, -1 is returned -//! -//! @brief Gets entry from scan result table. -//! The scan results are returned one by one, and each entry -//! represents a single AP found in the area. The following is a -//! format of the scan result: -//! - 4 Bytes: number of networks found -//! - 4 Bytes: The status of the scan: 0 - aged results, -//! 1 - results valid, 2 - no results -//! - 42 bytes: Result entry, where the bytes are arranged as follows: -//! -//! - 1 bit isValid - is result valid or not -//! - 7 bits rssi - RSSI value; -//! - 2 bits: securityMode - security mode of the AP: -//! 0 - Open, 1 - WEP, 2 WPA, 3 WPA2 -//! - 6 bits: SSID name length -//! - 2 bytes: the time at which the entry has entered into -//! scans result table -//! - 32 bytes: SSID name -//! - 6 bytes: BSSID -//! -//! @Note scan_timeout, is not supported on this version. -//! -//! @sa wlan_ioctl_set_scan_params -// -//***************************************************************************** - -#ifndef CC3000_TINY_DRIVER -INT32 wlan_ioctl_get_scan_results(UINT32 ulScanTimeout, - UINT8 *ucResults) -{ - UINT8 *ptr; - UINT8 *args; - - ptr = tSLInformation.pucTxCommandBuffer; - args = (ptr + HEADERS_SIZE_CMD); - - // Fill in temporary command buffer - args = UINT32_TO_STREAM(args, ulScanTimeout); - - // Initiate a HCI command - hci_command_send(HCI_CMND_WLAN_IOCTL_GET_SCAN_RESULTS, - ptr, WLAN_GET_SCAN_RESULTS_PARAMS_LEN); - - // Wait for command complete event - SimpleLinkWaitEvent(HCI_CMND_WLAN_IOCTL_GET_SCAN_RESULTS, ucResults); - - return(0); -} -#endif - -//***************************************************************************** -// -//! wlan_ioctl_set_scan_params -//! -//! @param uiEnable - start/stop application scan: -//! 1 = start scan with default interval value of 10 min. -//! in order to set a different scan interval value apply the value -//! in milliseconds. minimum 1 second. 0=stop). Wlan reset -//! (wlan_stop() wlan_start()) is needed when changing scan interval -//! value. Saved: No -//! @param uiMinDwellTime minimum dwell time value to be used for each -//! channel, in milliseconds. Saved: yes -//! Recommended Value: 100 (Default: 20) -//! @param uiMaxDwellTime maximum dwell time value to be used for each -//! channel, in milliseconds. Saved: yes -//! Recommended Value: 100 (Default: 30) -//! @param uiNumOfProbeRequests max probe request between dwell time. -//! Saved: yes. Recommended Value: 5 (Default:2) -//! @param uiChannelMask bitwise, up to 13 channels (0x1fff). -//! Saved: yes. Default: 0x7ff -//! @param uiRSSIThreshold RSSI threshold. Saved: yes (Default: -80) -//! @param uiSNRThreshold NSR threshold. Saved: yes (Default: 0) -//! @param uiDefaultTxPower probe Tx power. Saved: yes (Default: 205) -//! @param aiIntervalList pointer to array with 16 entries (16 channels) -//! each entry (UINT32) holds timeout between periodic scan -//! (connection scan) - in millisecond. Saved: yes. Default 2000ms. -//! -//! @return On success, zero is returned. On error, -1 is returned -//! -//! @brief start and stop scan procedure. Set scan parameters. -//! -//! @Note uiDefaultTxPower, is not supported on this version. -//! -//! @sa wlan_ioctl_get_scan_results -// -//***************************************************************************** - -#ifndef CC3000_TINY_DRIVER -INT32 wlan_ioctl_set_scan_params(UINT32 uiEnable, UINT32 uiMinDwellTime, - UINT32 uiMaxDwellTime, - UINT32 uiNumOfProbeRequests, - UINT32 uiChannelMask,INT32 iRSSIThreshold, - UINT32 uiSNRThreshold, - UINT32 uiDefaultTxPower, - UINT32 *aiIntervalList) -{ - UINT32 uiRes; - UINT8 *ptr; - UINT8 *args; - - ptr = tSLInformation.pucTxCommandBuffer; - args = (ptr + HEADERS_SIZE_CMD); - - // Fill in temporary command buffer - args = UINT32_TO_STREAM(args, 36); - args = UINT32_TO_STREAM(args, uiEnable); - args = UINT32_TO_STREAM(args, uiMinDwellTime); - args = UINT32_TO_STREAM(args, uiMaxDwellTime); - args = UINT32_TO_STREAM(args, uiNumOfProbeRequests); - args = UINT32_TO_STREAM(args, uiChannelMask); - args = UINT32_TO_STREAM(args, iRSSIThreshold); - args = UINT32_TO_STREAM(args, uiSNRThreshold); - args = UINT32_TO_STREAM(args, uiDefaultTxPower); - ARRAY_TO_STREAM(args, aiIntervalList, sizeof(UINT32) * - SL_SET_SCAN_PARAMS_INTERVAL_LIST_SIZE); - - // Initiate a HCI command - hci_command_send(HCI_CMND_WLAN_IOCTL_SET_SCANPARAM, - ptr, WLAN_SET_SCAN_PARAMS_LEN); - - // Wait for command complete event - SimpleLinkWaitEvent(HCI_CMND_WLAN_IOCTL_SET_SCANPARAM, &uiRes); - - return(uiRes); -} -#endif - -//***************************************************************************** -// -//! wlan_set_event_mask -//! -//! @param mask mask option: -//! HCI_EVNT_WLAN_UNSOL_CONNECT connect event -//! HCI_EVNT_WLAN_UNSOL_DISCONNECT disconnect event -//! HCI_EVNT_WLAN_ASYNC_SIMPLE_CONFIG_DONE smart config done -//! HCI_EVNT_WLAN_UNSOL_INIT init done -//! HCI_EVNT_WLAN_UNSOL_DHCP dhcp event report -//! HCI_EVNT_WLAN_ASYNC_PING_REPORT ping report -//! HCI_EVNT_WLAN_KEEPALIVE keepalive -//! HCI_EVNT_WLAN_TX_COMPLETE - disable information on end of transmission -//! Saved: no. -//! -//! @return On success, zero is returned. On error, -1 is returned -//! -//! @brief Mask event according to bit mask. In case that event is -//! masked (1), the device will not send the masked event to host. -// -//***************************************************************************** - -INT32 wlan_set_event_mask(UINT32 ulMask) -{ - INT32 ret; - UINT8 *ptr; - UINT8 *args; - - - if ((ulMask & HCI_EVNT_WLAN_TX_COMPLETE) == HCI_EVNT_WLAN_TX_COMPLETE) - { - tSLInformation.InformHostOnTxComplete = 0; - - // Since an event is a virtual event - i.e. it is not coming from CC3000 - // there is no need to send anything to the device if it was an only event - if (ulMask == HCI_EVNT_WLAN_TX_COMPLETE) - { - return 0; - } - - ulMask &= ~HCI_EVNT_WLAN_TX_COMPLETE; - ulMask |= HCI_EVNT_WLAN_UNSOL_BASE; - } - else - { - tSLInformation.InformHostOnTxComplete = 1; - } - - ret = EFAIL; - ptr = tSLInformation.pucTxCommandBuffer; - args = (UINT8 *)(ptr + HEADERS_SIZE_CMD); - - // Fill in HCI packet structure - args = UINT32_TO_STREAM(args, ulMask); - - // Initiate a HCI command - hci_command_send(HCI_CMND_EVENT_MASK, - ptr, WLAN_SET_MASK_PARAMS_LEN); - - // Wait for command complete event - SimpleLinkWaitEvent(HCI_CMND_EVENT_MASK, &ret); - - return(ret); -} - -//***************************************************************************** -// -//! wlan_ioctl_statusget -//! -//! @param none -//! -//! @return WLAN_STATUS_DISCONNECTED, WLAN_STATUS_SCANING, -//! STATUS_CONNECTING or WLAN_STATUS_CONNECTED -//! -//! @brief get wlan status: disconnected, scanning, connecting or connected -// -//***************************************************************************** - -#ifndef CC3000_TINY_DRIVER -INT32 wlan_ioctl_statusget(void) -{ - INT32 ret; - UINT8 *ptr; - - ret = EFAIL; - ptr = tSLInformation.pucTxCommandBuffer; - - hci_command_send(HCI_CMND_WLAN_IOCTL_STATUSGET, - ptr, 0); - - // Wait for command complete event - SimpleLinkWaitEvent(HCI_CMND_WLAN_IOCTL_STATUSGET, &ret); - - return(ret); -} -#endif - -//***************************************************************************** -// -//! wlan_smart_config_start -//! -//! @param algoEncryptedFlag indicates whether the information is encrypted -//! -//! @return On success, zero is returned. On error, -1 is returned -//! -//! @brief Start to acquire device profile. The device acquire its own -//! profile, if profile message is found. The acquired AP information -//! is stored in CC3000 EEPROM only in case AES128 encryption is used. -//! In case AES128 encryption is not used, a profile is created by -//! CC3000 internally. -//! -//! @Note An asynchronous event - Smart Config Done will be generated as soon -//! as the process finishes successfully. -//! -//! @sa wlan_smart_config_set_prefix , wlan_smart_config_stop -// -//***************************************************************************** - -INT32 wlan_smart_config_start(UINT32 algoEncryptedFlag) -{ - INT32 ret; - UINT8 *ptr; - UINT8 *args; - - ret = EFAIL; - ptr = tSLInformation.pucTxCommandBuffer; - args = (UINT8 *)(ptr + HEADERS_SIZE_CMD); - - // Fill in HCI packet structure - args = UINT32_TO_STREAM(args, algoEncryptedFlag); - ret = EFAIL; - - hci_command_send(HCI_CMND_WLAN_IOCTL_SIMPLE_CONFIG_START, ptr, - WLAN_SMART_CONFIG_START_PARAMS_LEN); - - // Wait for command complete event - SimpleLinkWaitEvent(HCI_CMND_WLAN_IOCTL_SIMPLE_CONFIG_START, &ret); - - return(ret); -} - -//***************************************************************************** -// -//! wlan_smart_config_stop -//! -//! @param algoEncryptedFlag indicates whether the information is encrypted -//! -//! @return On success, zero is returned. On error, -1 is returned -//! -//! @brief Stop the acquire profile procedure -//! -//! @sa wlan_smart_config_start , wlan_smart_config_set_prefix -// -//***************************************************************************** - -INT32 wlan_smart_config_stop(void) -{ - INT32 ret; - UINT8 *ptr; - - ret = EFAIL; - ptr = tSLInformation.pucTxCommandBuffer; - - hci_command_send(HCI_CMND_WLAN_IOCTL_SIMPLE_CONFIG_STOP, ptr, 0); - - // Wait for command complete event - SimpleLinkWaitEvent(HCI_CMND_WLAN_IOCTL_SIMPLE_CONFIG_STOP, &ret); - - return(ret); -} - -//***************************************************************************** -// -//! wlan_smart_config_set_prefix -//! -//! @param newPrefix 3 bytes identify the SSID prefix for the Smart Config. -//! -//! @return On success, zero is returned. On error, -1 is returned -//! -//! @brief Configure station ssid prefix. The prefix is used internally -//! in CC3000. It should always be TTT. -//! -//! @Note The prefix is stored in CC3000 NVMEM -//! -//! @sa wlan_smart_config_start , wlan_smart_config_stop -// -//***************************************************************************** - -INT32 wlan_smart_config_set_prefix(CHAR* cNewPrefix) -{ - INT32 ret; - UINT8 *ptr; - UINT8 *args; - - ret = EFAIL; - ptr = tSLInformation.pucTxCommandBuffer; - args = (ptr + HEADERS_SIZE_CMD); - - if (cNewPrefix == NULL) - return ret; - else // with the new Smart Config, prefix must be TTT - { - *cNewPrefix = 'T'; - *(cNewPrefix + 1) = 'T'; - *(cNewPrefix + 2) = 'T'; - } - - ARRAY_TO_STREAM(args, cNewPrefix, SL_SIMPLE_CONFIG_PREFIX_LENGTH); - - hci_command_send(HCI_CMND_WLAN_IOCTL_SIMPLE_CONFIG_SET_PREFIX, ptr, - SL_SIMPLE_CONFIG_PREFIX_LENGTH); - - // Wait for command complete event - SimpleLinkWaitEvent(HCI_CMND_WLAN_IOCTL_SIMPLE_CONFIG_SET_PREFIX, &ret); - - return(ret); -} - -//***************************************************************************** -// -//! wlan_smart_config_process -//! -//! @param none -//! -//! @return On success, zero is returned. On error, -1 is returned -//! -//! @brief process the acquired data and store it as a profile. The acquired -//! AP information is stored in CC3000 EEPROM encrypted. -//! The encrypted data is decrypted and stored as a profile. -//! behavior is as defined by connection policy. -// -//***************************************************************************** - - -#ifndef CC3000_UNENCRYPTED_SMART_CONFIG -INT32 wlan_smart_config_process() -{ - INT32 returnValue; - UINT32 ssidLen, keyLen; - UINT8 *decKeyPtr; - UINT8 *ssidPtr; - - // read the key from EEPROM - fileID 12 - returnValue = aes_read_key(key); - - if (returnValue != 0) - return returnValue; - - // read the received data from fileID #13 and parse it according to the followings: - // 1) SSID LEN - not encrypted - // 2) SSID - not encrypted - // 3) KEY LEN - not encrypted. always 32 bytes long - // 4) Security type - not encrypted - // 5) KEY - encrypted together with true key length as the first byte in KEY - // to elaborate, there are two corner cases: - // 1) the KEY is 32 bytes long. In this case, the first byte does not represent KEY length - // 2) the KEY is 31 bytes long. In this case, the first byte represent KEY length and equals 31 - returnValue = nvmem_read(NVMEM_SHARED_MEM_FILEID, SMART_CONFIG_PROFILE_SIZE, 0, profileArray); - - if (returnValue != 0) - return returnValue; - - ssidPtr = &profileArray[1]; - - ssidLen = profileArray[0]; - - decKeyPtr = &profileArray[profileArray[0] + 3]; - - aes_decrypt(decKeyPtr, key); - if (profileArray[profileArray[0] + 1] > 16) - aes_decrypt((UINT8 *)(decKeyPtr + 16), key); - - if (*(UINT8 *)(decKeyPtr +31) != 0) - { - if (*decKeyPtr == 31) - { - keyLen = 31; - decKeyPtr++; - } - else - { - keyLen = 32; - } - } - else - { - keyLen = *decKeyPtr; - decKeyPtr++; - } - - // add a profile - switch (profileArray[profileArray[0] + 2]) - { - case WLAN_SEC_UNSEC://None - { - returnValue = wlan_add_profile(profileArray[profileArray[0] + 2], // security type - ssidPtr, // SSID - ssidLen, // SSID length - NULL, // BSSID - 1, // Priority - 0, 0, 0, 0, 0); - - break; - } - - case WLAN_SEC_WEP://WEP - { - returnValue = wlan_add_profile(profileArray[profileArray[0] + 2], // security type - ssidPtr, // SSID - ssidLen, // SSID length - NULL, // BSSID - 1, // Priority - keyLen, // KEY length - 0, // KEY index - 0, - decKeyPtr, // KEY - 0); - - break; - } - - case WLAN_SEC_WPA://WPA - case WLAN_SEC_WPA2://WPA2 - { - returnValue = wlan_add_profile(WLAN_SEC_WPA2, // security type - ssidPtr, - ssidLen, - NULL, // BSSID - 1, // Priority - 0x18, // PairwiseCipher - 0x1e, // GroupCipher - 2, // KEY management - decKeyPtr, // KEY - keyLen); // KEY length - - break; - } - } - - return returnValue; -} -#endif //CC3000_UNENCRYPTED_SMART_CONFIG - -//***************************************************************************** -// -// Close the Doxygen group. -//! @} -// -//***************************************************************************** diff --git a/drivers/cc3100/inc/device.h b/drivers/cc3100/inc/device.h deleted file mode 100644 index 169736da21..0000000000 --- a/drivers/cc3100/inc/device.h +++ /dev/null @@ -1,656 +0,0 @@ -/* - * device.h - CC31xx/CC32xx Host Driver Implementation - * - * Copyright (C) 2014 Texas Instruments Incorporated - http://www.ti.com/ - * - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * - * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the - * distribution. - * - * Neither the name of Texas Instruments Incorporated nor the names of - * its contributors may be used to endorse or promote products derived - * from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * -*/ - -/*****************************************************************************/ -/* Include files */ -/*****************************************************************************/ -#include "simplelink.h" - -#ifndef __DEVICE_H__ -#define __DEVICE_H__ - - - -#ifdef __cplusplus -extern "C" { -#endif - - - -/*! - - \addtogroup device - @{ - -*/ - -/*****************************************************************************/ -/* Macro declarations */ -/*****************************************************************************/ - - -/* SL internal Error codes */ - -/* Receive this error in case there are no resources to issue the command - If possible, increase the number of MAX_CUNCURENT_ACTIONS (result in memory increase) - If not, try again later */ -#define SL_POOL_IS_EMPTY (-2000) - -/* Receive this error in case a given length for RX buffer was too small. - Receive payload was bigger than the given buffer size. Therefore, payload is cut according to receive size - Recommend to increase buffer size */ -#define SL_ESMALLBUF (-2001) - -/* Receive this error in case zero length is supplied to a "get" API - Recommend to supply length according to requested information (view options defines for help) */ -#define SL_EZEROLEN (-2002) - -/* User supplied invalid parameter */ -#define SL_INVALPARAM (-2003) - - -/* Failed to open interface */ -#define SL_BAD_INTERFACE (-2004) - -/* End of SL internal Error codes */ - - - -/*****************************************************************************/ -/* Errors returned from the general error async event */ -/*****************************************************************************/ - -/* Send types */ -typedef enum -{ - SL_ERR_SENDER_HEALTH_MON, - SL_ERR_SENDER_CLI_UART, - SL_ERR_SENDER_SUPPLICANT, - SL_ERR_SENDER_NETWORK_STACK, - SL_ERR_SENDER_WLAN_DRV_IF, - SL_ERR_SENDER_WILINK, - SL_ERR_SENDER_INIT_APP, - SL_ERR_SENDER_NETX, - SL_ERR_SENDER_HOST_APD, - SL_ERR_SENDER_MDNS, - SL_ERR_SENDER_HTTP_SERVER, - SL_ERR_SENDER_DHCP_SERVER, - SL_ERR_SENDER_DHCP_CLIENT, - SL_ERR_DISPATCHER, - SL_ERR_NUM_SENDER_LAST=0xFF -}SlErrorSender_e; - - -/* Error codes */ -#define SL_ERROR_STATIC_ADDR_SUBNET_ERROR (-60) /* network stack error*/ -#define SL_ERROR_ILLEGAL_CHANNEL (-61) /* supplicant error */ -#define SL_ERROR_SUPPLICANT_ERROR (-72) /* init error code */ -#define SL_ERROR_HOSTAPD_INIT_FAIL (-73) /* init error code */ -#define SL_ERROR_HOSTAPD_INIT_IF_FAIL (-74) /* init error code */ -#define SL_ERROR_WLAN_DRV_INIT_FAIL (-75) /* init error code */ -#define SL_ERROR_WLAN_DRV_START_FAIL (-76) /* wlan start error */ -#define SL_ERROR_FS_FILE_TABLE_LOAD_FAILED (-77) /* init file system failed */ -#define SL_ERROR_PREFERRED_NETWORKS_FILE_LOAD_FAILED (-78) /* init file system failed */ -#define SL_ERROR_HOSTAPD_BSSID_VALIDATION_ERROR (-79) /* Ap configurations BSSID error */ -#define SL_ERROR_HOSTAPD_FAILED_TO_SETUP_INTERFACE (-80) /* Ap configurations interface error */ -#define SL_ERROR_MDNS_ENABLE_FAIL (-81) /* mDNS enable failed */ -#define SL_ERROR_HTTP_SERVER_ENABLE_FAILED (-82) /* HTTP server enable failed */ -#define SL_ERROR_DHCP_SERVER_ENABLE_FAILED (-83) /* DHCP server enable failed */ -#define SL_ERROR_PREFERRED_NETWORK_LIST_FULL (-93) /* supplicant error */ -#define SL_ERROR_PREFERRED_NETWORKS_FILE_WRITE_FAILED (-94) /* supplicant error */ -#define SL_ERROR_DHCP_CLIENT_RENEW_FAILED (-100) /* DHCP client error */ -/* WLAN Connection management status */ -#define SL_ERROR_CON_MGMT_STATUS_UNSPECIFIED (-102) -#define SL_ERROR_CON_MGMT_STATUS_AUTH_REJECT (-103) -#define SL_ERROR_CON_MGMT_STATUS_ASSOC_REJECT (-104) -#define SL_ERROR_CON_MGMT_STATUS_SECURITY_FAILURE (-105) -#define SL_ERROR_CON_MGMT_STATUS_AP_DEAUTHENTICATE (-106) -#define SL_ERROR_CON_MGMT_STATUS_AP_DISASSOCIATE (-107) -#define SL_ERROR_CON_MGMT_STATUS_ROAMING_TRIGGER (-108) -#define SL_ERROR_CON_MGMT_STATUS_DISCONNECT_DURING_CONNECT (-109) -#define SL_ERROR_CON_MGMT_STATUS_SG_RESELECT (-110) -#define SL_ERROR_CON_MGMT_STATUS_ROC_FAILURE (-111) -#define SL_ERROR_CON_MGMT_STATUS_MIC_FAILURE (-112) -/* end of WLAN connection management error statuses */ -#define SL_ERROR_WAKELOCK_ERROR_PREFIX (-115) /* Wake lock expired */ -#define SL_ERROR_LENGTH_ERROR_PREFIX (-116) /* Uart header length error */ -#define SL_ERROR_MDNS_CREATE_FAIL (-121) /* mDNS create failed */ -#define SL_ERROR_GENERAL_ERROR (-127) - - - -#define SL_DEVICE_GENERAL_CONFIGURATION (1) -#define SL_DEVICE_GENERAL_CONFIGURATION_DATE_TIME (11) -#define SL_DEVICE_GENERAL_VERSION (12) -#define SL_DEVICE_STATUS (2) - -/* - Declare the different event group classifications - The SimpleLink device send asynchronous events. Each event has a group - classification according to its nature. -*/ -/* SL_EVENT_CLASS_WLAN connection user events */ -#define SL_WLAN_CONNECT_EVENT (1) -#define SL_WLAN_DISCONNECT_EVENT (2) -/* WLAN Smart Config user events */ -#define SL_WLAN_SMART_CONFIG_COMPLETE_EVENT (3) -#define SL_WLAN_SMART_CONFIG_STOP_EVENT (4) -/* WLAN AP user events */ -#define SL_WLAN_STA_CONNECTED_EVENT (5) -#define SL_WLAN_STA_DISCONNECTED_EVENT (6) -/* WLAN P2P user events */ -#define SL_WLAN_P2P_DEV_FOUND_EVENT (7) -#define SL_WLAN_P2P_NEG_REQ_RECEIVED_EVENT (8) -#define SL_WLAN_CONNECTION_FAILED_EVENT (9) -/* SL_EVENT_CLASS_DEVICE user events */ -#define SL_DEVICE_FATAL_ERROR_EVENT (1) -#define SL_DEVICE_ABORT_ERROR_EVENT (2) - -/* SL_EVENT_CLASS_BSD user events */ -#define SL_SOCKET_TX_FAILED_EVENT (1) -#define SL_SOCKET_ASYNC_EVENT (2) -/* SL_EVENT_CLASS_NETAPP user events */ -#define SL_NETAPP_IPV4_IPACQUIRED_EVENT (1) -#define SL_NETAPP_IPV6_IPACQUIRED_EVENT (2) -#define SL_NETAPP_IP_LEASED_EVENT (3) -#define SL_NETAPP_IP_RELEASED_EVENT (4) - -/* Server Events */ -#define SL_NETAPP_HTTPGETTOKENVALUE_EVENT (1) -#define SL_NETAPP_HTTPPOSTTOKENVALUE_EVENT (2) - - -/* - Declare the different event group classifications for sl_DevGet - for getting status indications - */ - -/* Events list to mask/unmask*/ -#define SL_EVENT_CLASS_GLOBAL (0) -#define SL_EVENT_CLASS_DEVICE (1) -#define SL_EVENT_CLASS_WLAN (2) -#define SL_EVENT_CLASS_BSD (3) -#define SL_EVENT_CLASS_NETAPP (4) -#define SL_EVENT_CLASS_NETCFG (5) -#define SL_EVENT_CLASS_FS (6) - - -/****************** DEVICE CLASS status ****************/ -#define EVENT_DROPPED_DEVICE_ASYNC_GENERAL_ERROR (0x00000001L) -#define STATUS_DEVICE_SMART_CONFIG_ACTIVE (0x80000000L) - -/****************** WLAN CLASS status ****************/ -#define EVENT_DROPPED_WLAN_WLANASYNCONNECTEDRESPONSE (0x00000001L) -#define EVENT_DROPPED_WLAN_WLANASYNCDISCONNECTEDRESPONSE (0x00000002L) -#define EVENT_DROPPED_WLAN_STA_CONNECTED (0x00000004L) -#define EVENT_DROPPED_WLAN_STA_DISCONNECTED (0x00000008L) -#define STATUS_WLAN_STA_CONNECTED (0x80000000L) - -/****************** NETAPP CLASS status ****************/ -#define EVENT_DROPPED_NETAPP_IPACQUIRED (0x00000001L) -#define EVENT_DROPPED_NETAPP_IPACQUIRED_V6 (0x00000002L) -#define EVENT_DROPPED_NETAPP_IP_LEASED (0x00000004L) -#define EVENT_DROPPED_NETAPP_IP_RELEASED (0x00000008L) - -/****************** BSD CLASS status ****************/ -#define EVENT_DROPPED_SOCKET_TXFAILEDASYNCRESPONSE (0x00000001L) - -/****************** FS CLASS ****************/ - - - -/*****************************************************************************/ -/* Structure/Enum declarations */ -/*****************************************************************************/ - -#define ROLE_UNKNOWN_ERR (-1) - -#ifdef SL_IF_TYPE_UART -typedef struct -{ - _u32 BaudRate; - _u8 FlowControlEnable; - _u8 CommPort; -} SlUartIfParams_t; -#endif - -typedef struct -{ - _u32 ChipId; - _u32 FwVersion[4]; - _u8 PhyVersion[4]; -}_SlPartialVersion; - -typedef struct -{ - _SlPartialVersion ChipFwAndPhyVersion; - _u32 NwpVersion[4]; - _u16 RomVersion; - _u16 Padding; -}SlVersionFull; - - -typedef struct -{ - _u32 AbortType; - _u32 AbortData; -}sl_DeviceReportAbort; - - -typedef struct -{ - _i8 status; - SlErrorSender_e sender; -}sl_DeviceReport; - -typedef union -{ - sl_DeviceReport deviceEvent; - sl_DeviceReportAbort deviceReport; -} _SlDeviceEventData_u; - -typedef struct -{ - _u32 Event; - _SlDeviceEventData_u EventData; -} SlDeviceEvent_t; - -typedef struct -{ - /* time */ - _u32 sl_tm_sec; - _u32 sl_tm_min; - _u32 sl_tm_hour; - /* date */ - _u32 sl_tm_day; /* 1-31 */ - _u32 sl_tm_mon; /* 1-12 */ - _u32 sl_tm_year; /* YYYY 4 digits */ - _u32 sl_tm_week_day; /* not required */ - _u32 sl_tm_year_day; /* not required */ - _u32 reserved[3]; -}SlDateTime_t; - - -/******************************************************************************/ -/* Type declarations */ -/******************************************************************************/ -typedef void (*P_INIT_CALLBACK)(_u32 Status); - -/*****************************************************************************/ -/* Function prototypes */ -/*****************************************************************************/ - -/*! - \brief Start the SimpleLink device - - This function initialize the communication interface, set the enable pin - of the device, and call to the init complete callback. - - \param[in] pIfHdl Opened Interface Object. In case the interface - must be opened outside the SimpleLink Driver, the - user might give the handler to be used in \n - any access of the communication interface with the - device (UART/SPI). \n - The SimpleLink driver will open an interface port - only if this parameter is null! \n - \param[in] pDevName The name of the device to open. Could be used when - the pIfHdl is null, to transfer information to the - open interface function \n - This pointer could be used to pass additional information to - sl_IfOpen in case it is required (e.g. UART com port name) - \param[in] pInitCallBack Pointer to function that would be called - on completion of the initialization process.\n - If this parameter is NULL the function is - blocked until the device initialization - is completed, otherwise the function returns - immediately. - - \return Returns the current active role (STA/AP/P2P) or an error code: - - ROLE_STA, ROLE_AP, ROLE_P2P in case of success, - otherwise in failure one of the following is return: - - ROLE_STA_ERR (Failure to load MAC/PHY in STA role) - - ROLE_AP_ERR (Failure to load MAC/PHY in AP role) - - ROLE_P2P_ERR (Failure to load MAC/PHY in P2P role) - - - \sa sl_Stop - - \note belongs to \ref basic_api - - \warning This function must be called before any other SimpleLink API is used, or after sl_Stop is called for reinit the device - \par Example: - \code - An example for open interface without callback routine. The interface name and handler are - handled by the sl_IfOpen routine: - - if( sl_Start(NULL, NULL, NULL) < 0 ) - { - LOG("Error opening interface to device\n"); - } - \endcode -*/ -#if _SL_INCLUDE_FUNC(sl_Start) -_i16 sl_Start(const void* pIfHdl, _i8* pDevName, const P_INIT_CALLBACK pInitCallBack); -#endif - -/*! - \brief Stop the SimpleLink device - - This function clears the enable pin of the device, closes the communication \n - interface and invokes the stop complete callback - - \param[in] timeout Stop timeout in msec. Should be used to give the device time to finish \n - any transmission/reception that is not completed when the function was called. \n - Additional options: - - 0 Enter to hibernate immediately \n - - 0xFFFF Host waits for device's response before \n - hibernating, without timeout protection \n - - 0 < Timeout[msec] < 0xFFFF Host waits for device's response before \n - hibernating, with a defined timeout protection \n - This timeout defines the max time to wait. The NWP \n - response can be sent earlier than this timeout. - - \return On success, zero is returned. On error, -1 is returned - - \sa sl_Start - - \note This API will shutdown the device and invoke the "i/f close" function regardless \n - if it was opened implicitly or explicitly. \n - It is up to the platform interface library to properly handle interface close \n - routine \n - belongs to \ref basic_api \n - \warning -*/ -#if _SL_INCLUDE_FUNC(sl_Stop) -_i16 sl_Stop(const _u16 timeout); -#endif - - -/*! - \brief Internal function for setting device configurations - - \return On success, zero is returned. On error, -1 is - returned - - \param[in] DeviceSetId configuration id - \param[in] Option configurations option - \param[in] ConfigLen configurations len - \param[in] pValues configurations values - - \sa - \note - \warning - \par Examples: - \code - Setting device time and date example: - - SlDateTime_t dateTime= {0}; - dateTime.sl_tm_day = (_u32)23; // Day of month (DD format) range 1-31 - dateTime.sl_tm_mon = (_u32)6; // Month (MM format) in the range of 1-12 - dateTime.sl_tm_year = (_u32)2014; // Year (YYYY format) - dateTime.sl_tm_hour = (_u32)17; // Hours in the range of 0-23 - dateTime.sl_tm_min = (_u32)55; // Minutes in the range of 0-59 - dateTime.sl_tm_sec = (_u32)22; // Seconds in the range of 0-59 - sl_DevSet(SL_DEVICE_GENERAL_CONFIGURATION, - SL_DEVICE_GENERAL_CONFIGURATION_DATE_TIME, - sizeof(SlDateTime_t), - (_u8 *)(&dateTime)); - - \endcode -*/ -#if _SL_INCLUDE_FUNC(sl_DevSet) -_i32 sl_DevSet(const _u8 DeviceSetId ,const _u8 Option,const _u8 ConfigLen,const _u8 *pValues); -#endif - -/*! - \brief Internal function for getting device configurations - \return On success, zero is returned. On error, -1 is - returned - \param[in] DeviceGetId configuration id - example SL_DEVICE_STATUS - \param[out] pOption Get configurations option, example for get status options - - SL_EVENT_CLASS_GLOBAL - - SL_EVENT_CLASS_DEVICE - - SL_EVENT_CLASS_WLAN - - SL_EVENT_CLASS_BSD - - SL_EVENT_CLASS_NETAPP - - SL_EVENT_CLASS_NETCFG - - SL_EVENT_CLASS_FS - \param[out] pConfigLen The length of the allocated memory as input, when the - function complete, the value of this parameter would be - the len that actually read from the device.\n - If the device return length that is longer from the input - value, the function will cut the end of the returned structure - and will return SL_ESMALLBUF - \param[out] pValues Get configurations values - \sa - \note - \warning - \par Examples: - \code - Example for getting WLAN class status: - _u32 statusWlan; - _u8 pConfigOpt; - _u8 pConfigLen; - pConfigOpt = SL_EVENT_CLASS_WLAN; - pConfigLen = sizeof(_u32); - sl_DevGet(SL_DEVICE_STATUS,&pConfigOpt,&pConfigLen,(_u8 *)(&statusWlan)); - Example for getting version: - SlVersionFull ver; - pConfigLen = sizeof(ver); - pConfigOpt = SL_DEVICE_GENERAL_VERSION; - sl_DevGet(SL_DEVICE_GENERAL_CONFIGURATION,&pConfigOpt,&pConfigLen,(_u8 *)(&ver)); - printf("CHIP %d\nMAC 31.%d.%d.%d.%d\nPHY %d.%d.%d.%d\nNWP %d.%d.%d.%d\nROM %d\nHOST %d.%d.%d.%d\n", - ver.ChipFwAndPhyVersion.ChipId, - ver.ChipFwAndPhyVersion.FwVersion[0],ver.ChipFwAndPhyVersion.FwVersion[1], - ver.ChipFwAndPhyVersion.FwVersion[2],ver.ChipFwAndPhyVersion.FwVersion[3], - ver.ChipFwAndPhyVersion.PhyVersion[0],ver.ChipFwAndPhyVersion.PhyVersion[1], - ver.ChipFwAndPhyVersion.PhyVersion[2],ver.ChipFwAndPhyVersion.PhyVersion[3], - ver.NwpVersion[0],ver.NwpVersion[1],ver.NwpVersion[2],ver.NwpVersion[3], - ver.RomVersion, - SL_MAJOR_VERSION_NUM,SL_MINOR_VERSION_NUM,SL_VERSION_NUM,SL_SUB_VERSION_NUM); - - \endcode - \code - Getting Device time and date example: - - SlDateTime_t dateTime = {0}; - _i8 configLen = sizeof(SlDateTime_t); - _i8 configOpt = SL_DEVICE_GENERAL_CONFIGURATION_DATE_TIME; - sl_DevGet(SL_DEVICE_GENERAL_CONFIGURATION,&configOpt, &configLen,(_u8 *)(&dateTime)); - - printf("Day %d,Mon %d,Year %d,Hour %,Min %d,Sec %d\n",dateTime.sl_tm_day,dateTime.sl_tm_mon,dateTime.sl_tm_year - dateTime.sl_tm_hour,dateTime.sl_tm_min,dateTime.sl_tm_sec); - \endcode -*/ -#if _SL_INCLUDE_FUNC(sl_DevGet) -_i32 sl_DevGet(const _u8 DeviceGetId,_u8 *pOption,_u8 *pConfigLen, _u8 *pValues); -#endif - - -/*! - \brief Set asynchronous event mask - - Mask asynchronous events from the device. Masked events do not - generate asynchronous messages from the device. - By default - all events are active - - \param[in] EventClass The classification groups that the - mask is referred to. Need to be one of - the following: - - SL_EVENT_CLASS_GLOBAL - - SL_EVENT_CLASS_DEVICE - - SL_EVENT_CLASS_WLAN - - SL_EVENT_CLASS_BSD - - SL_EVENT_CLASS_NETAPP - - SL_EVENT_CLASS_NETCFG - - SL_EVENT_CLASS_FS - - - \param[in] Mask Event Mask bitmap. Valid mask are (per group): - - SL_EVENT_CLASS_WLAN user events - - SL_WLAN_CONNECT_EVENT - - SL_WLAN_DISCONNECT_EVENT - - SL_EVENT_CLASS_DEVICE user events - - SL_DEVICE_FATAL_ERROR_EVENT - - SL_EVENT_CLASS_BSD user events - - SL_SOCKET_TX_FAILED_EVENT - - SL_SOCKET_ASYNC_EVENT - - SL_EVENT_CLASS_NETAPP user events - - SL_NETAPP_IPV4_IPACQUIRED_EVENT - - SL_NETAPP_IPV6_IPACQUIRED_EVENT - - \return On success, zero is returned. On error, -1 is returned - - \sa sl_EventMaskGet - - \note belongs to \ref ext_api - - \warning - \par Example: - \code - - An example of masking connection/disconnection async events from WLAN class: - sl_EventMaskSet(SL_EVENT_CLASS_WLAN, (SL_WLAN_CONNECT_EVENT | SL_WLAN_DISCONNECT_EVENT) ); - - \endcode -*/ -#if _SL_INCLUDE_FUNC(sl_EventMaskSet) -_i16 sl_EventMaskSet(const _u8 EventClass ,const _u32 Mask); -#endif - -/*! - \brief Get current event mask of the device - - return the events bit mask from the device. In case that event is - masked, the device is not sending this event. - - \param[in] EventClass The classification groups that the - mask is referred to. Need to be one of - the following: - - SL_EVENT_CLASS_GLOBAL - - SL_EVENT_CLASS_DEVICE - - SL_EVENT_CLASS_WLAN - - SL_EVENT_CLASS_BSD - - SL_EVENT_CLASS_NETAPP - - SL_EVENT_CLASS_NETCFG - - SL_EVENT_CLASS_FS - - \param[out] pMask Pointer to Mask bitmap where the - value should be stored. Bitmasks are the same as in \ref sl_EventMaskSet - - \return On success, zero is returned. On error, -1 is returned - - \sa sl_EventMaskSet - - \note belongs to \ref ext_api - - \warning - \par Example: - \code - - An example of getting an event mask for WLAN class - _u32 maskWlan; - sl_StatusGet(SL_EVENT_CLASS_WLAN,&maskWlan); - - \endcode -*/ -#if _SL_INCLUDE_FUNC(sl_EventMaskGet) -_i16 sl_EventMaskGet(const _u8 EventClass,_u32 *pMask); -#endif - - -/*! - \brief the simple link task entry - - \Param - This function must be called from the main loop or from dedicated thread in - the following cases: - - Non-Os Platform - should be called from the mail loop - - Multi Threaded Platform when the user does not implement the external spawn functions - - should be called from dedicated thread allocated to the simplelink driver. - In this mode the function never return. - - \return None - - \sa sl_Stop - - \note belongs to \ref basic_api - - \warning This function must be called from a thread that is start running before - any call to other simple link API -*/ -#if _SL_INCLUDE_FUNC(sl_Task) -void sl_Task(void); -#endif - - -/*! - \brief Setting the internal uart mode - - \param[in] pUartParams Pointer to the uart configuration parameter set: - baudrate - up to 711 Kbps - flow control - enable/disable - comm port - the comm port number - - \return On success zero is returned, otherwise - Failed. - - \sa sl_Stop - - \note belongs to \ref basic_api - - \warning This function must consider the host uart capability -*/ -#ifdef SL_IF_TYPE_UART -#if _SL_INCLUDE_FUNC(sl_UartSetMode) -_i16 sl_UartSetMode(const SlUartIfParams_t* pUartParams); -#endif -#endif - -/*! - - Close the Doxygen group. - @} - - */ - - -#ifdef __cplusplus -} -#endif /* __cplusplus */ - -#endif /* __DEVICE_H__ */ - - diff --git a/drivers/cc3100/inc/driver.h b/drivers/cc3100/inc/driver.h deleted file mode 100644 index 4ef484dfb5..0000000000 --- a/drivers/cc3100/inc/driver.h +++ /dev/null @@ -1,247 +0,0 @@ -/* - * driver.h - CC31xx/CC32xx Host Driver Implementation - * - * Copyright (C) 2014 Texas Instruments Incorporated - http://www.ti.com/ - * - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * - * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the - * distribution. - * - * Neither the name of Texas Instruments Incorporated nor the names of - * its contributors may be used to endorse or promote products derived - * from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * -*/ - -#ifndef __DRIVER_INT_H__ -#define __DRIVER_INT_H__ - - -/*****************************************************************************/ -/* Macro declarations */ -/*****************************************************************************/ - -#ifndef CPU_FREQ_IN_MHZ - #define CPU_FREQ_IN_MHZ (200) -#endif -#define USEC_DELAY (50) - -/*****************************************************************************/ -/* Structure/Enum declarations */ -/*****************************************************************************/ - -typedef struct -{ - _SlOpcode_t Opcode; - _SlArgSize_t TxDescLen; - _SlArgSize_t RxDescLen; -}_SlCmdCtrl_t; - -typedef struct -{ - _u16 TxPayloadLen; - _i16 RxPayloadLen; - _i16 ActualRxPayloadLen; - _u8 *pTxPayload; - _u8 *pRxPayload; -}_SlCmdExt_t; - - -typedef struct _SlArgsData_t -{ - _u8 *pArgs; - _u8 *pData; -} _SlArgsData_t; - - -typedef struct _SlPoolObj_t -{ - _SlSyncObj_t SyncObj; - _u8 *pRespArgs; - _u8 ActionID; - _u8 AdditionalData; /* use for socketID and one bit which indicate supprt IPV6 or not (1=support, 0 otherwise) */ - _u8 NextIndex; - -} _SlPoolObj_t; - - -typedef enum -{ - SOCKET_0, - SOCKET_1, - SOCKET_2, - SOCKET_3, - SOCKET_4, - SOCKET_5, - SOCKET_6, - SOCKET_7, - MAX_SOCKET_ENUM_IDX, -#ifndef SL_TINY_EXT - ACCEPT_ID = MAX_SOCKET_ENUM_IDX, - CONNECT_ID, -#else - CONNECT_ID = MAX_SOCKET_ENUM_IDX, -#endif -#ifndef SL_TINY_EXT - SELECT_ID, -#endif - GETHOSYBYNAME_ID, -#ifndef SL_TINY_EXT - GETHOSYBYSERVICE_ID, - PING_ID, -#endif - START_STOP_ID, - RECV_ID -}_SlActionID_e; - -typedef struct _SlActionLookup_t -{ - _u8 ActionID; - _u16 ActionAsyncOpcode; - _SlSpawnEntryFunc_t AsyncEventHandler; - -} _SlActionLookup_t; - - -typedef struct -{ - _u8 TxPoolCnt; - _SlLockObj_t TxLockObj; - _SlSyncObj_t TxSyncObj; -}_SlFlowContCB_t; - -typedef enum -{ - RECV_RESP_CLASS, - CMD_RESP_CLASS, - ASYNC_EVT_CLASS, - DUMMY_MSG_CLASS -}_SlRxMsgClass_e; - -typedef struct -{ - _u8 *pAsyncBuf; /* place to write pointer to buffer with CmdResp's Header + Arguments */ - _u8 ActionIndex; - _SlSpawnEntryFunc_t AsyncEvtHandler; /* place to write pointer to AsyncEvent handler (calc-ed by Opcode) */ - _SlRxMsgClass_e RxMsgClass; /* type of Rx message */ -} AsyncExt_t; - -typedef _u8 _SlSd_t; - -typedef struct -{ - _SlCmdCtrl_t *pCmdCtrl; - _u8 *pTxRxDescBuff; - _SlCmdExt_t *pCmdExt; - AsyncExt_t AsyncExt; -}_SlFunctionParams_t; - - -typedef struct -{ - _SlFd_t FD; - _SlLockObj_t GlobalLockObj; - _SlCommandHeader_t TempProtocolHeader; - P_INIT_CALLBACK pInitCallback; - - _SlPoolObj_t ObjPool[MAX_CONCURRENT_ACTIONS]; - _u8 FreePoolIdx; - _u8 PendingPoolIdx; - _u8 ActivePoolIdx; - _u32 ActiveActionsBitmap; - _SlLockObj_t ProtectionLockObj; - - _SlSyncObj_t CmdSyncObj; - _u8 IsCmdRespWaited; - _SlFlowContCB_t FlowContCB; - _u8 TxSeqNum; - _u8 RxDoneCnt; - _u8 SocketNonBlocking; - _u8 SocketTXFailure; - /* for stack reduction the parameters are globals */ - _SlFunctionParams_t FunctionParams; - - _u8 ActionIndex; -}_SlDriverCb_t; - -extern _volatile _u8 RxIrqCnt; - -extern _SlDriverCb_t* g_pCB; -extern P_SL_DEV_PING_CALLBACK pPingCallBackFunc; - -/*****************************************************************************/ -/* Function prototypes */ -/*****************************************************************************/ -extern void _SlDrvDriverCBInit(void); -extern void _SlDrvDriverCBDeinit(void); -extern void _SlDrvRxIrqHandler(void *pValue); -extern _SlReturnVal_t _SlDrvCmdOp(_SlCmdCtrl_t *pCmdCtrl , void* pTxRxDescBuff , _SlCmdExt_t* pCmdExt); -extern _SlReturnVal_t _SlDrvCmdSend(_SlCmdCtrl_t *pCmdCtrl , void* pTxRxDescBuff , _SlCmdExt_t* pCmdExt); -extern _SlReturnVal_t _SlDrvDataReadOp(_SlSd_t Sd, _SlCmdCtrl_t *pCmdCtrl , void* pTxRxDescBuff , _SlCmdExt_t* pCmdExt); -extern _SlReturnVal_t _SlDrvDataWriteOp(_SlSd_t Sd, _SlCmdCtrl_t *pCmdCtrl , void* pTxRxDescBuff , _SlCmdExt_t* pCmdExt); -extern void _sl_HandleAsync_InitComplete(void *pVoidBuf); -extern void _sl_HandleAsync_Connect(void *pVoidBuf); - - -#ifndef SL_TINY_EXT -extern _i16 _SlDrvBasicCmd(_SlOpcode_t Opcode); -extern void _sl_HandleAsync_Accept(void *pVoidBuf); -extern void _sl_HandleAsync_DnsGetHostByService(void *pVoidBuf); -extern void _sl_HandleAsync_Select(void *pVoidBuf); -#endif - - -extern void _sl_HandleAsync_DnsGetHostByName(void *pVoidBuf); -extern void _sl_HandleAsync_DnsGetHostByAddr(void *pVoidBuf); -extern void _sl_HandleAsync_PingResponse(void *pVoidBuf); -extern void _SlDrvNetAppEventHandler(void* pArgs); -extern void _SlDrvDeviceEventHandler(void* pArgs); -extern void _sl_HandleAsync_Stop(void *pVoidBuf); -extern _u8 _SlDrvWaitForPoolObj(_u8 ActionID, _u8 SocketID); -extern void _SlDrvReleasePoolObj(_u8 pObj); -extern _u16 _SlDrvAlignSize(_u16 msgLen); -extern _u8 _SlDrvProtectAsyncRespSetting(_u8 *pAsyncRsp, _u8 ActionID, _u8 SocketID); - - -extern void _SlDrvSyncObjWaitForever(_SlSyncObj_t *pSyncObj); -extern void _SlDrvSyncObjSignal(_SlSyncObj_t *pSyncObj); -extern void _SlDrvObjLock(_SlLockObj_t *pLockObj, _SlTime_t Timeout); -extern void _SlDrvObjLockWaitForever(_SlLockObj_t *pLockObj); -extern void _SlDrvProtectionObjLockWaitForever(); -extern void _SlDrvObjUnLock(_SlLockObj_t *pLockObj); -extern void _SlDrvProtectionObjUnLock(); - -extern void _SlDrvMemZero(void* Addr, _u16 size); -extern void _SlDrvResetCmdExt(_SlCmdExt_t* pCmdExt); - - - -#define _SL_PROTOCOL_ALIGN_SIZE(msgLen) (((msgLen)+3) & (~3)) -#define _SL_IS_PROTOCOL_ALIGNED_SIZE(msgLen) (!((msgLen) & 3)) - - -#define _SL_PROTOCOL_CALC_LEN(pCmdCtrl,pCmdExt) ((pCmdExt) ? \ - (_SL_PROTOCOL_ALIGN_SIZE(pCmdCtrl->TxDescLen) + _SL_PROTOCOL_ALIGN_SIZE(pCmdExt->TxPayloadLen)) : \ - (_SL_PROTOCOL_ALIGN_SIZE(pCmdCtrl->TxDescLen))) -#endif /* __DRIVER_INT_H__ */ diff --git a/drivers/cc3100/inc/flowcont.h b/drivers/cc3100/inc/flowcont.h deleted file mode 100644 index 3dcc130d83..0000000000 --- a/drivers/cc3100/inc/flowcont.h +++ /dev/null @@ -1,61 +0,0 @@ -/* - * flowcont.h - CC31xx/CC32xx Host Driver Implementation - * - * Copyright (C) 2014 Texas Instruments Incorporated - http://www.ti.com/ - * - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * - * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the - * distribution. - * - * Neither the name of Texas Instruments Incorporated nor the names of - * its contributors may be used to endorse or promote products derived - * from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * -*/ - -#ifndef __FLOWCONT_H__ -#define __FLOWCONT_H__ - - -#ifdef __cplusplus -extern "C" { -#endif - -/*****************************************************************************/ -/* Macro declarations */ -/*****************************************************************************/ -#define FLOW_CONT_MIN 1 - -/*****************************************************************************/ -/* Function prototypes */ -/*****************************************************************************/ -extern void _SlDrvFlowContInit(void); -extern void _SlDrvFlowContDeinit(void); - -#ifdef __cplusplus -} -#endif /* __cplusplus */ - -#endif /* __FLOWCONT_H__ */ - diff --git a/drivers/cc3100/inc/fs.h b/drivers/cc3100/inc/fs.h deleted file mode 100644 index 078feafff6..0000000000 --- a/drivers/cc3100/inc/fs.h +++ /dev/null @@ -1,382 +0,0 @@ -/* - * fs.h - CC31xx/CC32xx Host Driver Implementation - * - * Copyright (C) 2014 Texas Instruments Incorporated - http://www.ti.com/ - * - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * - * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the - * distribution. - * - * Neither the name of Texas Instruments Incorporated nor the names of - * its contributors may be used to endorse or promote products derived - * from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * -*/ - -/*****************************************************************************/ -/* Include files */ -/*****************************************************************************/ - -#include "simplelink.h" - -#ifndef __FS_H__ -#define __FS_H__ - - - -#ifdef __cplusplus -extern "C" { -#endif - -/*! - - \addtogroup FileSystem - @{ - -*/ - -/*****************************************************************************/ -/* Macro declarations */ -/*****************************************************************************/ - -/* FS error codes */ -#define SL_FS_OK (0) -#define SL_FS_ERR_EMPTY_SFLASH (-67) -#define SL_FS_ERR_FILE_IS_NOT_SECURE_AND_SIGN (-66) -#define SL_FS_ERASING_FLASH (-65) -#define SL_FS_FILE_HAS_NOT_BEEN_CLOSE_CORRECTLY (-64) -#define SL_FS_WRONG_SIGNATURE (-63) -#define SL_FS_WRONG_SIGNATURE_OR_CERTIFIC_NAME_LENGTH (-62) -#define SL_FS_NOT_16_ALIGNED (-61) -#define SL_FS_CERT_CHAIN_ERROR (-60) -#define SL_FS_FILE_NAME_EXIST (-59) -#define SL_FS_SECURITY_BUF_ALREADY_ALLOC (-58) -#define SL_FS_SECURE_FILE_MUST_BE_COMMIT (-57) -#define SL_FS_ERR_INCORRECT_OFFSET_ALIGNMENT (-56) -#define SL_FS_ERR_FAILED_READ_NVMEM_HEADER (-55) -#define SL_FS_WRONG_FILE_NAME (-54) -#define SL_FS_FILE_SYSTEM_IS_LOCKED (-53) -#define SL_FS_SECURITY_ALLERT (-52) -#define SL_FS_FILE_UNVALID_FILE_SIZE (-51) -#define SL_FS_ERR_TOKEN_IS_NOT_VALID (-50) -#define SL_FS_NO_DEVICE_IS_LOADED (-49) -#define SL_FS_DATA_ADDRESS_SHOUD_BE_IN_DATA_RAM (-48) -#define SL_FS_DATA_IS_NOT_ALIGNED (-47) -#define SL_FS_ERR_OVERLAP_DETECTION_THRESHHOLD (-46) -#define SL_FS_FILE_HAS_RESERVED_NV_INDEX (-45) -#define SL_FS_ERR_MAX_FS_FILES_IS_LARGER (-44) -#define SL_FS_ERR_MAX_FS_FILES_IS_SMALLER (-43) -#define SL_FS_FILE_MAX_SIZE_EXCEEDED (-42) -#define SL_FS_INVALID_BUFFER_FOR_READ (-41) -#define SL_FS_INVALID_BUFFER_FOR_WRITE (-40) -#define SL_FS_ERR_FILE_IMAGE_IS_CORRUPTED (-39) -#define SL_FS_ERR_SIZE_OF_FILE_EXT_EXCEEDED (-38) -#define SL_FS_WARNING_FILE_NAME_NOT_KEPT (-37) -#define SL_FS_ERR_DEVICE_IS_NOT_FORMATTED (-36) -#define SL_FS_ERR_FAILED_WRITE_NVMEM_HEADER (-35) -#define SL_FS_ERR_NO_AVAILABLE_NV_INDEX (-34) -#define SL_FS_ERR_FAILED_TO_ALLOCATE_MEM (-33) -#define SL_FS_ERR_FAILED_TO_READ_INTEGRITY_HEADER_2 (-32) -#define SL_FS_ERR_FAILED_TO_READ_INTEGRITY_HEADER_1 (-31) -#define SL_FS_ERR_NO_AVAILABLE_BLOCKS (-30) -#define SL_FS_ERR_FILE_MAX_SIZE_BIGGER_THAN_EXISTING_FILE (-29) -#define SL_FS_ERR_FILE_EXISTS_ON_DIFFERENT_DEVICE_ID (-28) -#define SL_FS_ERR_INVALID_ACCESS_TYPE (-27) -#define SL_FS_ERR_FILE_ALREADY_EXISTS (-26) -#define SL_FS_ERR_PROGRAM (-25) -#define SL_FS_ERR_NO_ENTRIES_AVAILABLE (-24) -#define SL_FS_ERR_FILE_ACCESS_IS_DIFFERENT (-23) -#define SL_FS_ERR_BAD_FILE_MODE (-22) -#define SL_FS_ERR_FAILED_READ_NVFILE (-21) -#define SL_FS_ERR_FAILED_INIT_STORAGE (-20) -#define SL_FS_ERR_CONTINUE_WRITE_MUST_BE_MOD_4 (-19) -#define SL_FS_ERR_FAILED_LOAD_FILE (-18) -#define SL_FS_ERR_INVALID_HANDLE (-17) -#define SL_FS_ERR_FAILED_TO_WRITE (-16) -#define SL_FS_ERR_OFFSET_OUT_OF_RANGE (-15) -#define SL_FS_ERR_ALLOC (-14) -#define SL_FS_ERR_READ_DATA_LENGTH (-13) -#define SL_FS_ERR_INVALID_FILE_ID (-12) -#define SL_FS_ERR_FILE_NOT_EXISTS (-11) -#define SL_FS_ERR_EMPTY_ERROR (-10) -#define SL_FS_ERR_INVALID_ARGS (-9) -#define SL_FS_ERR_FAILED_TO_CREATE_FILE (-8) -#define SL_FS_ERR_FS_ALREADY_LOADED (-7) -#define SL_FS_ERR_UNKNOWN (-6) -#define SL_FS_ERR_FAILED_TO_CREATE_LOCK_OBJ (-5) -#define SL_FS_ERR_DEVICE_NOT_LOADED (-4) -#define SL_FS_ERR_INVALID_MAGIC_NUM (-3) -#define SL_FS_ERR_FAILED_TO_READ (-2) -#define SL_FS_ERR_NOT_SUPPORTED (-1) -/* end of error codes */ - -#define _FS_MODE_ACCESS_RESERVED_OFFSET (24) -#define _FS_MODE_ACCESS_RESERVED_MASK (0xFF) -#define _FS_MODE_ACCESS_FLAGS_OFFSET (16) -#define _FS_MODE_ACCESS_FLAGS_MASK (0xFF) -#define _FS_MODE_ACCESS_OFFSET (12) -#define _FS_MODE_ACCESS_MASK (0xF) -#define _FS_MODE_OPEN_SIZE_GRAN_OFFSET (8) -#define _FS_MODE_OPEN_SIZE_GRAN_MASK (0xF) -#define _FS_MODE_OPEN_SIZE_OFFSET (0) -#define _FS_MODE_OPEN_SIZE_MASK (0xFF) -#define MAX_MODE_SIZE (0xFF) -#define _FS_MODE(Access, SizeGran, Size,Flags) (_u32)(((_u32)((Access) & _FS_MODE_ACCESS_MASK)<<_FS_MODE_ACCESS_OFFSET) | \ - ((_u32)((SizeGran) & _FS_MODE_OPEN_SIZE_GRAN_MASK)<<_FS_MODE_OPEN_SIZE_GRAN_OFFSET) | \ - ((_u32)((Size) & _FS_MODE_OPEN_SIZE_MASK)<<_FS_MODE_OPEN_SIZE_OFFSET) | \ - ((_u32)((Flags) & _FS_MODE_ACCESS_FLAGS_MASK)<<_FS_MODE_ACCESS_FLAGS_OFFSET)) - - -/* sl_FsOpen options */ -/* Open for Read */ -#define FS_MODE_OPEN_READ _FS_MODE(_FS_MODE_OPEN_READ,0,0,0) -/* Open for Write (in case file exist) */ -#define FS_MODE_OPEN_WRITE _FS_MODE(_FS_MODE_OPEN_WRITE,0,0,0) -/* Open for Creating a new file */ -#define FS_MODE_OPEN_CREATE(maxSizeInBytes,accessModeFlags) _sl_GetCreateFsMode(maxSizeInBytes,accessModeFlags) - -/*****************************************************************************/ -/* Structure/Enum declarations */ -/*****************************************************************************/ -typedef struct -{ - _u16 flags; - _u32 FileLen; - _u32 AllocatedLen; - _u32 Token[4]; -}SlFsFileInfo_t; - -typedef enum -{ - _FS_MODE_OPEN_READ = 0, - _FS_MODE_OPEN_WRITE, - _FS_MODE_OPEN_CREATE, - _FS_MODE_OPEN_WRITE_CREATE_IF_NOT_EXIST -}SlFsFileOpenAccessType_e; - -typedef enum -{ - _FS_FILE_OPEN_FLAG_COMMIT = 0x1, /* MIRROR - for fail safe */ - _FS_FILE_OPEN_FLAG_SECURE = 0x2, /* SECURE */ - _FS_FILE_OPEN_FLAG_NO_SIGNATURE_TEST = 0x4, /* Relevant to secure file only */ - _FS_FILE_OPEN_FLAG_STATIC = 0x8, /* Relevant to secure file only */ - _FS_FILE_OPEN_FLAG_VENDOR = 0x10, /* Relevant to secure file only */ - _FS_FILE_PUBLIC_WRITE= 0x20, /* Relevant to secure file only, the file can be opened for write without Token */ - _FS_FILE_PUBLIC_READ = 0x40 /* Relevant to secure file only, the file can be opened for read without Token */ -}SlFileOpenFlags_e; - -typedef enum -{ - _FS_MODE_SIZE_GRAN_256B = 0, /* MAX_SIZE = 64K */ - _FS_MODE_SIZE_GRAN_1KB, /* MAX_SIZE = 256K */ - _FS_MODE_SIZE_GRAN_4KB, /* MAX_SZIE = 1M */ - _FS_MODE_SIZE_GRAN_16KB, /* MAX_SIZE = 4M */ - _FS_MODE_SIZE_GRAN_64KB, /* MAX_SIZE = 16M */ - _FS_MAX_MODE_SIZE_GRAN -}_SlFsFileOpenMaxSizeGran_e; - -/*****************************************************************************/ -/* Internal Function prototypes */ -/*****************************************************************************/ -_u32 _sl_GetCreateFsMode(_u32 maxSizeInBytes,_u32 accessFlags); - -/*****************************************************************************/ -/* Function prototypes */ -/*****************************************************************************/ - -/*! - \brief open file for read or write from/to storage device - - \param[in] pFileName File Name buffer pointer - \param[in] AccessModeAndMaxSize Options: As described below - \param[in] pToken Reserved for future use. Use NULL for this field - \param[out] pFileHandle Pointing on the file and used for read and write commands to the file - - AccessModeAndMaxSize possible input \n - FS_MODE_OPEN_READ - Read a file \n - FS_MODE_OPEN_WRITE - Open for write for an existing file \n - FS_MODE_OPEN_CREATE(maxSizeInBytes,accessModeFlags) - Open for creating a new file. Max file size is defined in bytes. \n - For optimal FS size, use max size in 4K-512 bytes steps (e.g. 3584,7680,117760) \n - Several access modes bits can be combined together from SlFileOpenFlags_e enum - - \return On success, zero is returned. On error, an error code is returned - - \sa sl_FsRead sl_FsWrite sl_FsClose - \note belongs to \ref basic_api - \warning - \par Example: - \code - char* DeviceFileName = "MyFile.txt"; - unsigned long MaxSize = 63 * 1024; //62.5K is max file size - long DeviceFileHandle = -1; - long RetVal; //negative retval is an error - unsigned long Offset = 0; - unsigned char InputBuffer[100]; - - // Create a file and write data. The file in this example is secured, without signature and with a fail safe commit - RetVal = sl_FsOpen((unsigned char *)DeviceFileName, - FS_MODE_OPEN_CREATE(MaxSize , _FS_FILE_OPEN_FLAG_NO_SIGNATURE_TEST | _FS_FILE_OPEN_FLAG_COMMIT ), - NULL, &DeviceFileHandle); - - Offset = 0; - //Preferred in secure file that the Offset and the length will be aligned to 16 bytes. - RetVal = sl_FsWrite( DeviceFileHandle, Offset, (unsigned char *)"HelloWorld", strlen("HelloWorld")); - - RetVal = sl_FsClose(DeviceFileHandle, NULL, NULL , 0); - - // open the same file for read, using the Token we got from the creation procedure above - RetVal = sl_FsOpen((unsigned char *)DeviceFileName, - FS_MODE_OPEN_READ, - NULL, &DeviceFileHandle); - - Offset = 0; - RetVal = sl_FsRead( DeviceFileHandle, Offset, (unsigned char *)InputBuffer, strlen("HelloWorld")); - - RetVal = sl_FsClose(DeviceFileHandle, NULL, NULL , 0); - - \endcode -*/ -#if _SL_INCLUDE_FUNC(sl_FsOpen) -_i32 sl_FsOpen(const _u8 *pFileName,const _u32 AccessModeAndMaxSize,_u32 *pToken,_i32 *pFileHandle); -#endif - -/*! - \brief close file in storage device - - \param[in] FileHdl Pointer to the file (assigned from sl_FsOpen) - \param[in] pCeritificateFileName Reserved for future use. Use NULL. - \param[in] pSignature Reserved for future use. Use NULL. - \param[in] SignatureLen Reserved for future use. Use 0. - - - \return On success, zero is returned. On error, an error code is returned - - \sa sl_FsRead sl_FsWrite sl_FsOpen - \note Call the fs_Close with signature = 'A' signature len = 1 for activating an abort action - \warning - \par Example: - \code - sl_FsClose(FileHandle,0,0,0); - \endcode -*/ -#if _SL_INCLUDE_FUNC(sl_FsClose) -_i16 sl_FsClose(const _i32 FileHdl,const _u8* pCeritificateFileName,const _u8* pSignature,const _u32 SignatureLen); -#endif - -/*! - \brief Read block of data from a file in storage device - - \param[in] FileHdl Pointer to the file (assigned from sl_FsOpen) - \param[in] Offset Offset to specific read block - \param[out] pData Pointer for the received data - \param[in] Len Length of the received data - - \return On success, returns the number of read bytes. On error, negative number is returned - - \sa sl_FsClose sl_FsWrite sl_FsOpen - \note belongs to \ref basic_api - \warning - \par Example: - \code - Status = sl_FsRead(FileHandle, 0, &readBuff[0], readSize); - \endcode -*/ -#if _SL_INCLUDE_FUNC(sl_FsRead) -_i32 sl_FsRead(const _i32 FileHdl,_u32 Offset ,_u8* pData,_u32 Len); -#endif - -/*! - \brief write block of data to a file in storage device - - \param[in] FileHdl Pointer to the file (assigned from sl_FsOpen) - \param[in] Offset Offset to specific block to be written - \param[in] pData Pointer the transmitted data to the storage device - \param[in] Len Length of the transmitted data - - \return On success, returns the number of written bytes. On error, an error code is returned - - \sa - \note belongs to \ref basic_api - \warning - \par Example: - \code - Status = sl_FsWrite(FileHandle, 0, &buff[0], readSize); - \endcode -*/ -#if _SL_INCLUDE_FUNC(sl_FsWrite) -_i32 sl_FsWrite(const _i32 FileHdl,_u32 Offset,_u8* pData,_u32 Len); -#endif - -/*! - \brief get info on a file - - \param[in] pFileName File name - \param[in] Token Reserved for future use. Use 0 - \param[out] pFsFileInfo Returns the File's Information: flags,file size, allocated size and Tokens - - \return On success, zero is returned. On error, an error code is returned - - \sa sl_FsOpen - \note belongs to \ref basic_api - \warning - \par Example: - \code - Status = sl_FsGetInfo("FileName.html",0,&FsFileInfo); - \endcode -*/ -#if _SL_INCLUDE_FUNC(sl_FsGetInfo) -_i16 sl_FsGetInfo(const _u8 *pFileName,const _u32 Token,SlFsFileInfo_t* pFsFileInfo); -#endif - -/*! - \brief Delete specific file from a storage or all files from a storage (format) - - \param[in] pFileName File Name - \param[in] Token Reserved for future use. Use 0 - \return On success, zero is returned. On error, an error code is returned - - \sa - \note belongs to \ref basic_api - \warning - \par Example: - \code - Status = sl_FsDel("FileName.html",0); - \endcode -*/ -#if _SL_INCLUDE_FUNC(sl_FsDel) -_i16 sl_FsDel(const _u8 *pFileName,const _u32 Token); -#endif -/*! - - Close the Doxygen group. - @} - - */ - -#ifdef __cplusplus -} -#endif /* __cplusplus */ - -#endif /* __FS_H__ */ - diff --git a/drivers/cc3100/inc/netapp.h b/drivers/cc3100/inc/netapp.h deleted file mode 100644 index a968e7d0ba..0000000000 --- a/drivers/cc3100/inc/netapp.h +++ /dev/null @@ -1,884 +0,0 @@ -/* - * netapp.h - CC31xx/CC32xx Host Driver Implementation - * - * Copyright (C) 2014 Texas Instruments Incorporated - http://www.ti.com/ - * - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * - * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the - * distribution. - * - * Neither the name of Texas Instruments Incorporated nor the names of - * its contributors may be used to endorse or promote products derived - * from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * -*/ - -/*****************************************************************************/ -/* Include files */ -/*****************************************************************************/ - -#include "simplelink.h" - -#ifndef __NETAPP_H__ -#define __NETAPP_H__ - - - - -#ifdef __cplusplus -extern "C" { -#endif - -/*! - - \addtogroup netapp - @{ - -*/ - -/*****************************************************************************/ -/* Macro declarations */ -/*****************************************************************************/ - -/*ERROR code*/ -#define SL_ERROR_NETAPP_RX_BUFFER_LENGTH_ERROR (-230) - -/* Http Server interface */ -#define MAX_INPUT_STRING (64) /* because of WPA */ - -#define MAX_AUTH_NAME_LEN (20) -#define MAX_AUTH_PASSWORD_LEN (20) -#define MAX_AUTH_REALM_LEN (20) - -#define MAX_DEVICE_URN_LEN (15+1) -#define MAX_DOMAIN_NAME_LEN (24+1) - -#define MAX_ACTION_LEN (30) -/* Important: in case the max len is changed, make sure the struct sl_NetAppHttpServerSendToken_t in protocol.h is padded correctly! */ -#define MAX_TOKEN_NAME_LEN (20) -#define MAX_TOKEN_VALUE_LEN MAX_INPUT_STRING - -#define NETAPP_MAX_SERVICE_TEXT_SIZE (256) -#define NETAPP_MAX_SERVICE_NAME_SIZE (60) -#define NETAPP_MAX_SERVICE_HOST_NAME_SIZE (64) - - -/* Server Responses */ -#define SL_NETAPP_RESPONSE_NONE (0) -#define SL_NETAPP_HTTPSETTOKENVALUE (1) - -#define SL_NETAPP_FAMILY_MASK (0x80) - -/* mDNS types */ -#define SL_NET_APP_MASK_IPP_TYPE_OF_SERVICE (0x00000001) -#define SL_NET_APP_MASK_DEVICE_INFO_TYPE_OF_SERVICE (0x00000002) -#define SL_NET_APP_MASK_HTTP_TYPE_OF_SERVICE (0x00000004) -#define SL_NET_APP_MASK_HTTPS_TYPE_OF_SERVICE (0x00000008) -#define SL_NET_APP_MASK_WORKSATION_TYPE_OF_SERVICE (0x00000010) -#define SL_NET_APP_MASK_GUID_TYPE_OF_SERVICE (0x00000020) -#define SL_NET_APP_MASK_H323_TYPE_OF_SERVICE (0x00000040) -#define SL_NET_APP_MASK_NTP_TYPE_OF_SERVICE (0x00000080) -#define SL_NET_APP_MASK_OBJECITVE_TYPE_OF_SERVICE (0x00000100) -#define SL_NET_APP_MASK_RDP_TYPE_OF_SERVICE (0x00000200) -#define SL_NET_APP_MASK_REMOTE_TYPE_OF_SERVICE (0x00000400) -#define SL_NET_APP_MASK_RTSP_TYPE_OF_SERVICE (0x00000800) -#define SL_NET_APP_MASK_SIP_TYPE_OF_SERVICE (0x00001000) -#define SL_NET_APP_MASK_SMB_TYPE_OF_SERVICE (0x00002000) -#define SL_NET_APP_MASK_SOAP_TYPE_OF_SERVICE (0x00004000) -#define SL_NET_APP_MASK_SSH_TYPE_OF_SERVICE (0x00008000) -#define SL_NET_APP_MASK_TELNET_TYPE_OF_SERVICE (0x00010000) -#define SL_NET_APP_MASK_TFTP_TYPE_OF_SERVICE (0x00020000) -#define SL_NET_APP_MASK_XMPP_CLIENT_TYPE_OF_SERVICE (0x00040000) -#define SL_NET_APP_MASK_RAOP_TYPE_OF_SERVICE (0x00080000) -#define SL_NET_APP_MASK_ALL_TYPE_OF_SERVICE (0xFFFFFFFF) - -/********************************************************************************************************/ -/* sl_NetAppDnsGetHostByName error codes */ - -#define SL_NET_APP_DNS_QUERY_NO_RESPONSE (-159) /* DNS query failed, no response */ -#define SL_NET_APP_DNS_NO_SERVER (-161) /* No DNS server was specified */ -#define SL_NET_APP_DNS_PARAM_ERROR (-162) /* mDNS parameters error */ -#define SL_NET_APP_DNS_QUERY_FAILED (-163) /* DNS query failed; no DNS server sent an 'answer' */ -#define SL_NET_APP_DNS_INTERNAL_1 (-164) -#define SL_NET_APP_DNS_INTERNAL_2 (-165) -#define SL_NET_APP_DNS_MALFORMED_PACKET (-166) /* Improperly formed or corrupted DNS packet received */ -#define SL_NET_APP_DNS_INTERNAL_3 (-167) -#define SL_NET_APP_DNS_INTERNAL_4 (-168) -#define SL_NET_APP_DNS_INTERNAL_5 (-169) -#define SL_NET_APP_DNS_INTERNAL_6 (-170) -#define SL_NET_APP_DNS_INTERNAL_7 (-171) -#define SL_NET_APP_DNS_INTERNAL_8 (-172) -#define SL_NET_APP_DNS_INTERNAL_9 (-173) -#define SL_NET_APP_DNS_MISMATCHED_RESPONSE (-174) /* Server response type does not match the query request*/ -#define SL_NET_APP_DNS_INTERNAL_10 (-175) -#define SL_NET_APP_DNS_INTERNAL_11 (-176) -#define SL_NET_APP_DNS_NO_ANSWER (-177) /* No response for one-shot query */ -#define SL_NET_APP_DNS_NO_KNOWN_ANSWER (-178) /* No known answer for query */ -#define SL_NET_APP_DNS_NAME_MISMATCH (-179) /* Illegal service name according to the RFC */ -#define SL_NET_APP_DNS_NOT_STARTED (-180) /* mDNS is not running */ -#define SL_NET_APP_DNS_HOST_NAME_ERROR (-181) /* Host name error. Host name format is not allowed according to RFC 1033,1034,1035, 6763 */ -#define SL_NET_APP_DNS_NO_MORE_ENTRIES (-182) /* No more entries be found. */ - -#define SL_NET_APP_DNS_MAX_SERVICES_ERROR (-200) /* Maximum advertise services are already configured */ -#define SL_NET_APP_DNS_IDENTICAL_SERVICES_ERROR (-201) /* Trying to register a service that is already exists */ -#define SL_NET_APP_DNS_NOT_EXISTED_SERVICE_ERROR (-203) /* Trying to delete service that does not existed */ -#define SL_NET_APP_DNS_ERROR_SERVICE_NAME_ERROR (-204) /* Illegal service name according to the RFC */ -#define SL_NET_APP_DNS_RX_PACKET_ALLOCATION_ERROR (-205) /* Retry request */ -#define SL_NET_APP_DNS_BUFFER_SIZE_ERROR (-206) /* List size buffer is bigger than internally allowed in the NWP */ -#define SL_NET_APP_DNS_NET_APP_SET_ERROR (-207) /* Illegal length of one of the mDNS Set functions */ -#define SL_NET_APP_DNS_GET_SERVICE_LIST_FLAG_ERROR (-208) -#define SL_NET_APP_DNS_NO_CONFIGURATION_ERROR (-209) - -/* Set Dev name error codes (NETAPP_SET_GET_DEV_CONF_OPT_DEVICE_URN) */ -#define SL_ERROR_DEVICE_NAME_LEN_ERR (-117) -#define SL_ERROR_DEVICE_NAME_INVALID (-118) -/* Set domain name error codes (NETAPP_SET_GET_DEV_CONF_OPT_DOMAIN_NAME) */ -#define SL_ERROR_DOMAIN_NAME_LEN_ERR (-119) -#define SL_ERROR_DOMAIN_NAME_INVALID (-120) - -/********************************************************************************************************/ - -/* NetApp application IDs */ -#define SL_NET_APP_HTTP_SERVER_ID (1) -#define SL_NET_APP_DHCP_SERVER_ID (2) -#define SL_NET_APP_MDNS_ID (4) -#define SL_NET_APP_DNS_SERVER_ID (8) -#define SL_NET_APP_DEVICE_CONFIG_ID (16) -/* NetApp application set/get options */ -#define NETAPP_SET_DHCP_SRV_BASIC_OPT (0) -/* HTTP server set/get options */ -#define NETAPP_SET_GET_HTTP_OPT_PORT_NUMBER (0) -#define NETAPP_SET_GET_HTTP_OPT_AUTH_CHECK (1) -#define NETAPP_SET_GET_HTTP_OPT_AUTH_NAME (2) -#define NETAPP_SET_GET_HTTP_OPT_AUTH_PASSWORD (3) -#define NETAPP_SET_GET_HTTP_OPT_AUTH_REALM (4) -#define NETAPP_SET_GET_HTTP_OPT_ROM_PAGES_ACCESS (5) - -#define NETAPP_SET_GET_MDNS_CONT_QUERY_OPT (1) -#define NETAPP_SET_GET_MDNS_QEVETN_MASK_OPT (2) -#define NETAPP_SET_GET_MDNS_TIMING_PARAMS_OPT (3) - -/* DNS server set/get options */ -#define NETAPP_SET_GET_DNS_OPT_DOMAIN_NAME (0) - -/* Device Config set/get options */ -#define NETAPP_SET_GET_DEV_CONF_OPT_DEVICE_URN (0) -#define NETAPP_SET_GET_DEV_CONF_OPT_DOMAIN_NAME (1) - - -/*****************************************************************************/ -/* Structure/Enum declarations */ -/*****************************************************************************/ - -typedef struct -{ - _u32 PacketsSent; - _u32 PacketsReceived; - _u16 MinRoundTime; - _u16 MaxRoundTime; - _u16 AvgRoundTime; - _u32 TestTime; -}SlPingReport_t; - -typedef struct -{ - _u32 PingIntervalTime; /* delay between pings, in milliseconds */ - _u16 PingSize; /* ping packet size in bytes */ - _u16 PingRequestTimeout; /* timeout time for every ping in milliseconds */ - _u32 TotalNumberOfAttempts; /* max number of ping requests. 0 - forever */ - _u32 Flags; /* flag - 0 report only when finished, 1 - return response for every ping, 2 - stop after 1 successful ping. */ - _u32 Ip; /* IPv4 address or IPv6 first 4 bytes */ - _u32 Ip1OrPaadding; - _u32 Ip2OrPaadding; - _u32 Ip3OrPaadding; -}SlPingStartCommand_t; - -typedef struct _slHttpServerString_t -{ - _u8 len; - _u8 *data; -} slHttpServerString_t; - -typedef struct _slHttpServerData_t -{ - _u8 value_len; - _u8 name_len; - _u8 *token_value; - _u8 *token_name; -} slHttpServerData_t; - -typedef struct _slHttpServerPostData_t -{ - slHttpServerString_t action; - slHttpServerString_t token_name; - slHttpServerString_t token_value; -}slHttpServerPostData_t; - -typedef union -{ - slHttpServerString_t httpTokenName; /* SL_NETAPP_HTTPGETTOKENVALUE */ - slHttpServerPostData_t httpPostData; /* SL_NETAPP_HTTPPOSTTOKENVALUE */ -} SlHttpServerEventData_u; - -typedef union -{ - slHttpServerString_t token_value; -} SlHttpServerResponsedata_u; - -typedef struct -{ - _u32 Event; - SlHttpServerEventData_u EventData; -}SlHttpServerEvent_t; - -typedef struct -{ - _u32 Response; - SlHttpServerResponsedata_u ResponseData; -}SlHttpServerResponse_t; - - -typedef struct -{ - _u32 lease_time; - _u32 ipv4_addr_start; - _u32 ipv4_addr_last; -}SlNetAppDhcpServerBasicOpt_t; - -/*mDNS parameters*/ -typedef enum -{ - SL_NET_APP_FULL_SERVICE_WITH_TEXT_IPV4_TYPE = 1, - SL_NET_APP_FULL_SERVICE_IPV4_TYPE, - SL_NET_APP_SHORT_SERVICE_IPV4_TYPE - -} SlNetAppGetServiceListType_e; - -typedef struct -{ - _u32 service_ipv4; - _u16 service_port; - _u16 Reserved; -}SlNetAppGetShortServiceIpv4List_t; - -typedef struct -{ - _u32 service_ipv4; - _u16 service_port; - _u16 Reserved; - _u8 service_name[NETAPP_MAX_SERVICE_NAME_SIZE]; - _u8 service_host[NETAPP_MAX_SERVICE_HOST_NAME_SIZE]; -}SlNetAppGetFullServiceIpv4List_t; - -typedef struct -{ - _u32 service_ipv4; - _u16 service_port; - _u16 Reserved; - _u8 service_name[NETAPP_MAX_SERVICE_NAME_SIZE]; - _u8 service_host[NETAPP_MAX_SERVICE_HOST_NAME_SIZE]; - _u8 service_text[NETAPP_MAX_SERVICE_TEXT_SIZE]; -}SlNetAppGetFullServiceWithTextIpv4List_t; - -typedef struct -{ - /*The below parameters are used to configure the advertise times and interval - For example: - If: - Period is set to T - Repetitions are set to P - Telescopic factor is K=2 - The transmission shall be: - advertise P times - wait T - advertise P times - wait 4 * T - advertise P time - wait 16 * T ... (till max time reached / configuration changed / query issued) - */ - _u32 t; /* Number of ticks for the initial period. Default is 100 ticks for 1 second. */ - _u32 p; /* Number of repetitions. Default value is 1 */ - _u32 k; /* Telescopic factor. Default value is 2. */ - _u32 RetransInterval;/* Announcing retransmission interval */ - _u32 Maxinterval; /* Announcing max period interval */ - _u32 max_time; /* Announcing max time */ -}SlNetAppServiceAdvertiseTimingParameters_t; - -/*****************************************************************************/ -/* Types declarations */ -/*****************************************************************************/ -typedef void (*P_SL_DEV_PING_CALLBACK)(SlPingReport_t*); - -/*****************************************************************************/ -/* Function prototypes */ -/*****************************************************************************/ - - -/*! - \brief Starts a network application - - Gets and starts network application for the current WLAN mode - - \param[in] AppBitMap application bitmap, could be one or combination of the following: \n - - SL_NET_APP_HTTP_SERVER_ID - - SL_NET_APP_DHCP_SERVER_ID - - SL_NET_APP_MDNS_ID - - \return On error, negative number is returned - - \sa Stop one or more the above started applications using sl_NetAppStop - \note This command activates the application for the current WLAN mode (AP or STA) - \warning - \par Example: - \code - For example: Starting internal HTTP server + DHCP server: - sl_NetAppStart(SL_NET_APP_HTTP_SERVER_ID | SL_NET_APP_DHCP_SERVER_ID) - - \endcode -*/ -#if _SL_INCLUDE_FUNC(sl_NetAppStart) -_i16 sl_NetAppStart(const _u32 AppBitMap); -#endif -/*! - \brief Stops a network application - - Gets and stops network application for the current WLAN mode - - \param[in] AppBitMap application id, could be one of the following: \n - - SL_NET_APP_HTTP_SERVER_ID - - SL_NET_APP_DHCP_SERVER_ID - - SL_NET_APP_MDNS_ID - - \return On error, negative number is returned - - \sa - \note This command disables the application for the current active WLAN mode (AP or STA) - \warning - \par Example: - \code - - For example: Stopping internal HTTP server: - sl_NetAppStop(SL_NET_APP_HTTP_SERVER_ID); - - \endcode -*/ -#if _SL_INCLUDE_FUNC(sl_NetAppStop) -_i16 sl_NetAppStop(const _u32 AppBitMap); -#endif - -/*! - \brief Get host IP by name - - Obtain the IP Address of machine on network, by machine name. - - \param[in] hostname host name - \param[in] usNameLen name length - \param[out] out_ip_addr This parameter is filled in with - host IP address. In case that host name is not - resolved, out_ip_addr is zero. - \param[in] family protocol family - - \return On success, 0 is returned. - On error, negative is returned - SL_POOL_IS_EMPTY may be return in case there are no resources in the system - In this case try again later or increase MAX_CONCURRENT_ACTIONS - Possible DNS error codes: - - SL_NET_APP_DNS_QUERY_NO_RESPONSE - - SL_NET_APP_DNS_NO_SERVER - - SL_NET_APP_DNS_QUERY_FAILED - - SL_NET_APP_DNS_MALFORMED_PACKET - - SL_NET_APP_DNS_MISMATCHED_RESPONSE - - \sa - \note Only one sl_NetAppDnsGetHostByName can be handled at a time. - Calling this API while the same command is called from another thread, may result - in one of the two scenarios: - 1. The command will wait (internal) until the previous command finish, and then be executed. - 2. There are not enough resources and POOL_IS_EMPTY error will return. - In this case, MAX_CONCURRENT_ACTIONS can be increased (result in memory increase) or try - again later to issue the command. - \warning - In case an IP address in a string format is set as input, without any prefix (e.g. "1.2.3.4") the device will not - try to access the DNS and it will return the input address on the 'out_ip_addr' field - \par Example: - \code - _u32 DestinationIP; - sl_NetAppDnsGetHostByName("www.google.com", strlen("www.google.com"), &DestinationIP,SL_AF_INET); - - Addr.sin_family = SL_AF_INET; - Addr.sin_port = sl_Htons(80); - Addr.sin_addr.s_addr = sl_Htonl(DestinationIP); - AddrSize = sizeof(SlSockAddrIn_t); - SockID = sl_Socket(SL_AF_INET,SL_SOCK_STREAM, 0); - \endcode -*/ -#if _SL_INCLUDE_FUNC(sl_NetAppDnsGetHostByName) -_i16 sl_NetAppDnsGetHostByName(_i8 * hostname,const _u16 usNameLen, _u32* out_ip_addr,const _u8 family ); -#endif - -/*! - \brief Return service attributes like IP address, port and text according to service name - \par - The user sets a service name Full/Part (see example below), and should get: - - IP of service - - The port of service - - The text of service - - Hence it can make a connection to the specific service and use it. - It is similar to get host by name method. - It is done by a single shot query with PTR type on the service name. - The command that is sent is from constant parameters and variables parameters. - - \param[in] pService Service name can be full or partial. \n - Example for full service name: - 1. PC1._ipp._tcp.local - 2. PC2_server._ftp._tcp.local \n - . - Example for partial service name: - 1. _ipp._tcp.local - 2. _ftp._tcp.local - - \param[in] ServiceLen The length of the service name (in_pService). - \param[in] Family IPv4 or IPv6 (SL_AF_INET , SL_AF_INET6). - \param[out] pAddr Contains the IP address of the service. - \param[out] pPort Contains the port of the service. - \param[out] pTextLen Has 2 options. One as Input field and the other one as output: - - Input: \n - Contains the max length of the text that the user wants to get.\n - It means that if the text len of service is bigger that its value than - the text is cut to inout_TextLen value. - - Output: \n - Contain the length of the text that is returned. Can be full text or part of the text (see above). - - \param[out] pOut_pText Contains the text of the service full or partial - - \return On success, zero is returned - SL_POOL_IS_EMPTY may be return in case there are no resources in the system - In this case try again later or increase MAX_CONCURRENT_ACTIONS - In case No service is found error SL_NET_APP_DNS_NO_ANSWER will be returned - - \note The returns attributes belongs to the first service found. - There may be other services with the same service name that will response to the query. - The results of these responses are saved in the peer cache of the Device and should be read by another API. - - Only one sl_NetAppDnsGetHostByService can be handled at a time. - Calling this API while the same command is called from another thread, may result - in one of the two scenarios: - 1. The command will wait (internal) until the previous command finish, and then be executed. - 2. There are not enough resources and SL_POOL_IS_EMPTY error will return. - In this case, MAX_CONCURRENT_ACTIONS can be increased (result in memory increase) or try - again later to issue the command. - - \warning Text length can be 120 bytes only -*/ -#if _SL_INCLUDE_FUNC(sl_NetAppDnsGetHostByService) -_i32 sl_NetAppDnsGetHostByService(_i8 *pServiceName, /* string containing all (or only part): name + subtype + service */ - const _u8 ServiceLen, - const _u8 Family, /* 4-IPv4 , 16-IPv6 */ - _u32 pAddr[], - _u32 *pPort, - _u16 *pTextLen, /* in: max len , out: actual len */ - _i8 *pText - ); - -#endif - -/*! - \brief Get service List - Insert into out pBuffer a list of peer's services that are the NWP. - The list is in a form of service struct. The user should chose the type - of the service struct like: - - Full service parameters with text. - - Full service parameters. - - Short service parameters (port and IP only) especially for tiny hosts. - - The different types of struct are made to give the - Possibility to save memory in the host - - - The user also chose how many max services to get and start point index - NWP peer cache. - For example: - 1. Get max of 3 full services from index 0.Up to 3 full services - from index 0 are inserted into pBuffer (services that are in indexes 0,1,2). - 2. Get max of 4 full services from index 3.Up to 4 full services - from index 3 are inserted into pBuffer (services that are in indexes 3,4,5,6). - 3. Get max of 2 int services from index 6.Up to 2 int services - from index 6 are inserted into pBuffer (services that are in indexes 6,7). - - See below - command parameters. - - \param[in] indexOffset - The start index in the peer cache that from it the first service is returned. - \param[in] MaxServiceCount - The Max services that can be returned if existed or if not exceed the max index - in the peer cache - \param[in] Flags - an ENUM number that means which service struct to use (means which types of service to fill) - - use SlNetAppGetFullServiceWithTextIpv4List_t - - use SlNetAppGetFullServiceIpv4List_t - - use SlNetAppGetShortServiceIpv4List_t - - \param[out] Buffer - The Services are inserted into this buffer. In the struct form according to the bit that is set in the Flags - input parameter. - - \return ServiceFoundCount - The number of the services that were inserted into the buffer. zero means no service is found - negative number means an error - \sa sl_NetAppMDNSRegisterService - \note - \warning - if the out pBuffer size is bigger than an RX packet(1480), than - an error is returned because there - is no place in the RX packet. - The size is a multiply of MaxServiceCount and size of service struct(that is set - according to flag value). -*/ - -#if _SL_INCLUDE_FUNC(sl_NetAppGetServiceList) -_i16 sl_NetAppGetServiceList(const _u8 IndexOffest, - const _u8 MaxServiceCount, - const _u8 Flags, - _i8 *pBuffer, - const _u32 RxBufferLength - ); - -#endif - -/*! - \brief Unregister mDNS service - This function deletes the mDNS service from the mDNS package and the database. - - The mDNS service that is to be unregistered is a service that the application no longer wishes to provide. \n - The service name should be the full service name according to RFC - of the DNS-SD - meaning the value in name field in the SRV answer. - - Examples for service names: - 1. PC1._ipp._tcp.local - 2. PC2_server._ftp._tcp.local - - \param[in] pServiceName Full service name. \n - Example for service name: - 1. PC1._ipp._tcp.local - 2. PC2_server._ftp._tcp.local - \param[in] ServiceLen The length of the service. - \return On success, zero is returned - \sa sl_NetAppMDNSRegisterService - \note - \warning - The size of the service length should be smaller than 255. -*/ -#if _SL_INCLUDE_FUNC(sl_NetAppMDNSUnRegisterService) -_i16 sl_NetAppMDNSUnRegisterService(const _i8 *pServiceName,const _u8 ServiceNameLen); -#endif - -/*! - \brief Register a new mDNS service - \par - This function registers a new mDNS service to the mDNS package and the DB. - - This registered service is a service offered by the application. - The service name should be full service name according to RFC - of the DNS-SD - meaning the value in name field in the SRV answer. - Example for service name: - 1. PC1._ipp._tcp.local - 2. PC2_server._ftp._tcp.local - - If the option is_unique is set, mDNS probes the service name to make sure - it is unique before starting to announce the service on the network. - Instance is the instance portion of the service name. - - \param[in] ServiceLen The length of the service. - \param[in] TextLen The length of the service should be smaller than 64. - \param[in] port The port on this target host port. - \param[in] TTL The TTL of the service - \param[in] Options bitwise parameters: \n - - bit 0 - service is unique (means that the service needs to be unique) - - bit 31 - for internal use if the service should be added or deleted (set means ADD). - - bit 1-30 for future. - - \param[in] pServiceName The service name. - Example for service name: \n - 1. PC1._ipp._tcp.local - 2. PC2_server._ftp._tcp.local - - \param[in] pText The description of the service. - should be as mentioned in the RFC - (according to type of the service IPP,FTP...) - - \return On success, zero is returned - Possible error codes: - - Maximum advertise services are already configured. - Delete another existed service that is registered and then register again the new service - - Trying to register a service that is already exists - - Trying to delete service that does not existed - - Illegal service name according to the RFC - - Retry request - - Illegal length of one of the mDNS Set functions - - mDNS is not operational as the device has no IP.Connect the device to an AP to get an IP address. - - mDNS parameters error - - mDNS internal cache error - - mDNS internal error - - Adding a service is not allowed as it is already exist (duplicate service) - - mDNS is not running - - Host name error. Host name format is not allowed according to RFC 1033,1034,1035, 6763 - - List size buffer is bigger than internally allowed in the NWP (API get service list), - change the APIs’ parameters to decrease the size of the list - - - \sa sl_NetAppMDNSUnRegisterService - - \warning 1) Temporary - there is an allocation on stack of internal buffer. - Its size is NETAPP_MDNS_MAX_SERVICE_NAME_AND_TEXT_LENGTH. \n - It means that the sum of the text length and service name length cannot be bigger than - NETAPP_MDNS_MAX_SERVICE_NAME_AND_TEXT_LENGTH.\n - If it is - An error is returned. \n - 2) According to now from certain constraints the variables parameters are set in the - attribute part (contain constant parameters) -*/ -#if _SL_INCLUDE_FUNC(sl_NetAppMDNSRegisterService) -_i16 sl_NetAppMDNSRegisterService( const _i8* pServiceName, - const _u8 ServiceNameLen, - const _i8* pText, - const _u8 TextLen, - const _u16 Port, - const _u32 TTL, - _u32 Options); -#endif - -/*! - \brief send ICMP ECHO_REQUEST to network hosts - - Ping uses the ICMP protocol's mandatory ECHO_REQUEST - - \param[in] pPingParams Pointer to the ping request structure: \n - - if flags parameter is set to 0, ping will report back once all requested pings are done (as defined by TotalNumberOfAttempts). \n - - if flags parameter is set to 1, ping will report back after every ping, for TotalNumberOfAttempts. - - if flags parameter is set to 2, ping will stop after the first successful ping, and report back for the successful ping, as well as any preceding failed ones. - For stopping an ongoing ping activity, set parameters IP address to 0 - - \param[in] family SL_AF_INET or SL_AF_INET6 - \param[out] pReport Ping pReport - \param[out] pCallback Callback function upon completion. - If callback is NULL, the API is blocked until data arrives - - - \return On success, zero is returned. On error, -1 is returned - SL_POOL_IS_EMPTY may be return in case there are no resources in the system - In this case try again later or increase MAX_CONCURRENT_ACTIONS - - \sa sl_NetAppPingReport - \note Only one sl_NetAppPingStart can be handled at a time. - Calling this API while the same command is called from another thread, may result - in one of the two scenarios: - 1. The command will wait (internal) until the previous command finish, and then be executed. - 2. There are not enough resources and SL_POOL_IS_EMPTY error will return. - In this case, MAX_CONCURRENT_ACTIONS can be increased (result in memory increase) or try - again later to issue the command. - \warning - \par Example: - \code - - An example of sending 20 ping requests and reporting results to a callback routine when - all requests are sent: - - // callback routine - void pingRes(SlPingReport_t* pReport) - { - // handle ping results - } - - // ping activation - void PingTest() - { - SlPingReport_t report; - SlPingStartCommand_t pingCommand; - - pingCommand.Ip = SL_IPV4_VAL(10,1,1,200); // destination IP address is 10.1.1.200 - pingCommand.PingSize = 150; // size of ping, in bytes - pingCommand.PingIntervalTime = 100; // delay between pings, in milliseconds - pingCommand.PingRequestTimeout = 1000; // timeout for every ping in milliseconds - pingCommand.TotalNumberOfAttempts = 20; // max number of ping requests. 0 - forever - pingCommand.Flags = 0; // report only when finished - - sl_NetAppPingStart( &pingCommand, SL_AF_INET, &report, pingRes ) ; - } - - \endcode -*/ -#if _SL_INCLUDE_FUNC(sl_NetAppPingStart) -_i16 sl_NetAppPingStart(const SlPingStartCommand_t* pPingParams,const _u8 family,SlPingReport_t *pReport,const P_SL_DEV_PING_CALLBACK pPingCallback); -#endif - -/*! - \brief Internal function for setting network application configurations - - \return On success, zero is returned. On error, -1 is - returned - - \param[in] AppId Application id, could be one of the following: \n - - SL_NET_APP_HTTP_SERVER_ID - - SL_NET_APP_DHCP_SERVER_ID - - SL_NET_APP_MDNS_ID - - SL_NET_APP_DEVICE_CONFIG_ID - - \param[in] SetOptions set option, could be one of the following: \n - - SL_NET_APP_DHCP_SERVER_ID - - NETAPP_SET_DHCP_SRV_BASIC_OPT - - SL_NET_APP_HTTP_SERVER_ID - - NETAPP_SET_GET_HTTP_OPT_PORT_NUMBER - - NETAPP_SET_GET_HTTP_OPT_AUTH_CHECK - - NETAPP_SET_GET_HTTP_OPT_AUTH_NAME - - NETAPP_SET_GET_HTTP_OPT_AUTH_PASSWORD - - NETAPP_SET_GET_HTTP_OPT_AUTH_REALM - - NETAPP_SET_GET_HTTP_OPT_ROM_PAGES_ACCESS - - SL_NET_APP_MDNS_ID - - NETAPP_SET_GET_MDNS_CONT_QUERY_OPT - - NETAPP_SET_GET_MDNS_QEVETN_MASK_OPT - - NETAPP_SET_GET_MDNS_TIMING_PARAMS_OPT - - SL_NET_APP_DEVICE_CONFIG_ID - - NETAPP_SET_GET_DEV_CONF_OPT_DEVICE_URN - - NETAPP_SET_GET_DEV_CONF_OPT_DOMAIN_NAME - - - \param[in] OptionLen option structure length - - \param[in] pOptionValues pointer to the option structure - \sa - \note - \warning - \par - \code - Set DHCP Server (AP mode) parameters example: - - SlNetAppDhcpServerBasicOpt_t dhcpParams; - _u8 outLen = sizeof(SlNetAppDhcpServerBasicOpt_t); - dhcpParams.lease_time = 4096; // lease time (in seconds) of the IP Address - dhcpParams.ipv4_addr_start = SL_IPV4_VAL(192,168,1,10); // first IP Address for allocation. IP Address should be set as Hex number - i.e. 0A0B0C01 for (10.11.12.1) - dhcpParams.ipv4_addr_last = SL_IPV4_VAL(192,168,1,16); // last IP Address for allocation. IP Address should be set as Hex number - i.e. 0A0B0C01 for (10.11.12.1) - sl_NetAppStop(SL_NET_APP_DHCP_SERVER_ID); // Stop DHCP server before settings - sl_NetAppSet(SL_NET_APP_DHCP_SERVER_ID, NETAPP_SET_DHCP_SRV_BASIC_OPT, outLen, (_u8* )&dhcpParams); // set parameters - sl_NetAppStart(SL_NET_APP_DHCP_SERVER_ID); // Start DHCP server with new settings - \endcode - \code - Set Device URN name example: - - Device name, maximum length of 33 characters - Device name affects URN name, own SSID name in AP mode, and WPS file "device name" in WPS I.E (STA-WPS / P2P) - In case no device URN name set, the default name is "mysimplelink" - Allowed characters in device name are: 'a - z' , 'A - Z' , '0-9' and '-' - - _u8 *my_device = "MY-SIMPLELINK-DEV"; - sl_NetAppSet (SL_NET_APP_DEVICE_CONFIG_ID, NETAPP_SET_GET_DEV_CONF_OPT_DEVICE_URN, strlen(my_device), (_u8 *) my_device); - \endcode - -*/ -#if _SL_INCLUDE_FUNC(sl_NetAppSet) -_i32 sl_NetAppSet(const _u8 AppId ,const _u8 Option,const _u8 OptionLen,const _u8 *pOptionValue); -#endif - -/*! - \brief Internal function for getting network applications configurations - - \return On success, zero is returned. On error, -1 is - returned - - \param[in] AppId Application id, could be one of the following: \n - - SL_NET_APP_HTTP_SERVER_ID - - SL_NET_APP_DHCP_SERVER_ID - - SL_NET_APP_MDNS_ID - - SL_NET_APP_DEVICE_CONFIG_ID - - \param[in] SetOptions set option, could be one of the following: \n - - SL_NET_APP_DHCP_SERVER_ID - - NETAPP_SET_DHCP_SRV_BASIC_OPT - - SL_NET_APP_HTTP_SERVER_ID - - NETAPP_SET_GET_HTTP_OPT_PORT_NUMBER - - NETAPP_SET_GET_HTTP_OPT_AUTH_CHECK - - NETAPP_SET_GET_HTTP_OPT_AUTH_NAME - - NETAPP_SET_GET_HTTP_OPT_AUTH_PASSWORD - - NETAPP_SET_GET_HTTP_OPT_AUTH_REALM - - NETAPP_SET_GET_HTTP_OPT_ROM_PAGES_ACCESS - - SL_NET_APP_MDNS_ID - - NETAPP_SET_GET_MDNS_CONT_QUERY_OPT - - NETAPP_SET_GET_MDNS_QEVETN_MASK_OPT - - NETAPP_SET_GET_MDNS_TIMING_PARAMS_OPT - - SL_NET_APP_DEVICE_CONFIG_ID - - NETAPP_SET_GET_DEV_CONF_OPT_DEVICE_URN - - NETAPP_SET_GET_DEV_CONF_OPT_DOMAIN_NAME - - - \param[in] OptionLen The length of the allocated memory as input, when the - function complete, the value of this parameter would be - the len that actually read from the device. - If the device return length that is longer from the input - value, the function will cut the end of the returned structure - and will return ESMALLBUF - - \param[out] pValues pointer to the option structure which will be filled with the response from the device - - \sa - \note - \warning - \par - \code - Get DHCP Server parameters example: - - SlNetAppDhcpServerBasicOpt_t dhcpParams; - _u8 outLen = sizeof(SlNetAppDhcpServerBasicOpt_t); - sl_NetAppGet(SL_NET_APP_DHCP_SERVER_ID, NETAPP_SET_DHCP_SRV_BASIC_OPT, &outLen, (_u8* )&dhcpParams); - - printf("DHCP Start IP %d.%d.%d.%d End IP %d.%d.%d.%d Lease time seconds %d\n", - SL_IPV4_BYTE(dhcpParams.ipv4_addr_start,3),SL_IPV4_BYTE(dhcpParams.ipv4_addr_start,2), - SL_IPV4_BYTE(dhcpParams.ipv4_addr_start,1),SL_IPV4_BYTE(dhcpParams.ipv4_addr_start,0), - SL_IPV4_BYTE(dhcpParams.ipv4_addr_last,3),SL_IPV4_BYTE(dhcpParams.ipv4_addr_last,2), - SL_IPV4_BYTE(dhcpParams.ipv4_addr_last,1),SL_IPV4_BYTE(dhcpParams.ipv4_addr_last,0), - dhcpParams.lease_time); - \endcode - \code - Get Device URN name example: - Maximum length of 33 characters of device name. - Device name affects URN name, own SSID name in AP mode, and WPS file "device name" in WPS I.E (STA-WPS / P2P) - in case no device URN name set, the default name is "mysimplelink" - - _u8 my_device_name[35]; - sl_NetAppGet (SL_NET_APP_DEVICE_CONFIG_ID, NETAPP_SET_GET_DEV_CONF_OPT_DEVICE_URN, strlen(my_device_name), (_u8 *)my_device_name); - \endcode -*/ -#if _SL_INCLUDE_FUNC(sl_NetAppGet) -_i32 sl_NetAppGet(const _u8 AppId,const _u8 Option,_u8 *pOptionLen, _u8 *pOptionValue); -#endif - - - -/*! - - Close the Doxygen group. - @} - - */ - - -#ifdef __cplusplus -} -#endif /* __cplusplus */ - -#endif /* __NETAPP_H__ */ - diff --git a/drivers/cc3100/inc/netcfg.h b/drivers/cc3100/inc/netcfg.h deleted file mode 100644 index cc8cfbcaaf..0000000000 --- a/drivers/cc3100/inc/netcfg.h +++ /dev/null @@ -1,283 +0,0 @@ -/* - * netcfg.h - CC31xx/CC32xx Host Driver Implementation - * - * Copyright (C) 2014 Texas Instruments Incorporated - http://www.ti.com/ - * - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * - * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the - * distribution. - * - * Neither the name of Texas Instruments Incorporated nor the names of - * its contributors may be used to endorse or promote products derived - * from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * -*/ - -/*****************************************************************************/ -/* Include files */ -/*****************************************************************************/ -#include "simplelink.h" - - -#ifndef __NETCFG_H__ -#define __NETCFG_H__ - - -#ifdef __cplusplus -extern "C" { -#endif - - - -/*! - - \addtogroup netcfg - @{ - -*/ - - -/*****************************************************************************/ -/* Macro declarations */ -/*****************************************************************************/ - -#define SL_MAC_ADDR_LEN (6) -#define SL_IPV4_VAL(add_3,add_2,add_1,add_0) ((((_u32)add_3 << 24) & 0xFF000000) | (((_u32)add_2 << 16) & 0xFF0000) | (((_u32)add_1 << 8) & 0xFF00) | ((_u32)add_0 & 0xFF) ) -#define SL_IPV4_BYTE(val,index) ( (val >> (index*8)) & 0xFF ) - -#define IPCONFIG_MODE_DISABLE_IPV4 (0) -#define IPCONFIG_MODE_ENABLE_IPV4 (1) - -/*****************************************************************************/ -/* Structure/Enum declarations */ -/*****************************************************************************/ -typedef enum -{ - SL_MAC_ADDRESS_SET = 1, - SL_MAC_ADDRESS_GET = 2, - SL_IPV4_STA_P2P_CL_GET_INFO = 3, - SL_IPV4_STA_P2P_CL_DHCP_ENABLE = 4, - SL_IPV4_STA_P2P_CL_STATIC_ENABLE = 5, - SL_IPV4_AP_P2P_GO_GET_INFO = 6, - SL_IPV4_AP_P2P_GO_STATIC_ENABLE = 7, - SL_SET_HOST_RX_AGGR = 8, - MAX_SETTINGS = 0xFF -}Sl_NetCfg_e; - - -typedef struct -{ - _u32 ipV4; - _u32 ipV4Mask; - _u32 ipV4Gateway; - _u32 ipV4DnsServer; -}SlNetCfgIpV4Args_t; - - -/*****************************************************************************/ -/* Function prototypes */ -/*****************************************************************************/ - -/*! - \brief Internal function for setting network configurations - - \return On success, zero is returned. On error, -1 is - returned - - \param[in] ConfigId configuration id - \param[in] ConfigOpt configurations option - \param[in] ConfigLen configurations len - \param[in] pValues configurations values - - \sa - \note - \warning - - \par Examples: - \code - SL_MAC_ADDRESS_SET: - - Setting MAC address to the Device. - The new MAC address will override the default MAC address and it be saved in the FileSystem. - Requires restarting the device for updating this setting. - - _u8 MAC_Address[6]; - MAC_Address[0] = 0x8; - MAC_Address[1] = 0x0; - MAC_Address[2] = 0x28; - MAC_Address[3] = 0x22; - MAC_Address[4] = 0x69; - MAC_Address[5] = 0x31; - sl_NetCfgSet(SL_MAC_ADDRESS_SET,1,SL_MAC_ADDR_LEN,(_u8 *)newMacAddress); - sl_Stop(0); - sl_Start(NULL,NULL,NULL); - \endcode - - \code - SL_IPV4_STA_P2P_CL_STATIC_ENABLE: - - Setting a static IP address to the device working in STA mode or P2P client. - The IP address will be stored in the FileSystem. - In order to disable the static IP and get the address assigned from DHCP one should use SL_STA_P2P_CL_IPV4_DHCP_SET - - SlNetCfgIpV4Args_t ipV4; - ipV4.ipV4 = (_u32)SL_IPV4_VAL(10,1,1,201); // _u32 IP address - ipV4.ipV4Mask = (_u32)SL_IPV4_VAL(255,255,255,0); // _u32 Subnet mask for this STA/P2P - ipV4.ipV4Gateway = (_u32)SL_IPV4_VAL(10,1,1,1); // _u32 Default gateway address - ipV4.ipV4DnsServer = (_u32)SL_IPV4_VAL(8,16,32,64); // _u32 DNS server address - - sl_NetCfgSet(SL_IPV4_STA_P2P_CL_STATIC_ENABLE,IPCONFIG_MODE_ENABLE_IPV4,sizeof(SlNetCfgIpV4Args_t),(_u8 *)&ipV4); - sl_Stop(0); - sl_Start(NULL,NULL,NULL); - \endcode - - \code - SL_IPV4_STA_P2P_CL_DHCP_ENABLE: - - Setting IP address by DHCP to FileSystem using WLAN sta mode or P2P client. - This should be done once if using Serial Flash. - This is the system's default mode for acquiring an IP address after WLAN connection. - _u8 val = 1; - sl_NetCfgSet(SL_IPV4_STA_P2P_CL_DHCP_ENABLE,IPCONFIG_MODE_ENABLE_IPV4,1,&val); - sl_Stop(0); - sl_Start(NULL,NULL,NULL); - \endcode - - \code - SL_IPV4_AP_P2P_GO_STATIC_ENABLE: - - Setting a static IP address to the device working in AP mode or P2P go. - The IP address will be stored in the FileSystem. Requires restart. - - SlNetCfgIpV4Args_t ipV4; - ipV4.ipV4 = (_u32)SL_IPV4_VAL(10,1,1,201); // _u32 IP address - ipV4.ipV4Mask = (_u32)SL_IPV4_VAL(255,255,255,0); // _u32 Subnet mask for this AP/P2P - ipV4.ipV4Gateway = (_u32)SL_IPV4_VAL(10,1,1,1); // _u32 Default gateway address - ipV4.ipV4DnsServer = (_u32)SL_IPV4_VAL(8,16,32,64); // _u32 DNS server address - - sl_NetCfgSet(SL_IPV4_AP_P2P_GO_STATIC_ENABLE,IPCONFIG_MODE_ENABLE_IPV4,sizeof(SlNetCfgIpV4Args_t),(_u8 *)&ipV4); - sl_Stop(0); - sl_Start(NULL,NULL,NULL); - \endcode - - -*/ -#if _SL_INCLUDE_FUNC(sl_NetCfgSet) -_i32 sl_NetCfgSet(const _u8 ConfigId,const _u8 ConfigOpt,const _u8 ConfigLen,const _u8 *pValues); -#endif - - -/*! - \brief Internal function for getting network configurations - - \return On success, zero is returned. On error, -1 is - returned - - \param[in] ConfigId configuration id - - \param[out] pConfigOpt Get configurations option - - \param[out] pConfigLen The length of the allocated memory as input, when the - function complete, the value of this parameter would be - the len that actually read from the device.\n - If the device return length that is longer from the input - value, the function will cut the end of the returned structure - and will return ESMALLBUF - - \param[out] pValues - get configurations values - - \sa - \note - \warning - \par Examples: - \code - SL_MAC_ADDRESS_GET: - - Get the device MAC address. - The returned MAC address is taken from FileSystem first. If the MAC address was not set by SL_MAC_ADDRESS_SET, the default MAC address - is retrieved from HW. - - _u8 macAddressVal[SL_MAC_ADDR_LEN]; - _u8 macAddressLen = SL_MAC_ADDR_LEN; - sl_NetCfgGet(SL_MAC_ADDRESS_GET,NULL,&macAddressLen,(_u8 *)macAddressVal); - - \endcode - - \code - SL_IPV4_STA_P2P_CL_GET_INFO: - - Get IP address from WLAN station or P2P client. A DHCP flag is returned to indicate if the IP address is static or from DHCP. - - _u8 len = sizeof(SlNetCfgIpV4Args_t); - _u8 dhcpIsOn = 0; - SlNetCfgIpV4Args_t ipV4 = {0}; - sl_NetCfgGet(SL_IPV4_STA_P2P_CL_GET_INFO,&dhcpIsOn,&len,(_u8 *)&ipV4); - - printf("DHCP is %s IP %d.%d.%d.%d MASK %d.%d.%d.%d GW %d.%d.%d.%d DNS %d.%d.%d.%d\n", - (dhcpIsOn > 0) ? "ON" : "OFF", - SL_IPV4_BYTE(ipV4.ipV4,3),SL_IPV4_BYTE(ipV4.ipV4,2),SL_IPV4_BYTE(ipV4.ipV4,1),SL_IPV4_BYTE(ipV4.ipV4,0), - SL_IPV4_BYTE(ipV4.ipV4Mask,3),SL_IPV4_BYTE(ipV4.ipV4Mask,2),SL_IPV4_BYTE(ipV4.ipV4Mask,1),SL_IPV4_BYTE(ipV4.ipV4Mask,0), - SL_IPV4_BYTE(ipV4.ipV4Gateway,3),SL_IPV4_BYTE(ipV4.ipV4Gateway,2),SL_IPV4_BYTE(ipV4.ipV4Gateway,1),SL_IPV4_BYTE(ipV4.ipV4Gateway,0), - SL_IPV4_BYTE(ipV4.ipV4DnsServer,3),SL_IPV4_BYTE(ipV4.ipV4DnsServer,2),SL_IPV4_BYTE(ipV4.ipV4DnsServer,1),SL_IPV4_BYTE(ipV4.ipV4DnsServer,0)); - - \endcode - - \code - SL_IPV4_AP_P2P_GO_GET_INFO: - - Get static IP address for AP or P2P go. - - _u8 len = sizeof(SlNetCfgIpV4Args_t); - _u8 dhcpIsOn = 0; // this flag is meaningless on AP/P2P go. - SlNetCfgIpV4Args_t ipV4 = {0}; - sl_NetCfgGet(SL_IPV4_AP_P2P_GO_GET_INFO,&dhcpIsOn,&len,(_u8 *)&ipV4); - - printf("IP %d.%d.%d.%d MASK %d.%d.%d.%d GW %d.%d.%d.%d DNS %d.%d.%d.%d\n", - SL_IPV4_BYTE(ipV4.ipV4,3),SL_IPV4_BYTE(ipV4.ipV4,2),SL_IPV4_BYTE(ipV4.ipV4,1),SL_IPV4_BYTE(ipV4.ipV4,0), - SL_IPV4_BYTE(ipV4.ipV4Mask,3),SL_IPV4_BYTE(ipV4.ipV4Mask,2),SL_IPV4_BYTE(ipV4.ipV4Mask,1),SL_IPV4_BYTE(ipV4.ipV4Mask,0), - SL_IPV4_BYTE(ipV4.ipV4Gateway,3),SL_IPV4_BYTE(ipV4.ipV4Gateway,2),SL_IPV4_BYTE(ipV4.ipV4Gateway,1),SL_IPV4_BYTE(ipV4.ipV4Gateway,0), - SL_IPV4_BYTE(ipV4.ipV4DnsServer,3),SL_IPV4_BYTE(ipV4.ipV4DnsServer,2),SL_IPV4_BYTE(ipV4.ipV4DnsServer,1),SL_IPV4_BYTE(ipV4.ipV4DnsServer,0)); - - \endcode - - -*/ -#if _SL_INCLUDE_FUNC(sl_NetCfgGet) -_i32 sl_NetCfgGet(const _u8 ConfigId ,_u8 *pConfigOpt, _u8 *pConfigLen, _u8 *pValues); -#endif - -/*! - - Close the Doxygen group. - @} - - */ - - -#ifdef __cplusplus -} -#endif /* __cplusplus */ - -#endif /* __NETCFG_H__ */ - diff --git a/drivers/cc3100/inc/nonos.h b/drivers/cc3100/inc/nonos.h deleted file mode 100644 index 568c0ff26e..0000000000 --- a/drivers/cc3100/inc/nonos.h +++ /dev/null @@ -1,325 +0,0 @@ -/* - * nonos.h - CC31xx/CC32xx Host Driver Implementation - * - * Copyright (C) 2014 Texas Instruments Incorporated - http://www.ti.com/ - * - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * - * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the - * distribution. - * - * Neither the name of Texas Instruments Incorporated nor the names of - * its contributors may be used to endorse or promote products derived - * from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * -*/ - -#ifndef __NONOS_H__ -#define __NONOS_H__ - -#ifdef __cplusplus -extern "C" { -#endif - - -#ifndef SL_PLATFORM_MULTI_THREADED - -/* This function call the user defined function, if defined, from the sync wait loop */ -/* The use case of this function is to allow nonos system to call a user function to put the device into sleep */ -/* The wake up should be activated after getting an interrupt from the device to Host */ -/* The user function must return without blocking to prevent a delay on the event handling */ -/* -#define _SlSyncWaitLoopCallback UserSleepFunction -*/ - - - -#define NONOS_WAIT_FOREVER 0xFF -#define NONOS_NO_WAIT 0x00 - -#define NONOS_RET_OK (0) -#define NONOS_RET_ERR (0xFF) -#define OSI_OK NONOS_RET_OK - -#define __NON_OS_SYNC_OBJ_CLEAR_VALUE 0x11 -#define __NON_OS_SYNC_OBJ_SIGNAL_VALUE 0x22 -#define __NON_OS_LOCK_OBJ_UNLOCK_VALUE 0x33 -#define __NON_OS_LOCK_OBJ_LOCK_VALUE 0x44 - -/*! - \brief type definition for the return values of this adaptation layer -*/ -typedef _i8 _SlNonOsRetVal_t; - -/*! - \brief type definition for a time value -*/ -typedef _u8 _SlNonOsTime_t; - -/*! - \brief type definition for a sync object container - - Sync object is object used to synchronize between two threads or thread and interrupt handler. - One thread is waiting on the object and the other thread send a signal, which then - release the waiting thread. - The signal must be able to be sent from interrupt context. - This object is generally implemented by binary semaphore or events. -*/ -typedef _u8 _SlNonOsSemObj_t; - - -#define _SlTime_t _SlNonOsTime_t - -#define _SlSyncObj_t _SlNonOsSemObj_t - -#define _SlLockObj_t _SlNonOsSemObj_t - -#define SL_OS_WAIT_FOREVER NONOS_WAIT_FOREVER - -#define SL_OS_RET_CODE_OK NONOS_RET_OK - -#define SL_OS_NO_WAIT NONOS_NO_WAIT - - - - - -/*! - \brief This function creates a sync object - - The sync object is used for synchronization between different thread or ISR and - a thread. - - \param pSyncObj - pointer to the sync object control block - - \return upon successful creation the function return 0 - Otherwise, a negative value indicating the error code shall be returned - \note - \warning -*/ -#define _SlNonOsSyncObjCreate(pSyncObj) _SlNonOsSemSet(pSyncObj,__NON_OS_SYNC_OBJ_CLEAR_VALUE) - -/*! - \brief This function deletes a sync object - - \param pSyncObj - pointer to the sync object control block - - \return upon successful deletion the function should return 0 - Otherwise, a negative value indicating the error code shall be returned - \note - \warning -*/ -#define _SlNonOsSyncObjDelete(pSyncObj) _SlNonOsSemSet(pSyncObj,0) - -/*! - \brief This function generates a sync signal for the object. - - All suspended threads waiting on this sync object are resumed - - \param pSyncObj - pointer to the sync object control block - - \return upon successful signaling the function should return 0 - Otherwise, a negative value indicating the error code shall be returned - \note the function could be called from ISR context - \warning -*/ -#define _SlNonOsSyncObjSignal(pSyncObj) _SlNonOsSemSet(pSyncObj,__NON_OS_SYNC_OBJ_SIGNAL_VALUE) - -/*! - \brief This function waits for a sync signal of the specific sync object - - \param pSyncObj - pointer to the sync object control block - \param Timeout - numeric value specifies the maximum number of mSec to - stay suspended while waiting for the sync signal - Currently, the simple link driver uses only two values: - - NONOS_WAIT_FOREVER - - NONOS_NO_WAIT - - \return upon successful reception of the signal within the timeout window return 0 - Otherwise, a negative value indicating the error code shall be returned - \note - \warning -*/ -#define _SlNonOsSyncObjWait(pSyncObj , Timeout) _SlNonOsSemGet(pSyncObj,__NON_OS_SYNC_OBJ_SIGNAL_VALUE,__NON_OS_SYNC_OBJ_CLEAR_VALUE,Timeout) - -/*! - \brief This function clears a sync object - - \param pSyncObj - pointer to the sync object control block - - \return upon successful clearing the function should return 0 - Otherwise, a negative value indicating the error code shall be returned - \note - \warning -*/ -#define _SlNonOsSyncObjClear(pSyncObj) _SlNonOsSemSet(pSyncObj,__NON_OS_SYNC_OBJ_CLEAR_VALUE) - -/*! - \brief This function creates a locking object. - - The locking object is used for protecting a shared resources between different - threads. - - \param pLockObj - pointer to the locking object control block - - \return upon successful creation the function should return 0 - Otherwise, a negative value indicating the error code shall be returned - \note - \warning -*/ -#define _SlNonOsLockObjCreate(pLockObj) _SlNonOsSemSet(pLockObj,__NON_OS_LOCK_OBJ_UNLOCK_VALUE) - -/*! - \brief This function deletes a locking object. - - \param pLockObj - pointer to the locking object control block - - \return upon successful deletion the function should return 0 - Otherwise, a negative value indicating the error code shall be returned - \note - \warning -*/ -#define _SlNonOsLockObjDelete(pLockObj) _SlNonOsSemSet(pLockObj,0) - -/*! - \brief This function locks a locking object. - - All other threads that call this function before this thread calls - the _SlNonOsLockObjUnlock would be suspended - - \param pLockObj - pointer to the locking object control block - \param Timeout - numeric value specifies the maximum number of mSec to - stay suspended while waiting for the locking object - Currently, the simple link driver uses only two values: - - NONOS_WAIT_FOREVER - - NONOS_NO_WAIT - - - \return upon successful reception of the locking object the function should return 0 - Otherwise, a negative value indicating the error code shall be returned - \note - \warning -*/ -#define _SlNonOsLockObjLock(pLockObj , Timeout) _SlNonOsSemGet(pLockObj,__NON_OS_LOCK_OBJ_UNLOCK_VALUE,__NON_OS_LOCK_OBJ_LOCK_VALUE,Timeout) - -/*! - \brief This function unlock a locking object. - - \param pLockObj - pointer to the locking object control block - - \return upon successful unlocking the function should return 0 - Otherwise, a negative value indicating the error code shall be returned - \note - \warning -*/ -#define _SlNonOsLockObjUnlock(pLockObj) _SlNonOsSemSet(pLockObj,__NON_OS_LOCK_OBJ_UNLOCK_VALUE) - - -/*! - \brief This function call the pEntry callback from a different context - - \param pEntry - pointer to the entry callback function - - \param pValue - pointer to any type of memory structure that would be - passed to pEntry callback from the execution thread. - - \param flags - execution flags - reserved for future usage - - \return upon successful registration of the spawn the function return 0 - (the function is not blocked till the end of the execution of the function - and could be returned before the execution is actually completed) - Otherwise, a negative value indicating the error code shall be returned - \note - \warning -*/ -_SlNonOsRetVal_t _SlNonOsSpawn(_SlSpawnEntryFunc_t pEntry , void* pValue , _u32 flags); - - -/*! - \brief This function must be called from the main loop in non-os paltforms - - \param None - - \return 0 - No more activities - 1 - Activity still in progress - \note - \warning -*/ -_SlNonOsRetVal_t _SlNonOsMainLoopTask(void); - -extern _SlNonOsRetVal_t _SlNonOsSemGet(_SlNonOsSemObj_t* pSyncObj, _SlNonOsSemObj_t WaitValue, _SlNonOsSemObj_t SetValue, _SlNonOsTime_t Timeout); -extern _SlNonOsRetVal_t _SlNonOsSemSet(_SlNonOsSemObj_t* pSemObj , _SlNonOsSemObj_t Value); -extern _SlNonOsRetVal_t _SlNonOsSpawn(_SlSpawnEntryFunc_t pEntry , void* pValue , _u32 flags); - -#if (defined(_SlSyncWaitLoopCallback)) -extern void _SlSyncWaitLoopCallback(void); -#endif - - -/***************************************************************************** - - Overwrite SimpleLink driver OS adaptation functions - - - *****************************************************************************/ - -#undef sl_SyncObjCreate -#define sl_SyncObjCreate(pSyncObj,pName) _SlNonOsSemSet(pSyncObj,__NON_OS_SYNC_OBJ_CLEAR_VALUE) - -#undef sl_SyncObjDelete -#define sl_SyncObjDelete(pSyncObj) _SlNonOsSemSet(pSyncObj,0) - -#undef sl_SyncObjSignal -#define sl_SyncObjSignal(pSyncObj) _SlNonOsSemSet(pSyncObj,__NON_OS_SYNC_OBJ_SIGNAL_VALUE) - -#undef sl_SyncObjSignalFromIRQ -#define sl_SyncObjSignalFromIRQ(pSyncObj) _SlNonOsSemSet(pSyncObj,__NON_OS_SYNC_OBJ_SIGNAL_VALUE) - -#undef sl_SyncObjWait -#define sl_SyncObjWait(pSyncObj,Timeout) _SlNonOsSemGet(pSyncObj,__NON_OS_SYNC_OBJ_SIGNAL_VALUE,__NON_OS_SYNC_OBJ_CLEAR_VALUE,Timeout) - -#undef sl_LockObjCreate -#define sl_LockObjCreate(pLockObj,pName) _SlNonOsSemSet(pLockObj,__NON_OS_LOCK_OBJ_UNLOCK_VALUE) - -#undef sl_LockObjDelete -#define sl_LockObjDelete(pLockObj) _SlNonOsSemSet(pLockObj,0) - -#undef sl_LockObjLock -#define sl_LockObjLock(pLockObj,Timeout) _SlNonOsSemGet(pLockObj,__NON_OS_LOCK_OBJ_UNLOCK_VALUE,__NON_OS_LOCK_OBJ_LOCK_VALUE,Timeout) - -#undef sl_LockObjUnlock -#define sl_LockObjUnlock(pLockObj) _SlNonOsSemSet(pLockObj,__NON_OS_LOCK_OBJ_UNLOCK_VALUE) - -#undef sl_Spawn -#define sl_Spawn(pEntry,pValue,flags) _SlNonOsSpawn(pEntry,pValue,flags) - -#undef _SlTaskEntry -#define _SlTaskEntry _SlNonOsMainLoopTask - -#endif /* !SL_PLATFORM_MULTI_THREADED */ - -#ifdef __cplusplus -} -#endif /* __cplusplus */ - -#endif diff --git a/drivers/cc3100/inc/objInclusion.h b/drivers/cc3100/inc/objInclusion.h deleted file mode 100644 index cfe875e76e..0000000000 --- a/drivers/cc3100/inc/objInclusion.h +++ /dev/null @@ -1,322 +0,0 @@ -/* - * objInclusion.h - CC31xx/CC32xx Host Driver Implementation - * - * Copyright (C) 2014 Texas Instruments Incorporated - http://www.ti.com/ - * - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * - * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the - * distribution. - * - * Neither the name of Texas Instruments Incorporated nor the names of - * its contributors may be used to endorse or promote products derived - * from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * -*/ - -#include - -#ifndef OBJINCLUSION_H_ -#define OBJINCLUSION_H_ - -#ifdef __cplusplus -extern "C" { -#endif - -/****************************************************************************** - - For future use - -*******************************************************************************/ - -#define __inln /* if inline functions requiered: #define __inln inline */ - -#define SL_DEVICE /* Device silo is currently always mandatory */ - - - -/****************************************************************************** - - Qualifiers for package customizations - -*******************************************************************************/ - -#if defined (SL_DEVICE) -#define __dev 1 -#else -#define __dev 0 -#endif - -#if defined (SL_DEVICE) && defined (SL_INC_EXT_API) -#define __dev__ext 1 -#else -#define __dev__ext 0 -#endif - - -#if (!defined (SL_PLATFORM_MULTI_THREADED)) || (!defined (SL_PLATFORM_EXTERNAL_SPAWN)) -#define __int__spwn 1 -#else -#define __int__spwn 0 -#endif - -#if defined (SL_INC_NET_APP_PKG) -#define __nap 1 -#else -#define __nap 0 -#endif - -#if defined (SL_INC_NET_APP_PKG) && defined (SL_INC_SOCK_CLIENT_SIDE_API) -#define __nap__clt 1 -#else -#define __nap__clt 0 -#endif - -#if defined (SL_INC_NET_APP_PKG) && defined (SL_INC_EXT_API) -#define __nap__ext 1 -#else -#define __nap__ext 0 -#endif - -#if defined (SL_INC_NET_CFG_PKG) -#define __ncg 1 -#else -#define __ncg 0 -#endif - -#if defined (SL_INC_NET_CFG_PKG) && defined (SL_INC_EXT_API) -#define __ncg__ext 1 -#else -#define __ncg__ext 0 -#endif - -#if defined (SL_INC_NVMEM_PKG) -#define __nvm 1 -#else -#define __nvm 0 -#endif - -#if defined (SL_INC_SOCKET_PKG) -#define __sck 1 -#else -#define __sck 0 -#endif - -#if defined (SL_INC_SOCKET_PKG) && defined (SL_INC_EXT_API) -#define __sck__ext 1 -#else -#define __sck__ext 0 -#endif - -#if defined (SL_INC_SOCKET_PKG) && defined (SL_INC_SOCK_SERVER_SIDE_API) -#define __sck__srv 1 -#else -#define __sck__srv 0 -#endif - -#if defined (SL_INC_SOCKET_PKG) && defined (SL_INC_SOCK_CLIENT_SIDE_API) -#define __sck__clt 1 -#else -#define __sck__clt 0 -#endif - -#if defined (SL_INC_SOCKET_PKG) && defined (SL_INC_SOCK_RECV_API) -#define __sck__rcv 1 -#else -#define __sck__rcv 0 -#endif - -#if defined (SL_INC_SOCKET_PKG) && defined (SL_INC_SOCK_SEND_API) -#define __sck__snd 1 -#else -#define __sck__snd 0 -#endif - -#if defined (SL_INC_WLAN_PKG) -#define __wln 1 -#else -#define __wln 0 -#endif - -#if defined (SL_INC_WLAN_PKG) && defined (SL_INC_EXT_API) -#define __wln__ext 1 -#else -#define __wln__ext 0 -#endif - -/* The return 1 is the function need to be included in the output */ -#define _SL_INCLUDE_FUNC(Name) (_SL_INC_##Name) - -/* Driver */ -#define _SL_INC_sl_NetAppStart __nap__ext -#define _SL_INC_sl_NetAppStop __nap__ext - -#define _SL_INC_sl_NetAppDnsGetHostByName __nap__clt - - -#define _SL_INC_sl_NetAppDnsGetHostByService __nap__ext -#define _SL_INC_sl_NetAppMDNSRegisterService __nap__ext -#define _SL_INC_sl_NetAppMDNSUnRegisterService __nap__ext -#define _SL_INC_sl_NetAppMDNSRegisterUnregisterService __nap__ext -#define _SL_INC_sl_NetAppGetServiceList __nap__ext - - -#define _SL_INC_sl_DnsGetHostByAddr __nap__ext -#define _SL_INC_sl_NetAppPingStart __nap__ext -#define _SL_INC_sl_NetAppPingReport __nap__ext -#define _SL_INC_sl_NetAppSet __nap__ext -#define _SL_INC_sl_NetAppGet __nap__ext - - -/* FS */ -#define _SL_INC_sl_FsOpen __nvm - -#define _SL_INC_sl_FsClose __nvm - -#define _SL_INC_sl_FsRead __nvm - -#define _SL_INC_sl_FsWrite __nvm - -#define _SL_INC_sl_FsGetInfo __nvm - -#define _SL_INC_sl_FsDel __nvm - -/* netcfg */ -#define _SL_INC_sl_MacAdrrSet __ncg - -#define _SL_INC_sl_MacAdrrGet __ncg - -#define _SL_INC_sl_NetCfgGet __ncg - -#define _SL_INC_sl_NetCfgSet __ncg - - -/* socket */ -#define _SL_INC_sl_Socket __sck - -#define _SL_INC_sl_Close __sck - -#define _SL_INC_sl_Accept __sck__srv - -#define _SL_INC_sl_Bind __sck - -#define _SL_INC_sl_Listen __sck__srv - -#define _SL_INC_sl_Connect __sck__clt - -#define _SL_INC_sl_Select __sck - -#define _SL_INC_sl_SetSockOpt __sck - -#define _SL_INC_sl_GetSockOpt __sck__ext - -#define _SL_INC_sl_Recv __sck__rcv - -#define _SL_INC_sl_RecvFrom __sck__rcv - -#define _SL_INC_sl_Write __sck__snd - -#define _SL_INC_sl_Send __sck__snd - -#define _SL_INC_sl_SendTo __sck__snd - -#define _SL_INC_sl_Htonl __sck - -#define _SL_INC_sl_Htons __sck - -/* wlan */ -#define _SL_INC_sl_WlanConnect __wln__ext - -#define _SL_INC_sl_WlanDisconnect __wln__ext - -#define _SL_INC_sl_WlanProfileAdd __wln__ext - -#define _SL_INC_sl_WlanProfileGet __wln__ext - -#define _SL_INC_sl_WlanProfileDel __wln__ext - -#define _SL_INC_sl_WlanPolicySet __wln__ext - -#define _SL_INC_sl_WlanPolicyGet __wln__ext - -#define _SL_INC_sl_WlanGetNetworkList __wln__ext - -#define _SL_INC_sl_WlanRxFilterAdd __wln__ext - -#define _SL_INC_sl_WlanRxFilterSet __wln__ext - -#define _SL_INC_sl_WlanRxFilterGet __wln__ext - -#define _SL_INC_sl_SmartConfigStart __wln - -#define _SL_INC_sl_SmartConfigOptSet __wln__ext - - -#define _SL_INC_sl_WlanSmartConfigStart __wln - -#define _SL_INC_sl_WlanSmartConfigStop __wln - -#define _SL_INC_sl_WlanSetMode __wln - -#define _SL_INC_sl_WlanSet __wln - -#define _SL_INC_sl_WlanGet __wln - -#define _SL_INC_sl_SmartConfigOptSet __wln__ext - -#define _SL_INC_sl_SmartConfigOptGet __wln__ext - -#define _SL_INC_sl_WlanRxStatStart __wln__ext - -#define _SL_INC_sl_WlanRxStatStop __wln__ext - -#define _SL_INC_sl_WlanRxStatGet __wln__ext - - -/* device */ -#define _SL_INC_sl_Task __int__spwn - -#define _SL_INC_sl_Start __dev - -#define _SL_INC_sl_Stop __dev - -#define _SL_INC_sl_StatusGet __dev - -#ifdef SL_IF_TYPE_UART -#define _SL_INC_sl_UartSetMode __dev__ext -#endif - -#define _SL_INC_sl_EventMaskGet __dev__ext - -#define _SL_INC_sl_EventMaskSet __dev__ext - -#define _SL_INC_sl_DevGet __dev__ext - -#define _SL_INC_sl_DevSet __dev__ext - - -#ifdef __cplusplus -} -#endif /* __cplusplus */ - -#endif /*OBJINCLUSION_H_ */ diff --git a/drivers/cc3100/inc/protocol.h b/drivers/cc3100/inc/protocol.h deleted file mode 100644 index 8a1299a6ab..0000000000 --- a/drivers/cc3100/inc/protocol.h +++ /dev/null @@ -1,1182 +0,0 @@ -/* - * protocol.h - CC31xx/CC32xx Host Driver Implementation - * - * Copyright (C) 2014 Texas Instruments Incorporated - http://www.ti.com/ - * - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * - * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the - * distribution. - * - * Neither the name of Texas Instruments Incorporated nor the names of - * its contributors may be used to endorse or promote products derived - * from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * -*/ - -/*******************************************************************************\ -* -* FILE NAME: protocol.h -* -* DESCRIPTION: Constant and data structure definitions and function -* prototypes for the SL protocol module, which implements -* processing of SimpleLink Commands. -* -* AUTHOR: -* -\*******************************************************************************/ - -#ifndef _SL_PROTOCOL_TYPES_H_ -#define _SL_PROTOCOL_TYPES_H_ - -/**************************************************************************** -** -** User I/F pools definitions -** -****************************************************************************/ - -/**************************************************************************** -** -** Definitions for SimpleLink Commands -** -****************************************************************************/ - - -/* pattern for LE 8/16/32 or BE*/ -#define H2N_SYNC_PATTERN {0xBBDDEEFF,0x4321,0x34,0x12} -#define H2N_CNYS_PATTERN {0xBBDDEEFF,0x8765,0x78,0x56} - -#define H2N_DUMMY_PATTERN (_u32)0xFFFFFFFF -#define N2H_SYNC_PATTERN (_u32)0xABCDDCBA -#define SYNC_PATTERN_LEN (_u32)sizeof(_u32) -#define UART_SET_MODE_MAGIC_CODE (_u32)0xAA55AA55 -#define SPI_16BITS_BUG(pattern) (_u32)((_u32)pattern & (_u32)0xFFFF7FFF) -#define SPI_8BITS_BUG(pattern) (_u32)((_u32)pattern & (_u32)0xFFFFFF7F) - - - -typedef struct -{ - _u16 Opcode; - _u16 Len; -}_SlGenericHeader_t; - - -typedef struct -{ - _u32 Long; - _u16 Short; - _u8 Byte1; - _u8 Byte2; -}_SlSyncPattern_t; - -typedef _SlGenericHeader_t _SlCommandHeader_t; - -typedef struct -{ - _SlGenericHeader_t GenHeader; - _u8 TxPoolCnt; - _u8 DevStatus; - _u8 SocketTXFailure; - _u8 SocketNonBlocking; -}_SlResponseHeader_t; - -#define _SL_RESP_SPEC_HDR_SIZE (sizeof(_SlResponseHeader_t) - sizeof(_SlGenericHeader_t)) -#define _SL_RESP_HDR_SIZE sizeof(_SlResponseHeader_t) -#define _SL_CMD_HDR_SIZE sizeof(_SlCommandHeader_t) - -#define _SL_RESP_ARGS_START(_pMsg) (((_SlResponseHeader_t *)(_pMsg)) + 1) - -/* Used only in NWP! */ -typedef struct -{ - _SlCommandHeader_t sl_hdr; - _u8 func_args_start; -} T_SCMD; - - -#define WLAN_CONN_STATUS_BIT 0x01 -#define EVENTS_Q_STATUS_BIT 0x02 -#define PENDING_RCV_CMD_BIT 0x04 -#define FW_BUSY_PACKETS_BIT 0x08 - -#define INIT_STA_OK 0x11111111 -#define INIT_STA_ERR 0x22222222 -#define INIT_AP_OK 0x33333333 -#define INIT_AP_ERR 0x44444444 -#define INIT_P2P_OK 0x55555555 -#define INIT_P2P_ERR 0x66666666 - -/**************************************************************************** -** OPCODES -****************************************************************************/ -#define SL_IPV4_IPV6_OFFSET ( 9 ) -#define SL_OPCODE_IPV4 ( 0x0 << SL_IPV4_IPV6_OFFSET ) -#define SL_OPCODE_IPV6 ( 0x1 << SL_IPV4_IPV6_OFFSET ) - -#define SL_SYNC_ASYNC_OFFSET ( 10 ) -#define SL_OPCODE_SYNC (0x1 << SL_SYNC_ASYNC_OFFSET ) -#define SL_OPCODE_SILO_OFFSET ( 11 ) -#define SL_OPCODE_SILO_MASK ( 0xF << SL_OPCODE_SILO_OFFSET ) -#define SL_OPCODE_SILO_DEVICE ( 0x0 << SL_OPCODE_SILO_OFFSET ) -#define SL_OPCODE_SILO_WLAN ( 0x1 << SL_OPCODE_SILO_OFFSET ) -#define SL_OPCODE_SILO_SOCKET ( 0x2 << SL_OPCODE_SILO_OFFSET ) -#define SL_OPCODE_SILO_NETAPP ( 0x3 << SL_OPCODE_SILO_OFFSET ) -#define SL_OPCODE_SILO_NVMEM ( 0x4 << SL_OPCODE_SILO_OFFSET ) -#define SL_OPCODE_SILO_NETCFG ( 0x5 << SL_OPCODE_SILO_OFFSET ) - -#define SL_FAMILY_SHIFT (0x4) -#define SL_FLAGS_MASK (0xF) - -#define SL_OPCODE_DEVICE_INITCOMPLETE 0x0008 -#define SL_OPCODE_DEVICE_ABORT 0x000C -#define SL_OPCODE_DEVICE_STOP_COMMAND 0x8473 -#define SL_OPCODE_DEVICE_STOP_RESPONSE 0x0473 -#define SL_OPCODE_DEVICE_STOP_ASYNC_RESPONSE 0x0073 -#define SL_OPCODE_DEVICE_DEVICEASYNCDUMMY 0x0063 - -#define SL_OPCODE_DEVICE_VERSIONREADCOMMAND 0x8470 -#define SL_OPCODE_DEVICE_VERSIONREADRESPONSE 0x0470 -#define SL_OPCODE_DEVICE_DEVICEASYNCFATALERROR 0x0078 -#define SL_OPCODE_WLAN_WLANCONNECTCOMMAND 0x8C80 -#define SL_OPCODE_WLAN_WLANCONNECTRESPONSE 0x0C80 -#define SL_OPCODE_WLAN_WLANASYNCCONNECTEDRESPONSE 0x0880 -#define SL_OPCODE_WLAN_P2P_DEV_FOUND 0x0830 -#define SL_OPCODE_WLAN_CONNECTION_FAILED 0x0831 -#define SL_OPCODE_WLAN_P2P_NEG_REQ_RECEIVED 0x0832 - -#define SL_OPCODE_WLAN_WLANDISCONNECTCOMMAND 0x8C81 -#define SL_OPCODE_WLAN_WLANDISCONNECTRESPONSE 0x0C81 -#define SL_OPCODE_WLAN_WLANASYNCDISCONNECTEDRESPONSE 0x0881 -#define SL_OPCODE_WLAN_WLANCONNECTEAPCOMMAND 0x8C82 -#define SL_OPCODE_WLAN_WLANCONNECTEAPCRESPONSE 0x0C82 -#define SL_OPCODE_WLAN_PROFILEADDCOMMAND 0x8C83 -#define SL_OPCODE_WLAN_PROFILEADDRESPONSE 0x0C83 -#define SL_OPCODE_WLAN_PROFILEGETCOMMAND 0x8C84 -#define SL_OPCODE_WLAN_PROFILEGETRESPONSE 0x0C84 -#define SL_OPCODE_WLAN_PROFILEDELCOMMAND 0x8C85 -#define SL_OPCODE_WLAN_PROFILEDELRESPONSE 0x0C85 -#define SL_OPCODE_WLAN_POLICYSETCOMMAND 0x8C86 -#define SL_OPCODE_WLAN_POLICYSETRESPONSE 0x0C86 -#define SL_OPCODE_WLAN_POLICYGETCOMMAND 0x8C87 -#define SL_OPCODE_WLAN_POLICYGETRESPONSE 0x0C87 -#define SL_OPCODE_WLAN_FILTERADD 0x8C88 -#define SL_OPCODE_WLAN_FILTERADDRESPONSE 0x0C88 -#define SL_OPCODE_WLAN_FILTERGET 0x8C89 -#define SL_OPCODE_WLAN_FILTERGETRESPONSE 0x0C89 -#define SL_OPCODE_WLAN_FILTERDELETE 0x8C8A -#define SL_OPCODE_WLAN_FILTERDELETERESPOSNE 0x0C8A -#define SL_OPCODE_WLAN_WLANGETSTATUSCOMMAND 0x8C8F -#define SL_OPCODE_WLAN_WLANGETSTATUSRESPONSE 0x0C8F -#define SL_OPCODE_WLAN_STARTTXCONTINUESCOMMAND 0x8CAA -#define SL_OPCODE_WLAN_STARTTXCONTINUESRESPONSE 0x0CAA -#define SL_OPCODE_WLAN_STOPTXCONTINUESCOMMAND 0x8CAB -#define SL_OPCODE_WLAN_STOPTXCONTINUESRESPONSE 0x0CAB -#define SL_OPCODE_WLAN_STARTRXSTATCOMMAND 0x8CAC -#define SL_OPCODE_WLAN_STARTRXSTATRESPONSE 0x0CAC -#define SL_OPCODE_WLAN_STOPRXSTATCOMMAND 0x8CAD -#define SL_OPCODE_WLAN_STOPRXSTATRESPONSE 0x0CAD -#define SL_OPCODE_WLAN_GETRXSTATCOMMAND 0x8CAF -#define SL_OPCODE_WLAN_GETRXSTATRESPONSE 0x0CAF -#define SL_OPCODE_WLAN_POLICYSETCOMMANDNEW 0x8CB0 -#define SL_OPCODE_WLAN_POLICYSETRESPONSENEW 0x0CB0 -#define SL_OPCODE_WLAN_POLICYGETCOMMANDNEW 0x8CB1 -#define SL_OPCODE_WLAN_POLICYGETRESPONSENEW 0x0CB1 - -#define SL_OPCODE_WLAN_SMART_CONFIG_START_COMMAND 0x8CB2 -#define SL_OPCODE_WLAN_SMART_CONFIG_START_RESPONSE 0x0CB2 -#define SL_OPCODE_WLAN_SMART_CONFIG_START_ASYNC_RESPONSE 0x08B2 -#define SL_OPCODE_WLAN_SMART_CONFIG_STOP_COMMAND 0x8CB3 -#define SL_OPCODE_WLAN_SMART_CONFIG_STOP_RESPONSE 0x0CB3 -#define SL_OPCODE_WLAN_SMART_CONFIG_STOP_ASYNC_RESPONSE 0x08B3 -#define SL_OPCODE_WLAN_SET_MODE 0x8CB4 -#define SL_OPCODE_WLAN_SET_MODE_RESPONSE 0x0CB4 -#define SL_OPCODE_WLAN_CFG_SET 0x8CB5 -#define SL_OPCODE_WLAN_CFG_SET_RESPONSE 0x0CB5 -#define SL_OPCODE_WLAN_CFG_GET 0x8CB6 -#define SL_OPCODE_WLAN_CFG_GET_RESPONSE 0x0CB6 -#define SL_OPCODE_WLAN_STA_CONNECTED 0x082E -#define SL_OPCODE_WLAN_STA_DISCONNECTED 0x082F -#define SL_OPCODE_WLAN_EAP_PROFILEADDCOMMAND 0x8C67 -#define SL_OPCODE_WLAN_EAP_PROFILEADDCOMMAND_RESPONSE 0x0C67 - -#define SL_OPCODE_SOCKET_SOCKET 0x9401 -#define SL_OPCODE_SOCKET_SOCKETRESPONSE 0x1401 -#define SL_OPCODE_SOCKET_CLOSE 0x9402 -#define SL_OPCODE_SOCKET_CLOSERESPONSE 0x1402 -#define SL_OPCODE_SOCKET_ACCEPT 0x9403 -#define SL_OPCODE_SOCKET_ACCEPTRESPONSE 0x1403 -#define SL_OPCODE_SOCKET_ACCEPTASYNCRESPONSE 0x1003 -#define SL_OPCODE_SOCKET_ACCEPTASYNCRESPONSE_V6 0x1203 -#define SL_OPCODE_SOCKET_BIND 0x9404 -#define SL_OPCODE_SOCKET_BIND_V6 0x9604 -#define SL_OPCODE_SOCKET_BINDRESPONSE 0x1404 -#define SL_OPCODE_SOCKET_LISTEN 0x9405 -#define SL_OPCODE_SOCKET_LISTENRESPONSE 0x1405 -#define SL_OPCODE_SOCKET_CONNECT 0x9406 -#define SL_OPCODE_SOCKET_CONNECT_V6 0x9606 -#define SL_OPCODE_SOCKET_CONNECTRESPONSE 0x1406 -#define SL_OPCODE_SOCKET_CONNECTASYNCRESPONSE 0x1006 -#define SL_OPCODE_SOCKET_SELECT 0x9407 -#define SL_OPCODE_SOCKET_SELECTRESPONSE 0x1407 -#define SL_OPCODE_SOCKET_SELECTASYNCRESPONSE 0x1007 -#define SL_OPCODE_SOCKET_SETSOCKOPT 0x9408 -#define SL_OPCODE_SOCKET_SETSOCKOPTRESPONSE 0x1408 -#define SL_OPCODE_SOCKET_GETSOCKOPT 0x9409 -#define SL_OPCODE_SOCKET_GETSOCKOPTRESPONSE 0x1409 -#define SL_OPCODE_SOCKET_RECV 0x940A -#define SL_OPCODE_SOCKET_RECVASYNCRESPONSE 0x100A -#define SL_OPCODE_SOCKET_RECVFROM 0x940B -#define SL_OPCODE_SOCKET_RECVFROMASYNCRESPONSE 0x100B -#define SL_OPCODE_SOCKET_RECVFROMASYNCRESPONSE_V6 0x120B -#define SL_OPCODE_SOCKET_SEND 0x940C -#define SL_OPCODE_SOCKET_SENDTO 0x940D -#define SL_OPCODE_SOCKET_SENDTO_V6 0x960D -#define SL_OPCODE_SOCKET_TXFAILEDASYNCRESPONSE 0x100E -#define SL_OPCODE_SOCKET_SOCKETASYNCEVENT 0x100F -#define SL_OPCODE_NETAPP_START_COMMAND 0x9C0A -#define SL_OPCODE_NETAPP_START_RESPONSE 0x1C0A -#define SL_OPCODE_NETAPP_NETAPPSTARTRESPONSE 0x1C0A -#define SL_OPCODE_NETAPP_STOP_COMMAND 0x9C61 -#define SL_OPCODE_NETAPP_STOP_RESPONSE 0x1C61 -#define SL_OPCODE_NETAPP_NETAPPSET 0x9C0B -#define SL_OPCODE_NETAPP_NETAPPSETRESPONSE 0x1C0B -#define SL_OPCODE_NETAPP_NETAPPGET 0x9C27 -#define SL_OPCODE_NETAPP_NETAPPGETRESPONSE 0x1C27 -#define SL_OPCODE_NETAPP_DNSGETHOSTBYNAME 0x9C20 -#define SL_OPCODE_NETAPP_DNSGETHOSTBYNAMERESPONSE 0x1C20 -#define SL_OPCODE_NETAPP_DNSGETHOSTBYNAMEASYNCRESPONSE 0x1820 -#define SL_OPCODE_NETAPP_DNSGETHOSTBYNAMEASYNCRESPONSE_V6 0x1A20 -#define SL_OPCODE_NETAPP_NETAPP_MDNS_LOOKUP_SERVICE 0x9C71 -#define SL_OPCODE_NETAPP_NETAPP_MDNS_LOOKUP_SERVICE_RESPONSE 0x1C72 -#define SL_OPCODE_NETAPP_MDNSREGISTERSERVICE 0x9C34 -#define SL_OPCODE_NETAPP_MDNSREGISTERSERVICERESPONSE 0x1C34 -#define SL_OPCODE_NETAPP_MDNSGETHOSTBYSERVICE 0x9C35 -#define SL_OPCODE_NETAPP_MDNSGETHOSTBYSERVICERESPONSE 0x1C35 -#define SL_OPCODE_NETAPP_MDNSGETHOSTBYSERVICEASYNCRESPONSE 0x1835 -#define SL_OPCODE_NETAPP_MDNSGETHOSTBYSERVICEASYNCRESPONSE_V6 0x1A35 -#define SL_OPCODE_NETAPP_DNSGETHOSTBYADDR 0x9C26 -#define SL_OPCODE_NETAPP_DNSGETHOSTBYADDR_V6 0x9E26 -#define SL_OPCODE_NETAPP_DNSGETHOSTBYADDRRESPONSE 0x1C26 -#define SL_OPCODE_NETAPP_DNSGETHOSTBYADDRASYNCRESPONSE 0x1826 -#define SL_OPCODE_NETAPP_PINGSTART 0x9C21 -#define SL_OPCODE_NETAPP_PINGSTART_V6 0x9E21 -#define SL_OPCODE_NETAPP_PINGSTARTRESPONSE 0x1C21 -#define SL_OPCODE_NETAPP_PINGREPORTREQUEST 0x9C22 -#define SL_OPCODE_NETAPP_PINGREPORTREQUESTRESPONSE 0x1822 -#define SL_OPCODE_NETAPP_PINGSTOP 0x9C23 -#define SL_OPCODE_NETAPP_PINGSTOPRESPONSE 0x1C23 -#define SL_OPCODE_NETAPP_ARPFLUSH 0x9C24 -#define SL_OPCODE_NETAPP_ARPFLUSHRESPONSE 0x1C24 -#define SL_OPCODE_NETAPP_IPACQUIRED 0x1825 -#define SL_OPCODE_NETAPP_IPV4_LOST 0x1832 -#define SL_OPCODE_NETAPP_DHCP_IPV4_ACQUIRE_TIMEOUT 0x1833 -#define SL_OPCODE_NETAPP_IPACQUIRED_V6 0x1A25 -#define SL_OPCODE_NETAPP_IPERFSTARTCOMMAND 0x9C28 -#define SL_OPCODE_NETAPP_IPERFSTARTRESPONSE 0x1C28 -#define SL_OPCODE_NETAPP_IPERFSTOPCOMMAND 0x9C29 -#define SL_OPCODE_NETAPP_IPERFSTOPRESPONSE 0x1C29 -#define SL_OPCODE_NETAPP_CTESTSTARTCOMMAND 0x9C2A -#define SL_OPCODE_NETAPP_CTESTSTARTRESPONSE 0x1C2A -#define SL_OPCODE_NETAPP_CTESTASYNCRESPONSE 0x182A -#define SL_OPCODE_NETAPP_CTESTSTOPCOMMAND 0x9C2B -#define SL_OPCODE_NETAPP_CTESTSTOPRESPONSE 0x1C2B -#define SL_OPCODE_NETAPP_IP_LEASED 0x182C -#define SL_OPCODE_NETAPP_IP_RELEASED 0x182D -#define SL_OPCODE_NETAPP_HTTPGETTOKENVALUE 0x182E -#define SL_OPCODE_NETAPP_HTTPSENDTOKENVALUE 0x9C2F -#define SL_OPCODE_NETAPP_HTTPPOSTTOKENVALUE 0x1830 -#define SL_OPCODE_NVMEM_FILEOPEN 0xA43C -#define SL_OPCODE_NVMEM_FILEOPENRESPONSE 0x243C -#define SL_OPCODE_NVMEM_FILECLOSE 0xA43D -#define SL_OPCODE_NVMEM_FILECLOSERESPONSE 0x243D -#define SL_OPCODE_NVMEM_FILEREADCOMMAND 0xA440 -#define SL_OPCODE_NVMEM_FILEREADRESPONSE 0x2440 -#define SL_OPCODE_NVMEM_FILEWRITECOMMAND 0xA441 -#define SL_OPCODE_NVMEM_FILEWRITERESPONSE 0x2441 -#define SL_OPCODE_NVMEM_FILEGETINFOCOMMAND 0xA442 -#define SL_OPCODE_NVMEM_FILEGETINFORESPONSE 0x2442 -#define SL_OPCODE_NVMEM_FILEDELCOMMAND 0xA443 -#define SL_OPCODE_NVMEM_FILEDELRESPONSE 0x2443 -#define SL_OPCODE_NVMEM_NVMEMFORMATCOMMAND 0xA444 -#define SL_OPCODE_NVMEM_NVMEMFORMATRESPONSE 0x2444 - -#define SL_OPCODE_DEVICE_SETDEBUGLEVELCOMMAND 0x846A -#define SL_OPCODE_DEVICE_SETDEBUGLEVELRESPONSE 0x046A - -#define SL_OPCODE_DEVICE_NETCFG_SET_COMMAND 0x8432 -#define SL_OPCODE_DEVICE_NETCFG_SET_RESPONSE 0x0432 -#define SL_OPCODE_DEVICE_NETCFG_GET_COMMAND 0x8433 -#define SL_OPCODE_DEVICE_NETCFG_GET_RESPONSE 0x0433 -/* */ -#define SL_OPCODE_DEVICE_SETUARTMODECOMMAND 0x846B -#define SL_OPCODE_DEVICE_SETUARTMODERESPONSE 0x046B -#define SL_OPCODE_DEVICE_SSISIZESETCOMMAND 0x846B -#define SL_OPCODE_DEVICE_SSISIZESETRESPONSE 0x046B - -/* */ -#define SL_OPCODE_DEVICE_EVENTMASKSET 0x8464 -#define SL_OPCODE_DEVICE_EVENTMASKSETRESPONSE 0x0464 -#define SL_OPCODE_DEVICE_EVENTMASKGET 0x8465 -#define SL_OPCODE_DEVICE_EVENTMASKGETRESPONSE 0x0465 - -#define SL_OPCODE_DEVICE_DEVICEGET 0x8466 -#define SL_OPCODE_DEVICE_DEVICEGETRESPONSE 0x0466 -#define SL_OPCODE_DEVICE_DEVICESET 0x84B7 -#define SL_OPCODE_DEVICE_DEVICESETRESPONSE 0x04B7 - -#define SL_OPCODE_WLAN_SCANRESULTSGETCOMMAND 0x8C8C -#define SL_OPCODE_WLAN_SCANRESULTSGETRESPONSE 0x0C8C -#define SL_OPCODE_WLAN_SMARTCONFIGOPTSET 0x8C8D -#define SL_OPCODE_WLAN_SMARTCONFIGOPTSETRESPONSE 0x0C8D -#define SL_OPCODE_WLAN_SMARTCONFIGOPTGET 0x8C8E -#define SL_OPCODE_WLAN_SMARTCONFIGOPTGETRESPONSE 0x0C8E - - -/* Rx Filters opcodes */ -#define SL_OPCODE_WLAN_WLANRXFILTERADDCOMMAND 0x8C6C -#define SL_OPCODE_WLAN_WLANRXFILTERADDRESPONSE 0x0C6C -#define SL_OPCODE_WLAN_WLANRXFILTERSETCOMMAND 0x8C6D -#define SL_OPCODE_WLAN_WLANRXFILTERSETRESPONSE 0x0C6D -#define SL_OPCODE_WLAN_WLANRXFILTERGETSTATISTICSINFOCOMMAND 0x8C6E -#define SL_OPCODE_WLAN_WLANRXFILTERGETSTATISTICSINFORESPONSE 0x0C6E -#define SL_OPCODE_WLAN_WLANRXFILTERGETCOMMAND 0x8C6F -#define SL_OPCODE_WLAN_WLANRXFILTERGETRESPONSE 0x0C6F -#define SL_OPCODE_WLAN_WLANRXFILTERGETINFO 0x8C70 -#define SL_OPCODE_WLAN_WLANRXFILTERGETINFORESPONSE 0x0C70 - - -/******************************************************************************************/ -/* Device structs */ -/******************************************************************************************/ -typedef _u32 InitStatus_t; - - -typedef struct -{ - _i32 Status; -}InitComplete_t; - -typedef struct -{ - _i16 status; - _u16 padding; - -}_BasicResponse_t; - -typedef struct -{ - _u16 Timeout; - _u16 padding; -}_DevStopCommand_t; - -typedef struct -{ - _u32 group; - _u32 mask; -}_DevMaskEventSetCommand_t; - -typedef _BasicResponse_t _DevMaskEventSetResponse_t; - - -typedef struct -{ - _u32 group; -}_DevMaskEventGetCommand_t; - - -typedef struct -{ - _u32 group; - _u32 mask; -}_DevMaskEventGetResponse_t; - - -typedef struct -{ - _u32 group; -}_DevStatusGetCommand_t; - - -typedef struct -{ - _u32 group; - _u32 status; -}_DevStatusGetResponse_t; - -typedef struct -{ - _u32 ChipId; - _u32 FwVersion[4]; - _u8 PhyVersion[4]; -}_Device_VersionReadResponsePart_t; - -typedef struct -{ - _Device_VersionReadResponsePart_t part; - _u32 NwpVersion[4]; - _u16 RomVersion; - _u16 Padding; -}_Device_VersionReadResponseFull_t; - - -typedef struct -{ - _u32 BaudRate; - _u8 FlowControlEnable; -}_DevUartSetModeCommand_t; - -typedef _BasicResponse_t _DevUartSetModeResponse_t; - -/******************************************************/ - -typedef struct -{ - _u8 SsiSizeInBytes; - _u8 Padding[3]; -}_StellarisSsiSizeSet_t; - -/*****************************************************************************************/ -/* WLAN structs */ -/*****************************************************************************************/ -#define MAXIMAL_PASSWORD_LENGTH (64) - -typedef struct{ - _u8 SecType; - _u8 SsidLen; - _u8 Bssid[6]; - _u8 PasswordLen; -}_WlanConnectCommon_t; - -#define SSID_STRING(pCmd) (_i8 *)((_WlanConnectCommon_t *)(pCmd) + 1) -#define PASSWORD_STRING(pCmd) (SSID_STRING(pCmd) + ((_WlanConnectCommon_t *)(pCmd))->SsidLen) - -typedef struct{ - _WlanConnectCommon_t Common; - _u8 UserLen; - _u8 AnonUserLen; - _u8 CertIndex; - _u32 EapBitmask; -}_WlanConnectEapCommand_t; - -#define EAP_SSID_STRING(pCmd) (_i8 *)((_WlanConnectEapCommand_t *)(pCmd) + 1) -#define EAP_PASSWORD_STRING(pCmd) (EAP_SSID_STRING(pCmd) + ((_WlanConnectEapCommand_t *)(pCmd))->Common.SsidLen) -#define EAP_USER_STRING(pCmd) (EAP_PASSWORD_STRING(pCmd) + ((_WlanConnectEapCommand_t *)(pCmd))->Common.PasswordLen) -#define EAP_ANON_USER_STRING(pCmd) (EAP_USER_STRING(pCmd) + ((_WlanConnectEapCommand_t *)(pCmd))->UserLen) - - -typedef struct -{ - _u8 PolicyType; - _u8 Padding; - _u8 PolicyOption; - _u8 PolicyOptionLen; -}_WlanPoliciySetGet_t; - - -typedef struct{ - _u32 minDwellTime; - _u32 maxDwellTime; - _u32 numProbeResponse; - _u32 G_Channels_mask; - _i32 rssiThershold; - _i32 snrThershold; - _i32 defaultTXPower; - _u16 intervalList[16]; -}_WlanScanParamSetCommand_t; - - -typedef struct{ - _i8 SecType; - _u8 SsidLen; - _u8 Priority; - _u8 Bssid[6]; - _u8 PasswordLen; - _u8 WepKeyId; -}_WlanAddGetProfile_t; - - -typedef struct{ - _WlanAddGetProfile_t Common; - _u8 UserLen; - _u8 AnonUserLen; - _u8 CertIndex; - _u16 padding; - _u32 EapBitmask; -}_WlanAddGetEapProfile_t; - - - - -#define PROFILE_SSID_STRING(pCmd) ((_i8 *)((_WlanAddGetProfile_t *)(pCmd) + 1)) -#define PROFILE_PASSWORD_STRING(pCmd) (PROFILE_SSID_STRING(pCmd) + ((_WlanAddGetProfile_t *)(pCmd))->SsidLen) - -#define EAP_PROFILE_SSID_STRING(pCmd) (_i8 *)((_WlanAddGetEapProfile_t *)(pCmd) + 1) -#define EAP_PROFILE_PASSWORD_STRING(pCmd) (EAP_PROFILE_SSID_STRING(pCmd) + ((_WlanAddGetEapProfile_t *)(pCmd))->Common.SsidLen) -#define EAP_PROFILE_USER_STRING(pCmd) (EAP_PROFILE_PASSWORD_STRING(pCmd) + ((_WlanAddGetEapProfile_t *)(pCmd))->Common.PasswordLen) -#define EAP_PROFILE_ANON_USER_STRING(pCmd) (EAP_PROFILE_USER_STRING(pCmd) + ((_WlanAddGetEapProfile_t *)(pCmd))->UserLen) - - - -typedef struct -{ - _u8 index; - _u8 padding[3]; -}_WlanProfileDelGetCommand_t; - -typedef _BasicResponse_t _WlanGetNetworkListResponse_t; - -typedef struct -{ - _u8 index; - _u8 count; - _i8 padding[2]; -}_WlanGetNetworkListCommand_t; - - - - -typedef struct -{ - _u32 groupIdBitmask; - _u8 cipher; - _u8 publicKeyLen; - _u8 group1KeyLen; - _u8 group2KeyLen; -}_WlanSmartConfigStartCommand_t; - -#define SMART_CONFIG_START_PUBLIC_KEY_STRING(pCmd) ((_i8 *)((_WlanSmartConfigStartCommand_t *)(pCmd) + 1)) -#define SMART_CONFIG_START_GROUP1_KEY_STRING(pCmd) ((_i8 *) (SMART_CONFIG_START_PUBLIC_KEY_STRING(pCmd) + ((_WlanSmartConfigStartCommand_t *)(pCmd))->publicKeyLen)) -#define SMART_CONFIG_START_GROUP2_KEY_STRING(pCmd) ((_i8 *) (SMART_CONFIG_START_GROUP1_KEY_STRING(pCmd) + ((_WlanSmartConfigStartCommand_t *)(pCmd))->group1KeyLen)) - - - -typedef struct -{ - _u8 mode; - _u8 padding[3]; -}_WlanSetMode_t; - - - - -typedef struct -{ - _u16 Status; - _u16 ConfigId; - _u16 ConfigOpt; - _u16 ConfigLen; -}_WlanCfgSetGet_t; - - -/* ******************************************************************************/ -/* RX filters - Start */ -/* ******************************************************************************/ -/* -- 80 bytes */ -typedef struct _WlanRxFilterAddCommand_t -{ - /* -- 1 byte */ - SlrxFilterRuleType_t RuleType; - /* -- 1 byte */ - SlrxFilterFlags_t FilterFlags; - /* -- 1 byte */ - SlrxFilterID_t FilterId; - /* -- 1 byte */ - _u8 Padding; - /* -- 56 byte */ - SlrxFilterRule_t Rule; - /* -- 12 byte ( 3 padding ) */ - SlrxFilterTrigger_t Trigger; - /* -- 8 byte */ - SlrxFilterAction_t Action; -}_WlanRxFilterAddCommand_t; - - - -/* -- 4 bytes */ -typedef struct l_WlanRxFilterAddCommandReponse_t -{ - /* -- 1 byte */ - SlrxFilterID_t FilterId; - /* -- 1 Byte */ - _u8 Status; - /* -- 2 byte */ - _u8 Padding[2]; - -}_WlanRxFilterAddCommandReponse_t; - - - -/* - * \struct _WlanRxFilterSetCommand_t - */ -typedef struct _WlanRxFilterSetCommand_t -{ - _u16 InputBufferLength; - /* 1 byte */ - SLrxFilterOperation_t RxFilterOperation; - _u8 Padding[1]; -}_WlanRxFilterSetCommand_t; - -/** - * \struct _WlanRxFilterSetCommandReponse_t - */ -typedef struct _WlanRxFilterSetCommandReponse_t -{ - /* 1 byte */ - _u8 Status; - /* 3 bytes */ - _u8 Padding[3]; - -}_WlanRxFilterSetCommandReponse_t; - -/** - * \struct _WlanRxFilterGetCommand_t - */ -typedef struct _WlanRxFilterGetCommand_t -{ - _u16 OutputBufferLength; - /* 1 byte */ - SLrxFilterOperation_t RxFilterOperation; - _u8 Padding[1]; -}_WlanRxFilterGetCommand_t; - -/** - * \struct _WlanRxFilterGetCommandReponse_t - */ -typedef struct _WlanRxFilterGetCommandReponse_t -{ - /* 1 byte */ - _u8 Status; - /* 1 bytes */ - _u8 Padding; - /* 2 byte */ - _u16 OutputBufferLength; - -}_WlanRxFilterGetCommandReponse_t; - - - -/* ******************************************************************************/ -/* RX filters -- End */ -/* ******************************************************************************/ - -typedef struct -{ - _u16 status; - _u8 WlanRole; /* 0 = station, 2 = AP */ - _u8 Ipv6Enabled; - _u8 Ipv6DhcpEnabled; - - _u32 ipV6Global[4]; - _u32 ipV6Local[4]; - _u32 ipV6DnsServer[4]; - _u8 Ipv6DhcpState; - -}_NetappIpV6configRetArgs_t; - - -typedef struct -{ - _u8 ipV4[4]; - _u8 ipV4Mask[4]; - _u8 ipV4Gateway[4]; - _u8 ipV4DnsServer[4]; - _u8 ipV4Start[4]; - _u8 ipV4End[4]; -}_NetCfgIpV4AP_Args_t; - - - -typedef struct -{ - _u16 status; - _u8 MacAddr[6]; -} _MAC_Address_SetGet_t; - - -typedef struct -{ - _u16 Status; - _u16 ConfigId; - _u16 ConfigOpt; - _u16 ConfigLen; -}_NetCfgSetGet_t; - -typedef struct -{ - _u16 Status; - _u16 DeviceSetId; - _u16 Option; - _u16 ConfigLen; -}_DeviceSetGet_t; - - - - -/******************************************************************************************/ -/* Socket structs */ -/******************************************************************************************/ - -typedef struct -{ - _u8 Domain; - _u8 Type; - _u8 Protocol; - _u8 Padding; -}_SocketCommand_t; - - -typedef struct -{ - _i16 statusOrLen; - _u8 sd; - _u8 padding; -}_SocketResponse_t; - -typedef struct -{ - _u8 sd; - _u8 family; - _u8 padding1; - _u8 padding2; -}_AcceptCommand_t; - - -typedef struct -{ - _i16 statusOrLen; - _u8 sd; - _u8 family; - _u16 port; - _u16 paddingOrAddr; - _u32 address; -}_SocketAddrAsyncIPv4Response_t; - -typedef struct -{ - _i16 statusOrLen; - _u8 sd; - _u8 family; - _u16 port; - _u8 address[6]; -}_SocketAddrAsyncIPv6EUI48Response_t; -typedef struct -{ - _i16 statusOrLen; - _u8 sd; - _u8 family; - _u16 port; - _u16 paddingOrAddr; - _u32 address[4]; -}_SocketAddrAsyncIPv6Response_t; - - -typedef struct -{ - _i16 lenOrPadding; - _u8 sd; - _u8 FamilyAndFlags; - _u16 port; - _u16 paddingOrAddr; - _u32 address; -}_SocketAddrIPv4Command_t; - -typedef struct -{ - _i16 lenOrPadding; - _u8 sd; - _u8 FamilyAndFlags; - _u16 port; - _u8 address[6]; -}_SocketAddrIPv6EUI48Command_t; -typedef struct -{ - _i16 lenOrPadding; - _u8 sd; - _u8 FamilyAndFlags; - _u16 port; - _u16 paddingOrAddr; - _u32 address[4]; -}_SocketAddrIPv6Command_t; - -typedef union { - _SocketAddrIPv4Command_t IpV4; - _SocketAddrIPv6EUI48Command_t IpV6EUI48; -#ifdef SL_SUPPORT_IPV6 - _SocketAddrIPv6Command_t IpV6; -#endif -} _SocketAddrCommand_u; - -typedef union { - _SocketAddrAsyncIPv4Response_t IpV4; - _SocketAddrAsyncIPv6EUI48Response_t IpV6EUI48; -#ifdef SL_SUPPORT_IPV6 - _SocketAddrAsyncIPv6Response_t IpV6; -#endif -} _SocketAddrResponse_u; - -typedef struct -{ - _u8 sd; - _u8 backlog; - _u8 padding1; - _u8 padding2; -}_ListenCommand_t; - -typedef struct -{ - _u8 sd; - _u8 padding0; - _u8 padding1; - _u8 padding2; -}_CloseCommand_t; - - -typedef struct -{ - _u8 nfds; - _u8 readFdsCount; - _u8 writeFdsCount; - _u8 padding; - _u16 readFds; - _u16 writeFds; - _u16 tv_usec; - _u16 tv_sec; -}_SelectCommand_t; - - -typedef struct -{ - _u16 status; - _u8 readFdsCount; - _u8 writeFdsCount; - _u16 readFds; - _u16 writeFds; -}_SelectAsyncResponse_t; - -typedef struct -{ - _u8 sd; - _u8 level; - _u8 optionName; - _u8 optionLen; -}_setSockOptCommand_t; - -typedef struct -{ - _u8 sd; - _u8 level; - _u8 optionName; - _u8 optionLen; -}_getSockOptCommand_t; - -typedef struct -{ - _i16 status; - _u8 sd; - _u8 optionLen; -}_getSockOptResponse_t; - - -typedef struct -{ - _u16 StatusOrLen; - _u8 sd; - _u8 FamilyAndFlags; -}_sendRecvCommand_t; - -/***************************************************************************************** -* NETAPP structs -******************************************************************************************/ - - -typedef _BasicResponse_t _NetAppStartStopResponse_t; - -typedef struct -{ - _u32 appId; -}_NetAppStartStopCommand_t; - -typedef struct -{ - _u16 Status; - _u16 AppId; - _u16 ConfigOpt; - _u16 ConfigLen; -}_NetAppSetGet_t; -typedef struct -{ - _u16 port_number; -} _NetAppHttpServerGetSet_port_num_t; - -typedef struct -{ - _u8 auth_enable; -}_NetAppHttpServerGetSet_auth_enable_t; - -typedef struct _sl_NetAppHttpServerGetToken_t -{ - _u8 token_name_len; - _u8 padd1; - _u16 padd2; -}sl_NetAppHttpServerGetToken_t; - -typedef struct _sl_NetAppHttpServerSendToken_t -{ - _u8 token_value_len; - _u8 token_name_len; - _u8 token_name[MAX_TOKEN_NAME_LEN]; - _u16 padd; -}sl_NetAppHttpServerSendToken_t; - -typedef struct _sl_NetAppHttpServerPostToken_t -{ - _u8 post_action_len; - _u8 token_name_len; - _u8 token_value_len; - _u8 padding; -}sl_NetAppHttpServerPostToken_t; - - -typedef struct -{ - _u16 Len; - _u8 family; - _u8 padding; -}_GetHostByNameCommand_t; - -typedef struct -{ - _u16 status; - _u16 padding; - _u32 ip0; - _u32 ip1; - _u32 ip2; - _u32 ip3; -}_GetHostByNameIPv6AsyncResponse_t; - -typedef struct -{ - _u16 status; - _u8 padding1; - _u8 padding2; - _u32 ip0; -}_GetHostByNameIPv4AsyncResponse_t; - - - - -typedef enum -{ - CTST_BSD_UDP_TX, - CTST_BSD_UDP_RX, - CTST_BSD_TCP_TX, - CTST_BSD_TCP_RX, - CTST_BSD_TCP_SERVER_BI_DIR, - CTST_BSD_TCP_CLIENT_BI_DIR, - CTST_BSD_UDP_BI_DIR, - CTST_BSD_RAW_TX, - CTST_BSD_RAW_RX, - CTST_BSD_RAW_BI_DIR, - CTST_BSD_SECURED_TCP_TX, - CTST_BSD_SECURED_TCP_RX, - CTST_BSD_SECURED_TCP_SERVER_BI_DIR, - CTST_BSD_SECURED_TCP_CLIENT_BI_DIR - }CommTest_e; - -typedef struct _sl_protocol_CtestStartCommand_t -{ - _u32 Test; - _u16 DestPort; - _u16 SrcPort; - _u32 DestAddr[4]; - _u32 PayloadSize; - _u32 timeout; - _u32 csEnabled; - _u32 secure; - _u32 rawProtocol; - _u8 reserved1[4]; -}_CtestStartCommand_t; - -typedef struct -{ - _u8 test; - _u8 socket; - _i16 status; - _u32 startTime; - _u32 endTime; - _u16 txKbitsSec; - _u16 rxKbitsSec; - _u32 outOfOrderPackets; - _u32 missedPackets; - _i16 token; -}_CtestAsyncResponse_t; - -typedef struct -{ - _u32 pingIntervalTime; - _u16 PingSize; - _u16 pingRequestTimeout; - _u32 totalNumberOfAttempts; - _u32 flags; - _u32 ip0; - _u32 ip1OrPaadding; - _u32 ip2OrPaadding; - _u32 ip3OrPaadding; -}_PingStartCommand_t; - -typedef struct -{ - _u16 status; - _u16 rttMin; - _u16 rttMax; - _u16 rttAvg; - _u32 numSuccsessPings; - _u32 numSendsPings; - _u32 testTime; -}_PingReportResponse_t; - - -typedef struct -{ - _u32 ip; - _u32 gateway; - _u32 dns; -}_IpV4AcquiredAsync_t; - - -typedef enum -{ - ACQUIRED_IPV6_LOCAL = 1, - ACQUIRED_IPV6_GLOBAL -}IpV6AcquiredType_e; - - -typedef struct -{ - _u32 type; - _u32 ip[4]; - _u32 gateway[4]; - _u32 dns[4]; -}_IpV6AcquiredAsync_t; - - -typedef union -{ - _SocketCommand_t EventMask; - _sendRecvCommand_t DeviceInit; -}_device_commands_t; - -/***************************************************************************************** -* FS structs -******************************************************************************************/ - -typedef struct -{ - _u32 FileHandle; - _u32 Offset; - _u16 Len; - _u16 Padding; -}_FsReadCommand_t; - -typedef struct -{ - _u32 Mode; - _u32 Token; -}_FsOpenCommand_t; - -typedef struct -{ - _u32 FileHandle; - _u32 Token; -}_FsOpenResponse_t; - - -typedef struct -{ - _u32 FileHandle; - _u32 CertificFileNameLength; - _u32 SignatureLen; -}_FsCloseCommand_t; - - -typedef _BasicResponse_t _FsReadResponse_t; -typedef _BasicResponse_t _FsDeleteResponse_t; -typedef _BasicResponse_t _FsCloseResponse_t; - -typedef struct -{ - _u16 Status; - _u16 flags; - _u32 FileLen; - _u32 AllocatedLen; - _u32 Token[4]; -}_FsGetInfoResponse_t; - -typedef struct -{ - _u8 DeviceID; - _u8 Padding[3]; -}_FsFormatCommand_t; - -typedef _BasicResponse_t _FsFormatResponse_t; - -typedef struct -{ - _u32 Token; -}_FsDeleteCommand_t; - -typedef _FsDeleteCommand_t _FsGetInfoCommand_t; - -typedef struct -{ - _u32 FileHandle; - _u32 Offset; - _u16 Len; - _u16 Padding; -}_FsWriteCommand_t; - -typedef _BasicResponse_t _FsWriteResponse_t; - - - -/* TODO: Set MAx Async Payload length depending on flavor (Tiny, Small, etc.) */ - - -#ifdef SL_TINY_EXT -#define SL_ASYNC_MAX_PAYLOAD_LEN 120 /* size must be aligned to 4 */ -#else -#define SL_ASYNC_MAX_PAYLOAD_LEN 160 /* size must be aligned to 4 */ -#endif - -#define SL_ASYNC_MAX_MSG_LEN (_SL_RESP_HDR_SIZE + SL_ASYNC_MAX_PAYLOAD_LEN) - -#define RECV_ARGS_SIZE (sizeof(_SocketResponse_t)) -#define RECVFROM_IPV4_ARGS_SIZE (sizeof(_SocketAddrAsyncIPv4Response_t)) -#define RECVFROM_IPV6_ARGS_SIZE (sizeof(_SocketAddrAsyncIPv6Response_t)) - -#define SL_IPV4_ADDRESS_SIZE (sizeof(_u32)) -#define SL_IPV6_ADDRESS_SIZE (4 * sizeof(_u32)) - -#endif /* _SL_PROTOCOL_TYPES_H_ */ diff --git a/drivers/cc3100/inc/simplelink.h b/drivers/cc3100/inc/simplelink.h deleted file mode 100644 index 19ca17f0c7..0000000000 --- a/drivers/cc3100/inc/simplelink.h +++ /dev/null @@ -1,948 +0,0 @@ -/* - * simplelink.h - CC31xx/CC32xx Host Driver Implementation - * - * Copyright (C) 2014 Texas Instruments Incorporated - http://www.ti.com/ - * - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * - * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the - * distribution. - * - * Neither the name of Texas Instruments Incorporated nor the names of - * its contributors may be used to endorse or promote products derived - * from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * -*/ - - -/*! - \mainpage SimpleLink Driver - - \section intro_sec Introduction - - The SimpleLink CC31xx/CC2xx family allows to add Wi-Fi and networking capabilities - to low-cost embedded products without having prior Wi-Fi, RF or networking expertise. - The CC31xx/CC32xx is an ideal solution for microcontroller-based sensor and control - applications such as home appliances, home automation and smart metering. - The CC31xx/CC32xx has integrated a comprehensive TCP/IP network stack, Wi-Fi driver and - security supplicant leading to easier portability to microcontrollers, to an - ultra-low memory footprint, all without compromising the capabilities and robustness - of the final application. - - - - \section modules_sec Module Names - To make it simple, TI's SimpleLink CC31xx/CC32xx platform capabilities were divided into modules by topic (Silo). - These capabilities range from basic device management through wireless - network configuration, standard BSD socket and much more. - Listed below are the various modules in the SimpleLink CC31xx/CC32xx driver: - -# \ref device - controls the behaviour of the CC31xx/CC32xx device (start/stop, events masking and obtaining specific device status) - -# \ref wlan - controls the use of the WiFi WLAN module including: - - Connection features, such as: profiles, policies, SmartConfig� - - Advanced WLAN features, such as: scans, rx filters and rx statistics collection - -# \ref socket - controls standard client/server sockets programming options and capabilities - -# \ref netapp - activates networking applications, such as: HTTP Server, DHCP Server, Ping, DNS and mDNS. - -# \ref netcfg - controls the configuration of the device addresses (i.e. IP and MAC addresses) - -# \ref FileSystem - provides file system capabilities to TI's CC31XX that can be used by both the CC31XX device and the user. - - - \section proting_sec Porting Guide - - The porting of the SimpleLink driver to any new platform is based on few simple steps. - This guide takes you through this process step by step. Please follow the instructions - carefully to avoid any problems during this process and to enable efficient and proper - work with the device. - Please notice that all modifications and porting adjustments of the driver should be - made in the user.h header file only. - Keep making any of the changes only in this file will ensure smoothly transaction to - new versions of the driver at the future! - - - \subsection porting_step1 Step 1 - Create your own user.h file - - The first step is to create a user.h file that will include your configurations and - adjustments. You can use the empty template provided as part of this driver or - you can choose to base your file on file from one of the wide range of examples - applications provided by Texas Instruments - - - \subsection porting_step2 Step 2 - Select the capabilities set required for your application - - Texas Instruments made a lot of efforts to build set of predefined capability sets that would - fit most of the target application. - It is recommended to try and choose one of this predefined capabilities set before going to - build your own customized set. If you find compatible set you can skip the rest of this step. - - The available sets are: - -# SL_TINY - Compatible to be used on platforms with very limited resources. Provides - the best in class foot print in terms of Code and Data consumption. - -# SL_SMALL - Compatible to most common networking applications. Provide the most - common APIs with decent balance between code size, data size, functionality - and performances - -# SL_FULL - Provide access to all SimpleLink functionalities - - - \subsection porting_step3 Step 3 - Bind the device enable/disable output line - - The enable/disable line (nHib) provide mechanism to enter the device into the least current - consumption mode. This mode could be used when no traffic is required (tx/rx). - when this line is not connected to any IO of the host this define should be left empty. - Not connecting this line results in ability to start the driver only once. - - - \subsection porting_step4 Step 4 - Writing your interface communication driver - - The SimpleLink device support several standard communication protocol among SPI and - UART. Depending on your needs and your hardware design, you should choose the - communication channel type. - The interface for this communication channel should include 4 simple access functions: - -# open - -# close - -# read - -# write - - The way this driver would be implemented is directly effecting the efficiency and - the performances of the SimpleLink device on this platform. - If your system has DMA you should consider to use it in order to increase the utilization - of the communication channel - If you have enough memory resources you should consider using a buffer to increase the - efficiency of the write operations. - - - \subsection porting_step5 Step 5 - Choose your memory management model - - The SimpleLink driver support two memory models: - -# Static (default) - -# Dynamic - - If you choose to work in dynamic model you will have to provide alloc and free functions - to be used by the Simple Link driver otherwise nothing need to be done. - - - \subsection porting_step6 Step 6 - OS adaptation - - The SimpleLink driver could run on two kind of platforms: - -# Non-Os / Single Threaded (default) - -# Multi-Threaded - - If you choose to work in multi-threaded environment under operating system you will have to - provide some basic adaptation routines to allow the driver to protect access to resources - for different threads (locking object) and to allow synchronization between threads (sync objects). - In additional the driver support running without dedicated thread allocated solely to the simple - link driver. If you choose to work in this mode, you should also supply a spawn method that - will enable to run function on a temporary context. - - - \subsection porting_step7 Step 7 - Set your asynchronous event handlers routines - - The SimpleLink device generate asynchronous events in several situations. - These asynchronous events could be masked. - In order to catch these events you have to provide handler routines. - Please notice that if you not provide a handler routine and the event is received, - the driver will drop this event without any indication of this drop. - - - \subsection porting_step8 Step 8 - Run diagnostic tools to validate the correctness of your porting - - The driver is delivered with some porting diagnostic tools to simplify the porting validation process - and to reduce issues latter. It is very important to follow carefully this process. - - The diagnostic process include: - -# Validating Interface Communication Driver - -# Validating OS adaptation layer - -# Validating HW integrity - -# Validating basic work with the device - - - \section sw_license License - - * - * - * Copyright (C) 2014 Texas Instruments Incorporated - http://www.ti.com/ - * - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * - * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the - * distribution. - * - * Neither the name of Texas Instruments Incorporated nor the names of - * its contributors may be used to endorse or promote products derived - * from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * -*/ - - - -#ifndef __SIMPLELINK_H__ -#define __SIMPLELINK_H__ - -#include "user.h" - -#ifdef __cplusplus -extern "C" -{ -#endif - - -/*! \attention Async event activation notes - Function prototypes for event callback handlers - Event handler function names should be defined in the user.h file - e.g. - "#define sl_WlanEvtHdlr SLWlanEventHandler" - Indicates all WLAN events are handled by User func "SLWlanEventHandler" - Important notes: - 1. Event handlers cannot activate another SimpleLink API from the event's context - 2. Event's data is valid during event's context. Any application data - which is required for the user application should be copied or marked - into user's variables - 3. It is not recommended to delay the execution of the event callback handler - -*/ - -/*! - - \addtogroup UserEvents - @{ - -*/ - - -/*****************************************************************************/ -/* Macro declarations for Host Driver version */ -/*****************************************************************************/ -#define SL_DRIVER_VERSION "1.0.0.10" -#define SL_MAJOR_VERSION_NUM 1L -#define SL_MINOR_VERSION_NUM 0L -#define SL_VERSION_NUM 0L -#define SL_SUB_VERSION_NUM 10L - - -/*****************************************************************************/ -/* Macro declarations for predefined configurations */ -/*****************************************************************************/ - -#ifdef SL_TINY -#undef SL_INC_ARG_CHECK -#undef SL_INC_EXT_API -#undef SL_INC_SOCK_SERVER_SIDE_API -#undef SL_INC_WLAN_PKG -#undef SL_INC_NET_CFG_PKG -#undef SL_INC_FS_PKG -#undef SL_INC_SET_UART_MODE -#undef SL_INC_STD_BSD_API_NAMING -#undef SL_INC_SOCK_CLIENT_SIDE_API -#undef SL_INC_NET_APP_PKG -#undef SL_INC_SOCK_RECV_API -#undef SL_INC_SOCK_SEND_API -#undef SL_INC_SOCKET_PKG -#endif - -#ifdef SL_SMALL -#undef SL_INC_EXT_API -#undef SL_INC_NET_APP_PKG -#undef SL_INC_NET_CFG_PKG -#undef SL_INC_FS_PKG -#define SL_INC_ARG_CHECK -#define SL_INC_WLAN_PKG -#define SL_INC_SOCKET_PKG -#define SL_INC_SOCK_CLIENT_SIDE_API -#define SL_INC_SOCK_SERVER_SIDE_API -#define SL_INC_SOCK_RECV_API -#define SL_INC_SOCK_SEND_API -#define SL_INC_SET_UART_MODE -#endif - -#ifdef SL_FULL -#define SL_INC_EXT_API -#define SL_INC_NET_APP_PKG -#define SL_INC_NET_CFG_PKG -#define SL_INC_FS_PKG -#define SL_INC_ARG_CHECK -#define SL_INC_WLAN_PKG -#define SL_INC_SOCKET_PKG -#define SL_INC_SOCK_CLIENT_SIDE_API -#define SL_INC_SOCK_SERVER_SIDE_API -#define SL_INC_SOCK_RECV_API -#define SL_INC_SOCK_SEND_API -#define SL_INC_SET_UART_MODE -#endif - -#define SL_RET_CODE_OK (0) -#define SL_RET_CODE_INVALID_INPUT (-2) -#define SL_RET_CODE_SELF_ERROR (-3) -#define SL_RET_CODE_NWP_IF_ERROR (-4) -#define SL_RET_CODE_MALLOC_ERROR (-5) - -#define sl_Memcpy memcpy -#define sl_Memset memset - -#define sl_SyncObjClear(pObj) sl_SyncObjWait(pObj,SL_OS_NO_WAIT) - -#ifndef SL_TINY_EXT -#define SL_MAX_SOCKETS (8) -#else -#define SL_MAX_SOCKETS (2) -#endif - - -/*****************************************************************************/ -/* Types definitions */ -/*****************************************************************************/ -typedef void (*_SlSpawnEntryFunc_t)(void* pValue); - -#ifndef NULL -#define NULL (0) -#endif - -#ifndef FALSE -#define FALSE (0) -#endif - -#ifndef TRUE -#define TRUE (!FALSE) -#endif - -#ifndef OK -#define OK (0) -#endif - -#ifndef _SL_USER_TYPES - typedef unsigned char _u8; - typedef signed char _i8; - - typedef unsigned short _u16; - typedef signed short _i16; - - typedef unsigned long _u32; - typedef signed long _i32; - #define _volatile volatile - #define _const const -#endif - -typedef _u16 _SlOpcode_t; -typedef _u8 _SlArgSize_t; -typedef _i16 _SlDataSize_t; -typedef _i16 _SlReturnVal_t; - -#ifdef __cplusplus -} -#endif /* __cplusplus */ - - - -/* - * This event status used to block or continue the event propagation - * through all the registered external libs/user application - * - */ - - typedef enum { - EVENT_PROPAGATION_BLOCK = 0, - EVENT_PROPAGATION_CONTINUE - - } _SlEventPropogationStatus_e; - - - - - - -/*****************************************************************************/ -/* Include files */ -/*****************************************************************************/ - -#ifdef SL_PLATFORM_MULTI_THREADED - #include "spawn.h" -#else - #include "nonos.h" -#endif - - -/* - objInclusion.h and user.h must be included before all api header files - objInclusion.h must be the last arrangement just before including the API header files - since it based on the other configurations to decide which object should be included -*/ -#include "objInclusion.h" -#include "trace.h" -#include "fs.h" -#include "socket.h" -#include "netapp.h" -#include "wlan.h" -#include "device.h" -#include "netcfg.h" -#include "wlan_rx_filters.h" - - - /* The general events dispatcher which is - * initialized to the user handler */ -#ifdef sl_GeneralEvtHdlr -#define _SlDrvHandleGeneralEvents sl_GeneralEvtHdlr -#endif - - /* The wlan events dispatcher which is - * initialized to the user handler */ -#ifdef sl_WlanEvtHdlr -#define _SlDrvHandleWlanEvents sl_WlanEvtHdlr -#endif - - /* The NetApp events dispatcher which is - * initialized to the user handler */ -#ifdef sl_NetAppEvtHdlr -#define _SlDrvHandleNetAppEvents sl_NetAppEvtHdlr -#endif - - /* The http server events dispatcher which is - * initialized to the user handler if exists */ -#ifdef sl_HttpServerCallback -#define _SlDrvHandleHttpServerEvents sl_HttpServerCallback -#endif - - /* The socket events dispatcher which is - * initialized to the user handler */ -#ifdef sl_SockEvtHdlr -#define _SlDrvHandleSockEvents sl_SockEvtHdlr -#endif - - -#ifndef __CONCAT -#define __CONCAT(x,y) x ## y -#endif -#define __CONCAT2(x,y) __CONCAT(x,y) - - -/* - * The section below handles the external lib event registration - * according to the desired events it specified in its API header file. - * The external lib should be first installed by the user (see user.h) - */ -#ifdef SL_EXT_LIB_1 - - /* General Event Registration */ - #if __CONCAT2(SL_EXT_LIB_1, _NOTIFY_GENERAL_EVENT) - extern _SlEventPropogationStatus_e __CONCAT2(SL_EXT_LIB_1, _GeneralEventHdl) (SlDeviceEvent_t *); - #define SlExtLib1GeneralEventHandler __CONCAT2(SL_EXT_LIB_1, _GeneralEventHdl) - - #undef EXT_LIB_REGISTERED_GENERAL_EVENTS - #define EXT_LIB_REGISTERED_GENERAL_EVENTS - #endif - - /* Wlan Event Registration */ - #if __CONCAT2(SL_EXT_LIB_1, _NOTIFY_WLAN_EVENT) - extern _SlEventPropogationStatus_e __CONCAT2(SL_EXT_LIB_1, _WlanEventHdl) (SlWlanEvent_t *); - #define SlExtLib1WlanEventHandler __CONCAT2(SL_EXT_LIB_1, _WlanEventHdl) - - #undef EXT_LIB_REGISTERED_WLAN_EVENTS - #define EXT_LIB_REGISTERED_WLAN_EVENTS - #endif - - /* NetApp Event Registration */ - #if __CONCAT2(SL_EXT_LIB_1, _NOTIFY_NETAPP_EVENT) - extern _SlEventPropogationStatus_e __CONCAT2(SL_EXT_LIB_1, _NetAppEventHdl) (SlNetAppEvent_t *); - #define SlExtLib1NetAppEventHandler __CONCAT2(SL_EXT_LIB_1, _NetAppEventHdl) - - #undef EXT_LIB_REGISTERED_NETAPP_EVENTS - #define EXT_LIB_REGISTERED_NETAPP_EVENTS - #endif - - /* Http Server Event Registration */ - #if __CONCAT2(SL_EXT_LIB_1, _NOTIFY_HTTP_SERVER_EVENT) - extern _SlEventPropogationStatus_e __CONCAT2(SL_EXT_LIB_1, _HttpServerEventHdl) (SlHttpServerEvent_t* , SlHttpServerResponse_t*); - #define SlExtLib1HttpServerEventHandler __CONCAT2(SL_EXT_LIB_1, _HttpServerEventHdl) - - #undef EXT_LIB_REGISTERED_HTTP_SERVER_EVENTS - #define EXT_LIB_REGISTERED_HTTP_SERVER_EVENTS - #endif - - /* Socket Event Registration */ - #if __CONCAT2(SL_EXT_LIB_1, _NOTIFY_SOCK_EVENT) - extern _SlEventPropogationStatus_e __CONCAT2(SL_EXT_LIB_1, _SockEventHdl) (SlSockEvent_t *); - #define SlExtLib1SockEventHandler __CONCAT2(SL_EXT_LIB_1, _SockEventHdl) - - #undef EXT_LIB_REGISTERED_SOCK_EVENTS - #define EXT_LIB_REGISTERED_SOCK_EVENTS - #endif - -#endif - - -#ifdef SL_EXT_LIB_2 - - /* General Event Registration */ - #if __CONCAT2(SL_EXT_LIB_2, _NOTIFY_GENERAL_EVENT) - extern _SlEventPropogationStatus_e __CONCAT2(SL_EXT_LIB_2, _GeneralEventHdl) (SlDeviceEvent_t *); - #define SlExtLib2GeneralEventHandler __CONCAT2(SL_EXT_LIB_2, _GeneralEventHdl) - - #undef EXT_LIB_REGISTERED_GENERAL_EVENTS - #define EXT_LIB_REGISTERED_GENERAL_EVENTS - #endif - - /* Wlan Event Registration */ - #if __CONCAT2(SL_EXT_LIB_2, _NOTIFY_WLAN_EVENT) - extern _SlEventPropogationStatus_e __CONCAT2(SL_EXT_LIB_2, _WlanEventHdl) (SlWlanEvent_t *); - #define SlExtLib2WlanEventHandler __CONCAT2(SL_EXT_LIB_2, _WlanEventHdl) - - #undef EXT_LIB_REGISTERED_WLAN_EVENTS - #define EXT_LIB_REGISTERED_WLAN_EVENTS - #endif - - /* NetApp Event Registration */ - #if __CONCAT2(SL_EXT_LIB_2, _NOTIFY_NETAPP_EVENT) - extern _SlEventPropogationStatus_e __CONCAT2(SL_EXT_LIB_2, _NetAppEventHdl) (SlNetAppEvent_t *); - #define SlExtLib2NetAppEventHandler __CONCAT2(SL_EXT_LIB_2, _NetAppEventHdl) - - #undef EXT_LIB_REGISTERED_NETAPP_EVENTS - #define EXT_LIB_REGISTERED_NETAPP_EVENTS - #endif - - /* Http Server Event Registration */ - #if __CONCAT2(SL_EXT_LIB_2, _NOTIFY_HTTP_SERVER_EVENT) - extern _SlEventPropogationStatus_e __CONCAT2(SL_EXT_LIB_2, _HttpServerEventHdl) (SlHttpServerEvent_t* , SlHttpServerResponse_t*); - #define SlExtLib2HttpServerEventHandler __CONCAT2(SL_EXT_LIB_2, _HttpServerEventHdl) - - #undef EXT_LIB_REGISTERED_HTTP_SERVER_EVENTS - #define EXT_LIB_REGISTERED_HTTP_SERVER_EVENTS - #endif - - /* Socket Event Registration */ - #if __CONCAT2(SL_EXT_LIB_2, _NOTIFY_SOCK_EVENT) - extern _SlEventPropogationStatus_e __CONCAT2(SL_EXT_LIB_2, _SockEventHdl) (SlSockEvent_t *); - #define SlExtLib2SockEventHandler __CONCAT2(SL_EXT_LIB_2, _SockEventHdl) - - #undef EXT_LIB_REGISTERED_SOCK_EVENTS - #define EXT_LIB_REGISTERED_SOCK_EVENTS - #endif - -#endif - - -#ifdef SL_EXT_LIB_3 - - /* General Event Registration */ - #if __CONCAT2(SL_EXT_LIB_3, _NOTIFY_GENERAL_EVENT) - extern _SlEventPropogationStatus_e __CONCAT2(SL_EXT_LIB_3, _GeneralEventHdl) (SlDeviceEvent_t *); - #define SlExtLib3GeneralEventHandler __CONCAT2(SL_EXT_LIB_3, _GeneralEventHdl) - - #undef EXT_LIB_REGISTERED_GENERAL_EVENTS - #define EXT_LIB_REGISTERED_GENERAL_EVENTS - #endif - - /* Wlan Event Registration */ - #if __CONCAT2(SL_EXT_LIB_3, _NOTIFY_WLAN_EVENT) - extern _SlEventPropogationStatus_e __CONCAT2(SL_EXT_LIB_3, _WlanEventHdl) (SlWlanEvent_t *); - #define SlExtLib3WlanEventHandler __CONCAT2(SL_EXT_LIB_3, _WlanEventHdl) - - #undef EXT_LIB_REGISTERED_WLAN_EVENTS - #define EXT_LIB_REGISTERED_WLAN_EVENTS - #endif - - /* NetApp Event Registration */ - #if __CONCAT2(SL_EXT_LIB_3, _NOTIFY_NETAPP_EVENT) - extern _SlEventPropogationStatus_e __CONCAT2(SL_EXT_LIB_3, _NetAppEventHdl) (SlNetAppEvent_t *); - #define SlExtLib3NetAppEventHandler __CONCAT2(SL_EXT_LIB_3, _NetAppEventHdl) - - #undef EXT_LIB_REGISTERED_NETAPP_EVENTS - #define EXT_LIB_REGISTERED_NETAPP_EVENTS - #endif - - /* Http Server Event Registration */ - #if __CONCAT2(SL_EXT_LIB_3, _NOTIFY_HTTP_SERVER_EVENT) - extern _SlEventPropogationStatus_e __CONCAT2(SL_EXT_LIB_3, _HttpServerEventHdl) (SlHttpServerEvent_t* , SlHttpServerResponse_t*); - #define SlExtLib3HttpServerEventHandler __CONCAT2(SL_EXT_LIB_3, _HttpServerEventHdl) - - #undef EXT_LIB_REGISTERED_HTTP_SERVER_EVENTS - #define EXT_LIB_REGISTERED_HTTP_SERVER_EVENTS - #endif - - /* Socket Event Registration */ - #if __CONCAT2(SL_EXT_LIB_3, _NOTIFY_SOCK_EVENT) - extern _SlEventPropogationStatus_e __CONCAT2(SL_EXT_LIB_3, _SockEventHdl) (SlSockEvent_t *); - #define SlExtLib3SockEventHandler __CONCAT2(SL_EXT_LIB_3, _SockEventHdl) - - #undef EXT_LIB_REGISTERED_SOCK_EVENTS - #define EXT_LIB_REGISTERED_SOCK_EVENTS - #endif - -#endif - - -#ifdef SL_EXT_LIB_4 - - /* General Event Registration */ - #if __CONCAT2(SL_EXT_LIB_4, _NOTIFY_GENERAL_EVENT) - extern _SlEventPropogationStatus_e __CONCAT2(SL_EXT_LIB_4, _GeneralEventHdl) (SlDeviceEvent_t *); - #define SlExtLib4GeneralEventHandler __CONCAT2(SL_EXT_LIB_4, _GeneralEventHdl) - - #undef EXT_LIB_REGISTERED_GENERAL_EVENTS - #define EXT_LIB_REGISTERED_GENERAL_EVENTS - #endif - - /* Wlan Event Registration */ - #if __CONCAT2(SL_EXT_LIB_4, _NOTIFY_WLAN_EVENT) - extern _SlEventPropogationStatus_e __CONCAT2(SL_EXT_LIB_4, _WlanEventHdl) (SlWlanEvent_t *); - #define SlExtLib4WlanEventHandler __CONCAT2(SL_EXT_LIB_4, _WlanEventHdl) - - #undef EXT_LIB_REGISTERED_WLAN_EVENTS - #define EXT_LIB_REGISTERED_WLAN_EVENTS - #endif - - /* NetApp Event Registration */ - #if __CONCAT2(SL_EXT_LIB_4, _NOTIFY_NETAPP_EVENT) - extern _SlEventPropogationStatus_e __CONCAT2(SL_EXT_LIB_4, _NetAppEventHdl) (SlNetAppEvent_t *); - #define SlExtLib4NetAppEventHandler __CONCAT2(SL_EXT_LIB_4, _NetAppEventHdl) - - #undef EXT_LIB_REGISTERED_NETAPP_EVENTS - #define EXT_LIB_REGISTERED_NETAPP_EVENTS - #endif - - /* Http Server Event Registration */ - #if __CONCAT2(SL_EXT_LIB_4, _NOTIFY_HTTP_SERVER_EVENT) - extern _SlEventPropogationStatus_e __CONCAT2(SL_EXT_LIB_4, _HttpServerEventHdl) (SlHttpServerEvent_t* , SlHttpServerResponse_t*); - #define SlExtLib4HttpServerEventHandler __CONCAT2(SL_EXT_LIB_4, _HttpServerEventHdl) - - #undef EXT_LIB_REGISTERED_HTTP_SERVER_EVENTS - #define EXT_LIB_REGISTERED_HTTP_SERVER_EVENTS - #endif - - /* Socket Event Registration */ - #if __CONCAT2(SL_EXT_LIB_4, _NOTIFY_SOCK_EVENT) - extern _SlEventPropogationStatus_e __CONCAT2(SL_EXT_LIB_4, _SockEventHdl) (SlSockEvent_t *); - #define SlExtLib4SockEventHandler __CONCAT2(SL_EXT_LIB_4, _SockEventHdl) - - #undef EXT_LIB_REGISTERED_SOCK_EVENTS - #define EXT_LIB_REGISTERED_SOCK_EVENTS - #endif - -#endif - - -#ifdef SL_EXT_LIB_5 - - /* General Event Registration */ - #if __CONCAT2(SL_EXT_LIB_5, _NOTIFY_GENERAL_EVENT) - extern _SlEventPropogationStatus_e __CONCAT2(SL_EXT_LIB_5, _GeneralEventHdl) (SlDeviceEvent_t *); - #define SlExtLib5GeneralEventHandler __CONCAT2(SL_EXT_LIB_5, _GeneralEventHdl) - - #undef EXT_LIB_REGISTERED_GENERAL_EVENTS - #define EXT_LIB_REGISTERED_GENERAL_EVENTS - #endif - - /* Wlan Event Registration */ - #if __CONCAT2(SL_EXT_LIB_5, _NOTIFY_WLAN_EVENT) - extern _SlEventPropogationStatus_e __CONCAT2(SL_EXT_LIB_5, _WlanEventHdl) (SlWlanEvent_t *); - #define SlExtLib5WlanEventHandler __CONCAT2(SL_EXT_LIB_5, _WlanEventHdl) - - #undef EXT_LIB_REGISTERED_WLAN_EVENTS - #define EXT_LIB_REGISTERED_WLAN_EVENTS - #endif - - /* NetApp Event Registration */ - #if __CONCAT2(SL_EXT_LIB_5, _NOTIFY_NETAPP_EVENT) - extern _SlEventPropogationStatus_e __CONCAT2(SL_EXT_LIB_5, _NetAppEventHdl) (SlNetAppEvent_t *); - #define SlExtLib5NetAppEventHandler __CONCAT2(SL_EXT_LIB_5, _NetAppEventHdl) - - #undef EXT_LIB_REGISTERED_NETAPP_EVENTS - #define EXT_LIB_REGISTERED_NETAPP_EVENTS - #endif - - /* Http Server Event Registration */ - #if __CONCAT2(SL_EXT_LIB_5, _NOTIFY_HTTP_SERVER_EVENT) - extern _SlEventPropogationStatus_e __CONCAT2(SL_EXT_LIB_5, _HttpServerEventHdl) (SlHttpServerEvent_t* , SlHttpServerResponse_t*); - #define SlExtLib5HttpServerEventHandler __CONCAT2(SL_EXT_LIB_5, _HttpServerEventHdl) - - #undef EXT_LIB_REGISTERED_HTTP_SERVER_EVENTS - #define EXT_LIB_REGISTERED_HTTP_SERVER_EVENTS - #endif - - /* Socket Event Registration */ - #if __CONCAT2(SL_EXT_LIB_5, _NOTIFY_SOCK_EVENT) - extern _SlEventPropogationStatus_e __CONCAT2(SL_EXT_LIB_5, _SockEventHdl) (SlSockEvent_t *); - #define SlExtLib5SockEventHandler __CONCAT2(SL_EXT_LIB_5, _SockEventHdl) - - #undef EXT_LIB_REGISTERED_SOCK_EVENTS - #define EXT_LIB_REGISTERED_SOCK_EVENTS - #endif - -#endif - - - -#if defined(EXT_LIB_REGISTERED_GENERAL_EVENTS) -extern void _SlDrvHandleGeneralEvents(SlDeviceEvent_t *slGeneralEvent); -#endif - -#if defined(EXT_LIB_REGISTERED_WLAN_EVENTS) -extern void _SlDrvHandleWlanEvents(SlWlanEvent_t *slWlanEvent); -#endif - -#if defined (EXT_LIB_REGISTERED_NETAPP_EVENTS) -extern void _SlDrvHandleNetAppEvents(SlNetAppEvent_t *slNetAppEvent); -#endif - -#if defined(EXT_LIB_REGISTERED_HTTP_SERVER_EVENTS) -extern void _SlDrvHandleHttpServerEvents(SlHttpServerEvent_t *slHttpServerEvent, SlHttpServerResponse_t *slHttpServerResponse); -#endif - - -#if defined(EXT_LIB_REGISTERED_SOCK_EVENTS) -extern void _SlDrvHandleSockEvents(SlSockEvent_t *slSockEvent); -#endif - - -typedef void (*_SlSpawnEntryFunc_t)(void* pValue); - - -/* Async functions description*/ - -/*! - \brief General async event for inspecting general events - - \param[out] pSlDeviceEvent pointer to SlDeviceEvent_t - - \par - Parameters: \n - - pSlDeviceEvent->Event = SL_DEVICE_FATAL_ERROR_EVENT - - pSlDeviceEvent->EventData.deviceEvent fields: - - status: An error code indication from the device - - sender: The sender originator which is based on SlErrorSender_e enum - - - pSlDeviceEvent->Event = SL_DEVICE_ABORT_ERROR_EVENT - Indicates a severe error occured and the device stopped - - pSlDeviceEvent->EventData.deviceReport fields: - - AbortType: An idication of the event type - - AbortData: Additional info about the data error - - - \par Example for fatal error: - \code - printf(General Event Handler - ID=%d Sender=%d\n\n", - pSlDeviceEvent->EventData.deviceEvent.status, // status of the general event - pSlDeviceEvent->EventData.deviceEvent.sender); // sender type - \endcode - \par Example for abort request: - \code - printf(Abort type =%d Abort Data=%d\n\n", - pSlDeviceEvent->EventData.deviceReport.AbortType, - pSlDeviceEvent->EventData.deviceReport.AbortData); - - \endcode -*/ -#if (defined(sl_GeneralEvtHdlr)) -extern void sl_GeneralEvtHdlr(SlDeviceEvent_t *pSlDeviceEvent); -#endif - - -/*! - \brief WLAN Async event handler - - \param[out] pSlWlanEvent pointer to SlWlanEvent_t data - - \par - Parameters: - - - pSlWlanEvent->Event = SL_WLAN_CONNECT_EVENT , STA or P2P client connection indication event - - pSlWlanEvent->EventData.STAandP2PModeWlanConnected main fields: - - ssid_name - - ssid_len - - bssid - - go_peer_device_name - - go_peer_device_name_len - - - pSlWlanEvent->Event = SL_WLAN_DISCONNECT_EVENT , STA or P2P client disconnection event - - pSlWlanEvent->EventData.STAandP2PModeDisconnected main fields: - - ssid_name - - ssid_len - - reason_code - - - pSlWlanEvent->Event = SL_WLAN_STA_CONNECTED_EVENT , AP/P2P(Go) connected STA/P2P(Client) - - pSlWlanEvent->EventData.APModeStaConnected fields: - - go_peer_device_name - - mac - - go_peer_device_name_len - - wps_dev_password_id - - own_ssid: relevant for event sta-connected only - - own_ssid_len: relevant for event sta-connected only - - - pSlWlanEvent->Event = SL_WLAN_STA_DISCONNECTED_EVENT , AP/P2P(Go) disconnected STA/P2P(Client) - - pSlWlanEvent->EventData.APModestaDisconnected fields: - - go_peer_device_name - - mac - - go_peer_device_name_len - - wps_dev_password_id - - own_ssid: relevant for event sta-connected only - - own_ssid_len: relevant for event sta-connected only - - - pSlWlanEvent->Event = SL_WLAN_SMART_CONFIG_COMPLETE_EVENT - - pSlWlanEvent->EventData.smartConfigStartResponse fields: - - status - - ssid_len - - ssid - - private_token_len - - private_token - - - pSlWlanEvent->Event = SL_WLAN_SMART_CONFIG_STOP_EVENT - - pSlWlanEvent->EventData.smartConfigStopResponse fields: - - status - - - pSlWlanEvent->Event = SL_WLAN_P2P_DEV_FOUND_EVENT - - pSlWlanEvent->EventData.P2PModeDevFound fields: - - go_peer_device_name - - mac - - go_peer_device_name_len - - wps_dev_password_id - - own_ssid: relevant for event sta-connected only - - own_ssid_len: relevant for event sta-connected only - - - pSlWlanEvent->Event = SL_WLAN_P2P_NEG_REQ_RECEIVED_EVENT - - pSlWlanEvent->EventData.P2PModeNegReqReceived fields - - go_peer_device_name - - mac - - go_peer_device_name_len - - wps_dev_password_id - - own_ssid: relevant for event sta-connected only - - - pSlWlanEvent->Event = SL_WLAN_CONNECTION_FAILED_EVENT , P2P only - - pSlWlanEvent->EventData.P2PModewlanConnectionFailure fields: - - status -*/ -#if (defined(sl_WlanEvtHdlr)) -extern void sl_WlanEvtHdlr(SlWlanEvent_t* pSlWlanEvent); -#endif - - -/*! - \brief NETAPP Async event handler - - \param[out] pSlNetApp pointer to SlNetAppEvent_t data - - \par - Parameters: - - pSlNetApp->Event = SL_NETAPP_IPV4_IPACQUIRED_EVENT, IPV4 acquired event - - pSlNetApp->EventData.ipAcquiredV4 fields: - - ip - - gateway - - dns - - - pSlNetApp->Event = SL_NETAPP_IP_LEASED_EVENT, AP or P2P go dhcp lease event - - pSlNetApp->EventData.ipLeased fields: - - ip_address - - lease_time - - mac - - - pSlNetApp->Event = SL_NETAPP_IP_RELEASED_EVENT, AP or P2P go dhcp ip release event - - pSlNetApp->EventData.ipReleased fields - - ip_address - - mac - - reason - -*/ -#if (defined(sl_NetAppEvtHdlr)) -extern void sl_NetAppEvtHdlr(SlNetAppEvent_t* pSlNetApp); -#endif - -/*! - \brief Socket Async event handler - - \param[out] pSlSockEvent pointer to SlSockEvent_t data - - \par - Parameters:\n - - pSlSockEvent->Event = SL_SOCKET_TX_FAILED_EVENT - - pSlSockEvent->SockTxFailData fields: - - sd - - status - - pSlSockEvent->Event = SL_SOCKET_ASYNC_EVENT - - pSlSockEvent->SockAsyncData fields: - - sd - - type: SSL_ACCEPT or RX_FRAGMENTATION_TOO_BIG or OTHER_SIDE_CLOSE_SSL_DATA_NOT_ENCRYPTED - - val - -*/ -#if (defined(sl_SockEvtHdlr)) -extern void sl_SockEvtHdlr(SlSockEvent_t* pSlSockEvent); -#endif - -/*! - \brief HTTP server async event - - \param[out] pSlHttpServerEvent pointer to SlHttpServerEvent_t - \param[in] pSlHttpServerResponse pointer to SlHttpServerResponse_t - - \par - Parameters: \n - - - pSlHttpServerEvent->Event = SL_NETAPP_HTTPGETTOKENVALUE_EVENT - - pSlHttpServerEvent->EventData fields: - - httpTokenName - - data - - len - - pSlHttpServerResponse->ResponseData fields: - - data - - len - - - pSlHttpServerEvent->Event = SL_NETAPP_HTTPPOSTTOKENVALUE_EVENT - - pSlHttpServerEvent->EventData.httpPostData fields: - - action - - token_name - - token_value - - pSlHttpServerResponse->ResponseData fields: - - data - - len - -*/ -#if (defined(sl_HttpServerCallback)) -extern void sl_HttpServerCallback(SlHttpServerEvent_t *pSlHttpServerEvent, SlHttpServerResponse_t *pSlHttpServerResponse); -#endif -/*! - - Close the Doxygen group. - @} - - */ - -#ifdef __cplusplus -} -#endif /* __cplusplus */ - -#endif /* __SIMPLELINK_H__ */ - diff --git a/drivers/cc3100/inc/socket.h b/drivers/cc3100/inc/socket.h deleted file mode 100644 index 81554d4afc..0000000000 --- a/drivers/cc3100/inc/socket.h +++ /dev/null @@ -1,1573 +0,0 @@ -/* - * socket.h - CC31xx/CC32xx Host Driver Implementation - * - * Copyright (C) 2014 Texas Instruments Incorporated - http://www.ti.com/ - * - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * - * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the - * distribution. - * - * Neither the name of Texas Instruments Incorporated nor the names of - * its contributors may be used to endorse or promote products derived - * from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * -*/ - -/*****************************************************************************/ -/* Include files */ -/*****************************************************************************/ -#include "simplelink.h" - -#ifndef __SL_SOCKET_H__ -#define __SL_SOCKET_H__ - - - - -#ifdef __cplusplus -extern "C" { -#endif - -/*! - - \addtogroup socket - @{ - -*/ - -/*****************************************************************************/ -/* Macro declarations */ -/*****************************************************************************/ - -#define SL_FD_SETSIZE SL_MAX_SOCKETS /* Number of sockets to select on - same is max sockets! */ -#define BSD_SOCKET_ID_MASK (0x0F) /* Index using the LBS 4 bits for socket id 0-7 */ -/* Define some BSD protocol constants. */ -#define SL_SOCK_STREAM (1) /* TCP Socket */ -#define SL_SOCK_DGRAM (2) /* UDP Socket */ -#define SL_SOCK_RAW (3) /* Raw socket */ -#define SL_IPPROTO_TCP (6) /* TCP Raw Socket */ -#define SL_IPPROTO_UDP (17) /* UDP Raw Socket */ -#define SL_IPPROTO_RAW (255) /* Raw Socket */ -#define SL_SEC_SOCKET (100) /* Secured Socket Layer (SSL,TLS) */ - -/* Address families. */ -#define SL_AF_INET (2) /* IPv4 socket (UDP, TCP, etc) */ -#define SL_AF_INET6 (3) /* IPv6 socket (UDP, TCP, etc) */ -#define SL_AF_INET6_EUI_48 (9) -#define SL_AF_RF (6) /* data include RF parameter, All layer by user (Wifi could be disconnected) */ -#define SL_AF_PACKET (17) -/* Protocol families, same as address families. */ -#define SL_PF_INET AF_INET -#define SL_PF_INET6 AF_INET6 -#define SL_INADDR_ANY (0) /* bind any address */ - -/* error codes */ -#define SL_SOC_ERROR (-1) /* Failure. */ -#define SL_SOC_OK ( 0) /* Success. */ -#define SL_INEXE (-8) /* socket command in execution */ -#define SL_EBADF (-9) /* Bad file number */ -#define SL_ENSOCK (-10) /* The system limit on the total number of open socket, has been reached */ -#define SL_EAGAIN (-11) /* Try again */ -#define SL_EWOULDBLOCK SL_EAGAIN -#define SL_ENOMEM (-12) /* Out of memory */ -#define SL_EACCES (-13) /* Permission denied */ -#define SL_EFAULT (-14) /* Bad address */ -#define SL_ECLOSE (-15) /* close socket operation failed to transmit all queued packets */ -#define SL_EALREADY_ENABLED (-21) /* Transceiver - Transceiver already ON. there could be only one */ -#define SL_EINVAL (-22) /* Invalid argument */ -#define SL_EAUTO_CONNECT_OR_CONNECTING (-69) /* Transceiver - During connection, connected or auto mode started */ -#define SL_CONNECTION_PENDING (-72) /* Transceiver - Device is connected, disconnect first to open transceiver */ -#define SL_EUNSUPPORTED_ROLE (-86) /* Transceiver - Trying to start when WLAN role is AP or P2P GO */ -#define SL_EDESTADDRREQ (-89) /* Destination address required */ -#define SL_EPROTOTYPE (-91) /* Protocol wrong type for socket */ -#define SL_ENOPROTOOPT (-92) /* Protocol not available */ -#define SL_EPROTONOSUPPORT (-93) /* Protocol not supported */ -#define SL_ESOCKTNOSUPPORT (-94) /* Socket type not supported */ -#define SL_EOPNOTSUPP (-95) /* Operation not supported on transport endpoint */ -#define SL_EAFNOSUPPORT (-97) /* Address family not supported by protocol */ -#define SL_EADDRINUSE (-98) /* Address already in use */ -#define SL_EADDRNOTAVAIL (-99) /* Cannot assign requested address */ -#define SL_ENETUNREACH (-101) /* Network is unreachable */ -#define SL_ENOBUFS (-105) /* No buffer space available */ -#define SL_EOBUFF SL_ENOBUFS -#define SL_EISCONN (-106) /* Transport endpoint is already connected */ -#define SL_ENOTCONN (-107) /* Transport endpoint is not connected */ -#define SL_ETIMEDOUT (-110) /* Connection timed out */ -#define SL_ECONNREFUSED (-111) /* Connection refused */ -#define SL_EALREADY (-114) /* Non blocking connect in progress, try again */ - -#define SL_ESEC_RSA_WRONG_TYPE_E (-130) /* RSA wrong block type for RSA function */ -#define SL_ESEC_RSA_BUFFER_E (-131) /* RSA buffer error, output too small or */ -#define SL_ESEC_BUFFER_E (-132) /* output buffer too small or input too large */ -#define SL_ESEC_ALGO_ID_E (-133) /* setting algo id error */ -#define SL_ESEC_PUBLIC_KEY_E (-134) /* setting public key error */ -#define SL_ESEC_DATE_E (-135) /* setting date validity error */ -#define SL_ESEC_SUBJECT_E (-136) /* setting subject name error */ -#define SL_ESEC_ISSUER_E (-137) /* setting issuer name error */ -#define SL_ESEC_CA_TRUE_E (-138) /* setting CA basic constraint true error */ -#define SL_ESEC_EXTENSIONS_E (-139) /* setting extensions error */ -#define SL_ESEC_ASN_PARSE_E (-140) /* ASN parsing error, invalid input */ -#define SL_ESEC_ASN_VERSION_E (-141) /* ASN version error, invalid number */ -#define SL_ESEC_ASN_GETINT_E (-142) /* ASN get big _i16 error, invalid data */ -#define SL_ESEC_ASN_RSA_KEY_E (-143) /* ASN key init error, invalid input */ -#define SL_ESEC_ASN_OBJECT_ID_E (-144) /* ASN object id error, invalid id */ -#define SL_ESEC_ASN_TAG_NULL_E (-145) /* ASN tag error, not null */ -#define SL_ESEC_ASN_EXPECT_0_E (-146) /* ASN expect error, not zero */ -#define SL_ESEC_ASN_BITSTR_E (-147) /* ASN bit string error, wrong id */ -#define SL_ESEC_ASN_UNKNOWN_OID_E (-148) /* ASN oid error, unknown sum id */ -#define SL_ESEC_ASN_DATE_SZ_E (-149) /* ASN date error, bad size */ -#define SL_ESEC_ASN_BEFORE_DATE_E (-150) /* ASN date error, current date before */ -#define SL_ESEC_ASN_AFTER_DATE_E (-151) /* ASN date error, current date after */ -#define SL_ESEC_ASN_SIG_OID_E (-152) /* ASN signature error, mismatched oid */ -#define SL_ESEC_ASN_TIME_E (-153) /* ASN time error, unknown time type */ -#define SL_ESEC_ASN_INPUT_E (-154) /* ASN input error, not enough data */ -#define SL_ESEC_ASN_SIG_CONFIRM_E (-155) /* ASN sig error, confirm failure */ -#define SL_ESEC_ASN_SIG_HASH_E (-156) /* ASN sig error, unsupported hash type */ -#define SL_ESEC_ASN_SIG_KEY_E (-157) /* ASN sig error, unsupported key type */ -#define SL_ESEC_ASN_DH_KEY_E (-158) /* ASN key init error, invalid input */ -#define SL_ESEC_ASN_NTRU_KEY_E (-159) /* ASN ntru key decode error, invalid input */ -#define SL_ESEC_ECC_BAD_ARG_E (-170) /* ECC input argument of wrong type */ -#define SL_ESEC_ASN_ECC_KEY_E (-171) /* ASN ECC bad input */ -#define SL_ESEC_ECC_CURVE_OID_E (-172) /* Unsupported ECC OID curve type */ -#define SL_ESEC_BAD_FUNC_ARG (-173) /* Bad function argument provided */ -#define SL_ESEC_NOT_COMPILED_IN (-174) /* Feature not compiled in */ -#define SL_ESEC_UNICODE_SIZE_E (-175) /* Unicode password too big */ -#define SL_ESEC_NO_PASSWORD (-176) /* no password provided by user */ -#define SL_ESEC_ALT_NAME_E (-177) /* alt name size problem, too big */ -#define SL_ESEC_AES_GCM_AUTH_E (-180) /* AES-GCM Authentication check failure */ -#define SL_ESEC_AES_CCM_AUTH_E (-181) /* AES-CCM Authentication check failure */ -#define SL_SOCKET_ERROR_E (-208) /* Error state on socket */ - -#define SL_ESEC_MEMORY_ERROR (-203) /* out of memory */ -#define SL_ESEC_VERIFY_FINISHED_ERROR (-204) /* verify problem on finished */ -#define SL_ESEC_VERIFY_MAC_ERROR (-205) /* verify mac problem */ -#define SL_ESEC_UNKNOWN_HANDSHAKE_TYPE (-207) /* weird handshake type */ -#define SL_ESEC_SOCKET_ERROR_E (-208) /* error state on socket */ -#define SL_ESEC_SOCKET_NODATA (-209) /* expected data, not there */ -#define SL_ESEC_INCOMPLETE_DATA (-210) /* don't have enough data to complete task */ -#define SL_ESEC_UNKNOWN_RECORD_TYPE (-211) /* unknown type in record hdr */ -#define SL_ESEC_FATAL_ERROR (-213) /* recvd alert fatal error */ -#define SL_ESEC_ENCRYPT_ERROR (-214) /* error during encryption */ -#define SL_ESEC_NO_PEER_KEY (-216) /* need peer's key */ -#define SL_ESEC_NO_PRIVATE_KEY (-217) /* need the private key */ -#define SL_ESEC_RSA_PRIVATE_ERROR (-218) /* error during rsa priv op */ -#define SL_ESEC_NO_DH_PARAMS (-219) /* server missing DH params */ -#define SL_ESEC_BUILD_MSG_ERROR (-220) /* build message failure */ -#define SL_ESEC_BAD_HELLO (-221) /* client hello malformed */ -#define SL_ESEC_DOMAIN_NAME_MISMATCH (-222) /* peer subject name mismatch */ -#define SL_ESEC_WANT_READ (-223) /* want read, call again */ -#define SL_ESEC_NOT_READY_ERROR (-224) /* handshake layer not ready */ -#define SL_ESEC_PMS_VERSION_ERROR (-225) /* pre m secret version error */ -#define SL_ESEC_VERSION_ERROR (-226) /* record layer version error */ -#define SL_ESEC_WANT_WRITE (-227) /* want write, call again */ -#define SL_ESEC_BUFFER_ERROR (-228) /* malformed buffer input */ -#define SL_ESEC_VERIFY_CERT_ERROR (-229) /* verify cert error */ -#define SL_ESEC_VERIFY_SIGN_ERROR (-230) /* verify sign error */ - -#define SL_ESEC_LENGTH_ERROR (-241) /* record layer length error */ -#define SL_ESEC_PEER_KEY_ERROR (-242) /* can't decode peer key */ -#define SL_ESEC_ZERO_RETURN (-243) /* peer sent close notify */ -#define SL_ESEC_SIDE_ERROR (-244) /* wrong client/server type */ -#define SL_ESEC_NO_PEER_CERT (-245) /* peer didn't send key */ -#define SL_ESEC_ECC_CURVETYPE_ERROR (-250) /* Bad ECC Curve Type */ -#define SL_ESEC_ECC_CURVE_ERROR (-251) /* Bad ECC Curve */ -#define SL_ESEC_ECC_PEERKEY_ERROR (-252) /* Bad Peer ECC Key */ -#define SL_ESEC_ECC_MAKEKEY_ERROR (-253) /* Bad Make ECC Key */ -#define SL_ESEC_ECC_EXPORT_ERROR (-254) /* Bad ECC Export Key */ -#define SL_ESEC_ECC_SHARED_ERROR (-255) /* Bad ECC Shared Secret */ -#define SL_ESEC_NOT_CA_ERROR (-257) /* Not a CA cert error */ -#define SL_ESEC_BAD_PATH_ERROR (-258) /* Bad path for opendir */ -#define SL_ESEC_BAD_CERT_MANAGER_ERROR (-259) /* Bad Cert Manager */ -#define SL_ESEC_MAX_CHAIN_ERROR (-268) /* max chain depth exceeded */ -#define SL_ESEC_SUITES_ERROR (-271) /* suites pointer error */ -#define SL_ESEC_SSL_NO_PEM_HEADER (-272) /* no PEM header found */ -#define SL_ESEC_OUT_OF_ORDER_E (-273) /* out of order message */ -#define SL_ESEC_SANITY_CIPHER_E (-275) /* sanity check on cipher error */ -#define SL_ESEC_GEN_COOKIE_E (-277) /* Generate Cookie Error */ -#define SL_ESEC_NO_PEER_VERIFY (-278) /* Need peer cert verify Error */ -#define SL_ESEC_UNKNOWN_SNI_HOST_NAME_E (-281) /* Unrecognized host name Error */ -/* begin negotiation parameter errors */ -#define SL_ESEC_UNSUPPORTED_SUITE (-290) /* unsupported cipher suite */ -#define SL_ESEC_MATCH_SUITE_ERROR (-291 ) /* can't match cipher suite */ - -/* ssl tls security start with -300 offset */ -#define SL_ESEC_CLOSE_NOTIFY (-300) /* ssl/tls alerts */ -#define SL_ESEC_UNEXPECTED_MESSAGE (-310) /* ssl/tls alerts */ -#define SL_ESEC_BAD_RECORD_MAC (-320) /* ssl/tls alerts */ -#define SL_ESEC_DECRYPTION_FAILED (-321) /* ssl/tls alerts */ -#define SL_ESEC_RECORD_OVERFLOW (-322) /* ssl/tls alerts */ -#define SL_ESEC_DECOMPRESSION_FAILURE (-330) /* ssl/tls alerts */ -#define SL_ESEC_HANDSHAKE_FAILURE (-340) /* ssl/tls alerts */ -#define SL_ESEC_NO_CERTIFICATE (-341) /* ssl/tls alerts */ -#define SL_ESEC_BAD_CERTIFICATE (-342) /* ssl/tls alerts */ -#define SL_ESEC_UNSUPPORTED_CERTIFICATE (-343) /* ssl/tls alerts */ -#define SL_ESEC_CERTIFICATE_REVOKED (-344) /* ssl/tls alerts */ -#define SL_ESEC_CERTIFICATE_EXPIRED (-345) /* ssl/tls alerts */ -#define SL_ESEC_CERTIFICATE_UNKNOWN (-346) /* ssl/tls alerts */ -#define SL_ESEC_ILLEGAL_PARAMETER (-347) /* ssl/tls alerts */ -#define SL_ESEC_UNKNOWN_CA (-348) /* ssl/tls alerts */ -#define SL_ESEC_ACCESS_DENIED (-349) /* ssl/tls alerts */ -#define SL_ESEC_DECODE_ERROR (-350) /* ssl/tls alerts */ -#define SL_ESEC_DECRYPT_ERROR (-351) /* ssl/tls alerts */ -#define SL_ESEC_EXPORT_RESTRICTION (-360) /* ssl/tls alerts */ -#define SL_ESEC_PROTOCOL_VERSION (-370) /* ssl/tls alerts */ -#define SL_ESEC_INSUFFICIENT_SECURITY (-371) /* ssl/tls alerts */ -#define SL_ESEC_INTERNAL_ERROR (-380) /* ssl/tls alerts */ -#define SL_ESEC_USER_CANCELLED (-390) /* ssl/tls alerts */ -#define SL_ESEC_NO_RENEGOTIATION (-400) /* ssl/tls alerts */ -#define SL_ESEC_UNSUPPORTED_EXTENSION (-410) /* ssl/tls alerts */ -#define SL_ESEC_CERTIFICATE_UNOBTAINABLE (-411) /* ssl/tls alerts */ -#define SL_ESEC_UNRECOGNIZED_NAME (-412) /* ssl/tls alerts */ -#define SL_ESEC_BAD_CERTIFICATE_STATUS_RESPONSE (-413) /* ssl/tls alerts */ -#define SL_ESEC_BAD_CERTIFICATE_HASH_VALUE (-414) /* ssl/tls alerts */ -/* propierty secure */ -#define SL_ESECGENERAL (-450) /* error secure level general error */ -#define SL_ESECDECRYPT (-451) /* error secure level, decrypt recv packet fail */ -#define SL_ESECCLOSED (-452) /* secure layrer is closed by other size , tcp is still connected */ -#define SL_ESECSNOVERIFY (-453) /* Connected without server verification */ -#define SL_ESECNOCAFILE (-454) /* error secure level CA file not found*/ -#define SL_ESECMEMORY (-455) /* error secure level No memory space available */ -#define SL_ESECBADCAFILE (-456) /* error secure level bad CA file */ -#define SL_ESECBADCERTFILE (-457) /* error secure level bad Certificate file */ -#define SL_ESECBADPRIVATEFILE (-458) /* error secure level bad private file */ -#define SL_ESECBADDHFILE (-459) /* error secure level bad DH file */ -#define SL_ESECT00MANYSSLOPENED (-460) /* MAX SSL Sockets are opened */ -#define SL_ESECDATEERROR (-461) /* connected with certificate date verification error */ -#define SL_ESECHANDSHAKETIMEDOUT (-462) /* connection timed out due to handshake time */ - -/* end error codes */ - -/* Max payload size by protocol */ -#define SL_SOCKET_PAYLOAD_TYPE_MASK (0xF0) /*4 bits type, 4 bits sockets id */ -#define SL_SOCKET_PAYLOAD_TYPE_UDP_IPV4 (0x00) /* 1472 bytes */ -#define SL_SOCKET_PAYLOAD_TYPE_TCP_IPV4 (0x10) /* 1460 bytes */ -#define SL_SOCKET_PAYLOAD_TYPE_UDP_IPV6 (0x20) /* 1452 bytes */ -#define SL_SOCKET_PAYLOAD_TYPE_TCP_IPV6 (0x30) /* 1440 bytes */ -#define SL_SOCKET_PAYLOAD_TYPE_UDP_IPV4_SECURE (0x40) /* */ -#define SL_SOCKET_PAYLOAD_TYPE_TCP_IPV4_SECURE (0x50) /* */ -#define SL_SOCKET_PAYLOAD_TYPE_UDP_IPV6_SECURE (0x60) /* */ -#define SL_SOCKET_PAYLOAD_TYPE_TCP_IPV6_SECURE (0x70) /* */ -#define SL_SOCKET_PAYLOAD_TYPE_RAW_TRANCEIVER (0x80) /* 1536 bytes */ -#define SL_SOCKET_PAYLOAD_TYPE_RAW_PACKET (0x90) /* 1536 bytes */ -#define SL_SOCKET_PAYLOAD_TYPE_RAW_IP4 (0xa0) -#define SL_SOCKET_PAYLOAD_TYPE_RAW_IP6 (SL_SOCKET_PAYLOAD_TYPE_RAW_IP4 ) - - - -#define SL_SOL_SOCKET (1) /* Define the socket option category. */ -#define SL_IPPROTO_IP (2) /* Define the IP option category. */ -#define SL_SOL_PHY_OPT (3) /* Define the PHY option category. */ - -#define SL_SO_RCVBUF (8) /* Setting TCP receive buffer size */ -#define SL_SO_KEEPALIVE (9) /* Connections are kept alive with periodic messages */ -#define SL_SO_RCVTIMEO (20) /* Enable receive timeout */ -#define SL_SO_NONBLOCKING (24) /* Enable . disable nonblocking mode */ -#define SL_SO_SECMETHOD (25) /* security metohd */ -#define SL_SO_SECURE_MASK (26) /* security mask */ -#define SL_SO_SECURE_FILES (27) /* security files */ -#define SL_SO_CHANGE_CHANNEL (28) /* This option is available only when transceiver started */ -#define SL_SO_SECURE_FILES_PRIVATE_KEY_FILE_NAME (30) /* This option used to configue secure file */ -#define SL_SO_SECURE_FILES_CERTIFICATE_FILE_NAME (31) /* This option used to configue secure file */ -#define SL_SO_SECURE_FILES_CA_FILE_NAME (32) /* This option used to configue secure file */ -#define SL_SO_SECURE_FILES_DH_KEY_FILE_NAME (33) /* This option used to configue secure file */ - -#define SL_IP_MULTICAST_IF (60) /* Specify outgoing multicast interface */ -#define SL_IP_MULTICAST_TTL (61) /* Specify the TTL value to use for outgoing multicast packet. */ -#define SL_IP_ADD_MEMBERSHIP (65) /* Join IPv4 multicast membership */ -#define SL_IP_DROP_MEMBERSHIP (66) /* Leave IPv4 multicast membership */ -#define SL_IP_HDRINCL (67) /* Raw socket IPv4 header included. */ -#define SL_IP_RAW_RX_NO_HEADER (68) /* Proprietary socket option that does not includeIPv4/IPv6 header (and extension headers) on received raw sockets*/ -#define SL_IP_RAW_IPV6_HDRINCL (69) /* Transmitted buffer over IPv6 socket contains IPv6 header. */ - -#define SL_SO_PHY_RATE (100) /* WLAN Transmit rate */ -#define SL_SO_PHY_TX_POWER (101) /* TX Power level */ -#define SL_SO_PHY_NUM_FRAMES_TO_TX (102) /* Number of frames to transmit */ -#define SL_SO_PHY_PREAMBLE (103) /* Preamble for transmission */ - -#define SL_SO_SEC_METHOD_SSLV3 (0) /* security metohd SSL v3*/ -#define SL_SO_SEC_METHOD_TLSV1 (1) /* security metohd TLS v1*/ -#define SL_SO_SEC_METHOD_TLSV1_1 (2) /* security metohd TLS v1_1*/ -#define SL_SO_SEC_METHOD_TLSV1_2 (3) /* security metohd TLS v1_2*/ -#define SL_SO_SEC_METHOD_SSLv3_TLSV1_2 (4) /* use highest possible version from SSLv3 - TLS 1.2*/ -#define SL_SO_SEC_METHOD_DLSV1 (5) /* security metohd DTL v1 */ - -#define SL_SEC_MASK_SSL_RSA_WITH_RC4_128_SHA (1 << 0) -#define SL_SEC_MASK_SSL_RSA_WITH_RC4_128_MD5 (1 << 1) -#define SL_SEC_MASK_TLS_RSA_WITH_AES_256_CBC_SHA (1 << 2) -#define SL_SEC_MASK_TLS_DHE_RSA_WITH_AES_256_CBC_SHA (1 << 3) -#define SL_SEC_MASK_TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA (1 << 4) -#define SL_SEC_MASK_TLS_ECDHE_RSA_WITH_RC4_128_SHA (1 << 5) -#define SL_SEC_MASK_TLS_RSA_WITH_AES_128_CBC_SHA256 (1 << 6) -#define SL_SEC_MASK_TLS_RSA_WITH_AES_256_CBC_SHA256 (1 << 7) -#define SL_SEC_MASK_TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256 (1 << 8) -#define SL_SEC_MASK_TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256 (1 << 9) - - -#define SL_SEC_MASK_SECURE_DEFAULT ((SL_SEC_MASK_TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256 << 1) - 1) - -#define SL_MSG_DONTWAIT (0x00000008) /* Nonblocking IO */ - -/* AP DHCP Server - IP Release reason code */ -#define SL_IP_LEASE_PEER_RELEASE (0) -#define SL_IP_LEASE_PEER_DECLINE (1) -#define SL_IP_LEASE_EXPIRED (2) - -/* possible types when receiving SL_SOCKET_ASYNC_EVENT*/ -#define SSL_ACCEPT (1) /* accept failed due to ssl issue ( tcp pass) */ -#define RX_FRAGMENTATION_TOO_BIG (2) /* connection less mode, rx packet fragmentation > 16K, packet is being released */ -#define OTHER_SIDE_CLOSE_SSL_DATA_NOT_ENCRYPTED (3) /* remote side down from secure to unsecure */ - - - -#ifdef SL_INC_STD_BSD_API_NAMING - -#define FD_SETSIZE SL_FD_SETSIZE - -#define SOCK_STREAM SL_SOCK_STREAM -#define SOCK_DGRAM SL_SOCK_DGRAM -#define SOCK_RAW SL_SOCK_RAW -#define IPPROTO_TCP SL_IPPROTO_TCP -#define IPPROTO_UDP SL_IPPROTO_UDP -#define IPPROTO_RAW SL_IPPROTO_RAW - -#define AF_INET SL_AF_INET -#define AF_INET6 SL_AF_INET6 -#define AF_INET6_EUI_48 SL_AF_INET6_EUI_48 -#define AF_RF SL_AF_RF -#define AF_PACKET SL_AF_PACKET - -#define PF_INET SL_PF_INET -#define PF_INET6 SL_PF_INET6 - -#define INADDR_ANY SL_INADDR_ANY -#define ERROR SL_SOC_ERROR -#define INEXE SL_INEXE -#define EBADF SL_EBADF -#define ENSOCK SL_ENSOCK -#define EAGAIN SL_EAGAIN -#define EWOULDBLOCK SL_EWOULDBLOCK -#define ENOMEM SL_ENOMEM -#define EACCES SL_EACCES -#define EFAULT SL_EFAULT -#define EINVAL SL_EINVAL -#define EDESTADDRREQ SL_EDESTADDRREQ -#define EPROTOTYPE SL_EPROTOTYPE -#define ENOPROTOOPT SL_ENOPROTOOPT -#define EPROTONOSUPPORT SL_EPROTONOSUPPORT -#define ESOCKTNOSUPPORT SL_ESOCKTNOSUPPORT -#define EOPNOTSUPP SL_EOPNOTSUPP -#define EAFNOSUPPORT SL_EAFNOSUPPORT -#define EADDRINUSE SL_EADDRINUSE -#define EADDRNOTAVAIL SL_EADDRNOTAVAIL -#define ENETUNREACH SL_ENETUNREACH -#define ENOBUFS SL_ENOBUFS -#define EOBUFF SL_EOBUFF -#define EISCONN SL_EISCONN -#define ENOTCONN SL_ENOTCONN -#define ETIMEDOUT SL_ETIMEDOUT -#define ECONNREFUSED SL_ECONNREFUSED - -#define SOL_SOCKET SL_SOL_SOCKET -#define IPPROTO_IP SL_IPPROTO_IP -#define SO_KEEPALIVE SL_SO_KEEPALIVE - -#define SO_RCVTIMEO SL_SO_RCVTIMEO -#define SO_NONBLOCKING SL_SO_NONBLOCKING - -#define IP_MULTICAST_IF SL_IP_MULTICAST_IF -#define IP_MULTICAST_TTL SL_IP_MULTICAST_TTL -#define IP_ADD_MEMBERSHIP SL_IP_ADD_MEMBERSHIP -#define IP_DROP_MEMBERSHIP SL_IP_DROP_MEMBERSHIP - -#define socklen_t SlSocklen_t -#define timeval SlTimeval_t -#define sockaddr SlSockAddr_t -#define in6_addr SlIn6Addr_t -#define sockaddr_in6 SlSockAddrIn6_t -#define in_addr SlInAddr_t -#define sockaddr_in SlSockAddrIn_t - -#define MSG_DONTWAIT SL_MSG_DONTWAIT - -#define FD_SET SL_FD_SET -#define FD_CLR SL_FD_CLR -#define FD_ISSET SL_FD_ISSET -#define FD_ZERO SL_FD_ZERO -#define fd_set SlFdSet_t - -#define socket sl_Socket -#define close sl_Close -#define accept sl_Accept -#define bind sl_Bind -#define listen sl_Listen -#define connect sl_Connect -#define select sl_Select -#define setsockopt sl_SetSockOpt -#define getsockopt sl_GetSockOpt -#define recv sl_Recv -#define recvfrom sl_RecvFrom -#define write sl_Write -#define send sl_Send -#define sendto sl_SendTo -#define gethostbyname sl_NetAppDnsGetHostByName -#define htonl sl_Htonl -#define ntohl sl_Ntohl -#define htons sl_Htons -#define ntohs sl_Ntohs -#endif - -/*****************************************************************************/ -/* Structure/Enum declarations */ -/*****************************************************************************/ - -/* Internet address */ -typedef struct SlInAddr_t -{ -#ifndef s_addr - _u32 s_addr; /* Internet address 32 bits */ -#else - union S_un { - struct { _u8 s_b1,s_b2,s_b3,s_b4; } S_un_b; - struct { _u8 s_w1,s_w2; } S_un_w; - _u32 S_addr; - } S_un; -#endif -}SlInAddr_t; - - -/* sockopt */ -typedef struct -{ - _u32 KeepaliveEnabled; /* 0 = disabled;1 = enabled; default = 1*/ -}SlSockKeepalive_t; - -typedef struct -{ - _u32 ReuseaddrEnabled; /* 0 = disabled; 1 = enabled; default = 1*/ -}SlSockReuseaddr_t; - -typedef struct -{ - _u32 Winsize; /* receive window size for tcp sockets */ -}SlSockWinsize_t; - -typedef struct -{ - _u32 NonblockingEnabled;/* 0 = disabled;1 = enabled;default = 1*/ -}SlSockNonblocking_t; - - -typedef struct -{ - _u8 sd; - _u8 type; - _i16 val; - _u8* pExtraInfo; -} SlSocketAsyncEvent_t; - -typedef struct -{ - _i16 status; - _u8 sd; - _u8 padding; -} SlSockTxFailEventData_t; - - -typedef union -{ - SlSockTxFailEventData_t SockTxFailData; - SlSocketAsyncEvent_t SockAsyncData; -} SlSockEventData_u; - - -typedef struct -{ - _u32 Event; - SlSockEventData_u socketAsyncEvent; -} SlSockEvent_t; - - - - - - -typedef struct -{ - _u32 secureMask; -} SlSockSecureMask; - -typedef struct -{ - _u8 secureMethod; -} SlSockSecureMethod; - -typedef enum -{ - SL_BSD_SECURED_PRIVATE_KEY_IDX = 0, - SL_BSD_SECURED_CERTIFICATE_IDX, - SL_BSD_SECURED_CA_IDX, - SL_BSD_SECURED_DH_IDX -}slBsd_secureSocketFilesIndex_e; - -typedef struct -{ - SlInAddr_t imr_multiaddr; /* The IPv4 multicast address to join */ - SlInAddr_t imr_interface; /* The interface to use for this group */ -} SlSockIpMreq; - - -/* sockopt */ -typedef _u32 SlTime_t; -typedef _u32 SlSuseconds_t; - -typedef struct SlTimeval_t -{ - SlTime_t tv_sec; /* Seconds */ - SlSuseconds_t tv_usec; /* Microseconds */ -}SlTimeval_t; - -typedef _u16 SlSocklen_t; - -/* IpV4 socket address */ -typedef struct SlSockAddr_t -{ - _u16 sa_family; /* Address family (e.g. , AF_INET) */ - _u8 sa_data[14]; /* Protocol- specific address information*/ -}SlSockAddr_t; - - -/* IpV6 or Ipv6 EUI64 */ -typedef struct SlIn6Addr_t -{ - union - { - _u8 _S6_u8[16]; - _u32 _S6_u32[4]; - } _S6_un; -}SlIn6Addr_t; - -typedef struct SlSockAddrIn6_t -{ - _u16 sin6_family; /* AF_INET6 || AF_INET6_EUI_48*/ - _u16 sin6_port; /* Transport layer port. */ - _u32 sin6_flowinfo; /* IPv6 flow information. */ - SlIn6Addr_t sin6_addr; /* IPv6 address. */ - _u32 sin6_scope_id; /* set of interfaces for a scope. */ -}SlSockAddrIn6_t; - -/* Socket address, Internet style. */ - -typedef struct SlSockAddrIn_t -{ - _u16 sin_family; /* Internet Protocol (AF_INET). */ - _u16 sin_port; /* Address port (16 bits). */ - SlInAddr_t sin_addr; /* Internet address (32 bits). */ - _i8 sin_zero[8]; /* Not used. */ -}SlSockAddrIn_t; - -typedef struct -{ - _u32 ip; - _u32 gateway; - _u32 dns; -}SlIpV4AcquiredAsync_t; - -typedef struct -{ - _u32 type; - _u32 ip[4]; - _u32 gateway[4]; - _u32 dns[4]; -}SlIpV6AcquiredAsync_t; - -typedef struct -{ - _u32 ip_address; - _u32 lease_time; - _u8 mac[6]; - _u16 padding; -}SlIpLeasedAsync_t; - -typedef struct -{ - _u32 ip_address; - _u8 mac[6]; - _u16 reason; -}SlIpReleasedAsync_t; - - -typedef union -{ - SlIpV4AcquiredAsync_t ipAcquiredV4; /*SL_NETAPP_IPV4_IPACQUIRED_EVENT*/ - SlIpV6AcquiredAsync_t ipAcquiredV6; /*SL_NETAPP_IPV6_IPACQUIRED_EVENT*/ - _u32 sd; /*SL_SOCKET_TX_FAILED_EVENT*/ - SlIpLeasedAsync_t ipLeased; /* SL_NETAPP_IP_LEASED_EVENT */ - SlIpReleasedAsync_t ipReleased; /* SL_NETAPP_IP_RELEASED_EVENT */ -} SlNetAppEventData_u; - -typedef struct -{ - _u32 Event; - SlNetAppEventData_u EventData; -}SlNetAppEvent_t; - - -typedef struct sock_secureFiles -{ - _u8 secureFiles[4]; -}SlSockSecureFiles_t; - - -typedef struct SlFdSet_t /* The select socket array manager */ -{ - _u32 fd_array[(SL_FD_SETSIZE + 31)/32]; /* Bit map of SOCKET Descriptors */ -} SlFdSet_t; - -typedef struct -{ - _u8 rate; /* Recevied Rate */ - _u8 channel; /* The received channel*/ - _i8 rssi; /* The computed RSSI value in db of current frame */ - _u8 padding; /* pad to align to 32 bits */ - _u32 timestamp; /* Timestamp in microseconds, */ -}SlTransceiverRxOverHead_t; - - - -/*****************************************************************************/ -/* Function prototypes */ -/*****************************************************************************/ - -/*! - - \brief create an endpoint for communication - - The socket function creates a new socket of a certain socket type, identified - by an integer number, and allocates system resources to it. - This function is called by the application layer to obtain a socket handle. - - \param[in] domain specifies the protocol family of the created socket. - For example: - AF_INET for network protocol IPv4 - AF_RF for starting transceiver mode. Notes: - - sending and receiving any packet overriding 802.11 header - - for optimized power consumption the socket will be started in TX - only mode until receive command is activated - AF_INET6 for IPv6 - - - \param[in] type specifies the communication semantic, one of: - SOCK_STREAM (reliable stream-oriented service or Stream Sockets) - SOCK_DGRAM (datagram service or Datagram Sockets) - SOCK_RAW (raw protocols atop the network layer) - when used with AF_RF: - SOCK_DGRAM - L2 socket - SOCK_RAW - L1 socket - bypass WLAN CCA (Clear Channel Assessment) - - \param[in] protocol specifies a particular transport to be used with - the socket. - The most common are IPPROTO_TCP, IPPROTO_SCTP, IPPROTO_UDP, - IPPROTO_DCCP. - The value 0 may be used to select a default - protocol from the selected domain and type - - - \return On success, socket handle that is used for consequent socket operations. - A successful return code should be a positive number (int16) - On error, a negative (int16) value will be returned specifying the error code. - SL_EAFNOSUPPORT - illegal domain parameter - SL_EPROTOTYPE - illegal type parameter - SL_EACCES - permission denied - SL_ENSOCK - exceeded maximal number of socket - SL_ENOMEM - memory allocation error - SL_EINVAL - error in socket configuration - SL_EPROTONOSUPPORT - illegal protocol parameter - SL_EOPNOTSUPP - illegal combination of protocol and type parameters - - - \sa sl_Close - \note belongs to \ref basic_api - \warning -*/ -#if _SL_INCLUDE_FUNC(sl_Socket) -_i16 sl_Socket(_i16 Domain, _i16 Type, _i16 Protocol); -#endif - -/*! - \brief gracefully close socket - - This function causes the system to release resources allocated to a socket. \n - In case of TCP, the connection is terminated. - - \param[in] sd socket handle (received in sl_Socket) - - \return On success, zero is returned. - On error, a negative number is returned. - - \sa sl_Socket - \note belongs to \ref ext_api - \warning -*/ -#if _SL_INCLUDE_FUNC(sl_Close) -_i16 sl_Close(_i16 sd); -#endif - -/*! - \brief Accept a connection on a socket - - This function is used with connection-based socket types (SOCK_STREAM). - It extracts the first connection request on the queue of pending - connections, creates a new connected socket, and returns a new file - descriptor referring to that socket. - The newly created socket is not in the listening state. The - original socket sd is unaffected by this call. - The argument sd is a socket that has been created with - sl_Socket(), bound to a local address with sl_Bind(), and is - listening for connections after a sl_Listen(). The argument \b - \e addr is a pointer to a sockaddr structure. This structure - is filled in with the address of the peer socket, as known to - the communications layer. The exact format of the address - returned addr is determined by the socket's address family. - The \b \e addrlen argument is a value-result argument: it - should initially contain the size of the structure pointed to - by addr, on return it will contain the actual length (in - bytes) of the address returned. - - \param[in] sd socket descriptor (handle) - \param[out] addr the argument addr is a pointer - to a sockaddr structure. This - structure is filled in with the - address of the peer socket, as - known to the communications - layer. The exact format of the - address returned addr is - determined by the socket's - address\n - sockaddr:\n - code for the - address format. On this version - only AF_INET is supported.\n - - socket address, the length - depends on the code format - \param[out] addrlen the addrlen argument is a value-result - argument: it should initially contain the - size of the structure pointed to by addr - - \return On success, a socket handle. - On a non-blocking accept a possible negative value is SL_EAGAIN. - On failure, negative value. - SL_POOL_IS_EMPTY may be return in case there are no resources in the system - In this case try again later or increase MAX_CONCURRENT_ACTIONS - - \sa sl_Socket sl_Bind sl_Listen - \note belongs to \ref server_side - \warning -*/ -#if _SL_INCLUDE_FUNC(sl_Accept) -_i16 sl_Accept(_i16 sd, SlSockAddr_t *addr, SlSocklen_t *addrlen); -#endif - -/*! - \brief assign a name to a socket - - This function gives the socket the local address addr. - addr is addrlen bytes long. Traditionally, this is called - When a socket is created with socket, it exists in a name - space (address family) but has no name assigned. - It is necessary to assign a local address before a SOCK_STREAM - socket may receive connections. - - \param[in] sd socket descriptor (handle) - \param[in] addr specifies the destination - addrs\n sockaddr:\n - code for - the address format. On this - version only AF_INET is - supported.\n - socket address, - the length depends on the code - format - \param[in] addrlen contains the size of the structure pointed to by addr - - \return On success, zero is returned. On error, a negative error code is returned. - - \sa sl_Socket sl_Accept sl_Listen - \note belongs to \ref basic_api - \warning -*/ -#if _SL_INCLUDE_FUNC(sl_Bind) -_i16 sl_Bind(_i16 sd, const SlSockAddr_t *addr, _i16 addrlen); -#endif - -/*! - \brief listen for connections on a socket - - The willingness to accept incoming connections and a queue - limit for incoming connections are specified with listen(), - and then the connections are accepted with accept. - The listen() call applies only to sockets of type SOCK_STREAM - The backlog parameter defines the maximum length the queue of - pending connections may grow to. - - \param[in] sd socket descriptor (handle) - \param[in] backlog specifies the listen queue depth. - - - \return On success, zero is returned. On error, a negative error code is returned. - - \sa sl_Socket sl_Accept sl_Bind - \note belongs to \ref server_side - \warning -*/ -#if _SL_INCLUDE_FUNC(sl_Listen) -_i16 sl_Listen(_i16 sd, _i16 backlog); -#endif - -/*! - \brief Initiate a connection on a socket - - Function connects the socket referred to by the socket - descriptor sd, to the address specified by addr. The addrlen - argument specifies the size of addr. The format of the - address in addr is determined by the address space of the - socket. If it is of type SOCK_DGRAM, this call specifies the - peer with which the socket is to be associated; this address - is that to which datagrams are to be sent, and the only - address from which datagrams are to be received. If the - socket is of type SOCK_STREAM, this call attempts to make a - connection to another socket. The other socket is specified - by address, which is an address in the communications space - of the socket. - - - \param[in] sd socket descriptor (handle) - \param[in] addr specifies the destination addr\n - sockaddr:\n - code for the - address format. On this version - only AF_INET is supported.\n - - socket address, the length - depends on the code format - - \param[in] addrlen contains the size of the structure pointed - to by addr - - \return On success, a socket handle. - On a non-blocking connect a possible negative value is SL_EALREADY. - On failure, negative value. - SL_POOL_IS_EMPTY may be return in case there are no resources in the system - In this case try again later or increase MAX_CONCURRENT_ACTIONS - - \sa sl_Socket - \note belongs to \ref client_side - \warning -*/ -#if _SL_INCLUDE_FUNC(sl_Connect) -_i16 sl_Connect(_i16 sd, const SlSockAddr_t *addr, _i16 addrlen); -#endif - -/*! - \brief Monitor socket activity - - Select allow a program to monitor multiple file descriptors, - waiting until one or more of the file descriptors become - "ready" for some class of I/O operation - - - \param[in] nfds the highest-numbered file descriptor in any of the - three sets, plus 1. - \param[out] readsds socket descriptors list for read monitoring and accept monitoring - \param[out] writesds socket descriptors list for connect monitoring only, write monitoring is not supported, non blocking connect is supported - \param[out] exceptsds socket descriptors list for exception monitoring, not supported. - \param[in] timeout is an upper bound on the amount of time elapsed - before select() returns. Null or above 0xffff seconds means - infinity timeout. The minimum timeout is 10 milliseconds, - less than 10 milliseconds will be set automatically to 10 milliseconds. - Max microseconds supported is 0xfffc00. - - \return On success, select() returns the number of - file descriptors contained in the three returned - descriptor sets (that is, the total number of bits that - are set in readfds, writefds, exceptfds) which may be - zero if the timeout expires before anything interesting - happens. On error, a negative value is returned. - readsds - return the sockets on which Read request will - return without delay with valid data. - writesds - return the sockets on which Write request - will return without delay. - exceptsds - return the sockets closed recently. - SL_POOL_IS_EMPTY may be return in case there are no resources in the system - In this case try again later or increase MAX_CONCURRENT_ACTIONS - - \sa sl_Socket - \note If the timeout value set to less than 5ms it will automatically set - to 5ms to prevent overload of the system - belongs to \ref basic_api - - Only one sl_Select can be handled at a time. - Calling this API while the same command is called from another thread, may result - in one of the two scenarios: - 1. The command will wait (internal) until the previous command finish, and then be executed. - 2. There are not enough resources and SL_POOL_IS_EMPTY error will return. - In this case, MAX_CONCURRENT_ACTIONS can be increased (result in memory increase) or try - again later to issue the command. - - \warning -*/ -#if _SL_INCLUDE_FUNC(sl_Select) -_i16 sl_Select(_i16 nfds, SlFdSet_t *readsds, SlFdSet_t *writesds, SlFdSet_t *exceptsds, struct SlTimeval_t *timeout); - - -/*! - \brief Select's SlFdSet_t SET function - - Sets current socket descriptor on SlFdSet_t container -*/ -void SL_FD_SET(_i16 fd, SlFdSet_t *fdset); - -/*! - \brief Select's SlFdSet_t CLR function - - Clears current socket descriptor on SlFdSet_t container -*/ -void SL_FD_CLR(_i16 fd, SlFdSet_t *fdset); - - -/*! - \brief Select's SlFdSet_t ISSET function - - Checks if current socket descriptor is set (TRUE/FALSE) - - \return Returns TRUE if set, FALSE if unset - -*/ -_i16 SL_FD_ISSET(_i16 fd, SlFdSet_t *fdset); - -/*! - \brief Select's SlFdSet_t ZERO function - - Clears all socket descriptors from SlFdSet_t -*/ -void SL_FD_ZERO(SlFdSet_t *fdset); - - - -#endif - -/*! - \brief set socket options - - This function manipulate the options associated with a socket. - Options may exist at multiple protocol levels; they are always - present at the uppermost socket level. - - When manipulating socket options the level at which the option resides - and the name of the option must be specified. To manipulate options at - the socket level, level is specified as SOL_SOCKET. To manipulate - options at any other level the protocol number of the appropriate proto- - col controlling the option is supplied. For example, to indicate that an - option is to be interpreted by the TCP protocol, level should be set to - the protocol number of TCP; - - The parameters optval and optlen are used to access optval - - ues for setsockopt(). For getsockopt() they identify a - buffer in which the value for the requested option(s) are to - be returned. For getsockopt(), optlen is a value-result - parameter, initially containing the size of the buffer - pointed to by option_value, and modified on return to - indicate the actual size of the value returned. If no option - value is to be supplied or returned, option_value may be - NULL. - - \param[in] sd socket handle - \param[in] level defines the protocol level for this option - - SL_SOL_SOCKET Socket level configurations (L4, transport layer) - - SL_IPPROTO_IP IP level configurations (L3, network layer) - - SL_SOL_PHY_OPT Link level configurations (L2, link layer) - \param[in] optname defines the option name to interrogate - - SL_SOL_SOCKET - - SL_SO_KEEPALIVE \n - Enable/Disable periodic keep alive. - Keeps TCP connections active by enabling the periodic transmission of messages \n - Timeout is 5 minutes.\n - Default: Enabled \n - This options takes SlSockKeepalive_t struct as parameter - - SL_SO_RCVTIMEO \n - Sets the timeout value that specifies the maximum amount of time an input function waits until it completes. \n - Default: No timeout \n - This options takes SlTimeval_t struct as parameter - - SL_SO_RCVBUF \n - Sets tcp max recv window size. \n - This options takes SlSockWinsize_t struct as parameter - - SL_SO_NONBLOCKING \n - Sets socket to non-blocking operation Impacts: connect, accept, send, sendto, recv and recvfrom. \n - Default: Blocking. - This options takes SlSockNonblocking_t struct as parameter - - SL_SO_SECMETHOD \n - Sets method to tcp secured socket (SL_SEC_SOCKET) \n - Default: SL_SO_SEC_METHOD_SSLv3_TLSV1_2 \n - This options takes SlSockSecureMethod struct as parameter - - SL_SO_SEC_MASK \n - Sets specific cipher to tcp secured socket (SL_SEC_SOCKET) \n - Default: "Best" cipher suitable to method \n - This options takes SlSockSecureMask struct as parameter - - SL_SO_SECURE_FILES_CA_FILE_NAME \n - Map secured socket to CA file by name \n - This options takes _u8 buffer as parameter - - SL_SO_SECURE_FILES_PRIVATE_KEY_FILE_NAME \n - Map secured socket to private key by name \n - This options takes _u8 buffer as parameter - - SL_SO_SECURE_FILES_CERTIFICATE_FILE_NAME \n - Map secured socket to certificate file by name \n - This options takes _u8 buffer as parameter - - SL_SO_SECURE_FILES_DH_KEY_FILE_NAME \n - Map secured socket to Diffie Hellman file by name \n - This options takes _u8 buffer as parameter - - SL_SO_CHANGE_CHANNEL \n - Sets channel in transceiver mode. - This options takes _u32 as channel number parameter - - SL_IPPROTO_IP - - SL_IP_MULTICAST_TTL \n - Set the time-to-live value of outgoing multicast packets for this socket. \n - This options takes _u8 as parameter - - SL_IP_ADD_MEMBERSHIP \n - UDP socket, Join a multicast group. \n - This options takes SlSockIpMreq struct as parameter - - SL_IP_DROP_MEMBERSHIP \n - UDP socket, Leave a multicast group \n - This options takes SlSockIpMreq struct as parameter - - SL_IP_RAW_RX_NO_HEADER \n - Raw socket remove IP header from received data. \n - Default: data includes ip header \n - This options takes _u32 as parameter - - SL_IP_HDRINCL \n - RAW socket only, the IPv4 layer generates an IP header when sending a packet unless \n - the IP_HDRINCL socket option is enabled on the socket. \n - When it is enabled, the packet must contain an IP header. \n - Default: disabled, IPv4 header generated by Network Stack \n - This options takes _u32 as parameter - - SL_IP_RAW_IPV6_HDRINCL (inactive) \n - RAW socket only, the IPv6 layer generates an IP header when sending a packet unless \n - the IP_HDRINCL socket option is enabled on the socket. When it is enabled, the packet must contain an IP header \n - Default: disabled, IPv4 header generated by Network Stack \n - This options takes _u32 as parameter - - SL_SOL_PHY_OPT - - SL_SO_PHY_RATE \n - RAW socket, set WLAN PHY transmit rate \n - The values are based on RateIndex_e \n - This options takes _u32 as parameter - - SL_SO_PHY_TX_POWER \n - RAW socket, set WLAN PHY TX power \n - Valid rage is 1-15 \n - This options takes _u32 as parameter - - SL_SO_PHY_NUM_FRAMES_TO_TX \n - RAW socket, set number of frames to transmit in transceiver mode. - Default: 1 packet - This options takes _u32 as parameter - - SL_SO_PHY_PREAMBLE \n - RAW socket, set WLAN PHY preamble for Long/Short\n - This options takes _u32 as parameter - - \param[in] optval specifies a value for the option - \param[in] optlen specifies the length of the - option value - - \return On success, zero is returned. - On error, a negative value is returned. - \sa sl_getsockopt - \note belongs to \ref basic_api - \warning - \par Examples: - \par - SL_SO_KEEPALIVE: (disable Keepalive) - \code - SlSockKeepalive_t enableOption; - enableOption.KeepaliveEnabled = 0; - sl_SetSockOpt(SockID,SL_SOL_SOCKET,SL_SO_KEEPALIVE, (_u8 *)&enableOption,sizeof(enableOption)); - \endcode - \par - SL_SO_RCVTIMEO: - \code - struct SlTimeval_t timeVal; - timeVal.tv_sec = 1; // Seconds - timeVal.tv_usec = 0; // Microseconds. 10000 microseconds resolution - sl_SetSockOpt(SockID,SL_SOL_SOCKET,SL_SO_RCVTIMEO, (_u8 *)&timeVal, sizeof(timeVal)); // Enable receive timeout - \endcode - \par - SL_SO_RCVBUF: - \code - SlSockWinsize_t size; - size.Winsize = 3000; // bytes - sl_SetSockOpt(SockID,SL_SOL_SOCKET,SL_SO_RCVBUF, (_u8 *)&size, sizeof(size)); - \endcode - \par - SL_SO_NONBLOCKING: - \code - SlSockNonblocking_t enableOption; - enableOption.NonblockingEnabled = 1; - sl_SetSockOpt(SockID,SL_SOL_SOCKET,SL_SO_NONBLOCKING, (_u8 *)&enableOption,sizeof(enableOption)); // Enable/disable nonblocking mode - \endcode - \par - SL_SO_SECMETHOD: - \code - SlSockSecureMethod method; - method.secureMethod = SL_SO_SEC_METHOD_SSLV3; // security method we want to use - SockID = sl_Socket(SL_AF_INET,SL_SOCK_STREAM, SL_SEC_SOCKET); - sl_SetSockOpt(SockID, SL_SOL_SOCKET, SL_SO_SECMETHOD, (_u8 *)&method, sizeof(method)); - \endcode - \par - SL_SO_SECURE_MASK: - \code - SlSockSecureMask cipher; - cipher.secureMask = SL_SEC_MASK_SSL_RSA_WITH_RC4_128_SHA; // cipher type - SockID = sl_Socket(SL_AF_INET,SL_SOCK_STREAM, SL_SEC_SOCKET); - sl_SetSockOpt(SockID, SL_SOL_SOCKET, SL_SO_SEC_MASK,(_u8 *)&cipher, sizeof(cipher)); - \endcode - \par - SL_SO_SECURE_FILES_CA_FILE_NAME: - \code - sl_SetSockOpt(SockID,SL_SOL_SOCKET,SL_SO_SECURE_FILES_CA_FILE_NAME,"exuifaxCaCert.der",strlen("exuifaxCaCert.der")); - \endcode - - \par - SL_SO_SECURE_FILES_PRIVATE_KEY_FILE_NAME: - \code - sl_SetSockOpt(SockID,SL_SOL_SOCKET,SL_SO_SECURE_FILES_PRIVATE_KEY_FILE_NAME,"myPrivateKey.der",strlen("myPrivateKey.der")); - \endcode - - \par - SL_SO_SECURE_FILES_CERTIFICATE_FILE_NAME: - \code - sl_SetSockOpt(SockID,SL_SOL_SOCKET,SL_SO_SECURE_FILES_CERTIFICATE_FILE_NAME,"myCertificate.der",strlen("myCertificate.der")); - \endcode - - \par - SL_SO_SECURE_FILES_DH_KEY_FILE_NAME: - \code - sl_SetSockOpt(SockID,SL_SOL_SOCKET,SL_SO_SECURE_FILES_DH_KEY_FILE_NAME,"myDHinServerMode.der",strlen("myDHinServerMode.der")); - \endcode - - \par - SL_IP_MULTICAST_TTL: - \code - _u8 ttl = 20; - sl_SetSockOpt(SockID, SL_IPPROTO_IP, SL_IP_MULTICAST_TTL, &ttl, sizeof(ttl)); - \endcode - - \par - SL_IP_ADD_MEMBERSHIP: - \code - SlSockIpMreq mreq; - sl_SetSockOpt(SockID, SL_IPPROTO_IP, SL_IP_ADD_MEMBERSHIP, &mreq, sizeof(mreq)); - \endcode - - \par - SL_IP_DROP_MEMBERSHIP: - \code - SlSockIpMreq mreq; - sl_SetSockOpt(SockID, SL_IPPROTO_IP, SL_IP_DROP_MEMBERSHIP, &mreq, sizeof(mreq)); - \endcode - - \par - SL_SO_CHANGE_CHANNEL: - \code - _u32 newChannel = 6; // range is 1-13 - sl_SetSockOpt(SockID, SL_SOL_SOCKET, SL_SO_CHANGE_CHANNEL, &newChannel, sizeof(newChannel)); - \endcode - - \par - SL_IP_RAW_RX_NO_HEADER: - \code - _u32 header = 1; // remove ip header - sl_SetSockOpt(SockID, SL_IPPROTO_IP, SL_IP_RAW_RX_NO_HEADER, &header, sizeof(header)); - \endcode - - \par - SL_IP_HDRINCL: - \code - _u32 header = 1; - sl_SetSockOpt(SockID, SL_IPPROTO_IP, SL_IP_HDRINCL, &header, sizeof(header)); - \endcode - \par - SL_IP_RAW_IPV6_HDRINCL: - \code - _u32 header = 1; - sl_SetSockOpt(SockID, SL_IPPROTO_IP, SL_IP_RAW_IPV6_HDRINCL, &header, sizeof(header)); - \endcode - - \par - SL_SO_PHY_RATE: - \code - _u32 rate = 6; // see wlan.h RateIndex_e for values - sl_SetSockOpt(SockID, SL_SOL_PHY_OPT, SL_SO_PHY_RATE, &rate, sizeof(rate)); - \endcode - - \par - SL_SO_PHY_TX_POWER: - \code - _u32 txpower = 1; // valid range is 1-15 - sl_SetSockOpt(SockID, SL_SOL_PHY_OPT, SL_SO_PHY_TX_POWER, &txpower, sizeof(txpower)); - \endcode - - \par - SL_SO_PHY_NUM_FRAMES_TO_TX: - \code - _u32 numframes = 1; - sl_SetSockOpt(SockID, SL_SOL_PHY_OPT, SL_SO_PHY_NUM_FRAMES_TO_TX, &numframes, sizeof(numframes)); - \endcode - - \par - SL_SO_PHY_PREAMBLE: - \code - _u32 preamble = 1; - sl_SetSockOpt(SockID, SL_SOL_PHY_OPT, SL_SO_PHY_PREAMBLE, &preamble, sizeof(preamble)); - \endcode - -*/ -#if _SL_INCLUDE_FUNC(sl_SetSockOpt) -_i16 sl_SetSockOpt(_i16 sd, _i16 level, _i16 optname, const void *optval, SlSocklen_t optlen); -#endif - -/*! - \brief Get socket options - - This function manipulate the options associated with a socket. - Options may exist at multiple protocol levels; they are always - present at the uppermost socket level. - - When manipulating socket options the level at which the option resides - and the name of the option must be specified. To manipulate options at - the socket level, level is specified as SOL_SOCKET. To manipulate - options at any other level the protocol number of the appropriate proto- - col controlling the option is supplied. For example, to indicate that an - option is to be interpreted by the TCP protocol, level should be set to - the protocol number of TCP; - - The parameters optval and optlen are used to access optval - - ues for setsockopt(). For getsockopt() they identify a - buffer in which the value for the requested option(s) are to - be returned. For getsockopt(), optlen is a value-result - parameter, initially containing the size of the buffer - pointed to by option_value, and modified on return to - indicate the actual size of the value returned. If no option - value is to be supplied or returned, option_value may be - NULL. - - - \param[in] sd socket handle - \param[in] level defines the protocol level for this option - \param[in] optname defines the option name to interrogate - \param[out] optval specifies a value for the option - \param[out] optlen specifies the length of the - option value - - \return On success, zero is returned. - On error, a negative value is returned. - \sa sl_SetSockOpt - \note See sl_SetSockOpt - belongs to \ref ext_api - \warning -*/ -#if _SL_INCLUDE_FUNC(sl_GetSockOpt) -_i16 sl_GetSockOpt(_i16 sd, _i16 level, _i16 optname, void *optval, SlSocklen_t *optlen); -#endif - -/*! - \brief read data from TCP socket - - function receives a message from a connection-mode socket - - \param[in] sd socket handle - \param[out] buf Points to the buffer where the - message should be stored. - \param[in] Len Specifies the length in bytes of - the buffer pointed to by the buffer argument. - Range: 1-16000 bytes - \param[in] flags Specifies the type of message - reception. On this version, this parameter is not - supported. - - \return return the number of bytes received, - or a negative value if an error occurred. - using a non-blocking recv a possible negative value is SL_EAGAIN. - SL_POOL_IS_EMPTY may be return in case there are no resources in the system - In this case try again later or increase MAX_CONCURRENT_ACTIONS - - \sa sl_RecvFrom - \note belongs to \ref recv_api - \warning - \par Examples: - \code An example of receiving data using TCP socket: - - SlSockAddrIn_t Addr; - SlSockAddrIn_t LocalAddr; - _i16 AddrSize = sizeof(SlSockAddrIn_t); - _i16 SockID, newSockID; - _i16 Status; - _i8 Buf[RECV_BUF_LEN]; - - LocalAddr.sin_family = SL_AF_INET; - LocalAddr.sin_port = sl_Htons(5001); - LocalAddr.sin_addr.s_addr = 0; - - Addr.sin_family = SL_AF_INET; - Addr.sin_port = sl_Htons(5001); - Addr.sin_addr.s_addr = sl_Htonl(SL_IPV4_VAL(10,1,1,200)); - - SockID = sl_Socket(SL_AF_INET,SL_SOCK_STREAM, 0); - Status = sl_Bind(SockID, (SlSockAddr_t *)&LocalAddr, AddrSize); - Status = sl_Listen(SockID, 0); - newSockID = sl_Accept(SockID, (SlSockAddr_t*)&Addr, (SlSocklen_t*) &AddrSize); - Status = sl_Recv(newSockID, Buf, 1460, 0); - \endcode - \code Example code for Rx transceiver mode using a raw socket - _i8 buffer[1536]; - _i16 sd; - _u16 size; - SlTransceiverRxOverHead_t *transHeader; - sd = sl_Socket(SL_AF_RF,SL_SOCK_RAW,11); // channel 11 - while(1) - { - size = sl_Recv(sd,buffer,1536,0); - transHeader = (SlTransceiverRxOverHead_t *)buffer; - printf("RSSI is %d frame type is 0x%x size %d\n",transHeader->rssi,buffer[sizeof(SlTransceiverRxOverHead_t)],size); - } - \endcode -*/ -#if _SL_INCLUDE_FUNC(sl_Recv) -_i16 sl_Recv(_i16 sd, void *buf, _i16 Len, _i16 flags); -#endif - -/*! - \brief read data from socket - - function receives a message from a connection-mode or - connectionless-mode socket - - \param[in] sd socket handle - \param[out] buf Points to the buffer where the message should be stored. - \param[in] Len Specifies the length in bytes of the buffer pointed to by the buffer argument. - Range: 1-16000 bytes - \param[in] flags Specifies the type of message - reception. On this version, this parameter is not - supported. - \param[in] from pointer to an address structure - indicating the source - address.\n sockaddr:\n - code - for the address format. On this - version only AF_INET is - supported.\n - socket address, - the length depends on the code - format - \param[in] fromlen source address structure - size. This parameter MUST be set to the size of the structure pointed to by addr. - - - \return return the number of bytes received, - or a negative value if an error occurred. - using a non-blocking recv a possible negative value is SL_EAGAIN. - SL_RET_CODE_INVALID_INPUT (-2) will be returned if fromlen has incorrect length. - SL_POOL_IS_EMPTY may be return in case there are no resources in the system - In this case try again later or increase MAX_CONCURRENT_ACTIONS - - \sa sl_Recv - \note belongs to \ref recv_api - \warning - \par Example: - \code An example of receiving data: - - SlSockAddrIn_t Addr; - SlSockAddrIn_t LocalAddr; - _i16 AddrSize = sizeof(SlSockAddrIn_t); - _i16 SockID; - _i16 Status; - _i8 Buf[RECV_BUF_LEN]; - - LocalAddr.sin_family = SL_AF_INET; - LocalAddr.sin_port = sl_Htons(5001); - LocalAddr.sin_addr.s_addr = 0; - - SockID = sl_Socket(SL_AF_INET,SL_SOCK_DGRAM, 0); - Status = sl_Bind(SockID, (SlSockAddr_t *)&LocalAddr, AddrSize); - Status = sl_RecvFrom(SockID, Buf, 1472, 0, (SlSockAddr_t *)&Addr, (SlSocklen_t*)&AddrSize); - - \endcode -*/ -#if _SL_INCLUDE_FUNC(sl_RecvFrom) -_i16 sl_RecvFrom(_i16 sd, void *buf, _i16 Len, _i16 flags, SlSockAddr_t *from, SlSocklen_t *fromlen); -#endif - -/*! - \brief write data to TCP socket - - This function is used to transmit a message to another socket. - Returns immediately after sending data to device. - In case of TCP failure an async event SL_SOCKET_TX_FAILED_EVENT is going to - be received. - In case of a RAW socket (transceiver mode), extra 4 bytes should be reserved at the end of the - frame data buffer for WLAN FCS - - \param[in] sd socket handle - \param[in] buf Points to a buffer containing - the message to be sent - \param[in] Len message size in bytes. Range: 1-1460 bytes - \param[in] flags Specifies the type of message - transmission. On this version, this parameter is not - supported for TCP. - For transceiver mode, the SL_RAW_RF_TX_PARAMS macro can be used to determine - transmission parameters (channel,rate,tx_power,preamble) - - - \return Return the number of bytes transmitted, - or -1 if an error occurred - - \sa sl_SendTo - \note belongs to \ref send_api - \warning - \par Example: - \code An example of sending data: - - SlSockAddrIn_t Addr; - _i16 AddrSize = sizeof(SlSockAddrIn_t); - _i16 SockID; - _i16 Status; - _i8 Buf[SEND_BUF_LEN]; - - Addr.sin_family = SL_AF_INET; - Addr.sin_port = sl_Htons(5001); - Addr.sin_addr.s_addr = sl_Htonl(SL_IPV4_VAL(10,1,1,200)); - - SockID = sl_Socket(SL_AF_INET,SL_SOCK_STREAM, 0); - Status = sl_Connect(SockID, (SlSockAddr_t *)&Addr, AddrSize); - Status = sl_Send(SockID, Buf, 1460, 0 ); - - \endcode - */ -#if _SL_INCLUDE_FUNC(sl_Send ) -_i16 sl_Send(_i16 sd, const void *buf, _i16 Len, _i16 flags); -#endif - -/*! - \brief write data to socket - - This function is used to transmit a message to another socket - (connection less socket SOCK_DGRAM, SOCK_RAW). - Returns immediately after sending data to device. - In case of transmission failure an async event SL_SOCKET_TX_FAILED_EVENT is going to - be received. - - \param[in] sd socket handle - \param[in] buf Points to a buffer containing - the message to be sent - \param[in] Len message size in bytes. Range: 1-1460 bytes - \param[in] flags Specifies the type of message - transmission. On this version, this parameter is not - supported - \param[in] to pointer to an address structure - indicating the destination - address.\n sockaddr:\n - code - for the address format. On this - version only AF_INET is - supported.\n - socket address, - the length depends on the code - format - \param[in] tolen destination address structure size - - \return Return the number of transmitted bytes, - or -1 if an error occurred - - \sa sl_Send - \note belongs to \ref send_api - \warning - \par Example: - \code An example of sending data: - - SlSockAddrIn_t Addr; - _i16 AddrSize = sizeof(SlSockAddrIn_t); - _i16 SockID; - _i16 Status; - _i8 Buf[SEND_BUF_LEN]; - - Addr.sin_family = SL_AF_INET; - Addr.sin_port = sl_Htons(5001); - Addr.sin_addr.s_addr = sl_Htonl(SL_IPV4_VAL(10,1,1,200)); - - SockID = sl_Socket(SL_AF_INET,SL_SOCK_DGRAM, 0); - Status = sl_SendTo(SockID, Buf, 1472, 0, (SlSockAddr_t *)&Addr, AddrSize); - - \endcode -*/ -#if _SL_INCLUDE_FUNC(sl_SendTo) -_i16 sl_SendTo(_i16 sd, const void *buf, _i16 Len, _i16 flags, const SlSockAddr_t *to, SlSocklen_t tolen); -#endif - -/*! - \brief Reorder the bytes of a 32-bit unsigned value - - This function is used to Reorder the bytes of a 32-bit unsigned value from processor order to network order. - - \param[in] var variable to reorder - - \return Return the reorder variable, - - \sa sl_SendTo sl_Bind sl_Connect sl_RecvFrom sl_Accept - \note belongs to \ref send_api - \warning -*/ -#if _SL_INCLUDE_FUNC(sl_Htonl ) -_u32 sl_Htonl( _u32 val ); - -#define sl_Ntohl sl_Htonl /* Reorder the bytes of a 16-bit unsigned value from network order to processor orde. */ -#endif - -/*! - \brief Reorder the bytes of a 16-bit unsigned value - - This function is used to Reorder the bytes of a 16-bit unsigned value from processor order to network order. - - \param[in] var variable to reorder - - \return Return the reorder variable, - - \sa sl_SendTo sl_Bind sl_Connect sl_RecvFrom sl_Accept - \note belongs to \ref send_api - \warning -*/ -#if _SL_INCLUDE_FUNC(sl_Htons ) -_u16 sl_Htons( _u16 val ); - -#define sl_Ntohs sl_Htons /* Reorder the bytes of a 16-bit unsigned value from network order to processor orde. */ -#endif - -/*! - - Close the Doxygen group. - @} - - */ - - -#ifdef __cplusplus -} -#endif /* __cplusplus */ - -#endif /* __SOCKET_H__ */ - - diff --git a/drivers/cc3100/inc/spawn.h b/drivers/cc3100/inc/spawn.h deleted file mode 100644 index 82c112d2e1..0000000000 --- a/drivers/cc3100/inc/spawn.h +++ /dev/null @@ -1,63 +0,0 @@ -/* - * spawn.h - CC31xx/CC32xx Host Driver Implementation - * - * Copyright (C) 2014 Texas Instruments Incorporated - http://www.ti.com/ - * - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * - * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the - * distribution. - * - * Neither the name of Texas Instruments Incorporated nor the names of - * its contributors may be used to endorse or promote products derived - * from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * -*/ - -#ifndef __NONOS_H__ -#define __NONOS_H__ - -#ifdef __cplusplus -extern "C" { -#endif - - -#if (defined (SL_PLATFORM_MULTI_THREADED)) && (!defined (SL_PLATFORM_EXTERNAL_SPAWN)) - -extern void _SlInternalSpawnTaskEntry(); -extern _i16 _SlInternalSpawn(_SlSpawnEntryFunc_t pEntry , void* pValue , _u32 flags); - -#undef sl_Spawn -#define sl_Spawn(pEntry,pValue,flags) _SlInternalSpawn(pEntry,pValue,flags) - -#undef _SlTaskEntry -#define _SlTaskEntry _SlInternalSpawnTaskEntry - - -#endif - -#ifdef __cplusplus -} -#endif /* __cplusplus */ - -#endif diff --git a/drivers/cc3100/inc/trace.h b/drivers/cc3100/inc/trace.h deleted file mode 100644 index 4ca42c7701..0000000000 --- a/drivers/cc3100/inc/trace.h +++ /dev/null @@ -1,173 +0,0 @@ -/* - * trace.h - CC31xx/CC32xx Host Driver Implementation - * - * Copyright (C) 2014 Texas Instruments Incorporated - http://www.ti.com/ - * - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * - * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the - * distribution. - * - * Neither the name of Texas Instruments Incorporated nor the names of - * its contributors may be used to endorse or promote products derived - * from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * -*/ - - - -#include "simplelink.h" - -#ifndef __SIMPLELINK_TRACE_H__ -#define __SIMPLELINK_TRACE_H__ - - -#ifdef __cplusplus -extern "C" { -#endif - -/*****************************************************************************/ -/* Macro declarations */ -/*****************************************************************************/ - -#define SL_SYNC_SCAN_THRESHOLD (( _u32 )2000) - -#define _SL_ASSERT(expr) { ASSERT(expr); } -#define _SL_ERROR(expr, error) { if(!(expr)){return (error); } } - -#define SL_HANDLING_ASSERT 2 -#define SL_HANDLING_ERROR 1 -#define SL_HANDLING_NONE 0 - -#define SL_SELF_COND_HANDLING SL_HANDLING_NONE -#define SL_PROTOCOL_HANDLING SL_HANDLING_NONE -#define SL_DRV_RET_CODE_HANDLING SL_HANDLING_NONE -#define SL_NWP_IF_HANDLING SL_HANDLING_NONE -#define SL_OSI_RET_OK_HANDLING SL_HANDLING_NONE -#define SL_MALLOC_OK_HANDLING SL_HANDLING_NONE -#define SL_USER_ARGS_HANDLING SL_HANDLING_NONE - -#if (SL_DRV_RET_CODE_HANDLING == SL_HANDLING_ASSERT) -#define VERIFY_RET_OK(Func) {_SlReturnVal_t _RetVal = (Func); _SL_ASSERT((_SlReturnVal_t)SL_OS_RET_CODE_OK == _RetVal)} -#elif (SL_DRV_RET_CODE_HANDLING == SL_HANDLING_ERROR) -#define VERIFY_RET_OK(Func) {_SlReturnVal_t _RetVal = (Func); if (SL_OS_RET_CODE_OK != _RetVal) return _RetVal;} -#else -#define VERIFY_RET_OK(Func) (Func); -#endif - -#if (SL_PROTOCOL_HANDLING == SL_HANDLING_ASSERT) -#define VERIFY_PROTOCOL(expr) _SL_ASSERT(expr) -#elif (SL_PROTOCOL_HANDLING == SL_HANDLING_ERROR) -#define VERIFY_PROTOCOL(expr) _SL_ERROR(expr, SL_RET_CODE_PROTOCOL_ERROR) -#else -#define VERIFY_PROTOCOL(expr) -#endif - -#if (defined(PROTECT_SOCKET_ASYNC_RESP) && (SL_SELF_COND_HANDLING == SL_HANDLING_ASSERT)) -#define VERIFY_SOCKET_CB(expr) _SL_ASSERT(expr) -#elif (defined(PROTECT_SOCKET_ASYNC_RESP) && (SL_SELF_COND_HANDLING == SL_HANDLING_ERROR)) -#define VERIFY_SOCKET_CB(expr) _SL_ERROR(expr, SL_RET_CODE_SELF_ERROR) -#else -#define VERIFY_SOCKET_CB(expr) -#endif - -#if (SL_NWP_IF_HANDLING == SL_HANDLING_ASSERT) -#define NWP_IF_WRITE_CHECK(fd,pBuff,len) { _i16 RetSize, ExpSize = (len); RetSize = sl_IfWrite((fd),(pBuff),ExpSize); _SL_ASSERT(ExpSize == RetSize)} -#define NWP_IF_READ_CHECK(fd,pBuff,len) { _i16 RetSize, ExpSize = (len); RetSize = sl_IfRead((fd),(pBuff),ExpSize); _SL_ASSERT(ExpSize == RetSize)} -#elif (SL_NWP_IF_HANDLING == SL_HANDLING_ERROR) -#define NWP_IF_WRITE_CHECK(fd,pBuff,len) { _SL_ERROR((len == sl_IfWrite((fd),(pBuff),(len))), SL_RET_CODE_NWP_IF_ERROR);} -#define NWP_IF_READ_CHECK(fd,pBuff,len) { _SL_ERROR((len == sl_IfRead((fd),(pBuff),(len))), SL_RET_CODE_NWP_IF_ERROR);} -#else -#define NWP_IF_WRITE_CHECK(fd,pBuff,len) { sl_IfWrite((fd),(pBuff),(len));} -#define NWP_IF_READ_CHECK(fd,pBuff,len) { sl_IfRead((fd),(pBuff),(len));} -#endif - -#if (SL_OSI_RET_OK_HANDLING == SL_HANDLING_ASSERT) -#define OSI_RET_OK_CHECK(Func) {_SlReturnVal_t _RetVal = (Func); _SL_ASSERT((_SlReturnVal_t)SL_OS_RET_CODE_OK == _RetVal)} -#elif (SL_OSI_RET_OK_HANDLING == SL_HANDLING_ERROR) -#define OSI_RET_OK_CHECK(Func) {_SlReturnVal_t _RetVal = (Func); if (SL_OS_RET_CODE_OK != _RetVal) return _RetVal;} -#else -#define OSI_RET_OK_CHECK(Func) (Func); -#endif - -#if (SL_MALLOC_OK_HANDLING == SL_HANDLING_ASSERT) -#define MALLOC_OK_CHECK(Ptr) _SL_ASSERT(NULL != Ptr) -#elif (SL_MALLOC_OK_HANDLING == SL_HANDLING_ERROR) -#define MALLOC_OK_CHECK(Ptr) _SL_ERROR((NULL != Ptr), SL_RET_CODE_MALLOC_ERROR) -#else -#define MALLOC_OK_CHECK(Ptr) -#endif - -#ifdef SL_INC_ARG_CHECK - -#if (SL_USER_ARGS_HANDLING == SL_HANDLING_ASSERT) -#define ARG_CHECK_PTR(Ptr) _SL_ASSERT(NULL != Ptr) -#elif (SL_USER_ARGS_HANDLING == SL_HANDLING_ERROR) -#define ARG_CHECK_PTR(Ptr) _SL_ERROR((NULL != Ptr), SL_RET_CODE_INVALID_INPUT) -#else -#define ARG_CHECK_PTR(Ptr) -#endif - -#else -#define ARG_CHECK_PTR(Ptr) -#endif - -#define SL_TRACE0(level,msg_id,str) -#define SL_TRACE1(level,msg_id,str,p1) -#define SL_TRACE2(level,msg_id,str,p1,p2) -#define SL_TRACE3(level,msg_id,str,p1,p2,p3) -#define SL_TRACE4(level,msg_id,str,p1,p2,p3,p4) -#define SL_ERROR_TRACE(msg_id,str) -#define SL_ERROR_TRACE1(msg_id,str,p1) -#define SL_ERROR_TRACE2(msg_id,str,p1,p2) -#define SL_ERROR_TRACE3(msg_id,str,p1,p2,p3) -#define SL_ERROR_TRACE4(msg_id,str,p1,p2,p3,p4) -#define SL_TRACE_FLUSH() - -/* #define SL_DBG_CNT_ENABLE */ -#ifdef SL_DBG_CNT_ENABLE -#define _SL_DBG_CNT_INC(Cnt) g_DbgCnt. ## Cnt++ -#define _SL_DBG_SYNC_LOG(index,value) {if(index < SL_DBG_SYNC_LOG_SIZE){*(_u32 *)&g_DbgCnt.SyncLog[index] = *(_u32 *)(value);}} - -#else -#define _SL_DBG_CNT_INC(Cnt) -#define _SL_DBG_SYNC_LOG(index,value) -#endif - -#define SL_DBG_LEVEL_1 1 -#define SL_DBG_LEVEL_2 2 -#define SL_DBG_LEVEL_3 4 -#define SL_DBG_LEVEL_MASK (SL_DBG_LEVEL_2|SL_DBG_LEVEL_3) - -#define SL_INCLUDE_DBG_FUNC(Name) ((Name ## _DBG_LEVEL) & SL_DBG_LEVEL_MASK) - -#define _SlDrvPrintStat_DBG_LEVEL SL_DBG_LEVEL_3 -#define _SlDrvOtherFunc_DBG_LEVEL SL_DBG_LEVEL_1 - -#ifdef __cplusplus -} -#endif - - -#endif /*__SIMPLELINK_TRACE_H__*/ - diff --git a/drivers/cc3100/inc/wlan.h b/drivers/cc3100/inc/wlan.h deleted file mode 100644 index 156b94eab8..0000000000 --- a/drivers/cc3100/inc/wlan.h +++ /dev/null @@ -1,1308 +0,0 @@ -/* - * wlan.h - CC31xx/CC32xx Host Driver Implementation - * - * Copyright (C) 2014 Texas Instruments Incorporated - http://www.ti.com/ - * - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * - * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the - * distribution. - * - * Neither the name of Texas Instruments Incorporated nor the names of - * its contributors may be used to endorse or promote products derived - * from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * -*/ - -/*****************************************************************************/ -/* Include files */ -/*****************************************************************************/ -#include "simplelink.h" - -#ifndef __WLAN_H__ -#define __WLAN_H__ - - - - -#ifdef __cplusplus -extern "C" { -#endif - - -/*****************************************************************************/ -/* Macro declarations */ -/*****************************************************************************/ - -/*! - - \addtogroup wlan - @{ - -*/ - -#define SL_BSSID_LENGTH (6) -#define MAXIMAL_SSID_LENGTH (32) - -#define NUM_OF_RATE_INDEXES (20) -#define SIZE_OF_RSSI_HISTOGRAM (6) - -/* WLAN Disconnect Reason Codes */ -#define SL_DISCONNECT_RESERVED_0 (0) -#define SL_DISCONNECT_UNSPECIFIED_REASON (1) -#define SL_PREVIOUS_AUTHENTICATION_NO_LONGER_VALID (2) -#define SL_DEAUTHENTICATED_BECAUSE_SENDING_STATION_IS_LEAVING (3) -#define SL_DISASSOCIATED_DUE_TO_INACTIVITY (4) -#define SL_DISASSOCIATED_BECAUSE_AP_IS_UNABLE_TO_HANDLE_ALL_CURRENTLY_ASSOCIATED_STATIONS (5) -#define SL_CLASS_2_FRAME_RECEIVED_FROM_NONAUTHENTICATED_STATION (6) -#define SL_CLASS_3_FRAME_RECEIVED_FROM_NONASSOCIATED_STATION (7) -#define SL_DISASSOCIATED_BECAUSE_SENDING_STATION_IS_LEAVING_BSS (8) -#define SL_STATION_REQUESTING_ASSOCIATION_IS_NOT_AUTHENTICATED_WITH_RESPONDING_STATION (9) -#define SL_DISASSOCIATED_BECAUSE_THE_INFORMATION_IN_THE_POWER_CAPABILITY_ELEMENT_IS_UNACCEPTABLE (10) -#define SL_DISASSOCIATED_BECAUSE_THE_INFORMATION_IN_THE_SUPPORTED_CHANNELS_ELEMENT_IS_UNACCEPTABLE (11) -#define SL_DISCONNECT_RESERVED_1 (12) -#define SL_INVALID_INFORMATION_ELEMENT (13) -#define SL_MESSAGE_INTEGRITY_CODE_MIC_FAILURE (14) -#define SL_FOUR_WAY_HANDSHAKE_TIMEOUT (15) -#define SL_GROUP_KEY_HANDSHAKE_TIMEOUT (16) -#define SL_RE_ASSOCIATION_REQUEST_PROBE_RESPONSE_BEACON_FRAME (17) -#define SL_INVALID_GROUP_CIPHER (18) -#define SL_INVALID_PAIRWISE_CIPHER (19) -#define SL_INVALID_AKMP (20) -#define SL_UNSUPPORTED_RSN_INFORMATION_ELEMENT_VERSION (21) -#define SL_INVALID_RSN_INFORMATION_ELEMENT_CAPABILITIES (22) -#define SL_IEEE_802_1X_AUTHENTICATION_FAILED (23) -#define SL_CIPHER_SUITE_REJECTED_BECAUSE_OF_THE_SECURITY_POLICY (24) -#define SL_DISCONNECT_RESERVED_2 (25) -#define SL_DISCONNECT_RESERVED_3 (26) -#define SL_DISCONNECT_RESERVED_4 (27) -#define SL_DISCONNECT_RESERVED_5 (28) -#define SL_DISCONNECT_RESERVED_6 (29) -#define SL_DISCONNECT_RESERVED_7 (30) -#define SL_DISCONNECT_RESERVED_8 (31) -#define SL_USER_INITIATED_DISCONNECTION (200) - -/* Wlan error codes */ -#define SL_ERROR_KEY_ERROR (-3) -#define SL_ERROR_INVALID_ROLE (-71) -#define SL_ERROR_INVALID_SECURITY_TYPE (-84) -#define SL_ERROR_PASSPHRASE_TOO_LONG (-85) -#define SL_ERROR_WPS_NO_PIN_OR_WRONG_PIN_LEN (-87) -#define SL_ERROR_EAP_WRONG_METHOD (-88) -#define SL_ERROR_PASSWORD_ERROR (-89) -#define SL_ERROR_EAP_ANONYMOUS_LEN_ERROR (-90) -#define SL_ERROR_SSID_LEN_ERROR (-91) -#define SL_ERROR_USER_ID_LEN_ERROR (-92) -#define SL_ERROR_ILLEGAL_WEP_KEY_INDEX (-95) -#define SL_ERROR_INVALID_DWELL_TIME_VALUES (-96) -#define SL_ERROR_INVALID_POLICY_TYPE (-97) -#define SL_ERROR_PM_POLICY_INVALID_OPTION (-98) -#define SL_ERROR_PM_POLICY_INVALID_PARAMS (-99) -#define SL_ERROR_WIFI_ALREADY_DISCONNECTED (-129) -#define SL_ERROR_WIFI_NOT_CONNECTED (-59) - - - -#define SL_SEC_TYPE_OPEN (0) -#define SL_SEC_TYPE_WEP (1) -#define SL_SEC_TYPE_WPA (2) /* deprecated */ -#define SL_SEC_TYPE_WPA_WPA2 (2) -#define SL_SEC_TYPE_WPS_PBC (3) -#define SL_SEC_TYPE_WPS_PIN (4) -#define SL_SEC_TYPE_WPA_ENT (5) -#define SL_SEC_TYPE_P2P_PBC (6) -#define SL_SEC_TYPE_P2P_PIN_KEYPAD (7) -#define SL_SEC_TYPE_P2P_PIN_DISPLAY (8) -#define SL_SEC_TYPE_P2P_PIN_AUTO (9) /* NOT Supported yet */ - - - -#define SL_SCAN_SEC_TYPE_OPEN (0) -#define SL_SCAN_SEC_TYPE_WEP (1) -#define SL_SCAN_SEC_TYPE_WPA (2) -#define SL_SCAN_SEC_TYPE_WPA2 (3) - - - -#define TLS (0x1) -#define MSCHAP (0x0) -#define PSK (0x2) -#define TTLS (0x10) -#define PEAP0 (0x20) -#define PEAP1 (0x40) -#define FAST (0x80) - -#define FAST_AUTH_PROVISIONING (0x02) -#define FAST_UNAUTH_PROVISIONING (0x01) -#define FAST_NO_PROVISIONING (0x00) - -#define EAPMETHOD_PHASE2_SHIFT (8) -#define EAPMETHOD_PAIRWISE_CIPHER_SHIFT (19) -#define EAPMETHOD_GROUP_CIPHER_SHIFT (27) - -#define WPA_CIPHER_CCMP (0x1) -#define WPA_CIPHER_TKIP (0x2) -#define CC31XX_DEFAULT_CIPHER (WPA_CIPHER_CCMP | WPA_CIPHER_TKIP) - -#define EAPMETHOD(phase1,phase2,pairwise_cipher,group_cipher) \ -((phase1) | \ - ((phase2) << EAPMETHOD_PHASE2_SHIFT ) |\ - ((_u32)(pairwise_cipher) << EAPMETHOD_PAIRWISE_CIPHER_SHIFT ) |\ - ((_u32)(group_cipher) << EAPMETHOD_GROUP_CIPHER_SHIFT )) - -/* phase1 phase2 pairwise_cipher group_cipher */ -#define SL_ENT_EAP_METHOD_TLS EAPMETHOD(TLS , 0 , CC31XX_DEFAULT_CIPHER , CC31XX_DEFAULT_CIPHER) -#define SL_ENT_EAP_METHOD_TTLS_TLS EAPMETHOD(TTLS , TLS , CC31XX_DEFAULT_CIPHER , CC31XX_DEFAULT_CIPHER) -#define SL_ENT_EAP_METHOD_TTLS_MSCHAPv2 EAPMETHOD(TTLS , MSCHAP , CC31XX_DEFAULT_CIPHER , CC31XX_DEFAULT_CIPHER) -#define SL_ENT_EAP_METHOD_TTLS_PSK EAPMETHOD(TTLS , PSK , CC31XX_DEFAULT_CIPHER , CC31XX_DEFAULT_CIPHER) -#define SL_ENT_EAP_METHOD_PEAP0_TLS EAPMETHOD(PEAP0 , TLS , CC31XX_DEFAULT_CIPHER , CC31XX_DEFAULT_CIPHER) -#define SL_ENT_EAP_METHOD_PEAP0_MSCHAPv2 EAPMETHOD(PEAP0 , MSCHAP , CC31XX_DEFAULT_CIPHER , CC31XX_DEFAULT_CIPHER) -#define SL_ENT_EAP_METHOD_PEAP0_PSK EAPMETHOD(PEAP0 , PSK , CC31XX_DEFAULT_CIPHER , CC31XX_DEFAULT_CIPHER) -#define SL_ENT_EAP_METHOD_PEAP1_TLS EAPMETHOD(PEAP1 , TLS , CC31XX_DEFAULT_CIPHER , CC31XX_DEFAULT_CIPHER) -#define SL_ENT_EAP_METHOD_PEAP1_MSCHAPv2 EAPMETHOD(PEAP1 , MSCHAP , CC31XX_DEFAULT_CIPHER , CC31XX_DEFAULT_CIPHER) -#define SL_ENT_EAP_METHOD_PEAP1_PSK EAPMETHOD(PEAP1 , PSK , CC31XX_DEFAULT_CIPHER , CC31XX_DEFAULT_CIPHER) -#define SL_ENT_EAP_METHOD_FAST_AUTH_PROVISIONING EAPMETHOD(FAST , FAST_AUTH_PROVISIONING , CC31XX_DEFAULT_CIPHER , CC31XX_DEFAULT_CIPHER) -#define SL_ENT_EAP_METHOD_FAST_UNAUTH_PROVISIONING EAPMETHOD(FAST , FAST_UNAUTH_PROVISIONING , CC31XX_DEFAULT_CIPHER , CC31XX_DEFAULT_CIPHER) -#define SL_ENT_EAP_METHOD_FAST_NO_PROVISIONING EAPMETHOD(FAST , FAST_NO_PROVISIONING , CC31XX_DEFAULT_CIPHER , CC31XX_DEFAULT_CIPHER) - -#define SL_LONG_PREAMBLE (0) -#define SL_SHORT_PREAMBLE (1) - -#define SL_RAW_RF_TX_PARAMS_CHANNEL_SHIFT (0) -#define SL_RAW_RF_TX_PARAMS_RATE_SHIFT (6) -#define SL_RAW_RF_TX_PARAMS_POWER_SHIFT (11) -#define SL_RAW_RF_TX_PARAMS_PREAMBLE_SHIFT (15) - -#define SL_RAW_RF_TX_PARAMS(chan,rate,power,preamble) \ - ((chan << SL_RAW_RF_TX_PARAMS_CHANNEL_SHIFT) | \ - (rate << SL_RAW_RF_TX_PARAMS_RATE_SHIFT) | \ - (power << SL_RAW_RF_TX_PARAMS_POWER_SHIFT) | \ - (preamble << SL_RAW_RF_TX_PARAMS_PREAMBLE_SHIFT)) - - -/* wlan config application IDs */ -#define SL_WLAN_CFG_AP_ID (0) -#define SL_WLAN_CFG_GENERAL_PARAM_ID (1) -#define SL_WLAN_CFG_P2P_PARAM_ID (2) - -/* wlan AP Config set/get options */ -#define WLAN_AP_OPT_SSID (0) -#define WLAN_AP_OPT_CHANNEL (3) -#define WLAN_AP_OPT_HIDDEN_SSID (4) -#define WLAN_AP_OPT_SECURITY_TYPE (6) -#define WLAN_AP_OPT_PASSWORD (7) -#define WLAN_GENERAL_PARAM_OPT_COUNTRY_CODE (9) -#define WLAN_GENERAL_PARAM_OPT_STA_TX_POWER (10) -#define WLAN_GENERAL_PARAM_OPT_AP_TX_POWER (11) - -#define WLAN_P2P_OPT_DEV_NAME (12) -#define WLAN_P2P_OPT_DEV_TYPE (13) -#define WLAN_P2P_OPT_CHANNEL_N_REGS (14) -#define WLAN_GENERAL_PARAM_OPT_INFO_ELEMENT (16) -#define WLAN_GENERAL_PARAM_OPT_SCAN_PARAMS (18) /* change the scan channels and RSSI threshold using this configuration option */ - -/* SmartConfig CIPHER options */ -#define SMART_CONFIG_CIPHER_SFLASH (0) /* password is not delivered by the application. The Simple Manager should */ - /* check if the keys are stored in the Flash. */ -#define SMART_CONFIG_CIPHER_AES (1) /* AES (other types are not supported) */ -#define SMART_CONFIG_CIPHER_NONE (0xFF) /* do not check in the flash */ - - -#define SL_POLICY_CONNECTION (0x10) -#define SL_POLICY_SCAN (0x20) -#define SL_POLICY_PM (0x30) -#define SL_POLICY_P2P (0x40) - -#define VAL_2_MASK(position,value) ((1 & (value))<<(position)) -#define MASK_2_VAL(position,mask) (((1 << position) & (mask)) >> (position)) - -#define SL_CONNECTION_POLICY(Auto,Fast,Open,anyP2P,autoSmartConfig) (VAL_2_MASK(0,Auto) | VAL_2_MASK(1,Fast) | VAL_2_MASK(2,Open) | VAL_2_MASK(3,anyP2P) | VAL_2_MASK(4,autoSmartConfig)) -#define SL_SCAN_POLICY_EN(policy) (MASK_2_VAL(0,policy)) -#define SL_SCAN_POLICY(Enable) (VAL_2_MASK(0,Enable)) - - -#define SL_NORMAL_POLICY (0) -#define SL_LOW_LATENCY_POLICY (1) -#define SL_LOW_POWER_POLICY (2) -#define SL_ALWAYS_ON_POLICY (3) -#define SL_LONG_SLEEP_INTERVAL_POLICY (4) - -#define SL_P2P_ROLE_NEGOTIATE (3) -#define SL_P2P_ROLE_GROUP_OWNER (15) -#define SL_P2P_ROLE_CLIENT (0) - -#define SL_P2P_NEG_INITIATOR_ACTIVE (0) -#define SL_P2P_NEG_INITIATOR_PASSIVE (1) -#define SL_P2P_NEG_INITIATOR_RAND_BACKOFF (2) - -#define POLICY_VAL_2_OPTIONS(position,mask,policy) ((mask & policy) << position ) - -#define SL_P2P_POLICY(p2pNegType,p2pNegInitiator) (POLICY_VAL_2_OPTIONS(0,0xF,(p2pNegType > SL_P2P_ROLE_GROUP_OWNER ? SL_P2P_ROLE_GROUP_OWNER : p2pNegType)) | \ - POLICY_VAL_2_OPTIONS(4,0x1,(p2pNegType > SL_P2P_ROLE_GROUP_OWNER ? 1:0)) | \ - POLICY_VAL_2_OPTIONS(5,0x3, p2pNegInitiator)) - - -/* Info elements */ - -#define INFO_ELEMENT_DEFAULT_ID (0) /* 221 will be used */ - -/* info element size is up to 252 bytes (+ 3 bytes of OUI). */ -#define INFO_ELEMENT_MAX_SIZE (252) - -/* For AP - the total length of all info elements is 300 bytes (for example - 4 info elements of 75 bytes each) */ -#define INFO_ELEMENT_MAX_TOTAL_LENGTH_AP (300) -/* For P2P - the total length of all info elements is 150 bytes (for example - 4 info elements of 40 bytes each) */ -#define INFO_ELEMENT_MAX_TOTAL_LENGTH_P2P_GO (160) - -#define INFO_ELEMENT_AP_ROLE (0) -#define INFO_ELEMENT_P2P_GO_ROLE (1) - -/* we support up to 4 info elements per Role. */ -#define MAX_PRIVATE_INFO_ELEMENTS_SUPPROTED (4) - -#define INFO_ELEMENT_DEFAULT_OUI_0 (0x08) -#define INFO_ELEMENT_DEFAULT_OUI_1 (0x00) -#define INFO_ELEMENT_DEFAULT_OUI_2 (0x28) - -#define INFO_ELEMENT_DEFAULT_OUI (0x000000) /* 08, 00, 28 will be used */ - -/*****************************************************************************/ -/* Structure/Enum declarations */ -/*****************************************************************************/ - -typedef enum -{ - RATE_1M = 1, - RATE_2M = 2, - RATE_5_5M = 3, - RATE_11M = 4, - RATE_6M = 6, - RATE_9M = 7, - RATE_12M = 8, - RATE_18M = 9, - RATE_24M = 10, - RATE_36M = 11, - RATE_48M = 12, - RATE_54M = 13, - RATE_MCS_0 = 14, - RATE_MCS_1 = 15, - RATE_MCS_2 = 16, - RATE_MCS_3 = 17, - RATE_MCS_4 = 18, - RATE_MCS_5 = 19, - RATE_MCS_6 = 20, - RATE_MCS_7 = 21, - MAX_NUM_RATES = 0xFF -}SlRateIndex_e; - -typedef enum { - DEV_PW_DEFAULT=0, - DEV_PW_PIN_KEYPAD=1, - DEV_PW_PUSH_BUTTON=4, - DEV_PW_PIN_DISPLAY=5 -} sl_p2p_dev_password_method; - - -typedef struct -{ - _u32 status; - _u32 ssid_len; - _u8 ssid[32]; - _u32 private_token_len; - _u8 private_token[32]; -}slSmartConfigStartAsyncResponse_t; - -typedef struct -{ - _u16 status; - _u16 padding; -}slSmartConfigStopAsyncResponse_t; - -typedef struct -{ - _u16 status; - _u16 padding; -}slWlanConnFailureAsyncResponse_t; - -typedef struct -{ - _u8 connection_type;/* 0-STA,3-P2P_CL */ - _u8 ssid_len; - _u8 ssid_name[32]; - _u8 go_peer_device_name_len; - _u8 go_peer_device_name[32]; - _u8 bssid[6]; - _u8 reason_code; - _u8 padding[2]; -} slWlanConnectAsyncResponse_t; - -typedef struct -{ - _u8 go_peer_device_name[32]; - _u8 mac[6]; - _u8 go_peer_device_name_len; - _u8 wps_dev_password_id; - _u8 own_ssid[32];/* relevant for event sta-connected only */ - _u8 own_ssid_len;/* relevant for event sta-connected only */ - _u8 padding[3]; -}slPeerInfoAsyncResponse_t; - - -typedef union -{ - slSmartConfigStartAsyncResponse_t smartConfigStartResponse; /*SL_WLAN_SMART_CONFIG_COMPLETE_EVENT*/ - slSmartConfigStopAsyncResponse_t smartConfigStopResponse; /*SL_WLAN_SMART_CONFIG_STOP_EVENT */ - slPeerInfoAsyncResponse_t APModeStaConnected; /* SL_WLAN_STA_CONNECTED_EVENT - relevant only in AP mode - holds information regarding a new STA connection */ - slPeerInfoAsyncResponse_t APModestaDisconnected; /* SL_WLAN_STA_DISCONNECTED_EVENT - relevant only in AP mode - holds information regarding a STA disconnection */ - slWlanConnectAsyncResponse_t STAandP2PModeWlanConnected; /* SL_WLAN_CONNECT_EVENT - relevant only in STA and P2P mode - holds information regarding a new connection */ - slWlanConnectAsyncResponse_t STAandP2PModeDisconnected; /* SL_WLAN_DISCONNECT_EVENT - relevant only in STA and P2P mode - holds information regarding a disconnection */ - slPeerInfoAsyncResponse_t P2PModeDevFound; /* SL_WLAN_P2P_DEV_FOUND_EVENT - relevant only in P2P mode */ - slPeerInfoAsyncResponse_t P2PModeNegReqReceived; /* SL_WLAN_P2P_NEG_REQ_RECEIVED_EVENT - relevant only in P2P mode */ - slWlanConnFailureAsyncResponse_t P2PModewlanConnectionFailure; /* SL_WLAN_CONNECTION_FAILED_EVENT - relevant only in P2P mode */ - -} SlWlanEventData_u; - -typedef struct -{ - _u32 Event; - SlWlanEventData_u EventData; -} SlWlanEvent_t; - - -typedef struct -{ - _u32 ReceivedValidPacketsNumber; /* sum of the packets that been received OK (include filtered) */ - _u32 ReceivedFcsErrorPacketsNumber; /* sum of the packets that been dropped due to FCS error */ - _u32 ReceivedAddressMismatchPacketsNumber; /* sum of the packets that been received but filtered out by one of the HW filters */ - _i16 AvarageDataCtrlRssi; /* average RSSI for all valid data packets received */ - _i16 AvarageMgMntRssi; /* average RSSI for all valid management packets received */ - _u16 RateHistogram[NUM_OF_RATE_INDEXES]; /* rate histogram for all valid packets received */ - _u16 RssiHistogram[SIZE_OF_RSSI_HISTOGRAM]; /* RSSI histogram from -40 until -87 (all below and above\n RSSI will appear in the first and last cells */ - _u32 StartTimeStamp; /* the time stamp started collecting the statistics in uSec */ - _u32 GetTimeStamp; /* the time stamp called the get statistics command */ -}SlGetRxStatResponse_t; - - -typedef struct -{ - _u8 ssid[MAXIMAL_SSID_LENGTH]; - _u8 ssid_len; - _u8 sec_type; - _u8 bssid[SL_BSSID_LENGTH]; - _i8 rssi; - _i8 reserved[3]; -}Sl_WlanNetworkEntry_t; - - -typedef struct -{ - _u8 Type; - _i8* Key; - _u8 KeyLen; -}SlSecParams_t; - -typedef struct -{ - _i8* User; - _u8 UserLen; - _i8* AnonUser; - _u8 AnonUserLen; - _u8 CertIndex; /* not supported */ - _u32 EapMethod; -}SlSecParamsExt_t; - -typedef struct -{ - _i8 User[32]; - _u8 UserLen; - _i8 AnonUser[32]; - _u8 AnonUserLen; - _u8 CertIndex; /* not supported */ - _u32 EapMethod; -}SlGetSecParamsExt_t; - -typedef enum -{ - ROLE_STA = 0, - ROLE_AP = 2, - ROLE_P2P = 3, - ROLE_STA_ERR = -1, /* Failure to load MAC/PHY in STA role */ - ROLE_AP_ERR = -ROLE_AP, /* Failure to load MAC/PHY in AP role */ - ROLE_P2P_ERR = -ROLE_P2P /* Failure to load MAC/PHY in P2P role */ -}SlWlanMode_t; - -typedef struct -{ - _u32 G_Channels_mask; - _i32 rssiThershold; -}slWlanScanParamCommand_t; - - -typedef struct -{ - _u8 id; - _u8 oui[3]; - _u16 length; - _u8 data[252]; -} sl_protocol_InfoElement_t; - -typedef struct -{ - _u8 index; /* 0 - MAX_PRIVATE_INFO_ELEMENTS_SUPPROTED */ - _u8 role; /* bit0: AP = 0, GO = 1 */ - sl_protocol_InfoElement_t ie; -} sl_protocol_WlanSetInfoElement_t; - - -/*****************************************************************************/ -/* Function prototypes */ -/*****************************************************************************/ - - -/*! - \brief Connect to wlan network as a station - - \param[in] pName up to 32 bytes in case of STA the name is the SSID of the Access Point - \param[in] NameLen name length - \param[in] pMacAddr 6 bytes for MAC address - \param[in] pSecParams Security parameters (use NULL key for SL_SEC_TYPE_OPEN) - Security types options: \n - - SL_SEC_TYPE_OPEN - - SL_SEC_TYPE_WEP - - SL_SEC_TYPE_WPA_WPA2 - - SL_SEC_TYPE_WPA_ENT - - SL_SEC_TYPE_WPS_PBC - - SL_SEC_TYPE_WPS_PIN - - \param[in] pSecExtParams Enterprise parameters (set NULL in case Enterprise parameters is not in use) - - \return On success, zero is returned. On error, negative is returned - In case error number (-71) is returned, it indicates a connection was activated while the device it running in AP role - - \sa sl_WlanDisconnect - \note belongs to \ref ext_api - \warning In this version only single enterprise mode could be used - SL_SEC_TYPE_WPA is a deprecated definition, the new definition is SL_SEC_TYPE_WPA_WPA2 -*/ -#if _SL_INCLUDE_FUNC(sl_WlanConnect) -_i16 sl_WlanConnect(const _i8* pName,const _i16 NameLen,const _u8 *pMacAddr,const SlSecParams_t* pSecParams ,const SlSecParamsExt_t* pSecExtParams); -#endif - -/*! - \brief wlan disconnect - - Disconnect connection - - \return 0 disconnected done, other already disconnected - - \sa sl_WlanConnect - \note belongs to \ref ext_api - \warning -*/ -#if _SL_INCLUDE_FUNC(sl_WlanDisconnect) -_i16 sl_WlanDisconnect(void); -#endif - -/*! - \brief add profile - - When auto start is enabled, the device connects to a - station from the profiles table. Up to 7 profiles are - supported. If several profiles configured the device chose - the highest priority profile, within each priority group, - device will chose profile based on security policy, signal - strength, etc parameters. - - - \param[in] pName up to 32 bytes in case of STA the name is the - SSID of the Access Point - in case of P2P the name is the remote device name - \param[in] NameLen name length - \param[in] pMacAddr 6 bytes for MAC address - \param[in] pSecParams Security parameters - security type - (SL_SEC_TYPE_OPEN,SL_SEC_TYPE_WEP,SL_SEC_TYPE_WPA_WPA2, - SL_SEC_TYPE_P2P_PBC,SL_SEC_TYPE_P2P_PIN_KEYPAD,SL_SEC_TYPE_P2P_PIN_DISPLAY, SL_SEC_TYPE_WPA_ENT), key, and key length - in case of p2p security type pin the key refers to pin code - \param[in] pSecExtParams Enterprise parameters - identity, identity length, - Anonymous, Anonymous length, CertIndex (not supported, - certificates need to be placed in a specific file ID), - EapMethod.Use NULL in case Enterprise parameters is not in use - - \param[in] Priority profile priority. Lowest priority: 0 - \param[in] Options Not supported - - \return On success, profile stored index is returned. On error, negative value is returned - - \sa sl_WlanProfileGet , sl_WlanProfileDel - \note belongs to \ref ext_api - \warning Only one Enterprise profile is supported. - Please Note that in case of adding an existing profile (compared by pName,pMACAddr and security type) - the old profile will be deleted and the same index will be returned. - SL_SEC_TYPE_WPA is a deprecated definition, the new definition is SL_SEC_TYPE_WPA_WPA2 - -*/ -#if _SL_INCLUDE_FUNC(sl_WlanProfileAdd) -_i16 sl_WlanProfileAdd(const _i8* pName,const _i16 NameLen,const _u8 *pMacAddr,const SlSecParams_t* pSecParams ,const SlSecParamsExt_t* pSecExtParams,const _u32 Priority,const _u32 Options); -#endif - -/*! - \brief get profile - - read profile from the device - - \param[in] Index profile stored index, if index does not exists - error is return - \param[out] pName up to 32 bytes, in case of sta mode the name of the Access Point - in case of p2p mode the name of the Remote Device - \param[out] pNameLen name length - \param[out] pMacAddr 6 bytes for MAC address - \param[out] pSecParams security parameters - security type - (SL_SEC_TYPE_OPEN, SL_SEC_TYPE_WEP, SL_SEC_TYPE_WPA_WPA2 or - SL_SEC_TYPE_WPS_PBC, SL_SEC_TYPE_WPS_PIN, SL_SEC_TYPE_WPA_ENT,SL_SEC_TYPE_P2P_PBC,SL_SEC_TYPE_P2P_PIN_KEYPAD or SL_SEC_TYPE_P2P_PIN_DISPLAY), key and key length are not - in case of p2p security type pin the key refers to pin code - return due to security reasons. - \param[out] pSecExtParams enterprise parameters - identity, identity - length, Anonymous, Anonymous length - CertIndex (not supported), EapMethod. - \param[out] Priority profile priority - - \return On success, Profile security type is returned (0 or positive number). On error, -1 is - returned - - \sa sl_WlanProfileAdd , sl_WlanProfileDel - \note belongs to \ref ext_api - \warning -*/ -#if _SL_INCLUDE_FUNC(sl_WlanProfileGet) -_i16 sl_WlanProfileGet(const _i16 Index,_i8* pName, _i16 *pNameLen, _u8 *pMacAddr, SlSecParams_t* pSecParams, SlGetSecParamsExt_t* pSecExtParams, _u32 *pPriority); -#endif - -/*! - \brief Delete WLAN profile - - Delete WLAN profile - - \param[in] index number of profile to delete.Possible values are 0 to 6. - Index value 255 will delete all saved profiles - - \return On success, zero is returned. On error, -1 is - returned - - \sa sl_WlanProfileAdd , sl_WlanProfileGet - \note belongs to \ref ext_api - \warning -*/ -#if _SL_INCLUDE_FUNC(sl_WlanProfileDel) -_i16 sl_WlanProfileDel(const _i16 Index); -#endif - -/*! - \brief Set policy values - - \param[in] Type Type of policy to be modified. The Options are:\n - - SL_POLICY_CONNECTION - - SL_POLICY_SCAN - - SL_POLICY_PM - - SL_POLICY_P2P - \param[in] Policy The option value which depends on action type - \param[in] pVal An optional value pointer - \param[in] ValLen An optional value length, in bytes - \return On success, zero is returned. On error, -1 is - returned - \sa sl_WlanPolicyGet - \note belongs to \ref ext_api - \warning - \par - SL_POLICY_CONNECTION type defines three options available to connect the CC31xx device to the AP: \n - - - If Auto Connect is set, the CC31xx device tries to automatically reconnect to one of its stored profiles, each time the connection fails or the device is rebooted.\n - To set this option, use: \n - sl_WlanPolicySet(SL_POLICY_CONNECTION,SL_CONNECTION_POLICY(1,0,0,0,0),NULL,0) - - If Fast Connect is set, the CC31xx device tries to establish a fast connection to AP. \n - To set this option, use: \n - sl_WlanPolicySet(SL_POLICY_CONNECTION,SL_CONNECTION_POLICY(0,1,0,0,0),NULL,0) - - (relevant for P2P mode only) - If Any P2P is set, CC31xx/CC32xx device tries to automatically connect to the first P2P device available, \n - supporting push button only. To set this option, use: \n - sl_WlanPolicySet(SL_POLICY_CONNECTION,SL_CONNECTION_POLICY(0,0,0,1,0),NULL,0) - - For auto smart config upon restart (any command from Host will end this state) use: \n - sl_WlanPolicySet(SL_POLICY_CONNECTION,SL_CONNECTION_POLICY(0,0,0,0,1),NULL,0) \n - The options above could be combined to a single action, if more than one action is required. \n - \par - SL_POLICY_SCAN defines system scan time interval.Default interval is 10 minutes. \n - After settings scan interval, an immediate scan is activated. The next scan will be based on the interval settings. \n - - For example, setting scan interval to 1 minute interval use: \n - _u32 intervalInSeconds = 60; \n - #define SL_SCAN_ENABLE 1 \n - sl_WlanPolicySet(SL_POLICY_SCAN,SL_SCAN_ENABLE, (_u8 *)&intervalInSeconds,sizeof(intervalInSeconds)); \n - - - For example, disable scan: \n - #define SL_SCAN_DISABLE 0 \n - sl_WlanPolicySet(SL_POLICY_SCAN,SL_SCAN_DISABLE,0,0); \n - \par - SL_POLICY_PM defines a power management policy for Station mode only: - - For setting normal power management (default) policy use: sl_WlanPolicySet(SL_POLICY_PM , SL_NORMAL_POLICY, NULL,0) - - For setting low latency power management policy use: sl_WlanPolicySet(SL_POLICY_PM , SL_LOW_LATENCY_POLICY, NULL,0) - - For setting low power management policy use: sl_WlanPolicySet(SL_POLICY_PM , SL_LOW_POWER_POLICY, NULL,0) - - For setting always on power management policy use: sl_WlanPolicySet(SL_POLICY_PM , SL_ALWAYS_ON_POLICY, NULL,0) - - For setting Long Sleep Interval policy use: \n - _u16 PolicyBuff[4] = {0,0,800,0}; // PolicyBuff[2] is max sleep time in mSec \n - sl_WlanPolicySet(SL_POLICY_PM , SL_LONG_SLEEP_INTERVAL_POLICY, (_u8*)PolicyBuff,sizeof(PolicyBuff)); \n - - SL_POLICY_P2P defines p2p negotiation policy parameters for P2P role: - - To set intent negotiation value, set on of the following: - SL_P2P_ROLE_NEGOTIATE - intent 3 - SL_P2P_ROLE_GROUP_OWNER - intent 15 - SL_P2P_ROLE_CLIENT - intent 0 - - To set negotiation initiator value (initiator policy of first negotiation action frame), set on of the following: - SL_P2P_NEG_INITIATOR_ACTIVE - SL_P2P_NEG_INITIATOR_PASSIVE - SL_P2P_NEG_INITIATOR_RAND_BACKOFF - For example: \n - sl_WlanPolicySet(SL_POLICY_P2P, SL_P2P_POLICY(SL_P2P_ROLE_NEGOTIATE,SL_P2P_NEG_INITIATOR_RAND_BACKOFF),NULL,0) - -*/ -#if _SL_INCLUDE_FUNC(sl_WlanPolicySet) -_i16 sl_WlanPolicySet(const _u8 Type , const _u8 Policy, _u8 *pVal,const _u8 ValLen); -#endif -/*! - \brief get policy values - - \param[in] Type SL_POLICY_CONNECTION, SL_POLICY_SCAN, SL_POLICY_PM,SL_POLICY_P2P \n - - \param[in] Policy argument may be set to any value \n - - \param[out] The returned values, depends on each policy type, will be stored in the allocated buffer pointed by pVal - with a maximum buffer length set by the calling function and pointed to by argument *pValLen - - \return On success, zero is returned. On error, -1 is returned - - \sa sl_WlanPolicySet - - \note belongs to \ref ext_api - - \warning The value pointed by the argument *pValLen should be set to a value different from 0 and - greater than the buffer length returned from the SL device. Otherwise, an error will be returned. - -*/ -#if _SL_INCLUDE_FUNC(sl_WlanPolicyGet) -_i16 sl_WlanPolicyGet(const _u8 Type , _u8 Policy,_u8 *pVal,_u8 *pValLen); -#endif -/*! - \brief Gets the WLAN scan operation results - - Gets scan results , gets entry from scan result table - - \param[in] Index - Starting index identifier (range 0-19) for getting scan results - \param[in] Count - How many entries to fetch. Max is (20-"Index"). - \param[out] pEntries - pointer to an allocated Sl_WlanNetworkEntry_t. - the number of array items should match "Count" - sec_type: SL_SCAN_SEC_TYPE_OPEN, SL_SCAN_SEC_TYPE_WEP, SL_SCAN_SEC_TYPE_WPA or SL_SCAN_SEC_TYPE_WPA2 - - - \return Number of valid networks list items - - \sa - \note belongs to \ref ext_api - \warning This command do not initiate any active scanning action - \par Example: - \code An example of fetching max 10 results: - - Sl_WlanNetworkEntry_t netEntries[10]; - _i16 resultsCount = sl_WlanGetNetworkList(0,10,&netEntries[0]); - for(i=0; i< resultsCount; i++) - { - printf("%s\n",netEntries[i].ssid); - } - \endcode -*/ -#if _SL_INCLUDE_FUNC(sl_WlanGetNetworkList) -_i16 sl_WlanGetNetworkList(const _u8 Index,const _u8 Count, Sl_WlanNetworkEntry_t *pEntries); -#endif - -/*! - \brief Start collecting wlan RX statistics, for unlimited time. - - \return On success, zero is returned. On error, -1 is returned - - \sa sl_WlanRxStatStop sl_WlanRxStatGet - \note belongs to \ref ext_api - \warning - \par Example: - \code Getting wlan RX statistics: - - void RxStatCollectTwice() - { - SlGetRxStatResponse_t rxStat; - _i16 rawSocket; - _i8 DataFrame[200]; - struct SlTimeval_t timeval; - timeval.tv_sec = 0; // Seconds - timeval.tv_usec = 20000; // Microseconds. 10000 microseconds resolution - - sl_WlanRxStatStart(); // set statistics mode - - rawSocket = sl_Socket(SL_AF_RF, SL_SOCK_RAW, eChannel); - // set timeout - in case we have no activity for the specified channel - sl_SetSockOpt(rawSocket,SL_SOL_SOCKET,SL_SO_RCVTIMEO, &timeval, sizeof(timeval)); // Enable receive timeout - status = sl_Recv(rawSocket, DataFrame, sizeof(DataFrame), 0); - - Sleep(1000); // sleep for 1 sec - sl_WlanRxStatGet(&rxStat,0); // statistics has been cleared upon read - Sleep(1000); // sleep for 1 sec - sl_WlanRxStatGet(&rxStat,0); - - } - \endcode -*/ -#if _SL_INCLUDE_FUNC(sl_WlanRxStatStart) -_i16 sl_WlanRxStatStart(void); -#endif - - -/*! - \brief Stop collecting wlan RX statistic, (if previous called sl_WlanRxStatStart) - - \return On success, zero is returned. On error, -1 is returned - - \sa sl_WlanRxStatStart sl_WlanRxStatGet - \note belongs to \ref ext_api - \warning -*/ -#if _SL_INCLUDE_FUNC(sl_WlanRxStatStop) -_i16 sl_WlanRxStatStop(void); -#endif - - -/*! - \brief Get wlan RX statistics. upon calling this command, the statistics counters will be cleared. - - \param[in] Flags should be 0 ( not applicable right now, will be added the future ) - \param[in] pRxStat a pointer to SlGetRxStatResponse_t filled with Rx statistics results - \return On success, zero is returned. On error, -1 is returned - - \sa sl_WlanRxStatStart sl_WlanRxStatStop - \note belongs to \ref ext_api - \warning -*/ -#if _SL_INCLUDE_FUNC(sl_WlanRxStatGet) -_i16 sl_WlanRxStatGet(SlGetRxStatResponse_t *pRxStat,const _u32 Flags); -#endif - - -/*! - \brief Stop Smart Config procedure. Once Smart Config will be stopped, - Asynchronous event will be received - SL_OPCODE_WLAN_SMART_CONFIG_STOP_ASYNC_RESPONSE. - - \param[in] none - \param[out] none - - \return 0 - if Stop Smart Config is about to be executed without errors. - - \sa sl_WlanSmartConfigStart - \note belongs to \ref ext_api - \warning - -*/ -#if _SL_INCLUDE_FUNC(sl_WlanSmartConfigStop) -_i16 sl_WlanSmartConfigStop(void); -#endif - -/*! - \brief Start Smart Config procedure - \par - The target of the procedure is to let the \n - device to gain the network parameters: SSID and Password (if network is secured) \n - and to connect to it once located in the network range. \n - An external application should be used on a device connected to any mobile network. \n - The external application will transmit over the air the network parameters in secured manner.\n - The Password may be decrypted using a Key. \n - The decryption method may be decided in the command or embedded in the Flash. \n - The procedure can be activated for 1-3 group ID in the range of BIT_0 - BIT_15 where the default group ID id 0 (BIT_0) \n - Once Smart Config has ended successfully, Asynchronous event will be received - \n - SL_OPCODE_WLAN_SMART_CONFIG_START_ASYNC_RESPONSE. \n - The Event will hold the SSID and an extra field that might have been delivered as well (i.e. - device name) - - \param[in] groupIdBitmask - each bit represent a group ID that should be searched. - The Default group ID id BIT_0. 2 more group can be searched - in addition. The range is BIT_0 - BIT_15. - \param[in] chiper - 0: check in flash, 1 - AES, 0xFF - do not check in flash - \param[in] publicKeyLen - public key len (used for the default group ID - BIT_0) - \param[in] group1KeyLen - group ID1 length - \param[in] group2KeyLen - group ID2 length - \param[in] publicKey - public key (used for the default group ID - BIT_0) - \param[in] group1Key - group ID1 key - \param[in] group2Key - group ID2 key - - \param[out] none - - \return 0 - if Smart Config started successfully. - - \sa sl_WlanSmartConfigStop - \note belongs to \ref ext_api - \warning - \par - \code An example of starting smart Config on group ID's 0 + 1 + 2 - - sl_WlanSmartConfigStart(7, //group ID's (BIT_0 | BIT_1 | BIT_2) - 1, //decrypt key by AES method - 16, //decryption key length for group ID0 - 16, //decryption key length for group ID1 - 16, //decryption key length for group ID2 - "Key0Key0Key0Key0", //decryption key for group ID0 - "Key1Key1Key1Key1", //decryption key for group ID1 - "Key2Key2Key2Key2" //decryption key for group ID2 - ); - \endcode -*/ -#if _SL_INCLUDE_FUNC(sl_WlanSmartConfigStart) -_i16 sl_WlanSmartConfigStart(const _u32 groupIdBitmask, - const _u8 cipher, - const _u8 publicKeyLen, - const _u8 group1KeyLen, - const _u8 group2KeyLen, - const _u8* publicKey, - const _u8* group1Key, - const _u8* group2Key); -#endif - - -/*! - \brief Wlan set mode - - Setting WLAN mode - - \param[in] mode - WLAN mode to start the CC31xx device. Possible options are: - - ROLE_STA - for WLAN station mode - - ROLE_AP - for WLAN AP mode - - ROLE_P2P -for WLAN P2P mode - \return 0 - if mode was set correctly - \sa sl_Start sl_Stop - \note belongs to \ref ext_api - \warning After setting the mode the system must be restarted for activating the new mode - \par Example: - \code - //Switch from any role to STA: - sl_WlanSetMode(ROLE_STA); - sl_Stop(0); - sl_Start(NULL,NULL,NULL); - \endcode - -*/ -#if _SL_INCLUDE_FUNC(sl_WlanSetMode) -_i16 sl_WlanSetMode(const _u8 mode); -#endif - - -/*! - \brief Internal function for setting WLAN configurations - - \return On success, zero is returned. On error one of the following error codes returned: - - CONF_ERROR (-1) - - CONF_NVMEM_ACCESS_FAILED (-2) - - CONF_OLD_FILE_VERSION (-3) - - CONF_ERROR_NO_SUCH_COUNTRY_CODE (-4) - - - \param[in] ConfigId - configuration id - - SL_WLAN_CFG_AP_ID - - SL_WLAN_CFG_GENERAL_PARAM_ID - - SL_WLAN_CFG_P2P_PARAM_ID - - \param[in] ConfigOpt - configurations option - - SL_WLAN_CFG_AP_ID - - WLAN_AP_OPT_SSID \n - Set SSID for AP mode. \n - This options takes _u8 buffer as parameter - - WLAN_AP_OPT_CHANNEL \n - Set channel for AP mode. \n - The channel is dependant on the country code which is set. i.e. for "US" the channel should be in the range of [1-11] \n - This option takes _u8 as a parameter - - WLAN_AP_OPT_HIDDEN_SSID \n - Set Hidden SSID Mode for AP mode.Hidden options: \n - 0: disabled \n - 1: Send empty (length=0) SSID in beacon and ignore probe request for broadcast SSID \n - 2: Clear SSID (ASCII 0), but keep the original length (this may be required with some \n - clients that do not support empty SSID) and ignore probe requests for broadcast SSID \n - This option takes _u8 as a parameter - - WLAN_AP_OPT_SECURITY_TYPE \n - Set Security type for AP mode. Security options are: - - Open security: SL_SEC_TYPE_OPEN - - WEP security: SL_SEC_TYPE_WEP - - WPA security: SL_SEC_TYPE_WPA_WPA2 \n - This option takes _u8 pointer as a parameter - - WLAN_AP_OPT_PASSWORD \n - Set Password for for AP mode (for WEP or for WPA): \n - Password - for WPA: 8 - 63 characters \n - for WEP: 5 / 13 characters (ascii) \n - This options takes _u8 buffer as parameter - - SL_WLAN_CFG_GENERAL_PARAM_ID - - WLAN_GENERAL_PARAM_OPT_SCAN_PARAMS \n - Set scan parameters. - This option uses slWlanScanParamCommand_t as parameter - - WLAN_GENERAL_PARAM_OPT_COUNTRY_CODE \n - Set Country Code for AP mode \n - This options takes _u8 2 bytes buffer as parameter - - WLAN_GENERAL_PARAM_OPT_STA_TX_POWER \n - Set STA mode Tx power level \n - Number between 0-15, as dB offset from max power (0 will set MAX power) \n - This options takes _u8 as parameter - - WLAN_GENERAL_PARAM_OPT_AP_TX_POWER - Set AP mode Tx power level \n - Number between 0-15, as dB offset from max power (0 will set MAX power) \n - This options takes _u8 as parameter - - WLAN_GENERAL_PARAM_OPT_INFO_ELEMENT - Set Info Element for AP mode. \n - The Application can set up to MAX_PRIVATE_INFO_ELEMENTS_SUPPROTED info elements per Role (AP / P2P GO). \n - To delete an info element use the relevant index and length = 0. \n - The Application can set up to MAX_PRIVATE_INFO_ELEMENTS_SUPPROTED to the same role. \n - However, for AP - no more than INFO_ELEMENT_MAX_TOTAL_LENGTH_AP bytes can be stored for all info elements. \n - For P2P GO - no more than INFO_ELEMENT_MAX_TOTAL_LENGTH_P2P_GO bytes can be stored for all info elements. \n - This option takes sl_protocol_WlanSetInfoElement_t as parameter - - SL_WLAN_CFG_P2P_PARAM_ID - - WLAN_P2P_OPT_DEV_TYPE \n - Set P2P Device type.Maximum length of 17 characters. Device type is published under P2P I.E, \n - allows to make devices easier to recognize. \n - In case no device type is set, the default type is "1-0050F204-1" \n - This options takes _u8 buffer as parameter - - WLAN_P2P_OPT_CHANNEL_N_REGS \n - Set P2P Channels. \n - listen channel (either 1/6/11 for 2.4GHz) \n - listen regulatory class (81 for 2.4GHz) \n - oper channel (either 1/6/11 for 2.4GHz) \n - oper regulatory class (81 for 2.4GHz) \n - listen channel and regulatory class will determine the device listen channel during p2p find listen phase \n - oper channel and regulatory class will determine the operating channel preferred by this device (in case it is group owner this will be the operating channel) \n - channels should be one of the social channels (1/6/11). In case no listen/oper channel selected, a random 1/6/11 will be selected. - This option takes pointer to _u8[4] as parameter - - \param[in] ConfigLen - configurations len - - \param[in] pValues - configurations values - - \sa - \note - \warning - \par Examples: - \par - WLAN_AP_OPT_SSID: - \code - _u8 str[33]; - memset(str, 0, 33); - memcpy(str, ssid, len); // ssid string of 32 characters - sl_WlanSet(SL_WLAN_CFG_AP_ID, WLAN_AP_OPT_SSID, strlen(ssid), str); - \endcode - \par - WLAN_AP_OPT_CHANNEL: - \code - _u8 val = channel; - sl_WlanSet(SL_WLAN_CFG_AP_ID, WLAN_AP_OPT_CHANNEL, 1, (_u8 *)&val); - \endcode - \par - WLAN_AP_OPT_HIDDEN_SSID: - \code - _u8 val = hidden; - sl_WlanSet(SL_WLAN_CFG_AP_ID, WLAN_AP_OPT_HIDDEN_SSID, 1, (_u8 *)&val); - \endcode - \par - WLAN_AP_OPT_SECURITY_TYPE: - \code - _u8 val = SL_SEC_TYPE_WPA_WPA2; - sl_WlanSet(SL_WLAN_CFG_AP_ID, WLAN_AP_OPT_SECURITY_TYPE, 1, (_u8 *)&val); - \endcode - \par - WLAN_AP_OPT_PASSWORD: - \code - _u8 str[65]; - _u16 len = strlen(password); - memset(str, 0, 65); - memcpy(str, password, len); - sl_WlanSet(SL_WLAN_CFG_AP_ID, WLAN_AP_OPT_PASSWORD, len, (_u8 *)str); - \endcode - \par - WLAN_GENERAL_PARAM_OPT_STA_TX_POWER: - \code - _u8 stapower=(_u8)power; - sl_WlanSet(SL_WLAN_CFG_GENERAL_PARAM_ID, WLAN_GENERAL_PARAM_OPT_STA_TX_POWER,1,(_u8 *)&stapower); - \endcode - \par - WLAN_GENERAL_PARAM_OPT_SCAN_PARAMS: - \code - slWlanScanParamCommand_t ScanParamConfig; - ScanParamConfig.G_Channels_mask = 0x01; // bit mask for channels:1 means channel 1 is enabled, 3 means channels 1 + 2 are enabled - ScanParamConfig.rssiThershold = -70; // only for RSSI level which is higher than -70 - sl_WlanSet(SL_WLAN_CFG_GENERAL_PARAM_ID ,WLAN_GENERAL_PARAM_OPT_SCAN_PARAMS,sizeof(slWlanScanParamCommand_t),(_u8*)&ScanParamConfig); - \endcode - - \par - WLAN_GENERAL_PARAM_OPT_COUNTRY_CODE: - \code - _u8* str = (_u8 *) country; // string of 2 characters. i.e. - "US" - sl_WlanSet(SL_WLAN_CFG_GENERAL_PARAM_ID, WLAN_GENERAL_PARAM_OPT_COUNTRY_CODE, 2, str); - \endcode - \par - WLAN_GENERAL_PARAM_OPT_AP_TX_POWER: - \code - _u8 appower=(_u8)power; - sl_WlanSet(SL_WLAN_CFG_GENERAL_PARAM_ID, WLAN_GENERAL_PARAM_OPT_AP_TX_POWER,1,(_u8 *)&appower); - \endcode - \par - WLAN_P2P_OPT_DEV_TYPE: - \code - _u8 str[17]; - _u16 len = strlen(device_type); - memset(str, 0, 17); - memcpy(str, device_type, len); - sl_WlanSet(SL_WLAN_CFG_P2P_PARAM_ID, WLAN_P2P_OPT_DEV_TYPE, len, str); - \endcode - \par - WLAN_P2P_OPT_CHANNEL_N_REGS: - \code - _u8 str[4]; - str[0] = (_u8)11; // listen channel - str[1] = (_u8)81; // listen regulatory class - str[2] = (_u8)6; // oper channel - str[3] = (_u8)81; // oper regulatory class - sl_WlanSet(SL_WLAN_CFG_P2P_PARAM_ID, WLAN_P2P_OPT_CHANNEL_N_REGS, 4, str); - \endcode - \par - WLAN_GENERAL_PARAM_OPT_INFO_ELEMENT: - \code - sl_protocol_WlanSetInfoElement_t infoele; - infoele.index = Index; // Index of the info element. range: 0 - MAX_PRIVATE_INFO_ELEMENTS_SUPPROTED - infoele.role = Role; // INFO_ELEMENT_AP_ROLE (0) or INFO_ELEMENT_P2P_GO_ROLE (1) - infoele.ie.id = Id; // Info element ID. if INFO_ELEMENT_DEFAULT_ID (0) is set, ID will be set to 221. - // Organization unique ID. If all 3 bytes are zero - it will be replaced with 08,00,28. - infoele.ie.oui[0] = Oui0; // Organization unique ID first Byte - infoele.ie.oui[1] = Oui1; // Organization unique ID second Byte - infoele.ie.oui[2] = Oui2; // Organization unique ID third Byte - infoele.ie.length = Len; // Length of the info element. must be smaller than 253 bytes - memset(infoele.ie.data, 0, INFO_ELEMENT_MAX_SIZE); - if ( Len <= INFO_ELEMENT_MAX_SIZE ) - { - memcpy(infoele.ie.data, IE, Len); // Info element. length of the info element is [0-252] - sl_WlanSet(SL_WLAN_CFG_GENERAL_PARAM_ID,WLAN_GENERAL_PARAM_OPT_INFO_ELEMENT,sizeof(sl_protocol_WlanSetInfoElement_t),(_u8* ) &infoele); - } - sl_WlanSet(SL_WLAN_CFG_GENERAL_PARAM_ID,WLAN_GENERAL_PARAM_OPT_INFO_ELEMENT,sizeof(sl_protocol_WlanSetInfoElement_t),(_u8* ) &infoele); - \endcode - -*/ -#if _SL_INCLUDE_FUNC(sl_WlanSet) -_i16 sl_WlanSet(const _u16 ConfigId ,const _u16 ConfigOpt,const _u16 ConfigLen,const _u8 *pValues); -#endif - -/*! - \brief Internal function for getting WLAN configurations - - \return On success, zero is returned. On error, -1 is - returned - - \param[in] ConfigId - configuration id - - SL_WLAN_CFG_AP_ID - - SL_WLAN_CFG_GENERAL_PARAM_ID - - SL_WLAN_CFG_P2P_PARAM_ID - - \param[out] pConfigOpt - get configurations option - - SL_WLAN_CFG_AP_ID - - WLAN_AP_OPT_SSID \n - Get SSID for AP mode. \n - Get up to 32 characters of SSID \n - This options takes _u8 as parameter - - WLAN_AP_OPT_CHANNEL \n - Get channel for AP mode. \n - This option takes _u8 as a parameter - - WLAN_AP_OPT_HIDDEN_SSID \n - Get Hidden SSID Mode for AP mode.Hidden options: \n - 0: disabled \n - 1: Send empty (length=0) SSID in beacon and ignore probe request for broadcast SSID \n - 2: Clear SSID (ASCII 0), but keep the original length (this may be required with some \n - clients that do not support empty SSID) and ignore probe requests for broadcast SSID \n - This option takes _u8 as a parameter - - WLAN_AP_OPT_SECURITY_TYPE \n - Get Security type for AP mode. Security options are: - - Open security: SL_SEC_TYPE_OPEN - - WEP security: SL_SEC_TYPE_WEP - - WPA security: SL_SEC_TYPE_WPA_WPA2 \n - This option takes _u8 as a parameter - - WLAN_AP_OPT_PASSWORD \n - Get Password for for AP mode (for WEP or for WPA): \n - Returns password - string, fills up to 64 characters. \n - This options takes _u8 buffer as parameter - - SL_WLAN_CFG_GENERAL_PARAM_ID - - WLAN_GENERAL_PARAM_OPT_SCAN_PARAMS \n - Get scan parameters. - This option uses slWlanScanParamCommand_t as parameter - - WLAN_GENERAL_PARAM_OPT_COUNTRY_CODE \n - Get Country Code for AP mode \n - This options takes _u8 buffer as parameter - - WLAN_GENERAL_PARAM_OPT_STA_TX_POWER \n - Get STA mode Tx power level \n - Number between 0-15, as dB offset from max power (0 indicates MAX power) \n - This options takes _u8 as parameter - - WLAN_GENERAL_PARAM_OPT_AP_TX_POWER - Get AP mode Tx power level \n - Number between 0-15, as dB offset from max power (0 indicates MAX power) \n - This options takes _u8 as parameter - - SL_WLAN_CFG_P2P_PARAM_ID - - WLAN_P2P_OPT_CHANNEL_N_REGS \n - Get P2P Channels. \n - listen channel (either 1/6/11 for 2.4GHz) \n - listen regulatory class (81 for 2.4GHz) \n - oper channel (either 1/6/11 for 2.4GHz) \n - oper regulatory class (81 for 2.4GHz) \n - listen channel and regulatory class will determine the device listen channel during p2p find listen phase \n - oper channel and regulatory class will determine the operating channel preferred by this device (in case it is group owner this will be the operating channel) \n - channels should be one of the social channels (1/6/11). In case no listen/oper channel selected, a random 1/6/11 will be selected. \n - This option takes pointer to _u8[4] as parameter - - \param[out] pConfigLen - The length of the allocated memory as input, when the - function complete, the value of this parameter would be - the len that actually read from the device. - If the device return length that is longer from the input - value, the function will cut the end of the returned structure - and will return SL_ESMALLBUF. - - - \param[out] pValues - get configurations values - - \sa sl_WlanSet - - \note - - \warning - - \par Examples: - \par - WLAN_GENERAL_PARAM_OPT_SCAN_PARAMS: - \code - slWlanScanParamCommand_t ScanParamConfig; - _u16 Option = WLAN_GENERAL_PARAM_OPT_SCAN_PARAMS; - _u16 OptionLen = sizeof(slWlanScanParamCommand_t); - sl_WlanGet(SL_WLAN_CFG_GENERAL_PARAM_ID ,&Option,&OptionLen,(_u8 *)&ScanParamConfig); - \endcode - \par - WLAN_GENERAL_PARAM_OPT_AP_TX_POWER: - \code - _i8 TXPower = 0; - _u16 Option = WLAN_GENERAL_PARAM_OPT_AP_TX_POWER; - _u16 OptionLen = sizeof(_i8); - sl_WlanGet(SL_WLAN_CFG_GENERAL_PARAM_ID ,&Option,&OptionLen,(_u8 *)&TXPower); - \endcode - \par - WLAN_GENERAL_PARAM_OPT_STA_TX_POWER: - \code - _i8 TXPower = 0; - _u16 Option = WLAN_GENERAL_PARAM_OPT_STA_TX_POWER; - _u16 OptionLen = sizeof(_i8); - - sl_WlanGet(SL_WLAN_CFG_GENERAL_PARAM_ID ,&Option,&OptionLen,(_u8 *)&TXPower); - \endcode - \par - WLAN_P2P_OPT_DEV_TYPE: - \code - _i8 device_type[18]; - _u16 len = 18; - _u16 config_opt = WLAN_P2P_OPT_DEV_TYPE; - sl_WlanGet(SL_WLAN_CFG_P2P_PARAM_ID, &config_opt , &len, (_u8* )device_type); - \endcode - \par - WLAN_AP_OPT_SSID: - \code - _i8 ssid[32]; - _u16 len = 32; - _u16 config_opt = WLAN_AP_OPT_SSID; - sl_WlanGet(SL_WLAN_CFG_AP_ID, &config_opt , &len, (_u8* )ssid); - \endcode - \par - WLAN_GENERAL_PARAM_OPT_COUNTRY_CODE: - \code - _i8 country[3]; - _u16 len = 3; - _u16 config_opt = WLAN_GENERAL_PARAM_OPT_COUNTRY_CODE; - sl_WlanGet(SL_WLAN_CFG_GENERAL_PARAM_ID, &config_opt, &len, (_u8* )country); - \endcode - \par - WLAN_AP_OPT_CHANNEL: - \code - _i8 channel; - _u16 len = 1; - _u16 config_opt = WLAN_AP_OPT_CHANNEL; - sl_WlanGet(SL_WLAN_CFG_AP_ID, &config_opt, &len, (_u8* )&channel); - \endcode - \par - WLAN_AP_OPT_HIDDEN_SSID: - \code - _u8 hidden; - _u16 len = 1; - _u16 config_opt = WLAN_AP_OPT_HIDDEN_SSID; - sl_WlanGet(SL_WLAN_CFG_AP_ID, &config_opt, &len, (_u8* )&hidden); - \endcode - \par - WLAN_AP_OPT_SECURITY_TYPE: - \code - _u8 sec_type; - _u16 len = 1; - _u16 config_opt = WLAN_AP_OPT_SECURITY_TYPE; - sl_WlanGet(SL_WLAN_CFG_AP_ID, &config_opt, &len, (_u8* )&sec_type); - \endcode - \par - WLAN_AP_OPT_PASSWORD: - \code - _u8 password[64]; - _u16 len = 64; - memset(password,0,64); - _u16 config_opt = WLAN_AP_OPT_PASSWORD; - sl_WlanGet(SL_WLAN_CFG_AP_ID, &config_opt, &len, (_u8* )password); - - \endcode - \par - WLAN_P2P_OPT_CHANNEL_N_REGS: - \code - _u16 listen_channel,listen_reg,oper_channel,oper_reg; - _u16 len = 4; - _u16 config_opt = WLAN_P2P_OPT_CHANNEL_N_REGS; - _u8 channel_n_regs[4]; - sl_WlanGet(SL_WLAN_CFG_P2P_PARAM_ID, &config_opt, &len, (_u8* )channel_n_regs); - listen_channel = channel_n_regs[0]; - listen_reg = channel_n_regs[1]; - oper_channel = channel_n_regs[2]; - oper_reg = channel_n_regs[3]; - \endcode -*/ - -#if _SL_INCLUDE_FUNC(sl_WlanGet) -_i16 sl_WlanGet(const _u16 ConfigId, _u16 *pConfigOpt,_u16 *pConfigLen, _u8 *pValues); -#endif -/*! - - Close the Doxygen group. - @} - - */ - - -#ifdef __cplusplus -} -#endif /* __cplusplus */ - -#endif /* __WLAN_H__ */ - diff --git a/drivers/cc3100/inc/wlan_rx_filters.h b/drivers/cc3100/inc/wlan_rx_filters.h deleted file mode 100644 index 8bd712f0df..0000000000 --- a/drivers/cc3100/inc/wlan_rx_filters.h +++ /dev/null @@ -1,932 +0,0 @@ -/* - * wlan_rx_filters.h - CC31xx/CC32xx Host Driver Implementation - * - * Copyright (C) 2014 Texas Instruments Incorporated - http://www.ti.com/ - * - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * - * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the - * distribution. - * - * Neither the name of Texas Instruments Incorporated nor the names of - * its contributors may be used to endorse or promote products derived - * from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * -*/ - - -/*****************************************************************************/ -/* Include files */ -/*****************************************************************************/ -#include "simplelink.h" - -#ifndef RX_FILTERS_PREPROCESSOR_CLI_IF_H_ -#define RX_FILTERS_PREPROCESSOR_CLI_IF_H_ - - - -#ifdef __cplusplus -extern "C" { -#endif - - -/*****************************************************************************/ -/* Macro declarations */ -/*****************************************************************************/ - -/*! - * \def SL_RX_FILTER_MAX_FILTERS - * The Max number of filters for 64 filters - */ -#define SL_RX_FILTER_MAX_FILTERS 64 - -/*! - * \def SL_RX_FILTER_MAX_PRE_PREPARED_FILTERS_SETS - * The Max number of software filters - */ -#define SL_RX_FILTER_MAX_PRE_PREPARED_FILTERS_SETS (32) -/*! - * \def SL_RX_FILTER_NUM_OF_FILTER_HEADER_ARGS - * - */ -#define SL_RX_FILTER_NUM_OF_FILTER_HEADER_ARGS (2) -/*! - * \def SL_RX_FILTER_NUM_OF_FILTER_PAYLOAD_ARGS - * - */ -#define SL_RX_FILTER_NUM_OF_FILTER_PAYLOAD_ARGS (2) -/*! - * \def SL_RX_FILTER_NUM_OF_FILTER_PAYLOAD_ARGS - * - */ -#define SL_RX_FILTER_NUM_OF_COMBINATION_TYPE_ARGS (2) -/*! - * \def SL_RX_FILTER_LENGTH_OF_REGX_PATTERN_LENGTH - * - */ -#define SL_RX_FILTER_LENGTH_OF_REGX_PATTERN_LENGTH (32) - - -/* List of possible error numbers */ -#define RXFL_OK (0) /* O.K */ -#define RXFL_OUTPUT_OR_INPUT_BUFFER_LENGTH_TOO_SMALL (76) /* ! The output buffer length is smaller than required for that operation */ -#define RXFL_DEPENDENT_FILTER_SOFTWARE_FILTER_NOT_FIT (75) /* Node filter can't be child of software filter and vice_versa */ -#define RXFL_DEPENDENCY_IS_NOT_PERSISTENT (74) /* Dependency filter is not persistent */ -#define RXFL_SYSTEM_STATE_NOT_SUPPORTED_FOR_THIS_FILTER (72) /* System state is not supported */ -#define RXFL_TRIGGER_USE_REG5_TO_REG8 (71) /* Only counters 5 - 8 are allowed, for Tigger */ -#define RXFL_TRIGGER_USE_REG1_TO_REG4 (70) /* Only counters 1 - 4 are allowed, for trigger */ -#define RXFL_ACTION_USE_REG5_TO_REG8 (69) /* Only counters 5 - 8 are allowed, for action */ -#define RXFL_ACTION_USE_REG1_TO_REG4 (68) /* Only counters 1 - 4 are allowed, for action */ -#define RXFL_FIELD_SUPPORT_ONLY_EQUAL_AND_NOTEQUAL (67) /* Rule compare function Id is out of range */ -#define RXFL_WRONG_MULTICAST_BROADCAST_ADDRESS (66) /* The address should be of type mutlicast or broadcast */ -#define RXFL_THE_FILTER_IS_NOT_OF_HEADER_TYPE (65) /* The filter should be of header type */ -#define RXFL_WRONG_COMPARE_FUNC_FOR_BROADCAST_ADDRESS (64) /* The compare funcion is not suitable for broadcast address */ -#define RXFL_WRONG_MULTICAST_ADDRESS (63) /* The address should be of muticast type */ -#define RXFL_DEPENDENT_FILTER_IS_NOT_PERSISTENT (62) /* The dependency filter is not persistent */ -#define RXFL_DEPENDENT_FILTER_IS_NOT_ENABLED (61) /* The dependency filter is not enabled */ -#define RXFL_FILTER_HAS_CHILDS (60) /* The filter has childs and can't be removed */ -#define RXFL_CHILD_IS_ENABLED (59) /* Can't disable filter while the child is enabled */ -#define RXFL_DEPENDENCY_IS_DISABLED (58) /* Can't enable filetr in case its depndency filter is disabled */ -#define RXFL_NUMBER_OF_CONNECTION_POINTS_EXCEEDED (52) /* Number of connection points exceeded */ -#define RXFL_DEPENDENT_FILTER_DEPENDENCY_ACTION_IS_DROP (51) /* The dependent filter has Drop action, thus the filter can't be created */ -#define RXFL_FILTER_DO_NOT_EXISTS (50) /* The filter doesn't exists */ -#define RXFL_DEPEDENCY_NOT_ON_THE_SAME_LAYER (49) /* The filter and its dependency must be on the same layer */ -#define RXFL_NUMBER_OF_ARGS_EXCEEDED (48) /* Number of arguments excceded */ -#define RXFL_ACTION_NO_REG_NUMBER (47) /* Action require counter number */ -#define RXFL_DEPENDENT_FILTER_LAYER_DO_NOT_FIT (46) /* the filter and its dependency should be from the same layer */ -#define RXFL_DEPENDENT_FILTER_SYSTEM_STATE_DO_NOT_FIT (45) /* The filter and its dependency system state don't fit */ -#define RXFL_DEPENDENT_FILTER_DO_NOT_EXIST_2 (44) /* The parent filter don't exist */ -#define RXFL_DEPENDENT_FILTER_DO_NOT_EXIST_1 (43) /* The parent filter is null */ -#define RXFL_RULE_HEADER_ACTION_TYPE_NOT_SUPPORTED (42) /* The action type is not supported */ -#define RXFL_RULE_HEADER_TRIGGER_COMPARE_FUNC_OUT_OF_RANGE (41) /* The Trigger comparision function is out of range */ -#define RXFL_RULE_HEADER_TRIGGER_OUT_OF_RANGE (40) /* The Trigger is out of range */ -#define RXFL_RULE_HEADER_COMPARE_FUNC_OUT_OF_RANGE (39) /* The rule compare function is out of range */ -#define RXFL_FRAME_TYPE_NOT_SUPPORTED (38) /* ASCII frame type string is illegal */ -#define RXFL_RULE_FIELD_ID_NOT_SUPPORTED (37) /* Rule field ID is out of range */ -#define RXFL_RULE_HEADER_FIELD_ID_ASCII_NOT_SUPPORTED (36) /* This ASCII field ID is not supported */ -#define RXFL_RULE_HEADER_NOT_SUPPORTED (35) /* The header rule is not supported on current release */ -#define RXFL_RULE_HEADER_OUT_OF_RANGE (34) /* The header rule is out of range */ -#define RXFL_RULE_HEADER_COMBINATION_OPERATOR_OUT_OF_RANGE (33) /* Combination function Id is out of ramge */ -#define RXFL_RULE_HEADER_FIELD_ID_OUT_OF_RANGE (32) /* rule field Id is out of range */ -#define RXFL_UPDATE_NOT_SUPPORTED (31) /* Update not supported */ -#define RXFL_NO_FILTERS_ARE_DEFINED (24) /* No filters are defined in the system */ -#define RXFL_NUMBER_OF_FILTER_EXCEEDED (23) /* Number of max filters excceded */ - - -/******************************************************************************/ -/* Type declarations */ -/******************************************************************************/ - -/*! - - - * \typedef SlrxFilterID_t - * Unique filter ID which is allocated by the system , negative number means error - */ -typedef _i8 SlrxFilterID_t; - - -/*! - * \typedef SlrxFilterCompareMask_t - * The mask is used for the rule comparison function - */ -typedef _u8 SlrxFilterCompareMask_t; - -/*! - * \typedef SlrxFilterIdMask_t - * Representation of filters Id as a bit field - * The bit field is used to declare which filters are involved - * in operation. Number of filter can be up to 128 filters. i.e. 128 bits are needed. - * On the current release, up to 64 filters can be defined. - */ -typedef _u8 SlrxFilterIdMask_t[128/8]; - -/*! - * \typedef SlrxFilterPrePreparedFilters_t - * Describes the supported software filter sets, - */ -typedef _u8 SlrxFilterPrePreparedFilters_t; -#define SL_ARP_AUTO_REPLY_PRE_PREPARED_FILTERS (0) -#define SL_MULTICASTSIPV4_DROP_PREPREPARED_FILTERS (1) -#define SL_MULTICASTSIPV6_DROP_PREPREPARED_FILTERS (2) -#define SL_MULTICASTSWIFI_DROP_PREPREPARED_FILTERS (3) - - - -/*! - * \typedef SlrxFilterPrePreparedFiltersMask_t - * Describes the supported software filter sets, - * each bit represents different software filter set - * The filter sets are defined at SlrxFilterPrePreparedFilters_t - */ -typedef _u8 SlrxFilterPrePreparedFiltersMask_t[SL_RX_FILTER_MAX_PRE_PREPARED_FILTERS_SETS/8]; - - -/*! \typedef SlrxFilterRegxPattern_t - * The struct contains the regular expression pattern which is used in case of payload rule. - * Not supported in the current release - */ -typedef struct SlrxFilterRegxPattern_t -{ - _u8 x[SL_RX_FILTER_LENGTH_OF_REGX_PATTERN_LENGTH]; -}SlrxFilterRegxPattern_t; - - -/*! \typedef SlrxFilterAsciiArg_t - * The buffer is used to provide container for ASCII argument, which may be used in case of HEADER rule. - * example for ASCII argument can be : IP = 256.0.67.1 - */ -typedef _u8 SlrxFilterAsciiArg_t; - - -/*! \typedef SlrxFilterBinaryArg_t - * The buffer provides container for binary argument, which may be used in case of HEADER rule - */ -typedef _u8 SlrxFilterBinaryArg_t ; - - -/*! \typedef SlrxFilterActionArg_t - * Provides container for the filter action argument. - * for example: in case action is to send automatic response , the argument is the template to be used for the automatic response. - * - * - */ -typedef _u8 SlrxFilterActionArg_t ; - - - -/*! \typedef SlrxFilterOffset_t - * The offset relative to the packet payload start location. - * Not supported on current release - */ -typedef _u32 SlrxFilterOffset_t; - - - -/*! \typedef SlrxFilterRuleType_t - * Enumerates the different filter types. - * On the current release only HEADER and COMBINATION are supported. - */ -typedef _u8 SlrxFilterRuleType_t; -/* possible values for SlrxFilterRuleType_t */ -#define HEADER (0) -#define COMBINATION (1) -#define EXACT_PATTERN (2) -#define LIKELIHOOD_PATTERN (3) -#define ALWAYS_TRUE (4) -#define NUM_OF_FILTER_TYPES (5) - - -/*! \typedef SlrxFilterFlags_t - * Bit field which sets the behaviour of the RX filter - * - */ - -#define RX_FILTER_BINARY (0x1) -#define RX_FILTER_PERSISTENT (0x8) -#define RX_FILTER_ENABLE (0x10) - -typedef union SlrxFilterFlags_t -{ - - /* struct - { */ - /*! - * The filter argument can be set as binary argument or ASCII arguments. - * When the bit is on the argument are binary. - */ - /* _u8 Binary: 1; */ - /*! - * - */ - /* _u8 AutoSort : 1; */ - /*! - * - */ - /* _u8 AutoFaultDetect : 1; */ - /*! - * When the bit is on it means the the node is enabled . - */ - /* _u8 Enabled : 1; */ - /* _u8 padding : 3; */ - /* - };*/ - - _u8 IntRepresentation; - -}SlrxFilterFlags_t; - -/*! \typedef SlrxFilterCompareFunction_t - * Used as comparison function for the header type arguments - * - */ -typedef _u8 SlrxFilterCompareFunction_t; -/* Possible values for SlrxFilterCompareFunction_t */ -#define COMPARE_FUNC_IN_BETWEEN (0) -#define COMPARE_FUNC_EQUAL (1) -#define COMPARE_FUNC_NOT_EQUAL_TO (2) -#define COMPARE_FUNC_NOT_IN_BETWEEN (3) -#define COMPARE_FUNC_NUM_OF_FILTER_COMPARE_FUNC (4) - -/*! \typedef SlrxFilterCompareFunction_t - * Used as comparison function for the header type arguments - * - */ -typedef _u8 SlrxTriggerCompareFunction_t; -/* Possible values for SlrxTriggerCompareFunction_t */ -#define TRIGGER_COMPARE_FUNC_EQUAL (0) -/* arg1 == protocolVal ,not supported in current release */ -#define TRIGGER_COMPARE_FUNC_NOT_EQUAL_TO (1) -/* arg1 == protocolVal */ -#define TRIGGER_COMPARE_FUNC_SMALLER_THAN (2) -/* arg1 == protocolVal */ -#define TRIGGER_COMPARE_FUNC_BIGGER_THAN (3) -/* definition */ -#define TRIGGER_COMPARE_FUNC_NUM_OF_FILTER_COMPARE_FUNC (4) - - -/*! \typedef SlrxFilterHdrField_t - * Provides list of possible header types which may be defined as part of the rule - * - */ -typedef _u8 SlrxFilterHdrField_t; -/* Possible values for SlrxFilterHdrField_t */ -#define NULL_FIELD_ID_TYPE (0) -/* 802.11 control\data\management */ -#define FRAME_TYPE_FIELD (1) -/* 802.11 beacon\probe\.. */ -#define FRAME_SUBTYPE_FIELD (2) - /* 802.11 bssid type */ -#define BSSID_FIELD (3) - /* */ -#define MAC_SRC_ADDRESS_FIELD (4) - /* */ -#define MAC_DST_ADDRESS_FIELD (5) -/* */ -#define FRAME_LENGTH_FIELD (6) -/* */ -#define PROTOCOL_TYPE_FIELD (7) - /* */ -#define IP_VERSION_FIELD (8) - /* TCP / UDP */ -#define IP_PROTOCOL_FIELD (9) - /* */ -#define IPV4_SRC_ADRRESS_FIELD (10) -/* */ -#define IPV4_DST_ADDRESS_FIELD (11) -/* */ -#define IPV6_SRC_ADRRESS_FIELD (12) -/* */ -#define IPV6_DST_ADDRESS_FIELD (13) - /* */ -#define SRC_PORT_FIELD (14) - /* */ -#define DST_PORT_FIELD (15) - /* Definition */ -#define NUM_OF_FIELD_NAME_FIELD (16) - -/*! \union SlrxFilterHeaderArg_t - * The structure holds the header ARGS which are used in case of HDR rule. - */ -/* -- 36 bytes */ -typedef union SlrxFilterHeaderArg_t -{ - /*----------------------------- Large size ---------------------------------*/ - /*! buffer for binary arguments, number of argument may be up to SL_RX_FILTER_NUM_OF_FILTER_HEADER_ARGS - * example : IPV6 16 bytes, 39 characters - * ipv6 Ascii address: 2001:0db8:3c4d:0015:0000:0000:abcd:ef12 - */ - - SlrxFilterBinaryArg_t RxFilterDB16BytesRuleArgs[SL_RX_FILTER_NUM_OF_FILTER_HEADER_ARGS][16 ]; /* Binary Values for comparition */ - /*! buffer for ASCII arguments, number of argument may be up to SL_RX_FILTER_NUM_OF_FILTER_HEADER_ARGS - * example : IPV6 16 bytes, 39 characters - * ipv6 Ascii address: 2001:0db8:3c4d:0015:0000:0000:abcd:ef12 - * Ascii format for ipV6 is not supported - */ - /*----------------------------- Medium size ---------------------------------*/ - /*! buffer for binary arguments, number of argument may be up to SL_RX_FILTER_NUM_OF_FILTER_HEADER_ARGS - * MAC address: 6 bytes, 17 chars - */ - SlrxFilterBinaryArg_t RxFilterDB6BytesRuleArgs[SL_RX_FILTER_NUM_OF_FILTER_HEADER_ARGS][6]; /* Binary Values for comparition */ - /*! - * ! buffer for ASCII arguments, number of argument may be up to SL_RX_FILTER_NUM_OF_FILTER_HEADER_ARGS - * IP address: 4 bytes, 15 chars - * 2 bytes are added for padding - */ - SlrxFilterAsciiArg_t RxFilterDB18BytesAsciiRuleArgs[SL_RX_FILTER_NUM_OF_FILTER_HEADER_ARGS][18]; /* Ascii Values for comparison */ - /*----------------------------- Small size ---------------------------------*/ - /*! buffer for binary arguments, number of argument may be up to SL_RX_FILTER_NUM_OF_FILTER_HEADER_ARGS - * IP address: 4 bytes, 15 chars - * Port: 2 bytes, chars: 5 chars - */ - SlrxFilterBinaryArg_t RxFilterDB4BytesRuleArgs[SL_RX_FILTER_NUM_OF_FILTER_HEADER_ARGS][4]; /* Binary Values for comparison */ - /*! buffer for ASCII arguments, number of argument may be up to SL_RX_FILTER_NUM_OF_FILTER_HEADER_ARGS - * Port: 2 bytes, chars: 5 chars - */ - SlrxFilterAsciiArg_t RxFilterDB5BytesRuleAsciiArgs[SL_RX_FILTER_NUM_OF_FILTER_HEADER_ARGS][5]; /* Ascii Values for comparison */ - /*----------------------------- 1 byte size ---------------------------------*/ - /*! buffer for binary arguments, number of argument may be up to SL_RX_FILTER_NUM_OF_FILTER_HEADER_ARGS - */ - SlrxFilterBinaryArg_t RxFilterDB1BytesRuleArgs[SL_RX_FILTER_NUM_OF_FILTER_HEADER_ARGS][1]; /* Binary Values for comparison */ -}SlrxFilterHeaderArg_t; - - - -/*! \typedef SlrxFilterRuleHeaderArgsAndMask_t - * Structure which defines the Header Args and mask - */ -/* -- 52 bytes */ -typedef struct SlrxFilterRuleHeaderArgsAndMask_t -{ - /*! Argument for the comparison function */ - /* -- 36 byte */ - SlrxFilterHeaderArg_t RuleHeaderArgs; - - /*! the mask is used in order to enable partial comparison, - * Use the 0xFFFFFFFF in case you don't want to use mask - */ - /* -- 16 bytes */ - SlrxFilterCompareMask_t RuleHeaderArgsMask[16]; - -}SlrxFilterRuleHeaderArgsAndMask_t; - -/*! \typedef SlrxFilterHeaderType_t - * Structure which defines the Header rule - * The header rule defines compare function on the protocol header - * For example destMacAddre is between ( 12:6::78:77, 12:6::78:90 ) - * - */ -/* -- 56 byte */ -typedef struct SlrxFilterHeaderType_t -{ - /*! see :: SlrxFilterRuleHeaderArgsAndMask_t */ - /* -- 52 bytes */ - SlrxFilterRuleHeaderArgsAndMask_t RuleHeaderArgsAndMask; - - /*! Packet HDR field which will be compared to the argument */ - /* -- 1 byte */ - SlrxFilterHdrField_t RuleHeaderfield; - - /* -- 1 byte */ - /*! type of the comparison function - * see :: SlrxFilterCompareFunction_t - */ - SlrxFilterCompareFunction_t RuleCompareFunc; - - /*! padding */ - /* -- 2 bytes */ - _u8 RulePadding[2]; - -}SlrxFilterHeaderType_t; - -/*! \typedef SlrxFilterPayloadType_t - * Structure which defines payload rule. - * Not supported on current release. - */ -/* -- 40 byte */ -typedef struct SlrxFilterPayloadType_t -{ - /*! Not supported on current release */ - /* -- 32 byte */ - SlrxFilterRegxPattern_t RegxPattern; - /*! Not supported on current release */ - /* -- 4 byte */ - SlrxFilterOffset_t LowerOffset; - /*! Not supported on current release */ - /* -- 4 byte */ - SlrxFilterOffset_t UpperOffset; -}SlrxFilterPayloadType_t; - -/*! \typedef SlrxFilterCombinationTypeOperator_t - * Enumerate the optional operators for the combination type - * filterID1 is located in the first arg , filterId2 is the second arg,see ::SlrxFilterCombinationType_t.CombinationFilterId - */ -typedef _u8 SlrxFilterCombinationTypeOperator_t; -/* Possible values for SlrxFilterCombinationTypeOperator_t */ -/*! !filterID1 */ -#define COMBINED_FUNC_NOT (0) -/*! filterID1 && filterID2 */ -#define COMBINED_FUNC_AND (1) -/*! filterID1 && filterID2 */ -#define COMBINED_FUNC_OR (2) - -/*! \typedef SlrxFilterCombinationType_t - * Defines the structure which define the combination type filter - * The combined filter enable to make operation on one or two filter, - * for example !filterId1 or and(filterId2,filterId3). - * - */ -/* -- 4 byte */ -typedef struct SlrxFilterCombinationType_t -{ - /* ! combination operator */ - /* -- 1 byte */ - SlrxFilterCombinationTypeOperator_t CombinationTypeOperator; - /* ! filterID, may be one or two depends on the combination operator type */ - /* -- 2 byte */ - SlrxFilterID_t CombinationFilterId[SL_RX_FILTER_NUM_OF_COMBINATION_TYPE_ARGS]; - /* ! Padding */ - /* -- 1 byte */ - _u8 Padding; -}SlrxFilterCombinationType_t; - - -/*! \typedef SlrxFilterRule_t - * Rule structure composed of behavioral flags and the filter rule definitions - * - */ -/* -- 56 byte */ -typedef union SlrxFilterRule_t -{ - /* ! Header type rule , see explanation on the ::SlrxFilterHeaderType_t structure */ - /* -- 56 byte */ - SlrxFilterHeaderType_t HeaderType; - /* ! Payload rule, not supported in current release */ - /* -- 40 byte */ - SlrxFilterPayloadType_t PayLoadHeaderType; /* future for exact pattern or like hood pattern */ - /* ! Combined type rule , see explanation in ::SlrxFilterCombinationType_t structure */ - /* -- 4 byte */ - SlrxFilterCombinationType_t CombinationType; -}SlrxFilterRule_t; - -/*! \typedef SlrxFilterTriggerRoles_t - * Bit field which represents the roleId possible values - * In the current release only Station/AP roles are supported. - */ -#define RX_FILTER_ROLE_AP (1) -#define RX_FILTER_ROLE_STA (2) -#define RX_FILTER_ROLE_PROMISCUOUS (4) -#define RX_FILTER_ROLE_NULL (0) - -typedef union SlrxFilterTriggerRoles_t -{ -/* struct */ -/* { */ -/* _u8 RoleAP :1; */ -/* _u8 RoleStation :1; */ - /* The filter is activated only in Promiscuous mode */ -/* _u8 PromiscuousMode :1; */ -/* _u8 RoleReserved :5; */ -/* }; */ - /* ! Bit fiels of the Filter role */ - _u8 IntRepresentation; - -}SlrxFilterTriggerRoles_t; - -/*! \typedef SlrxFilterTriggerConnectionStates_t - * Bit field representing the possible values of the When section of the rule - * - */ -#define RX_FILTER_CONNECTION_STATE_STA_CONNECTED (1) -#define RX_FILTER_CONNECTION_STATE_STA_NOT_CONNECTED (2) -#define RX_FILTER_CONNECTION_STATE_STA_HAS_IP (4) -#define RX_FILTER_CONNECTION_STATE_STA_HAS_NO_IP (8) - -typedef union SlrxFilterTriggerConnectionStates_t -{ -/* struct */ -/* { */ -/* _u8 RoleStationWiFiConnected :1; */ -/* _u8 RoleStationWiFiDisconneted:1; */ -/* _u8 RoleStationWiFiHasIp:1; */ -/* _u8 RoleStationWiFiHasNoIp:1; */ -/* _u8 RoleStationWiFiSocketOpened:1; */ -/* _u8 RoleStationWiFiSocketclosed:1; */ -/* }; */ -/* */ - /* ! */ - _u8 IntRepresentation; - -}SlrxFilterTriggerConnectionStates_t; - -/*! \typedef SlrxFilterDBTriggerArg_t - * Provides container for entering the filter 'when' argument. - * The current release support 'When rules' which has no arguments. - * For example : - * When connect to specific AP -- the AP bssid is the argument. - * - */ -typedef _u32 SlrxFilterDBTriggerArg_t; - - - -/*! \typedef SlrxFilterCounterId_t - * the counter ID we have 4 counters - */ -typedef _u8 SlrxFilterCounterId_t; -/* Possible values for SlrxFilterCounterId_t */ -#define NO_TRIGGER (0) -#define RX_FILTER_COUNTER1 (1) -#define RX_FILTER_COUNTER2 (2) -#define RX_FILTER_COUNTER3 (3) -#define RX_FILTER_COUNTER4 (4) -#define RX_FILTER_COUNTER5 (5) -#define RX_FILTER_COUNTER6 (6) -#define RX_FILTER_COUNTER7 (7) -#define RX_FILTER_COUNTER8 (8) -#define MAX_RX_FILTER_COUNTER (9) - - - -/*! \typedef SlrxFilterActionArgs_t - * Possible value for filter action args - * - */ - -typedef _u8 SlrxFilterActionArgs_t; -/* Possible values for SlrxFilterActionArgs_t */ -#define ACTION_ARG_REG_1_4 (0) - /* ! Can be use as counter */ -#define ACTION_ARG_TEMPLATE (1) - /* ! Can be use as counter */ -#define ACTION_ARG_EVENT (2) - -/* ! GPIO number */ -#define ACTION_ARG_GPIO (4) -/*! - * \def SL_RX_FILTER_NUM_OF_BYTES_FOR_ACTIONS_ARGS - * - */ -#define SL_RX_FILTER_NUM_OF_BYTES_FOR_ACTIONS_ARGS (5) - - - - -/*! \typedef SlrxFilterTrigger_t - * The filter trigger, determine when the filter is triggered, - * The filter is triggered in the following condition :\n - * 1. The filter parent is triggered\n - * 2. The requested connection type exists, i.e. wlan_connect\n - * 3. The filter role is the same as the system role\n - * - */ -/* -- 12 byte */ -typedef struct SlrxFilterTrigger_t -{ - /*! The parent filter ID, this is the way to build filter tree. */ - /* NULL value means tree root. - */ - /* -- 1 byte */ - SlrxFilterID_t ParentFilterID; - /* ! See ::SlrxFilterCounterId_t explanation */ - /* -- 1 byte */ - SlrxFilterCounterId_t Trigger; - /* ! See :: SlrxFilterTriggerConnectionStates_t */ - /* -- 1 byte */ - SlrxFilterTriggerConnectionStates_t TriggerArgConnectionState; - /* ! See ::SlrxFilterTriggerRoles_t */ - /* -- 1 byte */ - SlrxFilterTriggerRoles_t TriggerArgRoleStatus; - /* ! The Trigger arguments are in the same order as the Trigger bit field order. */ - /* -- 4 byte */ - SlrxFilterDBTriggerArg_t TriggerArg; - /** The compare function which will be operate for each bit that is turned on in the ::SlrxFilterTrigger_t.Trigger field, - * for example , in case the second bit in the Trigger function is on the second function in the list will be executed. - * - */ - /* -- 1 byte */ - SlrxTriggerCompareFunction_t TriggerCompareFunction; - - /* ! padding */ - /* -- 3 byte */ - _u8 Padding[3]; -} SlrxFilterTrigger_t; - -/*! \typedef SlrxFilterActionType_t - * The actions are executed only if the filter is matched,\n - * In case of false match the packet is transfered to the HOST. \n - * The action is composed of bit field structure, - * up to 2 actions can be defined per filter. - * - */ -#define RX_FILTER_ACTION_NULL (0x0) -#define RX_FILTER_ACTION_DROP (0x1) -#define RX_FILTER_ACTION_GPIO (0x2) -#define RX_FILTER_ACTION_ON_REG_INCREASE (0x4) -#define RX_FILTER_ACTION_ON_REG_DECREASE (0x8) -#define RX_FILTER_ACTION_ON_REG_RESET (0x10) -#define RX_FILTER_ACTION_SEND_TEMPLATE (0x20) /* unsupported */ -#define RX_FILTER_ACTION_EVENT_TO_HOST (0x40) /* unsupported */ - -typedef union SlrxFilterActionType_t -{ -/* struct */ -/* { */ - /* ! No action to execute the packet is dropped,drop is always on leaf. */ - /* ! If not dropped ,The packet is passed to the next filter or in case it is the last filter to the host */ -/* _u8 ActionDrop : 1; */ - /* ! Not Supported in the current release */ -/* _u8 ActionGpio : 1; */ - /*! action can increase counter registers. - * 1 = Increase - * 2 = decrease - * 3 = reset - */ -/* _u8 ActionOnREGIncrease : 1; */ -/* _u8 ActionOnREGDecrease : 1; */ -/* _u8 ActionOnREGReset : 1; */ - - /* ! Not Supported in the current release */ -/* _u8 ActionSendTemplate : 1; */ - /* ! Not Supported in the current release */ -/* _u8 ActionEventToHost: 1; */ -/* _u8 padding: 1; */ -/* }; */ - - _u8 IntRepresentation; - -}SlrxFilterActionType_t; - -/*! \typedef SlrxFilterAction_t - * Several actions can be defined,\n - * The action is executed in case the filter rule is matched. - */ -/* -- 8 byte */ -typedef struct SlrxFilterAction_t -{ - /* -- 1 byte */ - /* ! Determine which actions are supported */ - SlrxFilterActionType_t ActionType; - /* ! Buffer for the action arguments */ - /** - * location 0 - The counter to increase - * In case the action is of type "increase" the arg will contain the counter number, - * The counter number values are as in ::SlrxFilterCounterId_t.\n - * location 1 - The template arg.\n - * location 2 - The event arg.\n - * - */ - /* -- 5 byte */ - SlrxFilterActionArg_t ActionArg[SL_RX_FILTER_NUM_OF_BYTES_FOR_ACTIONS_ARGS]; - - /* ! Padding */ - /* - 2 Bytes */ - _u8 Padding[2]; - -} SlrxFilterAction_t; - - -/*! \struct _WlanRxFilterOperationCommandBuff_t - * The structure is used for the interface HOST NWP.\n - * The supported operation : \n - * ::ENABLE_DISABLE_RX_FILTER,\n - * ::REMOVE_RX_FILTER,\n - * - */ -/* 20 bytes */ -typedef struct _WlanRxFilterOperationCommandBuff_t -{ - /* -- 16 bytes */ - SlrxFilterIdMask_t FilterIdMask; - /* 4 bytes */ - _u8 Padding[4]; -}_WlanRxFilterOperationCommandBuff_t; - - - -/* -- 56 bytes */ -typedef struct _WlanRxFilterUpdateArgsCommandBuff_t -{ - /* -- 1 bytes */ - _u8 FilterId; - - /* -- 1 bytes */ - /* ! the args representation */ - _u8 BinaryRepresentation; - - /* -- 52 byte */ - SlrxFilterRuleHeaderArgsAndMask_t FilterRuleHeaderArgsAndMask; - - /* -- 2 bytes */ - _u8 Padding[2]; -}_WlanRxFilterUpdateArgsCommandBuff_t; - - -/*! \typedef _WlanRxFilterRetrieveEnableStatusCommandResponseBuff_t - * The structure is used for the interface HOST NWP.\n - * - */ -/* -- 16 bytes */ -typedef struct _WlanRxFilterRetrieveEnableStatusCommandResponseBuff_t -{ - - /* ! the filter set bit map */ - /* -- 16 bytes */ - SlrxFilterIdMask_t FilterIdMask; - -}_WlanRxFilterRetrieveEnableStatusCommandResponseBuff_t; - - -/*! \struct _WlanRxFilterPrePreparedFiltersCommandBuff_t - * The function enables to perform operations on pre-prepared filters - * - */ -typedef struct _WlanRxFilterPrePreparedFiltersCommandBuff_t -{ - /* ! the filter set bit map */ - /* -- 4 bytes */ - SlrxFilterPrePreparedFiltersMask_t FilterPrePreparedFiltersMask; - -}_WlanRxFilterPrePreparedFiltersCommandBuff_t; - - -/*! \typedef sl_protocol_WlanRxFilterPrePreparedFiltersCommandResponseBuff_t - * - */ -/*-- 4 bytes */ -typedef struct _WlanRxFilterPrePreparedFiltersCommandResponseBuff_t -{ - /* -- 4 bytes */ - /* ! the filter set bit map */ - SlrxFilterPrePreparedFiltersMask_t FilterPrePreparedFiltersMask; - -}_WlanRxFilterPrePreparedFiltersCommandResponseBuff_t; - - - -typedef _u8 SLrxFilterOperation_t; -#define SL_ENABLE_DISABLE_RX_FILTER (0) -#define SL_REMOVE_RX_FILTER (1) -#define SL_STORE_RX_FILTERS (2) -#define SL_UPDATE_RX_FILTER_ARGS (3) -#define SL_FILTER_RETRIEVE_ENABLE_STATE (4) -#define SL_FILTER_PRE_PREPARED_RETRIEVE_CREATE_REMOVE_STATE (5) -#define SL_FILTER_PRE_PREPARED_SET_CREATE_REMOVE_STATE (6) - - -/* Bit manipulation for 8 bit */ -#define ISBITSET8(x,i) ((x[i>>3] & (0x80>>(i&7)))!=0) /* < Is bit set, 8 bit unsigned numbers = x , location = i */ -#define SETBIT8(x,i) x[i>>3]|=(0x80>>(i&7)); /* < Set bit,8 bit unsigned numbers = x , location = i */ -#define CLEARBIT8(x,i) x[i>>3]&=(0x80>>(i&7))^0xFF; /* < Clear bit,8 bit unsigned numbers = x , location = i */ - - -/*********************************************************************************************/ -/* Function prototypes */ -/*********************************************************************************************/ - -/*! - - \addtogroup wlan - @{ - -*/ - - -/*! - \brief Adds new filter rule to the system - - \param[in] RuleType The rule type - \param[in] FilterFlags Flags which set the type of header rule Args and sets the persistent flag - \param[in] pRule Determine the filter rule logic - \param[in] pTrigger Determine when the rule is triggered also sets rule parent. - \param[in] pAction Sets the action to be executed in case the match functions pass - \param[out] pFilterId The filterId which was created - - \return On success, zero is returned. Otherwise error code is returned - */ -#if _SL_INCLUDE_FUNC(sl_WlanRxFilterAdd) -SlrxFilterID_t sl_WlanRxFilterAdd( SlrxFilterRuleType_t RuleType, - SlrxFilterFlags_t FilterFlags, - const SlrxFilterRule_t* const Rule, - const SlrxFilterTrigger_t* const Trigger, - const SlrxFilterAction_t* const Action, - SlrxFilterID_t* pFilterId); - -#endif - - - - - -/*! - \brief Sets parameters to Rx filters - - \param[in] RxFilterOperation - possible operations : - - SL_ENABLE_DISABLE_RX_FILTER - Enables\disables filter in a filter list - - SL_REMOVE_RX_FILTER - Removes filter from memory ( to remove from flash call SL_STORE_RX_FILTERS after this command) - - SL_STORE_RX_FILTERS - Save the filters for persistent - - SL_UPDATE_RX_FILTER_ARGS - Update the arguments of existing filter - - SL_FILTER_PRE_PREPARED_SET_CREATE_REMOVE_STATE - Change the default creation of the pre-prepared filters - - \param[in] pInputBuffer options: - The buffer input is _WlanRxFilterOperationCommandBuff_t: - - SL_ENABLE_DISABLE_RX_FILTER - - SL_REMOVE_RX_FILTER - - SL_STORE_RX_FILTERS - The buffer input is _WlanRxFilterUpdateArgsCommandBuff_t: - - SL_UPDATE_RX_FILTER_ARGS - The buffer input is _WlanRxFilterPrePreparedFiltersCommandBuff_t: - - SL_FILTER_PRE_PREPARED_SET_CREATE_REMOVE_STATE - - \param[in] InputbufferLength The length in byte of the input buffer - - \return On success, zero is returned. Otherwise error code is returned - */ - -#if _SL_INCLUDE_FUNC(sl_WlanRxFilterSet) -_i16 sl_WlanRxFilterSet( const SLrxFilterOperation_t RxFilterOperation, - const _u8* const pInputBuffer, - _u16 InputbufferLength); -#endif - -/*! - \brief Gets parameters of Rx filters - - \param[in] RxFilterOperation - possible operations : - - SL_FILTER_RETRIEVE_ENABLE_STATE - Retrieves the enable disable status - - SL_FILTER_PRE_PREPARED_RETRIEVE_CREATE_REMOVE_STATE - Retrieves the pre-prepared filters creation status - - \param[in] pOutputBuffer - The buffer input is _WlanRxFilterRetrieveEnableStatusCommandResponseBuff_t: - - SL_FILTER_RETRIEVE_ENABLE_STATE - The buffer input is _WlanRxFilterPrePreparedFiltersCommandResponseBuff_t: - - SL_FILTER_PRE_PREPARED_RETRIEVE_CREATE_REMOVE_STATE - - \param[in] OutputbufferLength The length in byte of the output buffer - - \return On success, zero is returned. Otherwise error code is returned -*/ - -#if _SL_INCLUDE_FUNC(sl_WlanRxFilterGet) -_i16 sl_WlanRxFilterGet(const SLrxFilterOperation_t RxFilterOperation, - _u8* pOutputBuffer, - _u16 OutputbufferLength); -#endif - - -/*! - - Close the Doxygen group. - @} - - */ - -#ifdef __cplusplus -} -#endif /* __cplusplus */ - -#endif /* RX_FILTERS_PREPROCESSOR_CLI_IF_H_ */ - - diff --git a/drivers/cc3100/src/device.c b/drivers/cc3100/src/device.c deleted file mode 100644 index 3d4028fb4a..0000000000 --- a/drivers/cc3100/src/device.c +++ /dev/null @@ -1,557 +0,0 @@ -/* -* device.c - CC31xx/CC32xx Host Driver Implementation -* -* Copyright (C) 2014 Texas Instruments Incorporated - http://www.ti.com/ -* -* -* Redistribution and use in source and binary forms, with or without -* modification, are permitted provided that the following conditions -* are met: -* -* Redistributions of source code must retain the above copyright -* notice, this list of conditions and the following disclaimer. -* -* Redistributions in binary form must reproduce the above copyright -* notice, this list of conditions and the following disclaimer in the -* documentation and/or other materials provided with the -* distribution. -* -* Neither the name of Texas Instruments Incorporated nor the names of -* its contributors may be used to endorse or promote products derived -* from this software without specific prior written permission. -* -* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -* -*/ - - - -/*****************************************************************************/ -/* Include files */ -/*****************************************************************************/ -#include "simplelink.h" -#include "protocol.h" -#include "flowcont.h" -#include "driver.h" - - -/*****************************************************************************/ -/* Internal functions */ -/*****************************************************************************/ - -const _i8 StartResponseLUT[8] = -{ - ROLE_UNKNOWN_ERR, - ROLE_STA, - ROLE_STA_ERR, - ROLE_AP, - ROLE_AP_ERR, - ROLE_P2P, - ROLE_P2P_ERR, - ROLE_UNKNOWN_ERR -}; - - - -_i16 _sl_GetStartResponseConvert(_u32 Status) -{ - return (_i16)StartResponseLUT[Status & 0x7]; -} - -/*****************************************************************************/ -/* API Functions */ -/*****************************************************************************/ - - - -/*****************************************************************************/ -/* sl_Task */ -/*****************************************************************************/ -#if _SL_INCLUDE_FUNC(sl_Task) -void sl_Task(void) -{ -#ifdef _SlTaskEntry - _SlTaskEntry(); -#endif -} -#endif - -/*****************************************************************************/ -/* sl_Start */ -/*****************************************************************************/ -#if _SL_INCLUDE_FUNC(sl_Start) -_i16 sl_Start(const void* pIfHdl, _i8* pDevName, const P_INIT_CALLBACK pInitCallBack) -{ - _i16 ObjIdx = MAX_CONCURRENT_ACTIONS; - InitComplete_t AsyncRsp; - - /* Perform any preprocessing before enable networking services */ - sl_DeviceEnablePreamble(); - - /* ControlBlock init */ - _SlDrvDriverCBInit(); - - /* open the interface: usually SPI or UART */ - if (NULL == pIfHdl) - { - g_pCB->FD = sl_IfOpen((void *)pDevName, 0); - } - else - { - g_pCB->FD = (_SlFd_t)pIfHdl; - } - - ObjIdx = _SlDrvProtectAsyncRespSetting((_u8 *)&AsyncRsp, START_STOP_ID, SL_MAX_SOCKETS); - - if (MAX_CONCURRENT_ACTIONS == ObjIdx) - { - return SL_POOL_IS_EMPTY; - } - - if( g_pCB->FD >= (_SlFd_t)0) - { - sl_DeviceDisable(); - - sl_IfRegIntHdlr((SL_P_EVENT_HANDLER)_SlDrvRxIrqHandler, NULL); - - g_pCB->pInitCallback = pInitCallBack; - sl_DeviceEnable(); - - if (NULL == pInitCallBack) - { - _SlDrvSyncObjWaitForever(&g_pCB->ObjPool[ObjIdx].SyncObj); - - /* release Pool Object */ - _SlDrvReleasePoolObj(g_pCB->FunctionParams.AsyncExt.ActionIndex); - return _sl_GetStartResponseConvert(AsyncRsp.Status); - } - else - { - return SL_RET_CODE_OK; - } - } - return SL_BAD_INTERFACE; -} -#endif - -/*************************************************************************** -_sl_HandleAsync_InitComplete - handles init complete signalling to -a waiting object -****************************************************************************/ -void _sl_HandleAsync_InitComplete(void *pVoidBuf) -{ - InitComplete_t *pMsgArgs = (InitComplete_t *)_SL_RESP_ARGS_START(pVoidBuf); - - _SlDrvProtectionObjLockWaitForever(); - - if(g_pCB->pInitCallback) - { - g_pCB->pInitCallback(_sl_GetStartResponseConvert(pMsgArgs->Status)); - } - else - { - sl_Memcpy(g_pCB->ObjPool[g_pCB->FunctionParams.AsyncExt.ActionIndex].pRespArgs, pMsgArgs, sizeof(InitComplete_t)); - _SlDrvSyncObjSignal(&g_pCB->ObjPool[g_pCB->FunctionParams.AsyncExt.ActionIndex].SyncObj); - } - - _SlDrvProtectionObjUnLock(); - - if(g_pCB->pInitCallback) - { - _SlDrvReleasePoolObj(g_pCB->FunctionParams.AsyncExt.ActionIndex); - } - -} - -/*************************************************************************** -_sl_HandleAsync_Stop - handles stop signalling to -a waiting object -****************************************************************************/ -void _sl_HandleAsync_Stop(void *pVoidBuf) -{ - _BasicResponse_t *pMsgArgs = (_BasicResponse_t *)_SL_RESP_ARGS_START(pVoidBuf); - - VERIFY_SOCKET_CB(NULL != g_pCB->StopCB.pAsyncRsp); - - _SlDrvProtectionObjLockWaitForever(); - - sl_Memcpy(g_pCB->ObjPool[g_pCB->FunctionParams.AsyncExt.ActionIndex].pRespArgs, pMsgArgs, sizeof(_BasicResponse_t)); - - _SlDrvSyncObjSignal(&g_pCB->ObjPool[g_pCB->FunctionParams.AsyncExt.ActionIndex].SyncObj); - _SlDrvProtectionObjUnLock(); - - return; -} - - -/***************************************************************************** -sl_stop -******************************************************************************/ -typedef union -{ - _DevStopCommand_t Cmd; - _BasicResponse_t Rsp; -}_SlStopMsg_u; - -const _SlCmdCtrl_t _SlStopCmdCtrl = -{ - SL_OPCODE_DEVICE_STOP_COMMAND, - sizeof(_DevStopCommand_t), - sizeof(_BasicResponse_t) -}; - -#if _SL_INCLUDE_FUNC(sl_Stop) -_i16 sl_Stop(const _u16 timeout) -{ - _i16 RetVal=0; - _SlStopMsg_u Msg; - _BasicResponse_t AsyncRsp; - _i8 ObjIdx = MAX_CONCURRENT_ACTIONS; - /* if timeout is 0 the shutdown is forced immediately */ - if( 0 == timeout ) - { - sl_IfRegIntHdlr(NULL, NULL); - sl_DeviceDisable(); - RetVal = sl_IfClose(g_pCB->FD); - - } - else - { - /* let the device make the shutdown using the defined timeout */ - Msg.Cmd.Timeout = timeout; - - ObjIdx = _SlDrvProtectAsyncRespSetting((_u8 *)&AsyncRsp, START_STOP_ID, SL_MAX_SOCKETS); - if (MAX_CONCURRENT_ACTIONS == ObjIdx) - { - return SL_POOL_IS_EMPTY; - } - - VERIFY_RET_OK(_SlDrvCmdOp((_SlCmdCtrl_t *)&_SlStopCmdCtrl, &Msg, NULL)); - - if(SL_OS_RET_CODE_OK == (_i16)Msg.Rsp.status) - { - _SlDrvSyncObjWaitForever(&g_pCB->ObjPool[ObjIdx].SyncObj); - Msg.Rsp.status = AsyncRsp.status; - RetVal = Msg.Rsp.status; - } - - _SlDrvReleasePoolObj(ObjIdx); - sl_IfRegIntHdlr(NULL, NULL); - sl_DeviceDisable(); - sl_IfClose(g_pCB->FD); - } - _SlDrvDriverCBDeinit(); - - return RetVal; -} -#endif - - -/***************************************************************************** -sl_EventMaskSet -*****************************************************************************/ -typedef union -{ - _DevMaskEventSetCommand_t Cmd; - _BasicResponse_t Rsp; -}_SlEventMaskSetMsg_u; - - - - -#if _SL_INCLUDE_FUNC(sl_EventMaskSet) - -const _SlCmdCtrl_t _SlEventMaskSetCmdCtrl = -{ - SL_OPCODE_DEVICE_EVENTMASKSET, - sizeof(_DevMaskEventSetCommand_t), - sizeof(_BasicResponse_t) -}; - - -_i16 sl_EventMaskSet(const _u8 EventClass ,const _u32 Mask) -{ - _SlEventMaskSetMsg_u Msg; - - Msg.Cmd.group = EventClass; - Msg.Cmd.mask = Mask; - - VERIFY_RET_OK(_SlDrvCmdOp((_SlCmdCtrl_t *)&_SlEventMaskSetCmdCtrl, &Msg, NULL)); - - return (_i16)Msg.Rsp.status; -} -#endif - -/****************************************************************************** -sl_EventMaskGet -******************************************************************************/ -typedef union -{ - _DevMaskEventGetCommand_t Cmd; - _DevMaskEventGetResponse_t Rsp; -}_SlEventMaskGetMsg_u; - - - -#if _SL_INCLUDE_FUNC(sl_EventMaskGet) - -const _SlCmdCtrl_t _SlEventMaskGetCmdCtrl = -{ - SL_OPCODE_DEVICE_EVENTMASKGET, - sizeof(_DevMaskEventGetCommand_t), - sizeof(_DevMaskEventGetResponse_t) -}; - - -_i16 sl_EventMaskGet(const _u8 EventClass,_u32 *pMask) -{ - _SlEventMaskGetMsg_u Msg; - - Msg.Cmd.group = EventClass; - - VERIFY_RET_OK(_SlDrvCmdOp((_SlCmdCtrl_t *)&_SlEventMaskGetCmdCtrl, &Msg, NULL)); - - *pMask = Msg.Rsp.mask; - return SL_RET_CODE_OK; -} -#endif - - - -/****************************************************************************** -sl_DevGet -******************************************************************************/ - -typedef union -{ - _DeviceSetGet_t Cmd; - _DeviceSetGet_t Rsp; -}_SlDeviceMsgGet_u; - - - -#if _SL_INCLUDE_FUNC(sl_DevGet) - -const _SlCmdCtrl_t _SlDeviceGetCmdCtrl = -{ - SL_OPCODE_DEVICE_DEVICEGET, - sizeof(_DeviceSetGet_t), - sizeof(_DeviceSetGet_t) -}; - -_i32 sl_DevGet(const _u8 DeviceGetId,_u8 *pOption,_u8 *pConfigLen, _u8 *pValues) -{ - _SlDeviceMsgGet_u Msg; - _SlCmdExt_t CmdExt; - - if (*pConfigLen == 0) - { - return SL_EZEROLEN; - } - - if( pOption ) - { - - _SlDrvResetCmdExt(&CmdExt); - CmdExt.RxPayloadLen = *pConfigLen; - CmdExt.pRxPayload = (_u8 *)pValues; - - Msg.Cmd.DeviceSetId = DeviceGetId; - - Msg.Cmd.Option = (_u16)*pOption; - - VERIFY_RET_OK(_SlDrvCmdOp((_SlCmdCtrl_t *)&_SlDeviceGetCmdCtrl, &Msg, &CmdExt)); - - if( pOption ) - { - *pOption = (_u8)Msg.Rsp.Option; - } - - if (CmdExt.RxPayloadLen < CmdExt.ActualRxPayloadLen) - { - *pConfigLen = (_u8)CmdExt.RxPayloadLen; - return SL_ESMALLBUF; - } - else - { - *pConfigLen = (_u8)CmdExt.ActualRxPayloadLen; - } - - return (_i16)Msg.Rsp.Status; - } - else - { - return -1; - } -} -#endif - -/****************************************************************************** -sl_DevSet -******************************************************************************/ -typedef union -{ - _DeviceSetGet_t Cmd; - _BasicResponse_t Rsp; -}_SlDeviceMsgSet_u; - - - -#if _SL_INCLUDE_FUNC(sl_DevSet) - -const _SlCmdCtrl_t _SlDeviceSetCmdCtrl = -{ - SL_OPCODE_DEVICE_DEVICESET, - sizeof(_DeviceSetGet_t), - sizeof(_BasicResponse_t) -}; - -_i32 sl_DevSet(const _u8 DeviceSetId ,const _u8 Option,const _u8 ConfigLen,const _u8 *pValues) -{ - _SlDeviceMsgSet_u Msg; - _SlCmdExt_t CmdExt; - - - _SlDrvResetCmdExt(&CmdExt); - - CmdExt.TxPayloadLen = (ConfigLen+3) & (~3); - CmdExt.pTxPayload = (_u8 *)pValues; - - Msg.Cmd.DeviceSetId = DeviceSetId; - Msg.Cmd.ConfigLen = ConfigLen; - Msg.Cmd.Option = Option; - - VERIFY_RET_OK(_SlDrvCmdOp((_SlCmdCtrl_t *)&_SlDeviceSetCmdCtrl, &Msg, &CmdExt)); - - return (_i16)Msg.Rsp.status; -} -#endif - - -/****************************************************************************** -_SlDrvDeviceEventHandler - handles internally device async events -******************************************************************************/ -void _SlDrvDeviceEventHandler(void* pArgs) -{ - _SlResponseHeader_t *pHdr = (_SlResponseHeader_t *)pArgs; - - switch(pHdr->GenHeader.Opcode) - { - case SL_OPCODE_DEVICE_INITCOMPLETE: - _sl_HandleAsync_InitComplete(pHdr); - break; - case SL_OPCODE_DEVICE_STOP_ASYNC_RESPONSE: - _sl_HandleAsync_Stop(pHdr); - break; - - - case SL_OPCODE_DEVICE_ABORT: - { -#if defined (sl_GeneralEvtHdlr) || defined(EXT_LIB_REGISTERED_GENERAL_EVENTS) - SlDeviceEvent_t devHandler; - devHandler.Event = SL_DEVICE_ABORT_ERROR_EVENT; - devHandler.EventData.deviceReport.AbortType = *((_u32*)pArgs + 2); - devHandler.EventData.deviceReport.AbortData = *((_u32*)pArgs + 3); - _SlDrvHandleGeneralEvents(&devHandler); -#endif - } - break; - - case SL_OPCODE_DEVICE_DEVICEASYNCFATALERROR: -#if defined (sl_GeneralEvtHdlr) || defined(EXT_LIB_REGISTERED_GENERAL_EVENTS) - { - _BasicResponse_t *pMsgArgs = (_BasicResponse_t *)_SL_RESP_ARGS_START(pHdr); - SlDeviceEvent_t devHandler; - devHandler.Event = SL_DEVICE_FATAL_ERROR_EVENT; - devHandler.EventData.deviceEvent.status = pMsgArgs->status & 0xFF; - devHandler.EventData.deviceEvent.sender = (SlErrorSender_e)((pMsgArgs->status >> 8) & 0xFF); - _SlDrvHandleGeneralEvents(&devHandler); - } -#endif - break; - default: - SL_ERROR_TRACE2(MSG_306, "ASSERT: _SlDrvDeviceEventHandler : invalid opcode = 0x%x = %1", pHdr->GenHeader.Opcode, pHdr->GenHeader.Opcode); - } -} - - -/****************************************************************************** -sl_UartSetMode -******************************************************************************/ -#ifdef SL_IF_TYPE_UART -typedef union -{ - _DevUartSetModeCommand_t Cmd; - _DevUartSetModeResponse_t Rsp; -}_SlUartSetModeMsg_u; - - -#if _SL_INCLUDE_FUNC(sl_UartSetMode) - - -const _SlCmdCtrl_t _SlUartSetModeCmdCtrl = -{ - SL_OPCODE_DEVICE_SETUARTMODECOMMAND, - sizeof(_DevUartSetModeCommand_t), - sizeof(_DevUartSetModeResponse_t) -}; - -_i16 sl_UartSetMode(const SlUartIfParams_t* pUartParams) -{ - _SlUartSetModeMsg_u Msg; - _u32 magicCode = 0xFFFFFFFF; - - Msg.Cmd.BaudRate = pUartParams->BaudRate; - Msg.Cmd.FlowControlEnable = pUartParams->FlowControlEnable; - - - VERIFY_RET_OK(_SlDrvCmdOp((_SlCmdCtrl_t *)&_SlUartSetModeCmdCtrl, &Msg, NULL)); - - /* cmd response OK, we can continue with the handshake */ - if (SL_RET_CODE_OK == Msg.Rsp.status) - { - sl_IfMaskIntHdlr(); - - /* Close the comm port */ - sl_IfClose(g_pCB->FD); - - /* Re-open the comm port */ - sl_IfOpen((void * )pUartParams, UART_IF_OPEN_FLAG_RE_OPEN); - - sl_IfUnMaskIntHdlr(); - - /* send the magic code and wait for the response */ - sl_IfWrite(g_pCB->FD, (_u8* )&magicCode, 4); - - magicCode = UART_SET_MODE_MAGIC_CODE; - sl_IfWrite(g_pCB->FD, (_u8* )&magicCode, 4); - - /* clear magic code */ - magicCode = 0; - - /* wait (blocking) till the magic code to be returned from device */ - sl_IfRead(g_pCB->FD, (_u8* )&magicCode, 4); - - /* check for the received magic code matching */ - if (UART_SET_MODE_MAGIC_CODE != magicCode) - { - _SL_ASSERT(0); - } - } - - return (_i16)Msg.Rsp.status; -} -#endif -#endif - - diff --git a/drivers/cc3100/src/driver.c b/drivers/cc3100/src/driver.c deleted file mode 100644 index 817ff0edc6..0000000000 --- a/drivers/cc3100/src/driver.c +++ /dev/null @@ -1,1843 +0,0 @@ -/* -* driver.c - CC31xx/CC32xx Host Driver Implementation -* -* Copyright (C) 2014 Texas Instruments Incorporated - http://www.ti.com/ -* -* -* Redistribution and use in source and binary forms, with or without -* modification, are permitted provided that the following conditions -* are met: -* -* Redistributions of source code must retain the above copyright -* notice, this list of conditions and the following disclaimer. -* -* Redistributions in binary form must reproduce the above copyright -* notice, this list of conditions and the following disclaimer in the -* documentation and/or other materials provided with the -* distribution. -* -* Neither the name of Texas Instruments Incorporated nor the names of -* its contributors may be used to endorse or promote products derived -* from this software without specific prior written permission. -* -* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -* -*/ - -/*****************************************************************************/ -/* Include files */ -/*****************************************************************************/ -#include "simplelink.h" -#include "protocol.h" -#include "driver.h" -#include "flowcont.h" - -/*****************************************************************************/ -/* Macro declarations */ -/*****************************************************************************/ - -#define _SL_PENDING_RX_MSG(pDriverCB) (RxIrqCnt != (pDriverCB)->RxDoneCnt) - -/* 2 LSB of the N2H_SYNC_PATTERN are for sequence number -only in SPI interface -support backward sync pattern */ -#define N2H_SYNC_PATTERN_SEQ_NUM_BITS ((_u32)0x00000003) /* Bits 0..1 - use the 2 LBS for seq num */ -#define N2H_SYNC_PATTERN_SEQ_NUM_EXISTS ((_u32)0x00000004) /* Bit 2 - sign that sequence number exists in the sync pattern */ -#define N2H_SYNC_PATTERN_MASK ((_u32)0xFFFFFFF8) /* Bits 3..31 - constant SYNC PATTERN */ -#define N2H_SYNC_SPI_BUGS_MASK ((_u32)0x7FFF7F7F) /* Bits 7,15,31 - ignore the SPI (8,16,32 bites bus) error bits */ -#define BUF_SYNC_SPIM(pBuf) ((*(_u32 *)(pBuf)) & N2H_SYNC_SPI_BUGS_MASK) - -_u8 _SlDrvProtectAsyncRespSetting(_u8 *pAsyncRsp, _u8 ActionID, _u8 SocketID); -#define N2H_SYNC_SPIM (N2H_SYNC_PATTERN & N2H_SYNC_SPI_BUGS_MASK) -#define N2H_SYNC_SPIM_WITH_SEQ(TxSeqNum) ((N2H_SYNC_SPIM & N2H_SYNC_PATTERN_MASK) | N2H_SYNC_PATTERN_SEQ_NUM_EXISTS | ((TxSeqNum) & (N2H_SYNC_PATTERN_SEQ_NUM_BITS))) -#define MATCH_WOUT_SEQ_NUM(pBuf) ( BUF_SYNC_SPIM(pBuf) == N2H_SYNC_SPIM ) -#define MATCH_WITH_SEQ_NUM(pBuf, TxSeqNum) ( BUF_SYNC_SPIM(pBuf) == (N2H_SYNC_SPIM_WITH_SEQ(TxSeqNum)) ) -#define N2H_SYNC_PATTERN_MATCH(pBuf, TxSeqNum) \ - ( \ - ( (*((_u32 *)pBuf) & N2H_SYNC_PATTERN_SEQ_NUM_EXISTS) && ( MATCH_WITH_SEQ_NUM(pBuf, TxSeqNum) ) ) || \ - ( !(*((_u32 *)pBuf) & N2H_SYNC_PATTERN_SEQ_NUM_EXISTS) && ( MATCH_WOUT_SEQ_NUM(pBuf ) ) ) \ - ) - -#define OPCODE(_ptr) (((_SlResponseHeader_t *)(_ptr))->GenHeader.Opcode) -#define RSP_PAYLOAD_LEN(_ptr) (((_SlResponseHeader_t *)(_ptr))->GenHeader.Len - _SL_RESP_SPEC_HDR_SIZE) -#define SD(_ptr) (((_SocketAddrResponse_u *)(_ptr))->IpV4.sd) -/* Actual size of Recv/Recvfrom response data */ -#define ACT_DATA_SIZE(_ptr) (((_SocketAddrResponse_u *)(_ptr))->IpV4.statusOrLen) - - - - -/* General Events handling*/ -#if defined (EXT_LIB_REGISTERED_GENERAL_EVENTS) - -typedef _SlEventPropogationStatus_e (*general_callback) (SlDeviceEvent_t *); - -static const general_callback general_callbacks[] = -{ -#ifdef SlExtLib1GeneralEventHandler - SlExtLib1GeneralEventHandler, -#endif - -#ifdef SlExtLib2GeneralEventHandler - SlExtLib2GeneralEventHandler, -#endif - -#ifdef SlExtLib3GeneralEventHandler - SlExtLib3GeneralEventHandler, -#endif - -#ifdef SlExtLib4GeneralEventHandler - SlExtLib4GeneralEventHandler, -#endif - -#ifdef SlExtLib5GeneralEventHandler - SlExtLib5GeneralEventHandler, -#endif -}; - -#undef _SlDrvHandleGeneralEvents - -/******************************************************************** - _SlDrvHandleGeneralEvents - Iterates through all the general(device) event handlers which are - registered by the external libs/user application. -*********************************************************************/ -void _SlDrvHandleGeneralEvents(SlDeviceEvent_t *slGeneralEvent) -{ - _u8 i; - - /* Iterate over all the extenal libs handlers */ - for ( i = 0 ; i < sizeof(general_callbacks)/sizeof(general_callbacks[0]) ; i++ ) - { - if (EVENT_PROPAGATION_BLOCK == general_callbacks[i](slGeneralEvent) ) - { - /* exit immediately and do not call the user specific handler as well */ - return; - } - } - -/* At last call the Application specific handler if registered */ -#ifdef sl_GeneralEvtHdlr - sl_GeneralEvtHdlr(slGeneralEvent); -#endif - -} -#endif - - - -/* WLAN Events handling*/ - -#if defined (EXT_LIB_REGISTERED_WLAN_EVENTS) - -typedef _SlEventPropogationStatus_e (*wlan_callback) (SlWlanEvent_t *); - -static wlan_callback wlan_callbacks[] = -{ -#ifdef SlExtLib1WlanEventHandler - SlExtLib1WlanEventHandler, -#endif - -#ifdef SlExtLib2WlanEventHandler - SlExtLib2WlanEventHandler, -#endif - -#ifdef SlExtLib3WlanEventHandler - SlExtLib3WlanEventHandler, -#endif - -#ifdef SlExtLib4WlanEventHandler - SlExtLib4WlanEventHandler, -#endif - -#ifdef SlExtLib5WlanEventHandler - SlExtLib5WlanEventHandler, -#endif -}; - -#undef _SlDrvHandleWlanEvents - -/*********************************************************** - _SlDrvHandleWlanEvents - Iterates through all the wlan event handlers which are - registered by the external libs/user application. -************************************************************/ -void _SlDrvHandleWlanEvents(SlWlanEvent_t *slWlanEvent) -{ - _u8 i; - - /* Iterate over all the extenal libs handlers */ - for ( i = 0 ; i < sizeof(wlan_callbacks)/sizeof(wlan_callbacks[0]) ; i++ ) - { - if ( EVENT_PROPAGATION_BLOCK == wlan_callbacks[i](slWlanEvent) ) - { - /* exit immediately and do not call the user specific handler as well */ - return; - } - } - -/* At last call the Application specific handler if registered */ -#ifdef sl_WlanEvtHdlr - sl_WlanEvtHdlr(slWlanEvent); -#endif - -} -#endif - - -/* NetApp Events handling */ -#if defined (EXT_LIB_REGISTERED_NETAPP_EVENTS) - -typedef _SlEventPropogationStatus_e (*netApp_callback) (SlNetAppEvent_t *); - -static const netApp_callback netApp_callbacks[] = -{ -#ifdef SlExtLib1NetAppEventHandler - SlExtLib1NetAppEventHandler, -#endif - -#ifdef SlExtLib2NetAppEventHandler - SlExtLib2NetAppEventHandler, -#endif - -#ifdef SlExtLib3NetAppEventHandler - SlExtLib3NetAppEventHandler, -#endif - -#ifdef SlExtLib4NetAppEventHandler - SlExtLib4NetAppEventHandler, -#endif - -#ifdef SlExtLib5NetAppEventHandler - SlExtLib5NetAppEventHandler, -#endif -}; - -#undef _SlDrvHandleNetAppEvents - -/************************************************************ - _SlDrvHandleNetAppEvents - Iterates through all the net app event handlers which are - registered by the external libs/user application. -************************************************************/ -void _SlDrvHandleNetAppEvents(SlNetAppEvent_t *slNetAppEvent) -{ - _u8 i; - - /* Iterate over all the extenal libs handlers */ - for ( i = 0 ; i < sizeof(netApp_callbacks)/sizeof(netApp_callbacks[0]) ; i++ ) - { - if (EVENT_PROPAGATION_BLOCK == netApp_callbacks[i](slNetAppEvent) ) - { - /* exit immediately and do not call the user specific handler as well */ - return; - } - } - -/* At last call the Application specific handler if registered */ -#ifdef sl_NetAppEvtHdlr - sl_NetAppEvtHdlr(slNetAppEvent); -#endif - -} -#endif - - -/* Http Server Events handling */ -#if defined (EXT_LIB_REGISTERED_HTTP_SERVER_EVENTS) - -typedef _SlEventPropogationStatus_e (*httpServer_callback) (SlHttpServerEvent_t*, SlHttpServerResponse_t*); - -static const httpServer_callback httpServer_callbacks[] = -{ -#ifdef SlExtLib1HttpServerEventHandler - SlExtLib1HttpServerEventHandler, -#endif - -#ifdef SlExtLib2HttpServerEventHandler - SlExtLib2HttpServerEventHandler, -#endif - -#ifdef SlExtLib3HttpServerEventHandler - SlExtLib3HttpServerEventHandler, -#endif - -#ifdef SlExtLib4HttpServerEventHandler - SlExtLib4HttpServerEventHandler, -#endif - -#ifdef SlExtLib5HttpServerEventHandler - SlExtLib5HttpServerEventHandler, -#endif -}; - -#undef _SlDrvHandleHttpServerEvents - -/******************************************************************* - _SlDrvHandleHttpServerEvents - Iterates through all the http server event handlers which are - registered by the external libs/user application. -********************************************************************/ -void _SlDrvHandleHttpServerEvents(SlHttpServerEvent_t *slHttpServerEvent, SlHttpServerResponse_t *slHttpServerResponse) -{ - _u8 i; - - /* Iterate over all the external libs handlers */ - for ( i = 0 ; i < sizeof(httpServer_callbacks)/sizeof(httpServer_callbacks[0]) ; i++ ) - { - if ( EVENT_PROPAGATION_BLOCK == httpServer_callbacks[i](slHttpServerEvent, slHttpServerResponse) ) - { - /* exit immediately and do not call the user specific handler as well */ - return; - } - } - -/* At last call the Application specific handler if registered */ -#ifdef sl_HttpServerCallback - sl_HttpServerCallback(slHttpServerEvent, slHttpServerResponse); -#endif - -} -#endif - - -/* Socket Events */ -#if defined (EXT_LIB_REGISTERED_SOCK_EVENTS) - -typedef _SlEventPropogationStatus_e (*sock_callback) (SlSockEvent_t *); - -static const sock_callback sock_callbacks[] = -{ -#ifdef SlExtLib1SockEventHandler - SlExtLib1SockEventHandler, -#endif - -#ifdef SlExtLib2SockEventHandler - SlExtLib2SockEventHandler, -#endif - -#ifdef SlExtLib3SockEventHandler - SlExtLib3SockEventHandler, -#endif - -#ifdef SlExtLib4SockEventHandler - SlExtLib4SockEventHandler, -#endif - -#ifdef SlExtLib5SockEventHandler - SlExtLib5SockEventHandler, -#endif -}; - -/************************************************************* - _SlDrvHandleSockEvents - Iterates through all the socket event handlers which are - registered by the external libs/user application. -**************************************************************/ -void _SlDrvHandleSockEvents(SlSockEvent_t *slSockEvent) -{ - _u8 i; - - /* Iterate over all the external libs handlers */ - for ( i = 0 ; i < sizeof(sock_callbacks)/sizeof(sock_callbacks[0]) ; i++ ) - { - if ( EVENT_PROPAGATION_BLOCK == sock_callbacks[i](slSockEvent) ) - { - /* exit immediately and do not call the user specific handler as well */ - return; - } - } - -/* At last call the Application specific handler if registered */ -#ifdef sl_SockEvtHdlr - sl_SockEvtHdlr(slSockEvent); -#endif - -} - -#endif - - -#if (SL_MEMORY_MGMT != SL_MEMORY_MGMT_DYNAMIC) -typedef struct -{ - _u32 Align; - _SlDriverCb_t DriverCB; - _u8 AsyncRespBuf[SL_ASYNC_MAX_MSG_LEN]; -}_SlStatMem_t; - -_SlStatMem_t g_StatMem; -#endif - -_u8 _SlDrvProtectAsyncRespSetting(_u8 *pAsyncRsp, _u8 ActionID, _u8 SocketID) -{ - _u8 ObjIdx; - - - /* Use Obj to issue the command, if not available try later */ - ObjIdx = _SlDrvWaitForPoolObj(ActionID, SocketID); - - if (MAX_CONCURRENT_ACTIONS != ObjIdx) - { - _SlDrvProtectionObjLockWaitForever(); - g_pCB->ObjPool[ObjIdx].pRespArgs = pAsyncRsp; - _SlDrvProtectionObjUnLock(); - } - - return ObjIdx; -} - - -/*****************************************************************************/ -/* Variables */ -/*****************************************************************************/ -const _SlSyncPattern_t g_H2NSyncPattern = H2N_SYNC_PATTERN; -const _SlSyncPattern_t g_H2NCnysPattern = H2N_CNYS_PATTERN; -_volatile _u8 RxIrqCnt; - -#ifndef SL_TINY_EXT -const _SlActionLookup_t _SlActionLookupTable[] = -{ - {ACCEPT_ID, SL_OPCODE_SOCKET_ACCEPTASYNCRESPONSE, (_SlSpawnEntryFunc_t)_sl_HandleAsync_Accept}, - {CONNECT_ID, SL_OPCODE_SOCKET_CONNECTASYNCRESPONSE,(_SlSpawnEntryFunc_t)_sl_HandleAsync_Connect}, - {SELECT_ID, SL_OPCODE_SOCKET_SELECTASYNCRESPONSE,(_SlSpawnEntryFunc_t)_sl_HandleAsync_Select}, - {GETHOSYBYNAME_ID, SL_OPCODE_NETAPP_DNSGETHOSTBYNAMEASYNCRESPONSE,(_SlSpawnEntryFunc_t)_sl_HandleAsync_DnsGetHostByName}, - {GETHOSYBYSERVICE_ID, SL_OPCODE_NETAPP_MDNSGETHOSTBYSERVICEASYNCRESPONSE,(_SlSpawnEntryFunc_t)_sl_HandleAsync_DnsGetHostByService}, - {PING_ID, SL_OPCODE_NETAPP_PINGREPORTREQUESTRESPONSE, (_SlSpawnEntryFunc_t)_sl_HandleAsync_PingResponse}, - {START_STOP_ID, SL_OPCODE_DEVICE_STOP_ASYNC_RESPONSE,(_SlSpawnEntryFunc_t)_sl_HandleAsync_Stop} -}; -#else -const _SlActionLookup_t _SlActionLookupTable[] = -{ - {CONNECT_ID, SL_OPCODE_SOCKET_CONNECTASYNCRESPONSE,(_SlSpawnEntryFunc_t)_sl_HandleAsync_Connect}, - {GETHOSYBYNAME_ID, SL_OPCODE_NETAPP_DNSGETHOSTBYNAMEASYNCRESPONSE,(_SlSpawnEntryFunc_t)_sl_HandleAsync_DnsGetHostByName}, - {START_STOP_ID, SL_OPCODE_DEVICE_STOP_ASYNC_RESPONSE,(_SlSpawnEntryFunc_t)_sl_HandleAsync_Stop} -}; -#endif - - - -typedef struct -{ - _u16 opcode; - _u8 event; -} OpcodeKeyVal_t; - -/* The table translates opcode to user's event type */ -const OpcodeKeyVal_t OpcodeTranslateTable[] = -{ -{SL_OPCODE_WLAN_SMART_CONFIG_START_ASYNC_RESPONSE, SL_WLAN_SMART_CONFIG_COMPLETE_EVENT}, -{SL_OPCODE_WLAN_SMART_CONFIG_STOP_ASYNC_RESPONSE,SL_WLAN_SMART_CONFIG_STOP_EVENT}, -{SL_OPCODE_WLAN_STA_CONNECTED, SL_WLAN_STA_CONNECTED_EVENT}, -{SL_OPCODE_WLAN_STA_DISCONNECTED,SL_WLAN_STA_DISCONNECTED_EVENT}, -{SL_OPCODE_WLAN_P2P_DEV_FOUND,SL_WLAN_P2P_DEV_FOUND_EVENT}, -{SL_OPCODE_WLAN_P2P_NEG_REQ_RECEIVED, SL_WLAN_P2P_NEG_REQ_RECEIVED_EVENT}, -{SL_OPCODE_WLAN_CONNECTION_FAILED, SL_WLAN_CONNECTION_FAILED_EVENT}, -{SL_OPCODE_WLAN_WLANASYNCCONNECTEDRESPONSE, SL_WLAN_CONNECT_EVENT}, -{SL_OPCODE_WLAN_WLANASYNCDISCONNECTEDRESPONSE, SL_WLAN_DISCONNECT_EVENT}, -{SL_OPCODE_NETAPP_IPACQUIRED, SL_NETAPP_IPV4_IPACQUIRED_EVENT}, -{SL_OPCODE_NETAPP_IPACQUIRED_V6, SL_NETAPP_IPV6_IPACQUIRED_EVENT}, -{SL_OPCODE_NETAPP_IP_LEASED, SL_NETAPP_IP_LEASED_EVENT}, -{SL_OPCODE_NETAPP_IP_RELEASED, SL_NETAPP_IP_RELEASED_EVENT}, -{SL_OPCODE_SOCKET_TXFAILEDASYNCRESPONSE, SL_SOCKET_TX_FAILED_EVENT}, -{SL_OPCODE_SOCKET_SOCKETASYNCEVENT, SL_SOCKET_ASYNC_EVENT} -}; - - - -_SlDriverCb_t* g_pCB = NULL; -P_SL_DEV_PING_CALLBACK pPingCallBackFunc = NULL; -_u8 gFirstCmdMode = 0; - -/*****************************************************************************/ -/* Function prototypes */ -/*****************************************************************************/ -_SlReturnVal_t _SlDrvMsgRead(void); -_SlReturnVal_t _SlDrvMsgWrite(_SlCmdCtrl_t *pCmdCtrl,_SlCmdExt_t *pCmdExt, _u8 *pTxRxDescBuff); -_SlReturnVal_t _SlDrvMsgReadCmdCtx(void); -_SlReturnVal_t _SlDrvMsgReadSpawnCtx(void *pValue); -void _SlDrvClassifyRxMsg(_SlOpcode_t Opcode ); -_SlReturnVal_t _SlDrvRxHdrRead(_u8 *pBuf, _u8 *pAlignSize); -void _SlDrvShiftDWord(_u8 *pBuf); -void _SlDrvDriverCBInit(void); -void _SlAsyncEventGenericHandler(void); -_u8 _SlDrvWaitForPoolObj(_u8 ActionID, _u8 SocketID); -void _SlDrvReleasePoolObj(_u8 pObj); -void _SlRemoveFromList(_u8* ListIndex, _u8 ItemIndex); -_SlReturnVal_t _SlFindAndSetActiveObj(_SlOpcode_t Opcode, _u8 Sd); - - -/*****************************************************************************/ -/* Internal functions */ -/*****************************************************************************/ - - -/***************************************************************************** -_SlDrvDriverCBInit - init Driver Control Block -*****************************************************************************/ - -void _SlDrvDriverCBInit(void) -{ - _u8 Idx =0; - -#if (SL_MEMORY_MGMT == SL_MEMORY_MGMT_DYNAMIC) - g_pCB = sl_Malloc(sizeof(_SlDriverCb_t)); -#else - g_pCB = &(g_StatMem.DriverCB); -#endif - MALLOC_OK_CHECK(g_pCB); - - - _SlDrvMemZero(g_pCB, sizeof(_SlDriverCb_t)); - RxIrqCnt = 0; - OSI_RET_OK_CHECK( sl_SyncObjCreate(&g_pCB->CmdSyncObj, "CmdSyncObj") ); - sl_SyncObjClear(&g_pCB->CmdSyncObj); - - OSI_RET_OK_CHECK( sl_LockObjCreate(&g_pCB->GlobalLockObj, "GlobalLockObj") ); - OSI_RET_OK_CHECK( sl_LockObjCreate(&g_pCB->ProtectionLockObj, "ProtectionLockObj") ); - - /* Init Drv object */ - _SlDrvMemZero(&g_pCB->ObjPool[0], MAX_CONCURRENT_ACTIONS*sizeof(_SlPoolObj_t)); - - /* place all Obj in the free list*/ - g_pCB->FreePoolIdx = 0; - - for (Idx = 0 ; Idx < MAX_CONCURRENT_ACTIONS ; Idx++) - { - g_pCB->ObjPool[Idx].NextIndex = Idx + 1; - g_pCB->ObjPool[Idx].AdditionalData = SL_MAX_SOCKETS; - - OSI_RET_OK_CHECK( sl_SyncObjCreate(&g_pCB->ObjPool[Idx].SyncObj, "SyncObj")); - sl_SyncObjClear(&g_pCB->ObjPool[Idx].SyncObj); - } - - g_pCB->ActivePoolIdx = MAX_CONCURRENT_ACTIONS; - g_pCB->PendingPoolIdx = MAX_CONCURRENT_ACTIONS; - - /* Flow control init */ - g_pCB->FlowContCB.TxPoolCnt = FLOW_CONT_MIN; - OSI_RET_OK_CHECK(sl_LockObjCreate(&g_pCB->FlowContCB.TxLockObj, "TxLockObj")); - OSI_RET_OK_CHECK(sl_SyncObjCreate(&g_pCB->FlowContCB.TxSyncObj, "TxSyncObj")); - - gFirstCmdMode = 0; - -} - -/***************************************************************************** -_SlDrvDriverCBDeinit - De init Driver Control Block -*****************************************************************************/ -void _SlDrvDriverCBDeinit() -{ - _u8 Idx =0; - - /* Flow control de-init */ - g_pCB->FlowContCB.TxPoolCnt = 0; - OSI_RET_OK_CHECK(sl_LockObjDelete(&g_pCB->FlowContCB.TxLockObj)); - OSI_RET_OK_CHECK(sl_SyncObjDelete(&g_pCB->FlowContCB.TxSyncObj)); - - OSI_RET_OK_CHECK( sl_SyncObjDelete(&g_pCB->CmdSyncObj) ); - OSI_RET_OK_CHECK( sl_LockObjDelete(&g_pCB->GlobalLockObj) ); - OSI_RET_OK_CHECK( sl_LockObjDelete(&g_pCB->ProtectionLockObj) ); - - #ifndef SL_TINY_EXT - for (Idx = 0; Idx < MAX_CONCURRENT_ACTIONS; Idx++) - #endif - { - OSI_RET_OK_CHECK( sl_SyncObjDelete(&g_pCB->ObjPool[Idx].SyncObj) ); - } - - g_pCB->FreePoolIdx = 0; - g_pCB->PendingPoolIdx = MAX_CONCURRENT_ACTIONS; - g_pCB->ActivePoolIdx = MAX_CONCURRENT_ACTIONS; - -#if (SL_MEMORY_MGMT == SL_MEMORY_MGMT_DYNAMIC) - sl_Free(g_pCB); -#else - g_pCB = NULL; -#endif - - - g_pCB = NULL; -} - -/***************************************************************************** -_SlDrvRxIrqHandler - Interrupt handler -*****************************************************************************/ -void _SlDrvRxIrqHandler(void *pValue) -{ - sl_IfMaskIntHdlr(); - - RxIrqCnt++; - - if (TRUE == g_pCB->IsCmdRespWaited) - { - OSI_RET_OK_CHECK( sl_SyncObjSignalFromIRQ(&g_pCB->CmdSyncObj) ); - } - else - { - sl_Spawn((_SlSpawnEntryFunc_t)_SlDrvMsgReadSpawnCtx, NULL, 0); - } -} - -/***************************************************************************** -_SlDrvCmdOp -*****************************************************************************/ -_SlReturnVal_t _SlDrvCmdOp( - _SlCmdCtrl_t *pCmdCtrl , - void *pTxRxDescBuff , - _SlCmdExt_t *pCmdExt) -{ - _SlReturnVal_t RetVal; - - - _SlDrvObjLockWaitForever(&g_pCB->GlobalLockObj); - - g_pCB->IsCmdRespWaited = TRUE; - - SL_TRACE0(DBG_MSG, MSG_312, "_SlDrvCmdOp: call _SlDrvMsgWrite"); - - - /* send the message */ - RetVal = _SlDrvMsgWrite(pCmdCtrl, pCmdExt, pTxRxDescBuff); - - if(SL_OS_RET_CODE_OK == RetVal) - { - -#ifndef SL_IF_TYPE_UART - /* Waiting for SPI to stabilize after first command */ - if( 0 == gFirstCmdMode ) - { - volatile _u32 CountVal = 0; - gFirstCmdMode = 1; - CountVal = CPU_FREQ_IN_MHZ*USEC_DELAY; - while( CountVal-- ); - } -#endif - /* wait for respond */ - RetVal = _SlDrvMsgReadCmdCtx(); /* will free global lock */ - SL_TRACE0(DBG_MSG, MSG_314, "_SlDrvCmdOp: exited _SlDrvMsgReadCmdCtx"); - } - else - { - _SlDrvObjUnLock(&g_pCB->GlobalLockObj); - } - - return RetVal; -} - - - -/***************************************************************************** -_SlDrvDataReadOp -*****************************************************************************/ -_SlReturnVal_t _SlDrvDataReadOp( - _SlSd_t Sd, - _SlCmdCtrl_t *pCmdCtrl , - void *pTxRxDescBuff , - _SlCmdExt_t *pCmdExt) -{ - _SlReturnVal_t RetVal; - _u8 ObjIdx = MAX_CONCURRENT_ACTIONS; - _SlArgsData_t pArgsData; - - /* Validate input arguments */ - VERIFY_PROTOCOL(NULL != pCmdExt->pRxPayload); - - /* If zero bytes is requested, return error. */ - /* This allows us not to fill remote socket's IP address in return arguments */ - VERIFY_PROTOCOL(0 != pCmdExt->RxPayloadLen); - - /* Validate socket */ - if((Sd & BSD_SOCKET_ID_MASK) >= SL_MAX_SOCKETS) - { - return SL_EBADF; - } - - /*Use Obj to issue the command, if not available try later*/ - ObjIdx = (_u8)_SlDrvWaitForPoolObj(RECV_ID, Sd & BSD_SOCKET_ID_MASK); - - if (MAX_CONCURRENT_ACTIONS == ObjIdx) - { - return SL_POOL_IS_EMPTY; - } - - _SlDrvProtectionObjLockWaitForever(); - - pArgsData.pData = pCmdExt->pRxPayload; - pArgsData.pArgs = (_u8 *)pTxRxDescBuff; - g_pCB->ObjPool[ObjIdx].pRespArgs = (_u8 *)&pArgsData; - - _SlDrvProtectionObjUnLock(); - - - /* Do Flow Control check/update for DataWrite operation */ - _SlDrvObjLockWaitForever(&g_pCB->FlowContCB.TxLockObj); - - - /* Clear SyncObj for the case it was signalled before TxPoolCnt */ - /* dropped below '1' (last Data buffer was taken) */ - /* OSI_RET_OK_CHECK( sl_SyncObjClear(&g_pCB->FlowContCB.TxSyncObj) ); */ - sl_SyncObjClear(&g_pCB->FlowContCB.TxSyncObj); - - if(g_pCB->FlowContCB.TxPoolCnt <= FLOW_CONT_MIN) - { - - /* If TxPoolCnt was increased by other thread at this moment, - TxSyncObj won't wait here */ - _SlDrvSyncObjWaitForever(&g_pCB->FlowContCB.TxSyncObj); - - } - - _SlDrvObjLockWaitForever(&g_pCB->GlobalLockObj); - - - VERIFY_PROTOCOL(g_pCB->FlowContCB.TxPoolCnt > FLOW_CONT_MIN); - g_pCB->FlowContCB.TxPoolCnt--; - - _SlDrvObjUnLock(&g_pCB->FlowContCB.TxLockObj); - - /* send the message */ - RetVal = _SlDrvMsgWrite(pCmdCtrl, pCmdExt, (_u8 *)pTxRxDescBuff); - - _SlDrvObjUnLock(&g_pCB->GlobalLockObj); - - - if(SL_OS_RET_CODE_OK == RetVal) - { - /* Wait for response message. Will be signaled by _SlDrvMsgRead. */ - _SlDrvSyncObjWaitForever(&g_pCB->ObjPool[ObjIdx].SyncObj); - } - - _SlDrvReleasePoolObj(ObjIdx); - return RetVal; -} - -/* ******************************************************************************/ -/* _SlDrvDataWriteOp */ -/* ******************************************************************************/ -_SlReturnVal_t _SlDrvDataWriteOp( - _SlSd_t Sd, - _SlCmdCtrl_t *pCmdCtrl , - void *pTxRxDescBuff , - _SlCmdExt_t *pCmdExt) -{ - _SlReturnVal_t RetVal = SL_EAGAIN; /* initiated as SL_EAGAIN for the non blocking mode */ - while( 1 ) - { - /* Do Flow Control check/update for DataWrite operation */ - _SlDrvObjLockWaitForever(&g_pCB->FlowContCB.TxLockObj); - - /* Clear SyncObj for the case it was signalled before TxPoolCnt */ - /* dropped below '1' (last Data buffer was taken) */ - /* OSI_RET_OK_CHECK( sl_SyncObjClear(&g_pCB->FlowContCB.TxSyncObj) ); */ - sl_SyncObjClear(&g_pCB->FlowContCB.TxSyncObj); - - /* we have indication that the last send has failed - socket is no longer valid for operations */ - if(g_pCB->SocketTXFailure & (1<<(Sd & BSD_SOCKET_ID_MASK))) - { - _SlDrvObjUnLock(&g_pCB->FlowContCB.TxLockObj); - return SL_SOC_ERROR; - } - if(g_pCB->FlowContCB.TxPoolCnt <= FLOW_CONT_MIN + 1) - { - /* we have indication that this socket is set as blocking and we try to */ - /* unblock it - return an error */ - if( g_pCB->SocketNonBlocking & (1<< (Sd & BSD_SOCKET_ID_MASK))) - { - _SlDrvObjUnLock(&g_pCB->FlowContCB.TxLockObj); - return RetVal; - } - /* If TxPoolCnt was increased by other thread at this moment, */ - /* TxSyncObj won't wait here */ - _SlDrvSyncObjWaitForever(&g_pCB->FlowContCB.TxSyncObj); - } - if(g_pCB->FlowContCB.TxPoolCnt > FLOW_CONT_MIN + 1 ) - { - break; - } - else - { - _SlDrvObjUnLock(&g_pCB->FlowContCB.TxLockObj); - } - } - - _SlDrvObjLockWaitForever(&g_pCB->GlobalLockObj); - - - VERIFY_PROTOCOL(g_pCB->FlowContCB.TxPoolCnt > FLOW_CONT_MIN + 1 ); - g_pCB->FlowContCB.TxPoolCnt--; - - _SlDrvObjUnLock(&g_pCB->FlowContCB.TxLockObj); - - /* send the message */ - RetVal = _SlDrvMsgWrite(pCmdCtrl, pCmdExt, pTxRxDescBuff); - - _SlDrvObjUnLock(&g_pCB->GlobalLockObj); - - return RetVal; -} - -/* ******************************************************************************/ -/* _SlDrvMsgWrite */ -/* ******************************************************************************/ -_SlReturnVal_t _SlDrvMsgWrite(_SlCmdCtrl_t *pCmdCtrl,_SlCmdExt_t *pCmdExt, _u8 *pTxRxDescBuff) -{ - _u8 sendRxPayload = FALSE; - VERIFY_PROTOCOL(NULL != pCmdCtrl); - - g_pCB->FunctionParams.pCmdCtrl = pCmdCtrl; - g_pCB->FunctionParams.pTxRxDescBuff = pTxRxDescBuff; - g_pCB->FunctionParams.pCmdExt = pCmdExt; - - g_pCB->TempProtocolHeader.Opcode = pCmdCtrl->Opcode; - g_pCB->TempProtocolHeader.Len = _SL_PROTOCOL_CALC_LEN(pCmdCtrl, pCmdExt); - - if (pCmdExt && pCmdExt->RxPayloadLen < 0 && pCmdExt->TxPayloadLen) - { - pCmdExt->RxPayloadLen = pCmdExt->RxPayloadLen * (-1); /* change sign */ - sendRxPayload = TRUE; - g_pCB->TempProtocolHeader.Len = g_pCB->TempProtocolHeader.Len + pCmdExt->RxPayloadLen; - } - -#ifdef SL_START_WRITE_STAT - sl_IfStartWriteSequence(g_pCB->FD); -#endif - -#ifdef SL_IF_TYPE_UART - /* Write long sync pattern */ - NWP_IF_WRITE_CHECK(g_pCB->FD, (_u8 *)&g_H2NSyncPattern.Long, 2*SYNC_PATTERN_LEN); -#else - /* Write short sync pattern */ - NWP_IF_WRITE_CHECK(g_pCB->FD, (_u8 *)&g_H2NSyncPattern.Short, SYNC_PATTERN_LEN); -#endif - - /* Header */ - NWP_IF_WRITE_CHECK(g_pCB->FD, (_u8 *)&g_pCB->TempProtocolHeader, _SL_CMD_HDR_SIZE); - - /* Descriptors */ - if (pTxRxDescBuff && pCmdCtrl->TxDescLen > 0) - { - NWP_IF_WRITE_CHECK(g_pCB->FD, pTxRxDescBuff, - _SL_PROTOCOL_ALIGN_SIZE(pCmdCtrl->TxDescLen)); - } - - /* A special mode where Rx payload and Rx length are used as Tx as well */ - /* This mode requires no Rx payload on the response and currently used by fs_Close and sl_Send on */ - /* transceiver mode */ - if (sendRxPayload == TRUE ) - { - NWP_IF_WRITE_CHECK(g_pCB->FD, pCmdExt->pRxPayload, - _SL_PROTOCOL_ALIGN_SIZE(pCmdExt->RxPayloadLen)); - } - - /* Payload */ - if (pCmdExt && pCmdExt->TxPayloadLen > 0) - { - /* If the message has payload, it is mandatory that the message's arguments are protocol aligned. */ - /* Otherwise the aligning of arguments will create a gap between arguments and payload. */ - VERIFY_PROTOCOL(_SL_IS_PROTOCOL_ALIGNED_SIZE(pCmdCtrl->TxDescLen)); - - NWP_IF_WRITE_CHECK(g_pCB->FD, pCmdExt->pTxPayload, - _SL_PROTOCOL_ALIGN_SIZE(pCmdExt->TxPayloadLen)); - } - - - _SL_DBG_CNT_INC(MsgCnt.Write); - -#ifdef SL_START_WRITE_STAT - sl_IfEndWriteSequence(g_pCB->FD); -#endif - - return SL_OS_RET_CODE_OK; -} - -/* ******************************************************************************/ -/* _SlDrvMsgRead */ -/* ******************************************************************************/ -_SlReturnVal_t _SlDrvMsgRead(void) -{ - /* alignment for small memory models */ - union - { - _u8 TempBuf[_SL_RESP_HDR_SIZE]; - _u32 DummyBuf[2]; - } uBuf; - _u8 TailBuffer[4]; - _u16 LengthToCopy; - _u16 AlignedLengthRecv; - _u8 AlignSize; - _u8 *pAsyncBuf = NULL; - _u16 OpCode; - _u16 RespPayloadLen; - _u8 sd = SL_MAX_SOCKETS; - _SlRxMsgClass_e RxMsgClass; - - - /* save params in global CB */ - g_pCB->FunctionParams.AsyncExt.pAsyncBuf = NULL; - g_pCB->FunctionParams.AsyncExt.AsyncEvtHandler= NULL; - - - VERIFY_RET_OK(_SlDrvRxHdrRead((_u8*)(uBuf.TempBuf), &AlignSize)); - - OpCode = OPCODE(uBuf.TempBuf); - RespPayloadLen = RSP_PAYLOAD_LEN(uBuf.TempBuf); - - - /* 'Init Compelete' message bears no valid FlowControl info */ - if(SL_OPCODE_DEVICE_INITCOMPLETE != OpCode) - { - g_pCB->FlowContCB.TxPoolCnt = ((_SlResponseHeader_t *)uBuf.TempBuf)->TxPoolCnt; - g_pCB->SocketNonBlocking = ((_SlResponseHeader_t *)uBuf.TempBuf)->SocketNonBlocking; - g_pCB->SocketTXFailure = ((_SlResponseHeader_t *)uBuf.TempBuf)->SocketTXFailure; - - if(g_pCB->FlowContCB.TxPoolCnt > FLOW_CONT_MIN) - { - _SlDrvSyncObjSignal(&g_pCB->FlowContCB.TxSyncObj); - } - } - - /* Find the RX messaage class and set its async event handler */ - _SlDrvClassifyRxMsg(OpCode); - - RxMsgClass = g_pCB->FunctionParams.AsyncExt.RxMsgClass; - - - switch(RxMsgClass) - { - case ASYNC_EVT_CLASS: - - VERIFY_PROTOCOL(NULL == pAsyncBuf); - -#if (SL_MEMORY_MGMT == SL_MEMORY_MGMT_DYNAMIC) - g_pCB->FunctionParams.AsyncExt.pAsyncBuf = sl_Malloc(SL_ASYNC_MAX_MSG_LEN); -#else - g_pCB->FunctionParams.AsyncExt.pAsyncBuf = g_StatMem.AsyncRespBuf; -#endif - /* set the local pointer to the allocated one */ - pAsyncBuf = g_pCB->FunctionParams.AsyncExt.pAsyncBuf; - - /* clear the async buffer */ - _SlDrvMemZero(pAsyncBuf, SL_ASYNC_MAX_MSG_LEN); - - MALLOC_OK_CHECK(pAsyncBuf); - - sl_Memcpy(pAsyncBuf, uBuf.TempBuf, _SL_RESP_HDR_SIZE); - if (_SL_PROTOCOL_ALIGN_SIZE(RespPayloadLen) <= SL_ASYNC_MAX_PAYLOAD_LEN) - { - AlignedLengthRecv = _SL_PROTOCOL_ALIGN_SIZE(RespPayloadLen); - } - else - { - AlignedLengthRecv = _SL_PROTOCOL_ALIGN_SIZE(SL_ASYNC_MAX_PAYLOAD_LEN); - } - if (RespPayloadLen > 0) - { - NWP_IF_READ_CHECK(g_pCB->FD, - pAsyncBuf + _SL_RESP_HDR_SIZE, - AlignedLengthRecv); - } - /* In case ASYNC RX buffer length is smaller then the received data length, dump the rest */ - if ((_SL_PROTOCOL_ALIGN_SIZE(RespPayloadLen) > SL_ASYNC_MAX_PAYLOAD_LEN)) - { - AlignedLengthRecv = _SL_PROTOCOL_ALIGN_SIZE(RespPayloadLen) - SL_ASYNC_MAX_PAYLOAD_LEN; - while (AlignedLengthRecv > 0) - { - NWP_IF_READ_CHECK(g_pCB->FD,TailBuffer,4); - AlignedLengthRecv = AlignedLengthRecv - 4; - } - } - - _SlDrvProtectionObjLockWaitForever(); - - if ( -#ifndef SL_TINY_EXT - (SL_OPCODE_SOCKET_ACCEPTASYNCRESPONSE == OpCode) || - (SL_OPCODE_SOCKET_ACCEPTASYNCRESPONSE_V6 == OpCode) || -#endif - (SL_OPCODE_SOCKET_CONNECTASYNCRESPONSE == OpCode) - ) - { - /* go over the active list if exist to find obj waiting for this Async event */ - sd = ((((_SocketResponse_t *)(pAsyncBuf + _SL_RESP_HDR_SIZE))->sd) & BSD_SOCKET_ID_MASK); - } - _SlFindAndSetActiveObj(OpCode, sd); - - _SlDrvProtectionObjUnLock(); - - break; - case RECV_RESP_CLASS: - { - _u8 ExpArgSize; /* Expected size of Recv/Recvfrom arguments */ - - switch(OpCode) - { - case SL_OPCODE_SOCKET_RECVFROMASYNCRESPONSE: - ExpArgSize = RECVFROM_IPV4_ARGS_SIZE; - break; -#ifndef SL_TINY_EXT - case SL_OPCODE_SOCKET_RECVFROMASYNCRESPONSE_V6: - ExpArgSize = RECVFROM_IPV6_ARGS_SIZE; - break; -#endif - default: - /* SL_OPCODE_SOCKET_RECVASYNCRESPONSE: */ - ExpArgSize = RECV_ARGS_SIZE; - } - - /* Read first 4 bytes of Recv/Recvfrom response to get SocketId and actual */ - /* response data length */ - NWP_IF_READ_CHECK(g_pCB->FD, &uBuf.TempBuf[4], RECV_ARGS_SIZE); - - /* Validate Socket ID and Received Length value. */ - VERIFY_PROTOCOL((SD(&uBuf.TempBuf[4])& BSD_SOCKET_ID_MASK) < SL_MAX_SOCKETS); - - _SlDrvProtectionObjLockWaitForever(); - - /* go over the active list if exist to find obj waiting for this Async event */ - VERIFY_RET_OK(_SlFindAndSetActiveObj(OpCode,SD(&uBuf.TempBuf[4]) & BSD_SOCKET_ID_MASK)); - - /* Verify data is waited on this socket. The pArgs should have been set by _SlDrvDataReadOp(). */ - VERIFY_SOCKET_CB(NULL != ((_SlArgsData_t *)(g_pCB->ObjPool[g_pCB->FunctionParams.AsyncExt.ActionIndex].pData))->pArgs); - - sl_Memcpy( ((_SlArgsData_t *)(g_pCB->ObjPool[g_pCB->FunctionParams.AsyncExt.ActionIndex].pRespArgs))->pArgs, &uBuf.TempBuf[4], RECV_ARGS_SIZE); - - if(ExpArgSize > RECV_ARGS_SIZE) - { - NWP_IF_READ_CHECK(g_pCB->FD, - ((_SlArgsData_t *)(g_pCB->ObjPool[g_pCB->FunctionParams.AsyncExt.ActionIndex].pRespArgs))->pArgs + RECV_ARGS_SIZE, - ExpArgSize - RECV_ARGS_SIZE); - } - - /* Here g_pCB->ObjPool[g_pCB->FunctionParams.AsyncExt.ActionIndex].pData contains requested(expected) Recv/Recvfrom DataSize. */ - /* Overwrite requested DataSize with actual one. */ - /* If error is received, this information will be read from arguments. */ - if(ACT_DATA_SIZE(&uBuf.TempBuf[4]) > 0) - { - VERIFY_SOCKET_CB(NULL != ((_SlArgsData_t *)(g_pCB->ObjPool[g_pCB->FunctionParams.AsyncExt.ActionIndex].pRespArgs))->pData); - - /* Read 4 bytes aligned from interface */ - /* therefore check the requested length and read only */ - /* 4 bytes aligned data. The rest unaligned (if any) will be read */ - /* and copied to a TailBuffer */ - LengthToCopy = ACT_DATA_SIZE(&uBuf.TempBuf[4]) & (3); - AlignedLengthRecv = ACT_DATA_SIZE(&uBuf.TempBuf[4]) & (~3); - if( AlignedLengthRecv >= 4) - { - NWP_IF_READ_CHECK(g_pCB->FD,((_SlArgsData_t *)(g_pCB->ObjPool[g_pCB->FunctionParams.AsyncExt.ActionIndex].pRespArgs))->pData,AlignedLengthRecv ); - } - /* copy the unaligned part, if any */ - if( LengthToCopy > 0) - { - NWP_IF_READ_CHECK(g_pCB->FD,TailBuffer,4); - /* copy TailBuffer unaligned part (1/2/3 bytes) */ - sl_Memcpy(((_SlArgsData_t *)(g_pCB->ObjPool[g_pCB->FunctionParams.AsyncExt.ActionIndex].pRespArgs))->pData + AlignedLengthRecv,TailBuffer,LengthToCopy); - } - } - _SlDrvSyncObjSignal(&g_pCB->ObjPool[g_pCB->FunctionParams.AsyncExt.ActionIndex].SyncObj); - _SlDrvProtectionObjUnLock(); - } - break; - - case CMD_RESP_CLASS: - - /* Some commands pass a maximum arguments size. */ - /* In this case Driver will send extra dummy patterns to NWP if */ - /* the response message is smaller than maximum. */ - /* When RxDescLen is not exact, using RxPayloadLen is forbidden! */ - /* If such case cannot be avoided - parse message here to detect */ - /* arguments/payload border. */ - NWP_IF_READ_CHECK(g_pCB->FD, - g_pCB->FunctionParams.pTxRxDescBuff, - _SL_PROTOCOL_ALIGN_SIZE(g_pCB->FunctionParams.pCmdCtrl->RxDescLen)); - - if((NULL != g_pCB->FunctionParams.pCmdExt) && (0 != g_pCB->FunctionParams.pCmdExt->RxPayloadLen)) - { - /* Actual size of command's response payload: - */ - _i16 ActDataSize = RSP_PAYLOAD_LEN(uBuf.TempBuf) - g_pCB->FunctionParams.pCmdCtrl->RxDescLen; - - g_pCB->FunctionParams.pCmdExt->ActualRxPayloadLen = ActDataSize; - - /* Check that the space prepared by user for the response data is sufficient. */ - if(ActDataSize <= 0) - { - g_pCB->FunctionParams.pCmdExt->RxPayloadLen = 0; - } - else - { - /* In case the user supplied Rx buffer length which is smaller then the received data length, copy according to user length */ - if (ActDataSize > g_pCB->FunctionParams.pCmdExt->RxPayloadLen) - { - LengthToCopy = g_pCB->FunctionParams.pCmdExt->RxPayloadLen & (3); - AlignedLengthRecv = g_pCB->FunctionParams.pCmdExt->RxPayloadLen & (~3); - } - else - { - LengthToCopy = ActDataSize & (3); - AlignedLengthRecv = ActDataSize & (~3); - } - /* Read 4 bytes aligned from interface */ - /* therefore check the requested length and read only */ - /* 4 bytes aligned data. The rest unaligned (if any) will be read */ - /* and copied to a TailBuffer */ - - if( AlignedLengthRecv >= 4) - { - NWP_IF_READ_CHECK(g_pCB->FD, - g_pCB->FunctionParams.pCmdExt->pRxPayload, - AlignedLengthRecv ); - - } - /* copy the unaligned part, if any */ - if( LengthToCopy > 0) - { - NWP_IF_READ_CHECK(g_pCB->FD,TailBuffer,4); - /* copy TailBuffer unaligned part (1/2/3 bytes) */ - sl_Memcpy(g_pCB->FunctionParams.pCmdExt->pRxPayload + AlignedLengthRecv, - TailBuffer, - LengthToCopy); - ActDataSize = ActDataSize-4; - } - /* In case the user supplied Rx buffer length which is smaller then the received data length, dump the rest */ - if (ActDataSize > g_pCB->FunctionParams.pCmdExt->RxPayloadLen) - { - /* calculate the rest of the data size to dump */ - AlignedLengthRecv = ActDataSize - (g_pCB->FunctionParams.pCmdExt->RxPayloadLen & (~3)); - while( AlignedLengthRecv > 0) - { - NWP_IF_READ_CHECK(g_pCB->FD,TailBuffer, 4 ); - AlignedLengthRecv = AlignedLengthRecv - 4; - } - } - } - } - break; - - default: - /* DUMMY_MSG_CLASS: Flow control message has no payload. */ - break; - } - - if(AlignSize > 0) - { - NWP_IF_READ_CHECK(g_pCB->FD, uBuf.TempBuf, AlignSize); - } - - _SL_DBG_CNT_INC(MsgCnt.Read); - - /* Unmask Interrupt call */ - sl_IfUnMaskIntHdlr(); - - return SL_OS_RET_CODE_OK; -} - - -/* ******************************************************************************/ -/* _SlAsyncEventGenericHandler */ -/* ******************************************************************************/ -void _SlAsyncEventGenericHandler(void) -{ - _u32 SlAsyncEvent = 0; - _u8 OpcodeFound = FALSE; - _u8 i; - - _u32* pEventLocation = NULL; /* This pointer will override the async buffer with the translated event type */ - _SlResponseHeader_t *pHdr = (_SlResponseHeader_t *)g_pCB->FunctionParams.AsyncExt.pAsyncBuf; - - - /* if no async event registered nothing to do..*/ - if (g_pCB->FunctionParams.AsyncExt.AsyncEvtHandler == NULL) - return; - - /* Iterate through all the opcode in the table */ - for (i=0; i< (sizeof(OpcodeTranslateTable) / sizeof(OpcodeKeyVal_t)); i++) - { - if (OpcodeTranslateTable[i].opcode == pHdr->GenHeader.Opcode) - { - SlAsyncEvent = OpcodeTranslateTable[i].event; - OpcodeFound = TRUE; - break; - } - } - - /* No Async event found in the table */ - if (OpcodeFound == FALSE) - { - /* This case handles all the async events handlers of the DEVICE & SOCK Silos which are handled internally. - For these cases we send the async even buffer as is */ - g_pCB->FunctionParams.AsyncExt.AsyncEvtHandler(g_pCB->FunctionParams.AsyncExt.pAsyncBuf); - } - else - { - /* calculate the event type location to be filled in the async buffer */ - pEventLocation = (_u32*)(g_pCB->FunctionParams.AsyncExt.pAsyncBuf + sizeof (_SlResponseHeader_t) - sizeof(SlAsyncEvent) ); - - /* Override the async buffer (before the data starts ) with our event type */ - *pEventLocation = SlAsyncEvent; - - /* call the event handler registered by the user with our async buffer which now holds - the User's event type and its related data */ - g_pCB->FunctionParams.AsyncExt.AsyncEvtHandler(pEventLocation); - } - - -} - - -/* ******************************************************************************/ -/* _SlDrvMsgReadCmdCtx */ -/* ******************************************************************************/ -_SlReturnVal_t _SlDrvMsgReadCmdCtx(void) -{ - - /* after command response is received and isCmdRespWaited */ - /* flag is set FALSE, it is necessary to read out all */ - /* Async messages in Commands context, because ssiDma_IsrHandleSignalFromSlave */ - /* could have dispatched some Async messages to g_NwpIf.CmdSyncObj */ - /* after command response but before this response has been processed */ - /* by spi_singleRead and isCmdRespWaited was set FALSE. */ - while (TRUE == g_pCB->IsCmdRespWaited) - { - if(_SL_PENDING_RX_MSG(g_pCB)) - { - VERIFY_RET_OK(_SlDrvMsgRead()); - g_pCB->RxDoneCnt++; - - if (CMD_RESP_CLASS == g_pCB->FunctionParams.AsyncExt.RxMsgClass) - { - g_pCB->IsCmdRespWaited = FALSE; - - /* In case CmdResp has been read without waiting on CmdSyncObj - that */ - /* Sync object. That to prevent old signal to be processed. */ - sl_SyncObjClear(&g_pCB->CmdSyncObj); - } - else if (ASYNC_EVT_CLASS == g_pCB->FunctionParams.AsyncExt.RxMsgClass) - { - /* If Async event has been read in CmdResp context, check whether */ - /* there is a handler for this event. If there is, spawn specific */ - /* handler. Otherwise free the event's buffer. */ - /* This way there will be no "dry shots" from CmdResp context to */ - /* temporary context, i.e less waste of CPU and faster buffer */ - /* release. */ - _SlAsyncEventGenericHandler(); - - -#if (SL_MEMORY_MGMT == SL_MEMORY_MGMT_DYNAMIC) - sl_Free(g_pCB->FunctionParams.AsyncExt.pAsyncBuf); -#else - g_pCB->FunctionParams.AsyncExt.pAsyncBuf = NULL; -#endif - } - } - else - { - /* CmdSyncObj will be signaled by IRQ */ - _SlDrvSyncObjWaitForever(&g_pCB->CmdSyncObj); - } - } - - /* If there are more pending Rx Msgs after CmdResp is received, */ - /* that means that these are Async, Dummy or Read Data Msgs. */ - /* Spawn _SlDrvMsgReadSpawnCtx to trigger reading these messages from */ - /* Temporary context. */ - /* sl_Spawn is activated, using a different context */ - - _SlDrvObjUnLock(&g_pCB->GlobalLockObj); - - if(_SL_PENDING_RX_MSG(g_pCB)) - { - sl_Spawn((_SlSpawnEntryFunc_t)_SlDrvMsgReadSpawnCtx, NULL, 0); - } - - return SL_OS_RET_CODE_OK; -} - -/* ******************************************************************************/ -/* _SlDrvMsgReadSpawnCtx */ -/* ******************************************************************************/ -_SlReturnVal_t _SlDrvMsgReadSpawnCtx(void *pValue) -{ -#ifdef SL_POLLING_MODE_USED - _i16 retCode = OSI_OK; - /* for polling based systems */ - do - { - retCode = sl_LockObjLock(&g_pCB->GlobalLockObj, 0); - if ( OSI_OK != retCode ) - { - if (TRUE == g_pCB->IsCmdRespWaited) - { - _SlDrvSyncObjSignal(&g_pCB->CmdSyncObj); - return SL_RET_CODE_OK; - } - } - - } - while (OSI_OK != retCode); - -#else - _SlDrvObjLockWaitForever(&g_pCB->GlobalLockObj); -#endif - - - /* Messages might have been read by CmdResp context. Therefore after */ - /* getting LockObj, check again where the Pending Rx Msg is still present. */ - if(FALSE == (_SL_PENDING_RX_MSG(g_pCB))) - { - _SlDrvObjUnLock(&g_pCB->GlobalLockObj); - - return SL_RET_CODE_OK; - } - - VERIFY_RET_OK(_SlDrvMsgRead()); - - g_pCB->RxDoneCnt++; - - switch(g_pCB->FunctionParams.AsyncExt.RxMsgClass) - { - case ASYNC_EVT_CLASS: - /* If got here and protected by LockObj a message is waiting */ - /* to be read */ - VERIFY_PROTOCOL(NULL != g_pCB->FunctionParams.AsyncExt.pAsyncBuf); - - _SlAsyncEventGenericHandler(); - -#if (SL_MEMORY_MGMT == SL_MEMORY_MGMT_DYNAMIC) - sl_Free(g_pCB->FunctionParams.AsyncExt.pAsyncBuf); -#else - g_pCB->FunctionParams.AsyncExt.pAsyncBuf = NULL; -#endif - break; - case DUMMY_MSG_CLASS: - case RECV_RESP_CLASS: - /* These types are legal in this context. Do nothing */ - break; - case CMD_RESP_CLASS: - /* Command response is illegal in this context. */ - /* No 'break' here: Assert! */ - default: - VERIFY_PROTOCOL(0); - } - - _SlDrvObjUnLock(&g_pCB->GlobalLockObj); - - return(SL_RET_CODE_OK); -} - - - -/* - -#define SL_OPCODE_SILO_DEVICE ( 0x0 << SL_OPCODE_SILO_OFFSET ) -#define SL_OPCODE_SILO_WLAN ( 0x1 << SL_OPCODE_SILO_OFFSET ) -#define SL_OPCODE_SILO_SOCKET ( 0x2 << SL_OPCODE_SILO_OFFSET ) -#define SL_OPCODE_SILO_NETAPP ( 0x3 << SL_OPCODE_SILO_OFFSET ) -#define SL_OPCODE_SILO_NVMEM ( 0x4 << SL_OPCODE_SILO_OFFSET ) -#define SL_OPCODE_SILO_NETCFG ( 0x5 << SL_OPCODE_SILO_OFFSET ) - - -*/ - -/* The Lookup table below holds the event handlers to be called according to the incoming - RX message SILO type */ -const _SlSpawnEntryFunc_t RxMsgClassLUT[] = { - (_SlSpawnEntryFunc_t)_SlDrvDeviceEventHandler, /* SL_OPCODE_SILO_DEVICE */ -#if defined(sl_WlanEvtHdlr) || defined(EXT_LIB_REGISTERED_WLAN_EVENTS) - (_SlSpawnEntryFunc_t)_SlDrvHandleWlanEvents, /* SL_OPCODE_SILO_WLAN */ -#else - NULL, -#endif -#if defined (sl_SockEvtHdlr) || defined(EXT_LIB_REGISTERED_SOCK_EVENTS) - (_SlSpawnEntryFunc_t)_SlDrvHandleSockEvents, /* SL_OPCODE_SILO_SOCKET */ -#else - NULL, -#endif - -#if defined(sl_NetAppEvtHdlr) || defined(EXT_LIB_REGISTERED_NETAPP_EVENTS) - (_SlSpawnEntryFunc_t)_SlDrvHandleNetAppEvents, /* SL_OPCODE_SILO_NETAPP */ -#else - NULL, -#endif - NULL, /* SL_OPCODE_SILO_NVMEM */ - NULL, /* SL_OPCODE_SILO_NETCFG */ - NULL, - NULL -}; - - -/* ******************************************************************************/ -/* _SlDrvClassifyRxMsg */ -/* ******************************************************************************/ -void _SlDrvClassifyRxMsg( - _SlOpcode_t Opcode) -{ - _SlSpawnEntryFunc_t AsyncEvtHandler = NULL; - _SlRxMsgClass_e RxMsgClass = CMD_RESP_CLASS; - _u8 Silo; - - - if (0 == (SL_OPCODE_SYNC & Opcode)) - { /* Async event has received */ - - if (SL_OPCODE_DEVICE_DEVICEASYNCDUMMY == Opcode) - { - RxMsgClass = DUMMY_MSG_CLASS; - } - else if ( (SL_OPCODE_SOCKET_RECVASYNCRESPONSE == Opcode) || (SL_OPCODE_SOCKET_RECVFROMASYNCRESPONSE == Opcode) -#ifndef SL_TINY_EXT - || (SL_OPCODE_SOCKET_RECVFROMASYNCRESPONSE_V6 == Opcode) -#endif - ) - { - RxMsgClass = RECV_RESP_CLASS; - } - else - { - /* This is Async Event class message */ - RxMsgClass = ASYNC_EVT_CLASS; - - /* Despite the fact that 4 bits are allocated in the SILO field, we actually have only 6 SILOs - So we can use the 8 options of SILO in look up table */ - Silo = ((Opcode >> SL_OPCODE_SILO_OFFSET) & 0x7); - - VERIFY_PROTOCOL(Silo < (sizeof(RxMsgClassLUT)/sizeof(_SlSpawnEntryFunc_t))); - - /* Set the async event hander according to the LUT */ - AsyncEvtHandler = RxMsgClassLUT[Silo]; - - if ((SL_OPCODE_NETAPP_HTTPGETTOKENVALUE == Opcode) || (SL_OPCODE_NETAPP_HTTPPOSTTOKENVALUE == Opcode)) - { - AsyncEvtHandler = _SlDrvNetAppEventHandler; - } -#ifndef SL_TINY_EXT - else if (SL_OPCODE_NETAPP_PINGREPORTREQUESTRESPONSE == Opcode) - { - AsyncEvtHandler = (_SlSpawnEntryFunc_t)_sl_HandleAsync_PingResponse; - } -#endif - } - } - - g_pCB->FunctionParams.AsyncExt.RxMsgClass = RxMsgClass; - g_pCB->FunctionParams.AsyncExt.AsyncEvtHandler = AsyncEvtHandler; - -} - - -/* ******************************************************************************/ -/* _SlDrvRxHdrRead */ -/* ******************************************************************************/ -_SlReturnVal_t _SlDrvRxHdrRead(_u8 *pBuf, _u8 *pAlignSize) -{ - _u32 SyncCnt = 0; - _u8 ShiftIdx; - -#ifndef SL_IF_TYPE_UART - /* 1. Write CNYS pattern to NWP when working in SPI mode only */ - NWP_IF_WRITE_CHECK(g_pCB->FD, (_u8 *)&g_H2NCnysPattern.Short, SYNC_PATTERN_LEN); -#endif - - /* 2. Read 4 bytes (protocol aligned) */ - NWP_IF_READ_CHECK(g_pCB->FD, &pBuf[0], 4); - _SL_DBG_SYNC_LOG(SyncCnt,pBuf); - - /* Wait for SYNC_PATTERN_LEN from the device */ - while ( ! N2H_SYNC_PATTERN_MATCH(pBuf, g_pCB->TxSeqNum) ) - { - /* 3. Debug limit of scan */ - VERIFY_PROTOCOL(SyncCnt < SL_SYNC_SCAN_THRESHOLD); - - /* 4. Read next 4 bytes to Low 4 bytes of buffer */ - if(0 == (SyncCnt % (_u32)SYNC_PATTERN_LEN)) - { - NWP_IF_READ_CHECK(g_pCB->FD, &pBuf[4], 4); - _SL_DBG_SYNC_LOG(SyncCnt,pBuf); - } - - /* 5. Shift Buffer Up for checking if the sync is shifted */ - for(ShiftIdx = 0; ShiftIdx< 7; ShiftIdx++) - { - pBuf[ShiftIdx] = pBuf[ShiftIdx+1]; - } - pBuf[7] = 0; - - SyncCnt++; - } - - /* 5. Sync pattern found. If needed, complete number of read bytes to multiple of 4 (protocol align) */ - SyncCnt %= SYNC_PATTERN_LEN; - - if(SyncCnt > 0) - { - *(_u32 *)&pBuf[0] = *(_u32 *)&pBuf[4]; - NWP_IF_READ_CHECK(g_pCB->FD, &pBuf[SYNC_PATTERN_LEN - SyncCnt], (_u16)SyncCnt); - } - else - { - NWP_IF_READ_CHECK(g_pCB->FD, &pBuf[0], 4); - } - - /* 6. Scan for Double pattern. */ - while ( N2H_SYNC_PATTERN_MATCH(pBuf, g_pCB->TxSeqNum) ) - { - _SL_DBG_CNT_INC(Work.DoubleSyncPattern); - NWP_IF_READ_CHECK(g_pCB->FD, &pBuf[0], SYNC_PATTERN_LEN); - } - g_pCB->TxSeqNum++; - - /* 7. Here we've read Generic Header (4 bytes). Read the Resp Specific header (4 more bytes). */ - NWP_IF_READ_CHECK(g_pCB->FD, &pBuf[SYNC_PATTERN_LEN], _SL_RESP_SPEC_HDR_SIZE); - - /* 8. Here we've read the entire Resp Header. */ - /* Return number bytes needed to be sent after read for NWP Rx 4-byte alignment (protocol alignment) */ - *pAlignSize = (_u8)((SyncCnt > 0) ? (SYNC_PATTERN_LEN - SyncCnt) : 0); - - return SL_RET_CODE_OK; -} - -/* ***************************************************************************** */ -/* _SlDrvBasicCmd */ -/* ***************************************************************************** */ -typedef union -{ - _BasicResponse_t Rsp; -}_SlBasicCmdMsg_u; - - -#ifndef SL_TINY_EXT -_i16 _SlDrvBasicCmd(_SlOpcode_t Opcode) -{ - _SlBasicCmdMsg_u Msg = {{0, 0}}; - _SlCmdCtrl_t CmdCtrl; - - CmdCtrl.Opcode = Opcode; - CmdCtrl.TxDescLen = 0; - CmdCtrl.RxDescLen = sizeof(_BasicResponse_t); - - - VERIFY_RET_OK(_SlDrvCmdOp((_SlCmdCtrl_t *)&CmdCtrl, &Msg, NULL)); - - return (_i16)Msg.Rsp.status; -} - -/***************************************************************************** - _SlDrvCmdSend - Send SL command without waiting for command response - This function is unprotected and the caller should make - sure global lock is active -*****************************************************************************/ -_SlReturnVal_t _SlDrvCmdSend( - _SlCmdCtrl_t *pCmdCtrl , - void *pTxRxDescBuff , - _SlCmdExt_t *pCmdExt) -{ - _SlReturnVal_t RetVal; - _u8 IsCmdRespWaitedOriginalVal; - - _SlFunctionParams_t originalFuncParms; - - /* save the current RespWait flag before clearing it */ - IsCmdRespWaitedOriginalVal = g_pCB->IsCmdRespWaited; - - /* save the current command parameters */ - sl_Memcpy(&originalFuncParms, &g_pCB->FunctionParams, sizeof(_SlFunctionParams_t)); - - g_pCB->IsCmdRespWaited = FALSE; - - SL_TRACE0(DBG_MSG, MSG_312, "_SlDrvCmdSend: call _SlDrvMsgWrite"); - - /* send the message */ - RetVal = _SlDrvMsgWrite(pCmdCtrl, pCmdExt, pTxRxDescBuff); - - /* restore the original RespWait flag */ - g_pCB->IsCmdRespWaited = IsCmdRespWaitedOriginalVal; - - /* restore the original command parameters */ - sl_Memcpy(&g_pCB->FunctionParams, &originalFuncParms, sizeof(_SlFunctionParams_t)); - - return RetVal; - - -} -#endif - -/* ***************************************************************************** */ -/* _SlDrvWaitForPoolObj */ -/* ***************************************************************************** */ -_u8 _SlDrvWaitForPoolObj(_u8 ActionID, _u8 SocketID) -{ - _u8 CurrObjIndex = MAX_CONCURRENT_ACTIONS; - - /* Get free object */ - _SlDrvProtectionObjLockWaitForever(); - if (MAX_CONCURRENT_ACTIONS > g_pCB->FreePoolIdx) - { - /* save the current obj index */ - CurrObjIndex = g_pCB->FreePoolIdx; - /* set the new free index */ -#ifndef SL_TINY_EXT - if (MAX_CONCURRENT_ACTIONS > g_pCB->ObjPool[CurrObjIndex].NextIndex) - { - g_pCB->FreePoolIdx = g_pCB->ObjPool[CurrObjIndex].NextIndex; - } - else -#endif - { - /* No further free actions available */ - g_pCB->FreePoolIdx = MAX_CONCURRENT_ACTIONS; - } - } - else - { - _SlDrvProtectionObjUnLock(); - return CurrObjIndex; - } - g_pCB->ObjPool[CurrObjIndex].ActionID = (_u8)ActionID; - if (SL_MAX_SOCKETS > SocketID) - { - g_pCB->ObjPool[CurrObjIndex].AdditionalData = SocketID; - } -#ifndef SL_TINY_EXT - /*In case this action is socket related, SocketID bit will be on - In case SocketID is set to SL_MAX_SOCKETS, the socket is not relevant to the action. In that case ActionID bit will be on */ - while ( ( (SL_MAX_SOCKETS > SocketID) && (g_pCB->ActiveActionsBitmap & (1<ActiveActionsBitmap & (1<ObjPool[CurrObjIndex].NextIndex = g_pCB->PendingPoolIdx; - g_pCB->PendingPoolIdx = CurrObjIndex; - _SlDrvProtectionObjUnLock(); - - /* wait for action to be free */ - _SlDrvSyncObjWaitForever(&g_pCB->ObjPool[CurrObjIndex].SyncObj); - - /* set params and move to active (remove from pending list at _SlDrvReleasePoolObj) */ - _SlDrvProtectionObjLockWaitForever(); - } -#endif - /* mark as active. Set socket as active if action is on socket, otherwise mark action as active */ - if (SL_MAX_SOCKETS > SocketID) - { - g_pCB->ActiveActionsBitmap |= (1<ActiveActionsBitmap |= (1<ObjPool[CurrObjIndex].NextIndex = g_pCB->ActivePoolIdx; - g_pCB->ActivePoolIdx = CurrObjIndex; - /* unlock */ - _SlDrvProtectionObjUnLock(); - return CurrObjIndex; -} - -/* ******************************************************************************/ -/* _SlDrvReleasePoolObj */ -/* ******************************************************************************/ -void _SlDrvReleasePoolObj(_u8 ObjIdx) -{ -#ifndef SL_TINY_EXT - _u8 PendingIndex; -#endif - - _SlDrvProtectionObjLockWaitForever(); - - /* In Tiny mode, there is only one object pool so no pending actions are available */ -#ifndef SL_TINY_EXT - /* go over the pending list and release other pending action if needed */ - PendingIndex = g_pCB->PendingPoolIdx; - - while(MAX_CONCURRENT_ACTIONS > PendingIndex) - { - /* In case this action is socket related, SocketID is in use, otherwise will be set to SL_MAX_SOCKETS */ - if ( (g_pCB->ObjPool[PendingIndex].ActionID == g_pCB->ObjPool[ObjIdx].ActionID) && - ( (SL_MAX_SOCKETS == (g_pCB->ObjPool[PendingIndex].AdditionalData & BSD_SOCKET_ID_MASK)) || - ((SL_MAX_SOCKETS > (g_pCB->ObjPool[ObjIdx].AdditionalData & BSD_SOCKET_ID_MASK)) && ( (g_pCB->ObjPool[PendingIndex].AdditionalData & BSD_SOCKET_ID_MASK) == (g_pCB->ObjPool[ObjIdx].AdditionalData & BSD_SOCKET_ID_MASK) ))) ) - { - /* remove from pending list */ - _SlRemoveFromList(&g_pCB->PendingPoolIdx, PendingIndex); - _SlDrvSyncObjSignal(&g_pCB->ObjPool[PendingIndex].SyncObj); - break; - } - PendingIndex = g_pCB->ObjPool[PendingIndex].NextIndex; - } -#endif - - if (SL_MAX_SOCKETS > (g_pCB->ObjPool[ObjIdx].AdditionalData & BSD_SOCKET_ID_MASK)) - { - /* unset socketID */ - g_pCB->ActiveActionsBitmap &= ~(1<<(g_pCB->ObjPool[ObjIdx].AdditionalData & BSD_SOCKET_ID_MASK)); - } - else - { - /* unset actionID */ - g_pCB->ActiveActionsBitmap &= ~(1<ObjPool[ObjIdx].ActionID); - } - - /* delete old data */ - g_pCB->ObjPool[ObjIdx].pRespArgs = NULL; - g_pCB->ObjPool[ObjIdx].ActionID = 0; - g_pCB->ObjPool[ObjIdx].AdditionalData = SL_MAX_SOCKETS; - - /* remove from active list */ - _SlRemoveFromList(&g_pCB->ActivePoolIdx, ObjIdx); - /* move to free list */ - g_pCB->ObjPool[ObjIdx].NextIndex = g_pCB->FreePoolIdx; - g_pCB->FreePoolIdx = ObjIdx; - _SlDrvProtectionObjUnLock(); -} - - -/* ******************************************************************************/ -/* _SlRemoveFromList */ -/* ******************************************************************************/ -void _SlRemoveFromList(_u8 *ListIndex, _u8 ItemIndex) -{ -#ifndef SL_TINY_EXT - _u8 Idx; -#endif - - if (MAX_CONCURRENT_ACTIONS == g_pCB->ObjPool[*ListIndex].NextIndex) - { - *ListIndex = MAX_CONCURRENT_ACTIONS; - } - /* As MAX_CONCURRENT_ACTIONS is equal to 1 in Tiny mode */ -#ifndef SL_TINY_EXT - /* need to remove the first item in the list and therefore update the global which holds this index */ - else if (*ListIndex == ItemIndex) - { - *ListIndex = g_pCB->ObjPool[ItemIndex].NextIndex; - } - else - { - Idx = *ListIndex; - - while(MAX_CONCURRENT_ACTIONS > Idx) - { - /* remove from list */ - if (g_pCB->ObjPool[Idx].NextIndex == ItemIndex) - { - g_pCB->ObjPool[Idx].NextIndex = g_pCB->ObjPool[ItemIndex].NextIndex; - break; - } - - Idx = g_pCB->ObjPool[Idx].NextIndex; - } - } -#endif -} - - -/* ******************************************************************************/ -/* _SlFindAndSetActiveObj */ -/* ******************************************************************************/ -_SlReturnVal_t _SlFindAndSetActiveObj(_SlOpcode_t Opcode, _u8 Sd) -{ - _u8 ActiveIndex; - - ActiveIndex = g_pCB->ActivePoolIdx; - /* go over the active list if exist to find obj waiting for this Async event */ -#ifndef SL_TINY_EXT - while (MAX_CONCURRENT_ACTIONS > ActiveIndex) -#else - /* Only one Active action is availabe in tiny mode, so we can replace the loop with if condition */ - if (MAX_CONCURRENT_ACTIONS > ActiveIndex) -#endif - { - /* unset the Ipv4\IPv6 bit in the opcode if family bit was set */ - if (g_pCB->ObjPool[ActiveIndex].AdditionalData & SL_NETAPP_FAMILY_MASK) - { - Opcode &= ~SL_OPCODE_IPV6; - } - - if ((g_pCB->ObjPool[ActiveIndex].ActionID == RECV_ID) && (Sd == g_pCB->ObjPool[ActiveIndex].AdditionalData) && - ( (SL_OPCODE_SOCKET_RECVASYNCRESPONSE == Opcode) || (SL_OPCODE_SOCKET_RECVFROMASYNCRESPONSE == Opcode) -#ifndef SL_TINY_EXT - || (SL_OPCODE_SOCKET_RECVFROMASYNCRESPONSE_V6 == Opcode) -#endif - ) - - ) - { - g_pCB->FunctionParams.AsyncExt.ActionIndex = ActiveIndex; - return SL_RET_CODE_OK; - } - /* In case this action is socket related, SocketID is in use, otherwise will be set to SL_MAX_SOCKETS */ - if ( (_SlActionLookupTable[ g_pCB->ObjPool[ActiveIndex].ActionID - MAX_SOCKET_ENUM_IDX].ActionAsyncOpcode == Opcode) && - ( ((Sd == (g_pCB->ObjPool[ActiveIndex].AdditionalData & BSD_SOCKET_ID_MASK) ) && (SL_MAX_SOCKETS > Sd)) || (SL_MAX_SOCKETS == (g_pCB->ObjPool[ActiveIndex].AdditionalData & BSD_SOCKET_ID_MASK)) ) ) - { - /* set handler */ - g_pCB->FunctionParams.AsyncExt.AsyncEvtHandler = _SlActionLookupTable[ g_pCB->ObjPool[ActiveIndex].ActionID - MAX_SOCKET_ENUM_IDX].AsyncEventHandler; - g_pCB->FunctionParams.AsyncExt.ActionIndex = ActiveIndex; - return SL_RET_CODE_OK; - } - ActiveIndex = g_pCB->ObjPool[ActiveIndex].NextIndex; - } - - return SL_RET_CODE_SELF_ERROR; - - - -} - - -/* Wrappers for the object functions */ - -void _SlDrvSyncObjWaitForever(_SlSyncObj_t *pSyncObj) -{ - OSI_RET_OK_CHECK(sl_SyncObjWait(pSyncObj, SL_OS_WAIT_FOREVER)); -} - -void _SlDrvSyncObjSignal(_SlSyncObj_t *pSyncObj) -{ - OSI_RET_OK_CHECK(sl_SyncObjSignal(pSyncObj)); -} - -void _SlDrvObjLockWaitForever(_SlLockObj_t *pLockObj) -{ - OSI_RET_OK_CHECK(sl_LockObjLock(pLockObj, SL_OS_WAIT_FOREVER)); -} - -void _SlDrvProtectionObjLockWaitForever() -{ - OSI_RET_OK_CHECK(sl_LockObjLock(&g_pCB->ProtectionLockObj, SL_OS_WAIT_FOREVER)); - -} - -void _SlDrvObjUnLock(_SlLockObj_t *pLockObj) -{ - OSI_RET_OK_CHECK(sl_LockObjUnlock(pLockObj)); - -} - -void _SlDrvProtectionObjUnLock() -{ - OSI_RET_OK_CHECK(sl_LockObjUnlock(&g_pCB->ProtectionLockObj)); -} - - -void _SlDrvMemZero(void* Addr, _u16 size) -{ - sl_Memset(Addr, 0, size); -} - - -void _SlDrvResetCmdExt(_SlCmdExt_t* pCmdExt) -{ - _SlDrvMemZero(pCmdExt, sizeof (_SlCmdExt_t)); -} - - - - diff --git a/drivers/cc3100/src/flowcont.c b/drivers/cc3100/src/flowcont.c deleted file mode 100644 index 889241ea2b..0000000000 --- a/drivers/cc3100/src/flowcont.c +++ /dev/null @@ -1,71 +0,0 @@ -/* - * flowcont.c - CC31xx/CC32xx Host Driver Implementation - * - * Copyright (C) 2014 Texas Instruments Incorporated - http://www.ti.com/ - * - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * - * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the - * distribution. - * - * Neither the name of Texas Instruments Incorporated nor the names of - * its contributors may be used to endorse or promote products derived - * from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * -*/ - - - -/*****************************************************************************/ -/* Include files */ -/*****************************************************************************/ -#include "simplelink.h" -#include "protocol.h" -#include "driver.h" -#include "flowcont.h" - - -/*****************************************************************************/ -/* _SlDrvFlowContInit */ -/*****************************************************************************/ -void _SlDrvFlowContInit(void) -{ - g_pCB->FlowContCB.TxPoolCnt = FLOW_CONT_MIN; - - OSI_RET_OK_CHECK(sl_LockObjCreate(&g_pCB->FlowContCB.TxLockObj, "TxLockObj")); - - OSI_RET_OK_CHECK(sl_SyncObjCreate(&g_pCB->FlowContCB.TxSyncObj, "TxSyncObj")); -} - -/*****************************************************************************/ -/* _SlDrvFlowContDeinit */ -/*****************************************************************************/ -void _SlDrvFlowContDeinit(void) -{ - g_pCB->FlowContCB.TxPoolCnt = 0; - - OSI_RET_OK_CHECK(sl_LockObjDelete(&g_pCB->FlowContCB.TxLockObj)); - - OSI_RET_OK_CHECK(sl_SyncObjDelete(&g_pCB->FlowContCB.TxSyncObj)); -} - diff --git a/drivers/cc3100/src/fs.c b/drivers/cc3100/src/fs.c deleted file mode 100644 index cc2e9987d0..0000000000 --- a/drivers/cc3100/src/fs.c +++ /dev/null @@ -1,424 +0,0 @@ -/* - * fs.c - CC31xx/CC32xx Host Driver Implementation - * - * Copyright (C) 2014 Texas Instruments Incorporated - http://www.ti.com/ - * - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * - * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the - * distribution. - * - * Neither the name of Texas Instruments Incorporated nor the names of - * its contributors may be used to endorse or promote products derived - * from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * -*/ - - - -/*****************************************************************************/ -/* Include files */ -/*****************************************************************************/ -#include "simplelink.h" -#include "protocol.h" -#include "driver.h" - -/*****************************************************************************/ -/* Macro declarations */ -/*****************************************************************************/ -#define sl_min(a,b) (((a) < (b)) ? (a) : (b)) -#define MAX_NVMEM_CHUNK_SIZE 1460 - -/*****************************************************************************/ -/* Internal functions */ -/*****************************************************************************/ - -/*****************************************************************************/ -/* _sl_Strlen */ -/*****************************************************************************/ -_u16 _sl_Strlen(const _u8 *buffer) -{ - _u16 len = 0; - if( buffer != NULL ) - { - while(*buffer++) len++; - } - return len; -} - -/*****************************************************************************/ -/* _sl_GetCreateFsMode */ -/*****************************************************************************/ -_u32 _sl_GetCreateFsMode(_u32 maxSizeInBytes,_u32 accessFlags) -{ - _u32 granIdx = 0; - _u32 granNum = 0; - _u32 granTable[_FS_MAX_MODE_SIZE_GRAN] = {256,1024,4096,16384,65536}; - for(granIdx= _FS_MODE_SIZE_GRAN_256B ;granIdx< _FS_MAX_MODE_SIZE_GRAN;granIdx++) - { - if( granTable[granIdx]*255 >= maxSizeInBytes ) - break; - } - granNum = maxSizeInBytes/granTable[granIdx]; - if( maxSizeInBytes % granTable[granIdx] != 0 ) - granNum++; - - return _FS_MODE(_FS_MODE_OPEN_WRITE_CREATE_IF_NOT_EXIST, granIdx, granNum, accessFlags); -} - -/*****************************************************************************/ -/* API functions */ -/*****************************************************************************/ - -/*****************************************************************************/ -/* sl_FsOpen */ -/*****************************************************************************/ -typedef union -{ - _FsOpenCommand_t Cmd; - _FsOpenResponse_t Rsp; -}_SlFsOpenMsg_u; - - -#if _SL_INCLUDE_FUNC(sl_FsOpen) - -const _SlCmdCtrl_t _SlFsOpenCmdCtrl = -{ - SL_OPCODE_NVMEM_FILEOPEN, - sizeof(_FsOpenCommand_t), - sizeof(_FsOpenResponse_t) -}; - -_i32 sl_FsOpen(const _u8 *pFileName,const _u32 AccessModeAndMaxSize, _u32 *pToken,_i32 *pFileHandle) -{ - _SlReturnVal_t RetVal; - _SlFsOpenMsg_u Msg; - _SlCmdExt_t CmdExt; - - CmdExt.TxPayloadLen = (_sl_Strlen(pFileName)+4) & (~3); /* add 4: 1 for NULL and the 3 for align */ - CmdExt.RxPayloadLen = 0; - CmdExt.pTxPayload = (_u8*)pFileName; - CmdExt.pRxPayload = NULL; - - Msg.Cmd.Mode = AccessModeAndMaxSize; - - if(pToken != NULL) - { - Msg.Cmd.Token = *pToken; - } - else - { - Msg.Cmd.Token = 0; - } - - RetVal = _SlDrvCmdOp((_SlCmdCtrl_t *)&_SlFsOpenCmdCtrl, &Msg, &CmdExt); - *pFileHandle = Msg.Rsp.FileHandle; - if (pToken != NULL) - { - *pToken = Msg.Rsp.Token; - } - - /* in case of an error, return the erros file handler as an error code */ - if( *pFileHandle < 0 ) - { - return *pFileHandle; - } - return (_i32)RetVal; -} -#endif - -/*****************************************************************************/ -/* sl_FsClose */ -/*****************************************************************************/ -typedef union -{ - _FsCloseCommand_t Cmd; - _BasicResponse_t Rsp; -}_SlFsCloseMsg_u; - - -#if _SL_INCLUDE_FUNC(sl_FsClose) - -const _SlCmdCtrl_t _SlFsCloseCmdCtrl = -{ - SL_OPCODE_NVMEM_FILECLOSE, - sizeof(_FsCloseCommand_t), - sizeof(_FsCloseResponse_t) -}; - -_i16 sl_FsClose(const _i32 FileHdl, const _u8* pCeritificateFileName,const _u8* pSignature ,const _u32 SignatureLen) -{ - _SlFsCloseMsg_u Msg = {{0, 0}}; - _SlCmdExt_t ExtCtrl; - - Msg.Cmd.FileHandle = FileHdl; - if( pCeritificateFileName != NULL ) - { - Msg.Cmd.CertificFileNameLength = (_sl_Strlen(pCeritificateFileName)+4) & (~3); /* add 4: 1 for NULL and the 3 for align */ - } - Msg.Cmd.SignatureLen = SignatureLen; - - ExtCtrl.TxPayloadLen = ((SignatureLen+3) & (~3)); /* align */ - ExtCtrl.pTxPayload = (_u8*)pSignature; - ExtCtrl.RxPayloadLen = (_i16)Msg.Cmd.CertificFileNameLength; - ExtCtrl.pRxPayload = (_u8*)pCeritificateFileName; /* Add signature */ - - if(ExtCtrl.pRxPayload != NULL && ExtCtrl.RxPayloadLen != 0) - { - ExtCtrl.RxPayloadLen = ExtCtrl.RxPayloadLen * (-1); - } - - VERIFY_RET_OK(_SlDrvCmdOp((_SlCmdCtrl_t *)&_SlFsCloseCmdCtrl, &Msg, &ExtCtrl)); - - return (_i16)((_i16)Msg.Rsp.status); -} -#endif - - -/*****************************************************************************/ -/* sl_FsRead */ -/*****************************************************************************/ -typedef union -{ - _FsReadCommand_t Cmd; - _FsReadResponse_t Rsp; -}_SlFsReadMsg_u; - -#if _SL_INCLUDE_FUNC(sl_FsRead) - - -const _SlCmdCtrl_t _SlFsReadCmdCtrl = -{ - SL_OPCODE_NVMEM_FILEREADCOMMAND, - sizeof(_FsReadCommand_t), - sizeof(_FsReadResponse_t) -}; - -_i32 sl_FsRead(const _i32 FileHdl,_u32 Offset, _u8* pData,_u32 Len) -{ - _SlFsReadMsg_u Msg; - _SlCmdExt_t ExtCtrl; - _u16 ChunkLen; - _SlReturnVal_t RetVal =0; - _i32 RetCount = 0; - - ExtCtrl.TxPayloadLen = 0; - ExtCtrl.pTxPayload = NULL; - - ChunkLen = (_u16)sl_min(MAX_NVMEM_CHUNK_SIZE,Len); - ExtCtrl.RxPayloadLen = ChunkLen; - ExtCtrl.pRxPayload = (_u8 *)(pData); - Msg.Cmd.Offset = Offset; - Msg.Cmd.Len = ChunkLen; - Msg.Cmd.FileHandle = FileHdl; - do - { - RetVal = _SlDrvCmdOp((_SlCmdCtrl_t *)&_SlFsReadCmdCtrl, &Msg, &ExtCtrl); - if(SL_OS_RET_CODE_OK == RetVal) - { - if( Msg.Rsp.status < 0) - { - if( RetCount > 0) - { - return RetCount; - } - else - { - return Msg.Rsp.status; - } - } - RetCount += (_i32)Msg.Rsp.status; - Len -= ChunkLen; - Offset += ChunkLen; - Msg.Cmd.Offset = Offset; - ExtCtrl.pRxPayload += ChunkLen; - ChunkLen = (_u16)sl_min(MAX_NVMEM_CHUNK_SIZE,Len); - ExtCtrl.RxPayloadLen = ChunkLen; - Msg.Cmd.Len = ChunkLen; - Msg.Cmd.FileHandle = FileHdl; - } - else - { - return RetVal; - } - }while(ChunkLen > 0); - - return (_i32)RetCount; -} -#endif - -/*****************************************************************************/ -/* sl_FsWrite */ -/*****************************************************************************/ -typedef union -{ - _FsWriteCommand_t Cmd; - _FsWriteResponse_t Rsp; -}_SlFsWriteMsg_u; - - -#if _SL_INCLUDE_FUNC(sl_FsWrite) - -const _SlCmdCtrl_t _SlFsWriteCmdCtrl = -{ - SL_OPCODE_NVMEM_FILEWRITECOMMAND, - sizeof(_FsWriteCommand_t), - sizeof(_FsWriteResponse_t) -}; - -_i32 sl_FsWrite(const _i32 FileHdl,_u32 Offset, _u8* pData,_u32 Len) -{ - _SlFsWriteMsg_u Msg; - _SlCmdExt_t ExtCtrl; - _u16 ChunkLen; - _SlReturnVal_t RetVal; - _i32 RetCount = 0; - - ExtCtrl.RxPayloadLen = 0; - ExtCtrl.pRxPayload = NULL; - - ChunkLen = (_u16)sl_min(MAX_NVMEM_CHUNK_SIZE,Len); - ExtCtrl.TxPayloadLen = ChunkLen; - ExtCtrl.pTxPayload = (_u8 *)(pData); - Msg.Cmd.Offset = Offset; - Msg.Cmd.Len = ChunkLen; - Msg.Cmd.FileHandle = FileHdl; - - do - { - - RetVal = _SlDrvCmdOp((_SlCmdCtrl_t *)&_SlFsWriteCmdCtrl, &Msg, &ExtCtrl); - if(SL_OS_RET_CODE_OK == RetVal) - { - if( Msg.Rsp.status < 0) - { - if( RetCount > 0) - { - return RetCount; - } - else - { - return Msg.Rsp.status; - } - } - - RetCount += (_i32)Msg.Rsp.status; - Len -= ChunkLen; - Offset += ChunkLen; - Msg.Cmd.Offset = Offset; - ExtCtrl.pTxPayload += ChunkLen; - ChunkLen = (_u16)sl_min(MAX_NVMEM_CHUNK_SIZE,Len); - ExtCtrl.TxPayloadLen = ChunkLen; - Msg.Cmd.Len = ChunkLen; - Msg.Cmd.FileHandle = FileHdl; - } - else - { - return RetVal; - } - }while(ChunkLen > 0); - - return (_i32)RetCount; -} -#endif - -/*****************************************************************************/ -/* sl_FsGetInfo */ -/*****************************************************************************/ -typedef union -{ - _FsGetInfoCommand_t Cmd; - _FsGetInfoResponse_t Rsp; -}_SlFsGetInfoMsg_u; - - -#if _SL_INCLUDE_FUNC(sl_FsGetInfo) - - -const _SlCmdCtrl_t _SlFsGetInfoCmdCtrl = -{ - SL_OPCODE_NVMEM_FILEGETINFOCOMMAND, - sizeof(_FsGetInfoCommand_t), - sizeof(_FsGetInfoResponse_t) -}; - -_i16 sl_FsGetInfo(const _u8 *pFileName,const _u32 Token,SlFsFileInfo_t* pFsFileInfo) -{ - _SlFsGetInfoMsg_u Msg; - _SlCmdExt_t CmdExt; - - CmdExt.TxPayloadLen = (_sl_Strlen(pFileName)+4) & (~3); /* add 4: 1 for NULL and the 3 for align */ - CmdExt.RxPayloadLen = 0; - CmdExt.pTxPayload = (_u8*)pFileName; - CmdExt.pRxPayload = NULL; - Msg.Cmd.Token = Token; - - VERIFY_RET_OK(_SlDrvCmdOp((_SlCmdCtrl_t *)&_SlFsGetInfoCmdCtrl, &Msg, &CmdExt)); - - pFsFileInfo->flags = Msg.Rsp.flags; - pFsFileInfo->FileLen = Msg.Rsp.FileLen; - pFsFileInfo->AllocatedLen = Msg.Rsp.AllocatedLen; - pFsFileInfo->Token[0] = Msg.Rsp.Token[0]; - pFsFileInfo->Token[1] = Msg.Rsp.Token[1]; - pFsFileInfo->Token[2] = Msg.Rsp.Token[2]; - pFsFileInfo->Token[3] = Msg.Rsp.Token[3]; - return (_i16)((_i16)Msg.Rsp.Status); -} -#endif - -/*****************************************************************************/ -/* sl_FsDel */ -/*****************************************************************************/ -typedef union -{ - _FsDeleteCommand_t Cmd; - _FsDeleteResponse_t Rsp; -}_SlFsDeleteMsg_u; - - -#if _SL_INCLUDE_FUNC(sl_FsDel) - -const _SlCmdCtrl_t _SlFsDeleteCmdCtrl = -{ - SL_OPCODE_NVMEM_FILEDELCOMMAND, - sizeof(_FsDeleteCommand_t), - sizeof(_FsDeleteResponse_t) -}; - -_i16 sl_FsDel(const _u8 *pFileName,const _u32 Token) -{ - _SlFsDeleteMsg_u Msg; - _SlCmdExt_t CmdExt; - - CmdExt.TxPayloadLen = (_sl_Strlen(pFileName)+4) & (~3); /* add 4: 1 for NULL and the 3 for align */ - CmdExt.RxPayloadLen = 0; - CmdExt.pTxPayload = (_u8*)pFileName; - CmdExt.pRxPayload = NULL; - Msg.Cmd.Token = Token; - - - VERIFY_RET_OK(_SlDrvCmdOp((_SlCmdCtrl_t *)&_SlFsDeleteCmdCtrl, &Msg, &CmdExt)); - - return (_i16)((_i16)Msg.Rsp.status); -} -#endif diff --git a/drivers/cc3100/src/netapp.c b/drivers/cc3100/src/netapp.c deleted file mode 100644 index 11bcdefadf..0000000000 --- a/drivers/cc3100/src/netapp.c +++ /dev/null @@ -1,1304 +0,0 @@ -/* - * netapp.c - CC31xx/CC32xx Host Driver Implementation - * - * Copyright (C) 2014 Texas Instruments Incorporated - http://www.ti.com/ - * - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * - * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the - * distribution. - * - * Neither the name of Texas Instruments Incorporated nor the names of - * its contributors may be used to endorse or promote products derived - * from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * -*/ - - - -/*****************************************************************************/ -/* Include files */ -/*****************************************************************************/ -#include "simplelink.h" -#include "protocol.h" -#include "driver.h" - -/*****************************************************************************/ -/* Macro declarations */ -/*****************************************************************************/ -#define NETAPP_MDNS_OPTIONS_ADD_SERVICE_BIT ((_u32)0x1 << 31) - -#ifdef SL_TINY -#define NETAPP_MDNS_MAX_SERVICE_NAME_AND_TEXT_LENGTH 63 -#else -#define NETAPP_MDNS_MAX_SERVICE_NAME_AND_TEXT_LENGTH 255 -#endif - - -/*****************************************************************************/ -/* Functions prototypes */ -/*****************************************************************************/ -void _sl_HandleAsync_DnsGetHostByName(void *pVoidBuf); - -#ifndef SL_TINY_EXT -void _sl_HandleAsync_DnsGetHostByService(void *pVoidBuf); -void _sl_HandleAsync_PingResponse(void *pVoidBuf); -#endif - -void CopyPingResultsToReport(_PingReportResponse_t *pResults,SlPingReport_t *pReport); -_i16 sl_NetAppMDNSRegisterUnregisterService(const _i8* pServiceName, - const _u8 ServiceNameLen, - const _i8* pText, - const _u8 TextLen, - const _u16 Port, - const _u32 TTL, - const _u32 Options); - -#if defined(sl_HttpServerCallback) || defined(EXT_LIB_REGISTERED_HTTP_SERVER_EVENTS) -_u16 _sl_NetAppSendTokenValue(slHttpServerData_t * Token); -#endif -typedef union -{ - _NetAppStartStopCommand_t Cmd; - _NetAppStartStopResponse_t Rsp; -}_SlNetAppStartStopMsg_u; - - -#if _SL_INCLUDE_FUNC(sl_NetAppStart) - -const _SlCmdCtrl_t _SlNetAppStartCtrl = -{ - SL_OPCODE_NETAPP_START_COMMAND, - sizeof(_NetAppStartStopCommand_t), - sizeof(_NetAppStartStopResponse_t) -}; - -_i16 sl_NetAppStart(const _u32 AppBitMap) -{ - _SlNetAppStartStopMsg_u Msg; - Msg.Cmd.appId = AppBitMap; - VERIFY_RET_OK(_SlDrvCmdOp((_SlCmdCtrl_t *)&_SlNetAppStartCtrl, &Msg, NULL)); - - return Msg.Rsp.status; -} -#endif - -/***************************************************************************** - sl_NetAppStop -*****************************************************************************/ -#if _SL_INCLUDE_FUNC(sl_NetAppStop) - - -const _SlCmdCtrl_t _SlNetAppStopCtrl = -{ - SL_OPCODE_NETAPP_STOP_COMMAND, - sizeof(_NetAppStartStopCommand_t), - sizeof(_NetAppStartStopResponse_t) -}; - - - -_i16 sl_NetAppStop(const _u32 AppBitMap) -{ - _SlNetAppStartStopMsg_u Msg; - Msg.Cmd.appId = AppBitMap; - VERIFY_RET_OK(_SlDrvCmdOp((_SlCmdCtrl_t *)&_SlNetAppStopCtrl, &Msg, NULL)); - - return Msg.Rsp.status; -} -#endif - - -/******************************************************************************/ -/* sl_NetAppGetServiceList */ -/******************************************************************************/ -typedef struct -{ - _u8 IndexOffest; - _u8 MaxServiceCount; - _u8 Flags; - _i8 Padding; -}NetappGetServiceListCMD_t; - -typedef union -{ - NetappGetServiceListCMD_t Cmd; - _BasicResponse_t Rsp; -}_SlNetappGetServiceListMsg_u; - - -#if _SL_INCLUDE_FUNC(sl_NetAppGetServiceList) - -const _SlCmdCtrl_t _SlGetServiceListeCtrl = -{ - SL_OPCODE_NETAPP_NETAPP_MDNS_LOOKUP_SERVICE, - sizeof(NetappGetServiceListCMD_t), - sizeof(_BasicResponse_t) -}; - -_i16 sl_NetAppGetServiceList(const _u8 IndexOffest, - const _u8 MaxServiceCount, - const _u8 Flags, - _i8 *pBuffer, - const _u32 RxBufferLength - ) -{ - - _i32 retVal= 0; - _SlNetappGetServiceListMsg_u Msg; - _SlCmdExt_t CmdExt; - _u16 ServiceSize = 0; - _u16 BufferSize = 0; - - /* - Calculate RX pBuffer size - WARNING: - if this size is BufferSize than 1480 error should be returned because there - is no place in the RX packet. - */ - switch(Flags) - { - case SL_NET_APP_FULL_SERVICE_WITH_TEXT_IPV4_TYPE: - ServiceSize = sizeof(SlNetAppGetFullServiceWithTextIpv4List_t); - break; - - case SL_NET_APP_FULL_SERVICE_IPV4_TYPE: - ServiceSize = sizeof(SlNetAppGetFullServiceIpv4List_t); - break; - - case SL_NET_APP_SHORT_SERVICE_IPV4_TYPE: - ServiceSize = sizeof(SlNetAppGetShortServiceIpv4List_t); - break; - - default: - ServiceSize = sizeof(_BasicResponse_t); - break; - } - - - - BufferSize = MaxServiceCount * ServiceSize; - - /*Check the size of the requested services is smaller than size of the user buffer. - If not an error is returned in order to avoid overwriting memory. */ - if(RxBufferLength <= BufferSize) - { - return SL_ERROR_NETAPP_RX_BUFFER_LENGTH_ERROR; - } - - _SlDrvResetCmdExt(&CmdExt); - CmdExt.RxPayloadLen = BufferSize; - CmdExt.pRxPayload = (_u8 *)pBuffer; - - Msg.Cmd.IndexOffest = IndexOffest; - Msg.Cmd.MaxServiceCount = MaxServiceCount; - Msg.Cmd.Flags = Flags; - Msg.Cmd.Padding = 0; - - VERIFY_RET_OK(_SlDrvCmdOp((_SlCmdCtrl_t *)&_SlGetServiceListeCtrl, &Msg, &CmdExt)); - retVal = Msg.Rsp.status; - - return (_i16)retVal; -} - -#endif - -/*****************************************************************************/ -/* sl_mDNSRegisterService */ -/*****************************************************************************/ -/* - * The below struct depicts the constant parameters of the command/API RegisterService. - * - 1. ServiceLen - The length of the service should be smaller than NETAPP_MDNS_MAX_SERVICE_NAME_AND_TEXT_LENGTH. - 2. TextLen - The length of the text should be smaller than NETAPP_MDNS_MAX_SERVICE_NAME_AND_TEXT_LENGTH. - 3. port - The port on this target host. - 4. TTL - The TTL of the service - 5. Options - bitwise parameters: - bit 0 - is unique (means if the service needs to be unique) - bit 31 - for internal use if the service should be added or deleted (set means ADD). - bit 1-30 for future. - - NOTE: - - 1. There are another variable parameter is this API which is the service name and the text. - 2. According to now there is no warning and Async event to user on if the service is a unique. -* - */ - - -typedef struct -{ - _u8 ServiceNameLen; - _u8 TextLen; - _u16 Port; - _u32 TTL; - _u32 Options; -}NetappMdnsSetService_t; - -typedef union -{ - NetappMdnsSetService_t Cmd; - _BasicResponse_t Rsp; -}_SlNetappMdnsRegisterServiceMsg_u; - - -#if _SL_INCLUDE_FUNC(sl_NetAppMDNSRegisterUnregisterService) - -const _SlCmdCtrl_t _SlRegisterServiceCtrl = -{ - SL_OPCODE_NETAPP_MDNSREGISTERSERVICE, - sizeof(NetappMdnsSetService_t), - sizeof(_BasicResponse_t) -}; - -/****************************************************************************** - - sl_NetAppMDNSRegisterService - - CALLER user from its host - - - DESCRIPTION: - Add/delete service - The function manipulates the command that register the service and call - to the NWP in order to add/delete the service to/from the mDNS package and to/from the DB. - - This register service is a service offered by the application. - This unregister service is a service offered by the application before. - - The service name should be full service name according to RFC - of the DNS-SD - means the value in name field in SRV answer. - - Example for service name: - 1. PC1._ipp._tcp.local - 2. PC2_server._ftp._tcp.local - - If the option is_unique is set, mDNS probes the service name to make sure - it is unique before starting to announce the service on the network. - Instance is the instance portion of the service name. - - - - - PARAMETERS: - - The command is from constant parameters and variables parameters. - - Constant parameters are: - - ServiceLen - The length of the service. - TextLen - The length of the service should be smaller than 64. - port - The port on this target host. - TTL - The TTL of the service - Options - bitwise parameters: - bit 0 - is unique (means if the service needs to be unique) - bit 31 - for internal use if the service should be added or deleted (set means ADD). - bit 1-30 for future. - - The variables parameters are: - - Service name(full service name) - The service name. - Example for service name: - 1. PC1._ipp._tcp.local - 2. PC2_server._ftp._tcp.local - - Text - The description of the service. - should be as mentioned in the RFC - (according to type of the service IPP,FTP...) - - NOTE - pay attention - - 1. Temporary - there is an allocation on stack of internal buffer. - Its size is NETAPP_MDNS_MAX_SERVICE_NAME_AND_TEXT_LENGTH. - It means that the sum of the text length and service name length cannot be bigger than - NETAPP_MDNS_MAX_SERVICE_NAME_AND_TEXT_LENGTH. - If it is - An error is returned. - - 2. According to now from certain constraints the variables parameters are set in the - attribute part (contain constant parameters) - - - - RETURNS: Status - the immediate response of the command status. - 0 means success. - - - -******************************************************************************/ -_i16 sl_NetAppMDNSRegisterUnregisterService( const _i8* pServiceName, - const _u8 ServiceNameLen, - const _i8* pText, - const _u8 TextLen, - const _u16 Port, - const _u32 TTL, - const _u32 Options) - -{ - _SlNetappMdnsRegisterServiceMsg_u Msg; - _SlCmdExt_t CmdExt ; - _i8 ServiceNameAndTextBuffer[NETAPP_MDNS_MAX_SERVICE_NAME_AND_TEXT_LENGTH]; - _i8 *TextPtr; - - /* - - NOTE - pay attention - - 1. Temporary - there is an allocation on stack of internal buffer. - Its size is NETAPP_MDNS_MAX_SERVICE_NAME_AND_TEXT_LENGTH. - It means that the sum of the text length and service name length cannot be bigger than - NETAPP_MDNS_MAX_SERVICE_NAME_AND_TEXT_LENGTH. - If it is - An error is returned. - - 2. According to now from certain constraints the variables parameters are set in the - attribute part (contain constant parameters) - - - */ - - /*build the attribute part of the command. - It contains the constant parameters of the command*/ - - Msg.Cmd.ServiceNameLen = ServiceNameLen; - Msg.Cmd.Options = Options; - Msg.Cmd.Port = Port; - Msg.Cmd.TextLen = TextLen; - Msg.Cmd.TTL = TTL; - - /*Build the payload part of the command - Copy the service name and text to one buffer. - NOTE - pay attention - The size of the service length + the text length should be smaller than 255, - Until the simplelink drive supports to variable length through SPI command. */ - if(TextLen + ServiceNameLen > (NETAPP_MDNS_MAX_SERVICE_NAME_AND_TEXT_LENGTH - 1 )) /*-1 is for giving a place to set null termination at the end of the text*/ - { - return -1; - } - - _SlDrvMemZero(ServiceNameAndTextBuffer, NETAPP_MDNS_MAX_SERVICE_NAME_AND_TEXT_LENGTH); - - - /*Copy the service name*/ - sl_Memcpy(ServiceNameAndTextBuffer, - pServiceName, - ServiceNameLen); - - if(TextLen > 0 ) - { - - TextPtr = &ServiceNameAndTextBuffer[ServiceNameLen]; - /*Copy the text just after the service name*/ - sl_Memcpy(TextPtr, - pText, - TextLen); - - - } - - _SlDrvResetCmdExt(&CmdExt); - CmdExt.TxPayloadLen = (TextLen + ServiceNameLen); - CmdExt.pTxPayload = (_u8 *)ServiceNameAndTextBuffer; - - - VERIFY_RET_OK(_SlDrvCmdOp((_SlCmdCtrl_t *)&_SlRegisterServiceCtrl, &Msg, &CmdExt)); - - return (_i16)Msg.Rsp.status; - - -} -#endif - -/**********************************************************************************************/ -#if _SL_INCLUDE_FUNC(sl_NetAppMDNSRegisterService) - -_i16 sl_NetAppMDNSRegisterService( const _i8* pServiceName, - const _u8 ServiceNameLen, - const _i8* pText, - const _u8 TextLen, - const _u16 Port, - const _u32 TTL, - _u32 Options) - -{ - - /* - - NOTE - pay attention - - 1. Temporary - there is an allocation on stack of internal buffer. - Its size is NETAPP_MDNS_MAX_SERVICE_NAME_AND_TEXT_LENGTH. - It means that the sum of the text length and service name length cannot be bigger than - NETAPP_MDNS_MAX_SERVICE_NAME_AND_TEXT_LENGTH. - If it is - An error is returned. - - 2. According to now from certain constraints the variables parameters are set in the - attribute part (contain constant parameters) - - */ - - /*Set the add service bit in the options parameter. - In order not use different opcodes for the register service and unregister service - bit 31 in option is taken for this purpose. if it is set it means in NWP that the service should be added - if it is cleared it means that the service should be deleted and there is only meaning to pServiceName - and ServiceNameLen values. */ - Options |= NETAPP_MDNS_OPTIONS_ADD_SERVICE_BIT; - - return sl_NetAppMDNSRegisterUnregisterService( pServiceName, - ServiceNameLen, - pText, - TextLen, - Port, - TTL, - Options); - - -} -#endif -/**********************************************************************************************/ - - - -/**********************************************************************************************/ -#if _SL_INCLUDE_FUNC(sl_NetAppMDNSUnRegisterService) - -_i16 sl_NetAppMDNSUnRegisterService( const _i8* pServiceName, - const _u8 ServiceNameLen) - - -{ - _u32 Options = 0; - - /* - - NOTE - pay attention - - The size of the service length should be smaller than 255, - Until the simplelink drive supports to variable length through SPI command. - - - */ - - /*Clear the add service bit in the options parameter. - In order not use different opcodes for the register service and unregister service - bit 31 in option is taken for this purpose. if it is set it means in NWP that the service should be added - if it is cleared it means that the service should be deleted and there is only meaning to pServiceName - and ServiceNameLen values.*/ - - Options &= (~NETAPP_MDNS_OPTIONS_ADD_SERVICE_BIT); - - return sl_NetAppMDNSRegisterUnregisterService( pServiceName, - ServiceNameLen, - NULL, - 0, - 0, - 0, - Options); - - -} -#endif -/**********************************************************************************************/ - - - -/*****************************************************************************/ -/* sl_DnsGetHostByService */ -/*****************************************************************************/ -/* - * The below struct depicts the constant parameters of the command/API sl_DnsGetHostByService. - * - 1. ServiceLen - The length of the service should be smaller than 255. - 2. AddrLen - TIPv4 or IPv6 (SL_AF_INET , SL_AF_INET6). -* - */ - -typedef struct -{ - _u8 ServiceLen; - _u8 AddrLen; - _u16 Padding; -}_GetHostByServiceCommand_t; - - - -/* - * The below structure depict the constant parameters that are returned in the Async event answer - * according to command/API sl_DnsGetHostByService for IPv4 and IPv6. - * - 1Status - The status of the response. - 2.Address - Contains the IP address of the service. - 3.Port - Contains the port of the service. - 4.TextLen - Contains the max length of the text that the user wants to get. - it means that if the test of service is bigger that its value than - the text is cut to inout_TextLen value. - Output: Contain the length of the text that is returned. Can be full text or part - of the text (see above). - -* - */ -typedef struct -{ - _u16 Status; - _u16 TextLen; - _u32 Port; - _u32 Address; -}_GetHostByServiceIPv4AsyncResponse_t; - - -typedef struct -{ - _u16 Status; - _u16 TextLen; - _u32 Port; - _u32 Address[4]; -}_GetHostByServiceIPv6AsyncResponse_t; - - -typedef union -{ - _GetHostByServiceIPv4AsyncResponse_t IpV4; - _GetHostByServiceIPv6AsyncResponse_t IpV6; -}_GetHostByServiceAsyncResponseAttribute_u; - -/* - * The below struct contains pointers to the output parameters that the user gives - * - */ -typedef struct -{ - _i16 Status; - _u32 *out_pAddr; - _u32 *out_pPort; - _u16 *inout_TextLen; /* in: max len , out: actual len */ - _i8 *out_pText; -}_GetHostByServiceAsyncResponse_t; - - -typedef union -{ - _GetHostByServiceCommand_t Cmd; - _BasicResponse_t Rsp; -}_SlGetHostByServiceMsg_u; - - -#if _SL_INCLUDE_FUNC(sl_NetAppDnsGetHostByService) - -const _SlCmdCtrl_t _SlGetHostByServiceCtrl = -{ - SL_OPCODE_NETAPP_MDNSGETHOSTBYSERVICE, - sizeof(_GetHostByServiceCommand_t), - sizeof(_BasicResponse_t) -}; - -/******************************************************************************/ - -_i32 sl_NetAppDnsGetHostByService(_i8 *pServiceName, /* string containing all (or only part): name + subtype + service */ - const _u8 ServiceLen, - const _u8 Family, /* 4-IPv4 , 16-IPv6 */ - _u32 pAddr[], - _u32 *pPort, - _u16 *pTextLen, /* in: max len , out: actual len */ - _i8 *pText - ) -{ - _SlGetHostByServiceMsg_u Msg; - _SlCmdExt_t CmdExt ; - _GetHostByServiceAsyncResponse_t AsyncRsp; - _u8 ObjIdx = MAX_CONCURRENT_ACTIONS; - -/* - Note: - 1. The return's attributes are belonged to first service that is found. - It can be other services with the same service name will response to - the query. The results of these responses are saved in the peer cache of the NWP, and - should be read by another API. - - 2. Text length can be 120 bytes only - not more - It is because of constraints in the NWP on the buffer that is allocated for the Async event. - - 3.The API waits to Async event by blocking. It means that the API is finished only after an Async event - is sent by the NWP. - - 4.No rolling option!!! - only PTR type is sent. - - -*/ - /*build the attribute part of the command. - It contains the constant parameters of the command */ - - Msg.Cmd.ServiceLen = ServiceLen; - Msg.Cmd.AddrLen = Family; - - /*Build the payload part of the command - Copy the service name and text to one buffer.*/ - - _SlDrvResetCmdExt(&CmdExt); - CmdExt.TxPayloadLen = ServiceLen; - CmdExt.pTxPayload = (_u8 *)pServiceName; - - /*set pointers to the output parameters (the returned parameters). - This pointers are belonged to local struct that is set to global Async response parameter. - It is done in order not to run more than one sl_DnsGetHostByService at the same time. - The API should be run only if global parameter is pointed to NULL. */ - AsyncRsp.out_pText = pText; - AsyncRsp.inout_TextLen = (_u16* )pTextLen; - AsyncRsp.out_pPort = pPort; - AsyncRsp.out_pAddr = (_u32 *)pAddr; - - - ObjIdx = _SlDrvProtectAsyncRespSetting((_u8*)&AsyncRsp, GETHOSYBYSERVICE_ID, SL_MAX_SOCKETS); - - if (MAX_CONCURRENT_ACTIONS == ObjIdx) - { - return SL_POOL_IS_EMPTY; - } - - - if (SL_AF_INET6 == Family) - { - g_pCB->ObjPool[ObjIdx].AdditionalData |= SL_NETAPP_FAMILY_MASK; - } - /* Send the command */ - VERIFY_RET_OK(_SlDrvCmdOp((_SlCmdCtrl_t *)&_SlGetHostByServiceCtrl, &Msg, &CmdExt)); - - - - /* If the immediate reponse is O.K. than wait for aSYNC event response. */ - if(SL_RET_CODE_OK == Msg.Rsp.status) - { - _SlDrvSyncObjWaitForever(&g_pCB->ObjPool[ObjIdx].SyncObj); - - /* If we are - it means that Async event was sent. - The results are copied in the Async handle return functions */ - - Msg.Rsp.status = AsyncRsp.Status; - } - - _SlDrvReleasePoolObj(ObjIdx); - return Msg.Rsp.status; -} -#endif - -/******************************************************************************/ - -/****************************************************************************** - _sl_HandleAsync_DnsGetHostByService - - CALLER NWP - Async event on sl_DnsGetHostByService with IPv4 Family - - - DESCRIPTION: - - Async event on sl_DnsGetHostByService command with IPv4 Family. - Return service attributes like IP address, port and text according to service name. - The user sets a service name Full/Part (see example below), and should get the: - 1. IP of the service - 2. The port of service. - 3. The text of service. - - Hence it can make a connection to the specific service and use it. - It is similar to get host by name method. - - It is done by a single shot query with PTR type on the service name. - - - - Note: - 1. The return's attributes are belonged to first service that is found. - It can be other services with the same service name will response to - the query. The results of these responses are saved in the peer cache of the NWP, and - should be read by another API. - - - PARAMETERS: - - pVoidBuf - is point to opcode of the event. - it contains the outputs that are given to the user - - outputs description: - - 1.out_pAddr[] - output: Contain the IP address of the service. - 2.out_pPort - output: Contain the port of the service. - 3.inout_TextLen - Input: Contain the max length of the text that the user wants to get. - it means that if the test of service is bigger that its value than - the text is cut to inout_TextLen value. - Output: Contain the length of the text that is returned. Can be full text or part - of the text (see above). - - 4.out_pText - Contain the text of the service (full or part see above- inout_TextLen description). - - * - - - RETURNS: success or fail. - - - - - -******************************************************************************/ -#ifndef SL_TINY_EXT -void _sl_HandleAsync_DnsGetHostByService(void *pVoidBuf) -{ - - _GetHostByServiceAsyncResponse_t* Res; - _u16 TextLen; - _u16 UserTextLen; - - - /*pVoidBuf - is point to opcode of the event.*/ - - /*set pMsgArgs to point to the attribute of the event.*/ - _GetHostByServiceIPv4AsyncResponse_t *pMsgArgs = (_GetHostByServiceIPv4AsyncResponse_t *)_SL_RESP_ARGS_START(pVoidBuf); - - VERIFY_SOCKET_CB(NULL != g_pCB->ObjPool[g_pCB->FunctionParams.AsyncExt.ActionIndex].pRespArgs); - - /*IPv6*/ - if(g_pCB->ObjPool[g_pCB->FunctionParams.AsyncExt.ActionIndex].AdditionalData & SL_NETAPP_FAMILY_MASK) - { - return; - } - /*IPv4*/ - else - { - /************************************************************************************************* - - 1. Copy the attribute part of the evnt to the attribute part of the response - sl_Memcpy(g_pCB->GetHostByServiceCB.pAsyncRsp, pMsgArgs, sizeof(_GetHostByServiceIPv4AsyncResponse_t)); - - set to TextLen the text length of the service.*/ - TextLen = pMsgArgs->TextLen; - - /*Res pointed to mDNS global object struct */ - Res = (_GetHostByServiceAsyncResponse_t*)g_pCB->ObjPool[g_pCB->FunctionParams.AsyncExt.ActionIndex].pRespArgs; - - - - /*It is 4 bytes so we avoid from memcpy*/ - Res->out_pAddr[0] = pMsgArgs->Address; - Res->out_pPort[0] = pMsgArgs->Port; - Res->Status = pMsgArgs->Status; - - /*set to TextLen the text length of the user (input fromthe user).*/ - UserTextLen = Res->inout_TextLen[0]; - - /*Cut the service text if the user requested for smaller text.*/ - UserTextLen = (TextLen <= UserTextLen) ? TextLen : UserTextLen; - Res->inout_TextLen[0] = UserTextLen ; - - /************************************************************************************************** - - 2. Copy the payload part of the evnt (the text) to the payload part of the response - the lenght of the copy is according to the text length in the attribute part. */ - - - sl_Memcpy(Res->out_pText , - (_i8 *)(& pMsgArgs[1]) , /* & pMsgArgs[1] -> 1st byte after the fixed header = 1st byte of variable text.*/ - UserTextLen ); - - - /**************************************************************************************************/ - - _SlDrvSyncObjSignal(&g_pCB->ObjPool[g_pCB->FunctionParams.AsyncExt.ActionIndex].SyncObj); - return; - } -} - -/*****************************************************************************/ -/* _sl_HandleAsync_DnsGetHostByAddr */ -/*****************************************************************************/ -void _sl_HandleAsync_DnsGetHostByAddr(void *pVoidBuf) -{ - SL_TRACE0(DBG_MSG, MSG_303, "STUB: _sl_HandleAsync_DnsGetHostByAddr not implemented yet!"); - return; -} -#endif - -/*****************************************************************************/ -/* sl_DnsGetHostByName */ -/*****************************************************************************/ -typedef union -{ - _GetHostByNameIPv4AsyncResponse_t IpV4; - _GetHostByNameIPv6AsyncResponse_t IpV6; -}_GetHostByNameAsyncResponse_u; - -typedef union -{ - _GetHostByNameCommand_t Cmd; - _BasicResponse_t Rsp; -}_SlGetHostByNameMsg_u; - - -#if _SL_INCLUDE_FUNC(sl_NetAppDnsGetHostByName) -const _SlCmdCtrl_t _SlGetHostByNameCtrl = -{ - SL_OPCODE_NETAPP_DNSGETHOSTBYNAME, - sizeof(_GetHostByNameCommand_t), - sizeof(_BasicResponse_t) -}; - -_i16 sl_NetAppDnsGetHostByName(_i8 * hostname,const _u16 usNameLen, _u32* out_ip_addr,const _u8 family) -{ - _SlGetHostByNameMsg_u Msg; - _SlCmdExt_t ExtCtrl; - _GetHostByNameAsyncResponse_u AsyncRsp; - _u8 ObjIdx = MAX_CONCURRENT_ACTIONS; - - - _SlDrvResetCmdExt(&ExtCtrl); - ExtCtrl.TxPayloadLen = usNameLen; - ExtCtrl.pTxPayload = (_u8 *)hostname; - - Msg.Cmd.Len = usNameLen; - Msg.Cmd.family = family; - - /*Use Obj to issue the command, if not available try later */ - ObjIdx = (_u8)_SlDrvWaitForPoolObj(GETHOSYBYNAME_ID,SL_MAX_SOCKETS); - if (MAX_CONCURRENT_ACTIONS == ObjIdx) - { - return SL_POOL_IS_EMPTY; - } - - _SlDrvProtectionObjLockWaitForever(); - - g_pCB->ObjPool[ObjIdx].pRespArgs = (_u8 *)&AsyncRsp; - /*set bit to indicate IPv6 address is expected */ - if (SL_AF_INET6 == family) - { - g_pCB->ObjPool[ObjIdx].AdditionalData |= SL_NETAPP_FAMILY_MASK; - } - - _SlDrvProtectionObjUnLock(); - - VERIFY_RET_OK(_SlDrvCmdOp((_SlCmdCtrl_t *)&_SlGetHostByNameCtrl, &Msg, &ExtCtrl)); - - if(SL_RET_CODE_OK == Msg.Rsp.status) - { - _SlDrvSyncObjWaitForever(&g_pCB->ObjPool[ObjIdx].SyncObj); - - Msg.Rsp.status = AsyncRsp.IpV4.status; - - if(SL_OS_RET_CODE_OK == (_i16)Msg.Rsp.status) - { - sl_Memcpy((_i8 *)out_ip_addr, - (_i8 *)&AsyncRsp.IpV4.ip0, - (SL_AF_INET == family) ? SL_IPV4_ADDRESS_SIZE : SL_IPV6_ADDRESS_SIZE); - } - } - _SlDrvReleasePoolObj(ObjIdx); - return Msg.Rsp.status; -} -#endif - - -/******************************************************************************/ -/* _sl_HandleAsync_DnsGetHostByName */ -/******************************************************************************/ -void _sl_HandleAsync_DnsGetHostByName(void *pVoidBuf) -{ - _GetHostByNameIPv4AsyncResponse_t *pMsgArgs = (_GetHostByNameIPv4AsyncResponse_t *)_SL_RESP_ARGS_START(pVoidBuf); - - _SlDrvProtectionObjLockWaitForever(); - - VERIFY_SOCKET_CB(NULL != g_pCB->ObjPool[g_pCB->FunctionParams.AsyncExt.ActionIndex].pRespArgs); - - /*IPv6 */ - if(g_pCB->ObjPool[g_pCB->FunctionParams.AsyncExt.ActionIndex].AdditionalData & SL_NETAPP_FAMILY_MASK) - { - sl_Memcpy(g_pCB->ObjPool[g_pCB->FunctionParams.AsyncExt.ActionIndex].pRespArgs, pMsgArgs, sizeof(_GetHostByNameIPv6AsyncResponse_t)); - } - /*IPv4 */ - else - { - sl_Memcpy(g_pCB->ObjPool[g_pCB->FunctionParams.AsyncExt.ActionIndex].pRespArgs, pMsgArgs, sizeof(_GetHostByNameIPv4AsyncResponse_t)); - } - _SlDrvSyncObjSignal(&g_pCB->ObjPool[g_pCB->FunctionParams.AsyncExt.ActionIndex].SyncObj); - _SlDrvProtectionObjUnLock(); - return; -} - - -#ifndef SL_TINY_EXT -void CopyPingResultsToReport(_PingReportResponse_t *pResults,SlPingReport_t *pReport) -{ - pReport->PacketsSent = pResults->numSendsPings; - pReport->PacketsReceived = pResults->numSuccsessPings; - pReport->MinRoundTime = pResults->rttMin; - pReport->MaxRoundTime = pResults->rttMax; - pReport->AvgRoundTime = pResults->rttAvg; - pReport->TestTime = pResults->testTime; -} - -/*****************************************************************************/ -/* _sl_HandleAsync_PingResponse */ -/*****************************************************************************/ -void _sl_HandleAsync_PingResponse(void *pVoidBuf) -{ - _PingReportResponse_t *pMsgArgs = (_PingReportResponse_t *)_SL_RESP_ARGS_START(pVoidBuf); - SlPingReport_t pingReport; - - if(pPingCallBackFunc) - { - CopyPingResultsToReport(pMsgArgs,&pingReport); - pPingCallBackFunc(&pingReport); - } - else - { - - _SlDrvProtectionObjLockWaitForever(); - - VERIFY_SOCKET_CB(NULL != g_pCB->PingCB.PingAsync.pAsyncRsp); - - if (NULL != g_pCB->ObjPool[g_pCB->FunctionParams.AsyncExt.ActionIndex].pRespArgs) - { - sl_Memcpy(g_pCB->ObjPool[g_pCB->FunctionParams.AsyncExt.ActionIndex].pRespArgs, pMsgArgs, sizeof(_PingReportResponse_t)); - _SlDrvSyncObjSignal(&g_pCB->ObjPool[g_pCB->FunctionParams.AsyncExt.ActionIndex].SyncObj); - } - _SlDrvProtectionObjUnLock(); - } - return; -} -#endif - -/*****************************************************************************/ -/* sl_PingStart */ -/*****************************************************************************/ -typedef union -{ - _PingStartCommand_t Cmd; - _PingReportResponse_t Rsp; -}_SlPingStartMsg_u; - - -typedef enum -{ - CMD_PING_TEST_RUNNING = 0, - CMD_PING_TEST_STOPPED -}_SlPingStatus_e; - - -#if _SL_INCLUDE_FUNC(sl_NetAppPingStart) -_i16 sl_NetAppPingStart(const SlPingStartCommand_t* pPingParams,const _u8 family,SlPingReport_t *pReport,const P_SL_DEV_PING_CALLBACK pPingCallback) -{ - _SlCmdCtrl_t CmdCtrl = {0, sizeof(_PingStartCommand_t), sizeof(_BasicResponse_t)}; - _SlPingStartMsg_u Msg; - _PingReportResponse_t PingRsp; - _u8 ObjIdx = MAX_CONCURRENT_ACTIONS; - - if( 0 == pPingParams->Ip ) - {/* stop any ongoing ping */ - return _SlDrvBasicCmd(SL_OPCODE_NETAPP_PINGSTOP); - } - - if(SL_AF_INET == family) - { - CmdCtrl.Opcode = SL_OPCODE_NETAPP_PINGSTART; - sl_Memcpy(&Msg.Cmd.ip0, &pPingParams->Ip, SL_IPV4_ADDRESS_SIZE); - } - else - { - CmdCtrl.Opcode = SL_OPCODE_NETAPP_PINGSTART_V6; - sl_Memcpy(&Msg.Cmd.ip0, &pPingParams->Ip, SL_IPV6_ADDRESS_SIZE); - } - - Msg.Cmd.pingIntervalTime = pPingParams->PingIntervalTime; - Msg.Cmd.PingSize = pPingParams->PingSize; - Msg.Cmd.pingRequestTimeout = pPingParams->PingRequestTimeout; - Msg.Cmd.totalNumberOfAttempts = pPingParams->TotalNumberOfAttempts; - Msg.Cmd.flags = pPingParams->Flags; - - - if( pPingCallback ) - { - pPingCallBackFunc = pPingCallback; - } - else - { - /*Use Obj to issue the command, if not available try later */ - ObjIdx = (_u8)_SlDrvWaitForPoolObj(PING_ID,SL_MAX_SOCKETS); - if (MAX_CONCURRENT_ACTIONS == ObjIdx) - { - return SL_POOL_IS_EMPTY; - } - OSI_RET_OK_CHECK(sl_LockObjLock(&g_pCB->ProtectionLockObj, SL_OS_WAIT_FOREVER)); - /* async response handler for non callback mode */ - g_pCB->ObjPool[ObjIdx].pRespArgs = (_u8 *)&PingRsp; - pPingCallBackFunc = NULL; - OSI_RET_OK_CHECK(sl_LockObjUnlock(&g_pCB->ProtectionLockObj)); - } - - - VERIFY_RET_OK(_SlDrvCmdOp(&CmdCtrl, &Msg, NULL)); - /*send the command*/ - if(CMD_PING_TEST_RUNNING == (_i16)Msg.Rsp.status || CMD_PING_TEST_STOPPED == (_i16)Msg.Rsp.status ) - { - /* block waiting for results if no callback function is used */ - if( NULL == pPingCallback ) - { - _SlDrvSyncObjWaitForever(&g_pCB->ObjPool[ObjIdx].SyncObj); - - if( SL_OS_RET_CODE_OK == (_i16)PingRsp.status ) - { - CopyPingResultsToReport(&PingRsp,pReport); - } - _SlDrvReleasePoolObj(ObjIdx); - } - } - else - { /* ping failure, no async response */ - if( NULL == pPingCallback ) - { - _SlDrvReleasePoolObj(ObjIdx); - } - } - - return Msg.Rsp.status; -} -#endif - -/*****************************************************************************/ -/* sl_NetAppSet */ -/*****************************************************************************/ -typedef union -{ - _NetAppSetGet_t Cmd; - _BasicResponse_t Rsp; -}_SlNetAppMsgSet_u; - - -#if _SL_INCLUDE_FUNC(sl_NetAppSet) - -const _SlCmdCtrl_t _SlNetAppSetCmdCtrl = -{ - SL_OPCODE_NETAPP_NETAPPSET, - sizeof(_NetAppSetGet_t), - sizeof(_BasicResponse_t) -}; - -_i32 sl_NetAppSet(const _u8 AppId ,const _u8 Option,const _u8 OptionLen,const _u8 *pOptionValue) -{ - _SlNetAppMsgSet_u Msg; - _SlCmdExt_t CmdExt; - - - _SlDrvResetCmdExt(&CmdExt); - CmdExt.TxPayloadLen = (OptionLen+3) & (~3); - CmdExt.pTxPayload = (_u8 *)pOptionValue; - - - Msg.Cmd.AppId = AppId; - Msg.Cmd.ConfigLen = OptionLen; - Msg.Cmd.ConfigOpt = Option; - - VERIFY_RET_OK(_SlDrvCmdOp((_SlCmdCtrl_t *)&_SlNetAppSetCmdCtrl, &Msg, &CmdExt)); - - return (_i16)Msg.Rsp.status; -} -#endif - -/*****************************************************************************/ -/* sl_NetAppSendTokenValue */ -/*****************************************************************************/ -typedef union -{ - sl_NetAppHttpServerSendToken_t Cmd; - _BasicResponse_t Rsp; -}_SlNetAppMsgSendTokenValue_u; - - - -#if defined(sl_HttpServerCallback) || defined(EXT_LIB_REGISTERED_HTTP_SERVER_EVENTS) -const _SlCmdCtrl_t _SlNetAppSendTokenValueCmdCtrl = -{ - SL_OPCODE_NETAPP_HTTPSENDTOKENVALUE, - sizeof(sl_NetAppHttpServerSendToken_t), - sizeof(_BasicResponse_t) -}; - -_u16 _sl_NetAppSendTokenValue(slHttpServerData_t * Token_value) -{ - _SlNetAppMsgSendTokenValue_u Msg; - _SlCmdExt_t CmdExt; - - CmdExt.TxPayloadLen = (Token_value->value_len+3) & (~3); - CmdExt.RxPayloadLen = 0; - CmdExt.pTxPayload = (_u8 *) Token_value->token_value; - CmdExt.pRxPayload = NULL; - - Msg.Cmd.token_value_len = Token_value->value_len; - Msg.Cmd.token_name_len = Token_value->name_len; - sl_Memcpy(&Msg.Cmd.token_name[0], Token_value->token_name, Token_value->name_len); - - - VERIFY_RET_OK(_SlDrvCmdSend((_SlCmdCtrl_t *)&_SlNetAppSendTokenValueCmdCtrl, &Msg, &CmdExt)); - - return Msg.Rsp.status; -} -#endif - - -/*****************************************************************************/ -/* sl_NetAppGet */ -/*****************************************************************************/ -typedef union -{ - _NetAppSetGet_t Cmd; - _NetAppSetGet_t Rsp; -}_SlNetAppMsgGet_u; - - -#if _SL_INCLUDE_FUNC(sl_NetAppGet) -const _SlCmdCtrl_t _SlNetAppGetCmdCtrl = -{ - SL_OPCODE_NETAPP_NETAPPGET, - sizeof(_NetAppSetGet_t), - sizeof(_NetAppSetGet_t) -}; - -_i32 sl_NetAppGet(const _u8 AppId,const _u8 Option,_u8 *pOptionLen, _u8 *pOptionValue) -{ - _SlNetAppMsgGet_u Msg; - _SlCmdExt_t CmdExt; - - if (*pOptionLen == 0) - { - return SL_EZEROLEN; - } - - _SlDrvResetCmdExt(&CmdExt); - CmdExt.RxPayloadLen = *pOptionLen; - CmdExt.pRxPayload = (_u8 *)pOptionValue; - - Msg.Cmd.AppId = AppId; - Msg.Cmd.ConfigOpt = Option; - VERIFY_RET_OK(_SlDrvCmdOp((_SlCmdCtrl_t *)&_SlNetAppGetCmdCtrl, &Msg, &CmdExt)); - - - if (CmdExt.RxPayloadLen < CmdExt.ActualRxPayloadLen) - { - *pOptionLen = (_u8)CmdExt.RxPayloadLen; - return SL_ESMALLBUF; - } - else - { - *pOptionLen = (_u8)CmdExt.ActualRxPayloadLen; - } - - return (_i16)Msg.Rsp.Status; -} -#endif - - -/*****************************************************************************/ -/* _SlDrvNetAppEventHandler */ -/*****************************************************************************/ -void _SlDrvNetAppEventHandler(void* pArgs) -{ - _SlResponseHeader_t *pHdr = (_SlResponseHeader_t *)pArgs; -#if defined(sl_HttpServerCallback) || defined(EXT_LIB_REGISTERED_HTTP_SERVER_EVENTS) - SlHttpServerEvent_t httpServerEvent; - SlHttpServerResponse_t httpServerResponse; -#endif - - switch(pHdr->GenHeader.Opcode) - { - case SL_OPCODE_NETAPP_DNSGETHOSTBYNAMEASYNCRESPONSE: - case SL_OPCODE_NETAPP_DNSGETHOSTBYNAMEASYNCRESPONSE_V6: - _sl_HandleAsync_DnsGetHostByName(pArgs); - break; -#ifndef SL_TINY_EXT - case SL_OPCODE_NETAPP_MDNSGETHOSTBYSERVICEASYNCRESPONSE: - case SL_OPCODE_NETAPP_MDNSGETHOSTBYSERVICEASYNCRESPONSE_V6: - _sl_HandleAsync_DnsGetHostByService(pArgs); - break; - case SL_OPCODE_NETAPP_PINGREPORTREQUESTRESPONSE: - _sl_HandleAsync_PingResponse(pArgs); - break; -#endif - -#if defined(sl_HttpServerCallback) || defined(EXT_LIB_REGISTERED_HTTP_SERVER_EVENTS) - case SL_OPCODE_NETAPP_HTTPGETTOKENVALUE: - { - _u8 *pTokenName; - slHttpServerData_t Token_value; - sl_NetAppHttpServerGetToken_t *httpGetToken = (sl_NetAppHttpServerGetToken_t *)_SL_RESP_ARGS_START(pHdr); - pTokenName = (_u8 *)((sl_NetAppHttpServerGetToken_t *)httpGetToken + 1); - - httpServerResponse.Response = SL_NETAPP_HTTPSETTOKENVALUE; - httpServerResponse.ResponseData.token_value.len = MAX_TOKEN_VALUE_LEN; - - /* Reuse the async buffer for getting the token value response from the user */ - httpServerResponse.ResponseData.token_value.data = (_u8 *)_SL_RESP_ARGS_START(pHdr) + MAX_TOKEN_NAME_LEN; - - httpServerEvent.Event = SL_NETAPP_HTTPGETTOKENVALUE_EVENT; - httpServerEvent.EventData.httpTokenName.len = httpGetToken->token_name_len; - httpServerEvent.EventData.httpTokenName.data = pTokenName; - - Token_value.token_name = pTokenName; - - _SlDrvHandleHttpServerEvents (&httpServerEvent, &httpServerResponse); - - Token_value.value_len = httpServerResponse.ResponseData.token_value.len; - Token_value.name_len = httpServerEvent.EventData.httpTokenName.len; - Token_value.token_value = httpServerResponse.ResponseData.token_value.data; - - - _sl_NetAppSendTokenValue(&Token_value); - } - break; - - case SL_OPCODE_NETAPP_HTTPPOSTTOKENVALUE: - { - _u8 *pPostParams; - - sl_NetAppHttpServerPostToken_t *httpPostTokenArgs = (sl_NetAppHttpServerPostToken_t *)_SL_RESP_ARGS_START(pHdr); - pPostParams = (_u8 *)((sl_NetAppHttpServerPostToken_t *)httpPostTokenArgs + 1); - - httpServerEvent.Event = SL_NETAPP_HTTPPOSTTOKENVALUE_EVENT; - - httpServerEvent.EventData.httpPostData.action.len = httpPostTokenArgs->post_action_len; - httpServerEvent.EventData.httpPostData.action.data = pPostParams; - pPostParams+=httpPostTokenArgs->post_action_len; - - httpServerEvent.EventData.httpPostData.token_name.len = httpPostTokenArgs->token_name_len; - httpServerEvent.EventData.httpPostData.token_name.data = pPostParams; - pPostParams+=httpPostTokenArgs->token_name_len; - - httpServerEvent.EventData.httpPostData.token_value.len = httpPostTokenArgs->token_value_len; - httpServerEvent.EventData.httpPostData.token_value.data = pPostParams; - - httpServerResponse.Response = SL_NETAPP_RESPONSE_NONE; - - _SlDrvHandleHttpServerEvents (&httpServerEvent, &httpServerResponse); - - } - break; -#endif - - - default: - SL_ERROR_TRACE2(MSG_305, "ASSERT: _SlDrvNetAppEventHandler : invalid opcode = 0x%x = %1", pHdr->GenHeader.Opcode, pHdr->GenHeader.Opcode); - VERIFY_PROTOCOL(0); - } -} - diff --git a/drivers/cc3100/src/netcfg.c b/drivers/cc3100/src/netcfg.c deleted file mode 100644 index 3674e0720e..0000000000 --- a/drivers/cc3100/src/netcfg.c +++ /dev/null @@ -1,150 +0,0 @@ -/* -* netcfg.c - CC31xx/CC32xx Host Driver Implementation -* -* Copyright (C) 2014 Texas Instruments Incorporated - http://www.ti.com/ -* -* -* Redistribution and use in source and binary forms, with or without -* modification, are permitted provided that the following conditions -* are met: -* -* Redistributions of source code must retain the above copyright -* notice, this list of conditions and the following disclaimer. -* -* Redistributions in binary form must reproduce the above copyright -* notice, this list of conditions and the following disclaimer in the -* documentation and/or other materials provided with the -* distribution. -* -* Neither the name of Texas Instruments Incorporated nor the names of -* its contributors may be used to endorse or promote products derived -* from this software without specific prior written permission. -* -* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -* -*/ - - - -/*****************************************************************************/ -/* Include files */ -/*****************************************************************************/ -#include "simplelink.h" -#include "protocol.h" -#include "driver.h" - -/*****************************************************************************/ -/* sl_NetCfgSet */ -/*****************************************************************************/ -typedef union -{ - _NetCfgSetGet_t Cmd; - _BasicResponse_t Rsp; -}_SlNetCfgMsgSet_u; - -#if _SL_INCLUDE_FUNC(sl_NetCfgSet) - -const _SlCmdCtrl_t _SlNetCfgSetCmdCtrl = -{ - SL_OPCODE_DEVICE_NETCFG_SET_COMMAND, - sizeof(_NetCfgSetGet_t), - sizeof(_BasicResponse_t) -}; - -_i32 sl_NetCfgSet(const _u8 ConfigId ,const _u8 ConfigOpt,const _u8 ConfigLen,const _u8 *pValues) -{ - _SlNetCfgMsgSet_u Msg; - _SlCmdExt_t CmdExt; - - - _SlDrvResetCmdExt(&CmdExt); - CmdExt.TxPayloadLen = (ConfigLen+3) & (~3); - CmdExt.pTxPayload = (_u8 *)pValues; - - - Msg.Cmd.ConfigId = ConfigId; - Msg.Cmd.ConfigLen = ConfigLen; - Msg.Cmd.ConfigOpt = ConfigOpt; - - VERIFY_RET_OK(_SlDrvCmdOp((_SlCmdCtrl_t *)&_SlNetCfgSetCmdCtrl, &Msg, &CmdExt)); - - return (_i16)Msg.Rsp.status; -} -#endif - - -/*****************************************************************************/ -/* sl_NetCfgGet */ -/*****************************************************************************/ -typedef union -{ - _NetCfgSetGet_t Cmd; - _NetCfgSetGet_t Rsp; -}_SlNetCfgMsgGet_u; - -#if _SL_INCLUDE_FUNC(sl_NetCfgGet) - -const _SlCmdCtrl_t _SlNetCfgGetCmdCtrl = -{ - SL_OPCODE_DEVICE_NETCFG_GET_COMMAND, - sizeof(_NetCfgSetGet_t), - sizeof(_NetCfgSetGet_t) -}; - -_i32 sl_NetCfgGet(const _u8 ConfigId, _u8 *pConfigOpt,_u8 *pConfigLen, _u8 *pValues) -{ - _SlNetCfgMsgGet_u Msg; - _SlCmdExt_t CmdExt; - - if (*pConfigLen == 0) - { - return SL_EZEROLEN; - } - - _SlDrvResetCmdExt(&CmdExt); - CmdExt.RxPayloadLen = *pConfigLen; - CmdExt.pRxPayload = (_u8 *)pValues; - Msg.Cmd.ConfigLen = *pConfigLen; - Msg.Cmd.ConfigId = ConfigId; - - if( pConfigOpt ) - { - Msg.Cmd.ConfigOpt = (_u16)*pConfigOpt; - } - VERIFY_RET_OK(_SlDrvCmdOp((_SlCmdCtrl_t *)&_SlNetCfgGetCmdCtrl, &Msg, &CmdExt)); - - if( pConfigOpt ) - { - *pConfigOpt = (_u8)Msg.Rsp.ConfigOpt; - } - if (CmdExt.RxPayloadLen < CmdExt.ActualRxPayloadLen) - { - *pConfigLen = (_u8)CmdExt.RxPayloadLen; - if( SL_MAC_ADDRESS_GET == ConfigId ) - { - return SL_RET_CODE_OK; /* sp fix */ - } - else - { - return SL_ESMALLBUF; - } - } - else - { - *pConfigLen = (_u8)CmdExt.ActualRxPayloadLen; - } - - return (_i16)Msg.Rsp.Status; -} -#endif - diff --git a/drivers/cc3100/src/nonos.c b/drivers/cc3100/src/nonos.c deleted file mode 100644 index a20e895765..0000000000 --- a/drivers/cc3100/src/nonos.c +++ /dev/null @@ -1,171 +0,0 @@ -/* -* nonos.c - CC31xx/CC32xx Host Driver Implementation -* -* Copyright (C) 2014 Texas Instruments Incorporated - http://www.ti.com/ -* -* -* Redistribution and use in source and binary forms, with or without -* modification, are permitted provided that the following conditions -* are met: -* -* Redistributions of source code must retain the above copyright -* notice, this list of conditions and the following disclaimer. -* -* Redistributions in binary form must reproduce the above copyright -* notice, this list of conditions and the following disclaimer in the -* documentation and/or other materials provided with the -* distribution. -* -* Neither the name of Texas Instruments Incorporated nor the names of -* its contributors may be used to endorse or promote products derived -* from this software without specific prior written permission. -* -* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -* -*/ - - - -/*****************************************************************************/ -/* Include files */ -/*****************************************************************************/ -#include "simplelink.h" -#include "protocol.h" -#include "driver.h" - -#ifndef SL_PLATFORM_MULTI_THREADED - -#include "nonos.h" - -#ifndef SL_TINY_EXT -#define NONOS_MAX_SPAWN_ENTRIES 5 -#else -#define NONOS_MAX_SPAWN_ENTRIES 1 -#endif - - -typedef struct -{ - _SlSpawnEntryFunc_t pEntry; - void* pValue; -}_SlNonOsSpawnEntry_t; - -typedef struct -{ - _SlNonOsSpawnEntry_t SpawnEntries[NONOS_MAX_SPAWN_ENTRIES]; -}_SlNonOsCB_t; - -_SlNonOsCB_t g__SlNonOsCB; - - -_SlNonOsRetVal_t _SlNonOsSemSet(_SlNonOsSemObj_t* pSemObj , _SlNonOsSemObj_t Value) -{ - *pSemObj = Value; - return NONOS_RET_OK; -} - -_SlNonOsRetVal_t _SlNonOsSemGet(_SlNonOsSemObj_t* pSyncObj, _SlNonOsSemObj_t WaitValue, _SlNonOsSemObj_t SetValue, _SlNonOsTime_t Timeout) -{ -#ifdef _SlSyncWaitLoopCallback - _SlNonOsTime_t timeOutRequest = Timeout; -#endif - while (Timeout>0) - { - if (WaitValue == *pSyncObj) - { - *pSyncObj = SetValue; - break; - } - if (Timeout != NONOS_WAIT_FOREVER) - { - Timeout--; - } - _SlNonOsMainLoopTask(); -#ifdef _SlSyncWaitLoopCallback - if( (__NON_OS_SYNC_OBJ_SIGNAL_VALUE == WaitValue) && (timeOutRequest != NONOS_NO_WAIT) ) - { - if (WaitValue == *pSyncObj) - { - *pSyncObj = SetValue; - break; - } - _SlSyncWaitLoopCallback(); - } -#endif - } - - if (0 == Timeout) - { - return NONOS_RET_ERR; - } - else - { - return NONOS_RET_OK; - } -} - - -_SlNonOsRetVal_t _SlNonOsSpawn(_SlSpawnEntryFunc_t pEntry , void* pValue , _u32 flags) -{ - _i8 i = 0; - -#ifndef SL_TINY_EXT - for (i=0 ; ipEntry) - { - pE->pValue = pValue; - pE->pEntry = pEntry; -#ifndef SL_TINY_EXT - break; -#endif - } - } - - - return NONOS_RET_OK; -} - - -_SlNonOsRetVal_t _SlNonOsMainLoopTask(void) -{ - _i8 i=0; - - -#ifndef SL_TINY_EXT - for (i=0 ; ipEntry; - - if (NULL != pF) - { - if(RxIrqCnt != (g_pCB)->RxDoneCnt) - { - pF(0); /* (pValue) */ - } - - pE->pEntry = NULL; - pE->pValue = NULL; - } - } - - return NONOS_RET_OK; -} - - -#endif /*(SL_PLATFORM != SL_PLATFORM_NON_OS)*/ diff --git a/drivers/cc3100/src/socket.c b/drivers/cc3100/src/socket.c deleted file mode 100644 index 8ef9e09745..0000000000 --- a/drivers/cc3100/src/socket.c +++ /dev/null @@ -1,1150 +0,0 @@ -/* - * socket.c - CC31xx/CC32xx Host Driver Implementation - * - * Copyright (C) 2014 Texas Instruments Incorporated - http://www.ti.com/ - * - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * - * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the - * distribution. - * - * Neither the name of Texas Instruments Incorporated nor the names of - * its contributors may be used to endorse or promote products derived - * from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * -*/ - - - - -/*****************************************************************************/ -/* Include files */ -/*****************************************************************************/ -#include "simplelink.h" -#include "protocol.h" -#include "driver.h" - - -void _sl_BuildAddress(const SlSockAddr_t *addr, _SocketAddrCommand_u *pCmd); -void _sl_HandleAsync_Connect(void *pVoidBuf); - -#ifndef SL_TINY_EXT -void _sl_ParseAddress(_SocketAddrResponse_u *pRsp, SlSockAddr_t *addr, SlSocklen_t *addrlen); -void _sl_HandleAsync_Accept(void *pVoidBuf); -void _sl_HandleAsync_Select(void *pVoidBuf); -#endif -_u16 _sl_TruncatePayloadByProtocol(const _i16 pSd, const _u16 length); - -/*******************************************************************************/ -/* Functions */ -/*******************************************************************************/ - - - /* Note: parsing of family and port in the generic way for all IPV4, IPV6 and EUI48 */ - /* is possible as _i32 as these parameters are in the same offset and size for these */ - /* three families. */ -#define SL_SOCKET_PAYLOAD_BASE (1350) - -const _u8 _SlPayloadByProtocolLUT[16] = -{ - (1472 - SL_SOCKET_PAYLOAD_BASE), /* SL_SOCKET_PAYLOAD_TYPE_UDP_IPV4 */ - (1460 - SL_SOCKET_PAYLOAD_BASE), /* SL_SOCKET_PAYLOAD_TYPE_TCP_IPV4 */ - (1452 - SL_SOCKET_PAYLOAD_BASE), /* SL_SOCKET_PAYLOAD_TYPE_UDP_IPV6 */ - (1440 - SL_SOCKET_PAYLOAD_BASE), /* SL_SOCKET_PAYLOAD_TYPE_TCP_IPV6 */ - (1386 - SL_SOCKET_PAYLOAD_BASE), /* SL_SOCKET_PAYLOAD_TYPE_TCP_IPV4_SECURE */ - (1386 - SL_SOCKET_PAYLOAD_BASE), /* SL_SOCKET_PAYLOAD_TYPE_UDP_IPV4_SECURE */ - (1396 - SL_SOCKET_PAYLOAD_BASE), /* SL_SOCKET_PAYLOAD_TYPE_UDP_IPV6_SECURE */ - (1396 - SL_SOCKET_PAYLOAD_BASE), /* SL_SOCKET_PAYLOAD_TYPE_TCP_IPV6_SECURE */ - (1476 - SL_SOCKET_PAYLOAD_BASE), /* SL_SOCKET_PAYLOAD_TYPE_RAW_TRANCEIVER */ - (1514 - SL_SOCKET_PAYLOAD_BASE), /* SL_SOCKET_PAYLOAD_TYPE_RAW_PACKET */ - (1480 - SL_SOCKET_PAYLOAD_BASE), /* SL_SOCKET_PAYLOAD_TYPE_RAW_IP4 */ - (1480 - SL_SOCKET_PAYLOAD_BASE), /* SL_SOCKET_PAYLOAD_TYPE_RAW_IP6 */ - (1440 - SL_SOCKET_PAYLOAD_BASE), /* Default */ - (1440 - SL_SOCKET_PAYLOAD_BASE), /* Default */ - (1440 - SL_SOCKET_PAYLOAD_BASE), /* Default */ - (1440 - SL_SOCKET_PAYLOAD_BASE) /* Default */ -}; - - - -/* ******************************************************************************/ -/* _sl_BuildAddress */ -/* ******************************************************************************/ -void _sl_BuildAddress(const SlSockAddr_t *addr, _SocketAddrCommand_u *pCmd) -{ - - /* Note: parsing of family and port in the generic way for all IPV4, IPV6 and EUI48 - is possible as long as these parameters are in the same offset and size for these - three families. */ - pCmd->IpV4.FamilyAndFlags = (addr->sa_family << 4) & 0xF0; - pCmd->IpV4.port = ((SlSockAddrIn_t *)addr)->sin_port; - - if(SL_AF_INET == addr->sa_family) - { - pCmd->IpV4.address = ((SlSockAddrIn_t *)addr)->sin_addr.s_addr; - } - else if (SL_AF_INET6_EUI_48 == addr->sa_family ) - { - sl_Memcpy( pCmd->IpV6EUI48.address,((SlSockAddrIn6_t *)addr)->sin6_addr._S6_un._S6_u8, 6); - } -#ifdef SL_SUPPORT_IPV6 - else - { - sl_Memcpy(pCmd->IpV6.address, ((sockaddr_in6 *)addr)->sin6_addr._S6_un._S6_u32, 16 ); - } -#endif -} - - -/***************************************************************************** - _sl_TruncatePayloadByProtocol -*****************************************************************************/ -_u16 _sl_TruncatePayloadByProtocol(const _i16 sd, const _u16 length) -{ - unsigned int maxLength; - - - maxLength = SL_SOCKET_PAYLOAD_BASE + _SlPayloadByProtocolLUT[((sd & SL_SOCKET_PAYLOAD_TYPE_MASK) >> 4)]; - - - - if( length > maxLength ) - { - return maxLength; - } - else - { - return length; - } -} - -/*******************************************************************************/ -/* _sl_ParseAddress */ -/*******************************************************************************/ - -#ifndef SL_TINY_EXT -void _sl_ParseAddress(_SocketAddrResponse_u *pRsp, SlSockAddr_t *addr, SlSocklen_t *addrlen) -{ - /* Note: parsing of family and port in the generic way for all IPV4, IPV6 and EUI48 */ - /* is possible as long as these parameters are in the same offset and size for these */ - /* three families. */ - addr->sa_family = pRsp->IpV4.family; - ((SlSockAddrIn_t *)addr)->sin_port = pRsp->IpV4.port; - - *addrlen = (SL_AF_INET == addr->sa_family) ? sizeof(SlSockAddrIn_t) : sizeof(SlSockAddrIn6_t); - - if(SL_AF_INET == addr->sa_family) - { - ((SlSockAddrIn_t *)addr)->sin_addr.s_addr = pRsp->IpV4.address; - } - else if (SL_AF_INET6_EUI_48 == addr->sa_family ) - { - sl_Memcpy(((SlSockAddrIn6_t *)addr)->sin6_addr._S6_un._S6_u8, pRsp->IpV6EUI48.address, 6); - } -#ifdef SL_SUPPORT_IPV6 - else - { - sl_Memcpy(((sockaddr_in6 *)addr)->sin6_addr._S6_un._S6_u32, pRsp->IpV6.address, 16); - } -#endif -} - -#endif - -/*******************************************************************************/ -/* sl_Socket */ -/*******************************************************************************/ -typedef union -{ - _u32 Dummy; - _SocketCommand_t Cmd; - _SocketResponse_t Rsp; -}_SlSockSocketMsg_u; - - - -#if _SL_INCLUDE_FUNC(sl_Socket) - -const _SlCmdCtrl_t _SlSockSocketCmdCtrl = -{ - SL_OPCODE_SOCKET_SOCKET, - sizeof(_SocketCommand_t), - sizeof(_SocketResponse_t) -}; - -_i16 sl_Socket(_i16 Domain, _i16 Type, _i16 Protocol) -{ - _SlSockSocketMsg_u Msg; - - Msg.Cmd.Domain = (_u8)Domain; - Msg.Cmd.Type = (_u8)Type; - Msg.Cmd.Protocol = (_u8)Protocol; - - VERIFY_RET_OK(_SlDrvCmdOp((_SlCmdCtrl_t *)&_SlSockSocketCmdCtrl, &Msg, NULL)); - - if( Msg.Rsp.statusOrLen < 0 ) - { - return( Msg.Rsp.statusOrLen ); - } - else - { - return (_i16)((_u8)Msg.Rsp.sd); -} -} -#endif - -/*******************************************************************************/ -/* sl_Close */ -/*******************************************************************************/ -typedef union -{ - _CloseCommand_t Cmd; - _SocketResponse_t Rsp; -}_SlSockCloseMsg_u; - - -#if _SL_INCLUDE_FUNC(sl_Close) - -const _SlCmdCtrl_t _SlSockCloseCmdCtrl = -{ - SL_OPCODE_SOCKET_CLOSE, - sizeof(_CloseCommand_t), - sizeof(_SocketResponse_t) -}; - -_i16 sl_Close(_i16 sd) -{ - _SlSockCloseMsg_u Msg; - - Msg.Cmd.sd = (_u8)sd; - - VERIFY_RET_OK(_SlDrvCmdOp((_SlCmdCtrl_t *)&_SlSockCloseCmdCtrl, &Msg, NULL)); - - return Msg.Rsp.statusOrLen; -} -#endif - -/*******************************************************************************/ -/* sl_Bind */ -/*******************************************************************************/ -typedef union -{ - _SocketAddrCommand_u Cmd; - _SocketResponse_t Rsp; -}_SlSockBindMsg_u; - -#if _SL_INCLUDE_FUNC(sl_Bind) -_i16 sl_Bind(_i16 sd, const SlSockAddr_t *addr, _i16 addrlen) -{ - _SlSockBindMsg_u Msg; - _SlCmdCtrl_t CmdCtrl = {0, 0, sizeof(_SocketResponse_t)}; - - switch(addr->sa_family) - { - case SL_AF_INET : - CmdCtrl.Opcode = SL_OPCODE_SOCKET_BIND; - CmdCtrl.TxDescLen = sizeof(_SocketAddrIPv4Command_t); - break; -#ifndef SL_TINY_EXT - case SL_AF_INET6_EUI_48: - CmdCtrl.Opcode = SL_OPCODE_SOCKET_BIND_V6; - CmdCtrl.TxDescLen = sizeof(_SocketAddrIPv6EUI48Command_t); - break; - -#ifdef SL_SUPPORT_IPV6 - case AF_INET6: - CmdCtrl.Opcode = SL_OPCODE_SOCKET_BIND_V6; - CmdCtrl.TxDescLen = sizeof(_SocketAddrIPv6Command_t); - break; -#endif -#endif - - - case SL_AF_RF : - default: - return SL_RET_CODE_INVALID_INPUT; - } - - Msg.Cmd.IpV4.lenOrPadding = 0; - Msg.Cmd.IpV4.sd = (_u8)sd; - - _sl_BuildAddress(addr, &Msg.Cmd); - - VERIFY_RET_OK(_SlDrvCmdOp((_SlCmdCtrl_t *)&CmdCtrl, &Msg, NULL)); - - return Msg.Rsp.statusOrLen; -} -#endif - -/*******************************************************************************/ -/* sl_Sendto */ -/*******************************************************************************/ -typedef union -{ - _SocketAddrCommand_u Cmd; - /* no response for 'sendto' commands*/ -}_SlSendtoMsg_u; - -#if _SL_INCLUDE_FUNC(sl_SendTo) -_i16 sl_SendTo(_i16 sd, const void *pBuf, _i16 Len, _i16 flags, const SlSockAddr_t *to, SlSocklen_t tolen) -{ - _SlSendtoMsg_u Msg; - _SlCmdCtrl_t CmdCtrl = {0, 0, 0}; - _SlCmdExt_t CmdExt; - _u16 ChunkLen; - _i16 RetVal; - - _SlDrvResetCmdExt(&CmdExt); - CmdExt.TxPayloadLen = (_u16)Len; - CmdExt.pTxPayload = (_u8 *)pBuf; - - switch(to->sa_family) - { - case SL_AF_INET: - CmdCtrl.Opcode = SL_OPCODE_SOCKET_SENDTO; - CmdCtrl.TxDescLen = sizeof(_SocketAddrIPv4Command_t); - break; -#ifndef SL_TINY_EXT - case SL_AF_INET6_EUI_48: - CmdCtrl.Opcode = SL_OPCODE_SOCKET_BIND_V6; - CmdCtrl.TxDescLen = sizeof(_SocketAddrIPv6EUI48Command_t); - break; -#ifdef SL_SUPPORT_IPV6 - case AF_INET6: - CmdCtrl.Opcode = SL_OPCODE_SOCKET_SENDTO_V6; - CmdCtrl.TxDescLen = sizeof(_SocketAddrIPv6Command_t); - break; -#endif -#endif - case SL_AF_RF: - default: - return SL_RET_CODE_INVALID_INPUT; - } - - ChunkLen = _sl_TruncatePayloadByProtocol(sd,Len); - Msg.Cmd.IpV4.lenOrPadding = ChunkLen; - CmdExt.TxPayloadLen = ChunkLen; - - Msg.Cmd.IpV4.sd = (_u8)sd; - - _sl_BuildAddress(to, &Msg.Cmd); - - Msg.Cmd.IpV4.FamilyAndFlags |= flags & 0x0F; - - do - { - RetVal = _SlDrvDataWriteOp((_SlSd_t)sd, &CmdCtrl, &Msg, &CmdExt); - - if(SL_OS_RET_CODE_OK == RetVal) - { - CmdExt.pTxPayload += ChunkLen; - ChunkLen = (_u16)((_u8 *)pBuf + Len - CmdExt.pTxPayload); - ChunkLen = _sl_TruncatePayloadByProtocol(sd,ChunkLen); - CmdExt.TxPayloadLen = ChunkLen; - Msg.Cmd.IpV4.lenOrPadding = ChunkLen; - } - else - { - return RetVal; - } - }while(ChunkLen > 0); - - return (_i16)Len; -} -#endif - -/*******************************************************************************/ -/* sl_Recvfrom */ -/*******************************************************************************/ -typedef union -{ - _sendRecvCommand_t Cmd; - _SocketAddrResponse_u Rsp; -}_SlRecvfromMsg_u; - -const _SlCmdCtrl_t _SlRecvfomCmdCtrl = -{ - SL_OPCODE_SOCKET_RECVFROM, - sizeof(_sendRecvCommand_t), - sizeof(_SocketAddrResponse_u) -}; - - - -#if _SL_INCLUDE_FUNC(sl_RecvFrom) -_i16 sl_RecvFrom(_i16 sd, void *buf, _i16 Len, _i16 flags, SlSockAddr_t *from, SlSocklen_t *fromlen) -{ - _SlRecvfromMsg_u Msg; - _SlCmdExt_t CmdExt; - _i16 RetVal; - - - _SlDrvResetCmdExt(&CmdExt); - CmdExt.RxPayloadLen = Len; - CmdExt.pRxPayload = (_u8 *)buf; - - Msg.Cmd.sd = (_u8)sd; - Msg.Cmd.StatusOrLen = Len; - /* no size truncation in recv path */ - CmdExt.RxPayloadLen = Msg.Cmd.StatusOrLen; - - - Msg.Cmd.FamilyAndFlags = flags & 0x0F; - - - if(sizeof(SlSockAddrIn_t) == *fromlen) - { - Msg.Cmd.FamilyAndFlags |= (SL_AF_INET << 4); - } - else if (sizeof(SlSockAddrIn6_t) == *fromlen) - { - Msg.Cmd.FamilyAndFlags |= (SL_AF_INET6 << 4); - } - else - { - return SL_RET_CODE_INVALID_INPUT; - } - - RetVal = _SlDrvDataReadOp((_SlSd_t)sd, (_SlCmdCtrl_t *)&_SlRecvfomCmdCtrl, &Msg, &CmdExt); - if( RetVal != SL_OS_RET_CODE_OK ) - { - return RetVal; - } - - RetVal = Msg.Rsp.IpV4.statusOrLen; - - if(RetVal >= 0) - { - VERIFY_PROTOCOL(sd == Msg.Rsp.IpV4.sd); -#if 0 - _sl_ParseAddress(&Msg.Rsp, from, fromlen); -#else - from->sa_family = Msg.Rsp.IpV4.family; - if(SL_AF_INET == from->sa_family) - { - ((SlSockAddrIn_t *)from)->sin_port = Msg.Rsp.IpV4.port; - ((SlSockAddrIn_t *)from)->sin_addr.s_addr = Msg.Rsp.IpV4.address; - *fromlen = sizeof(SlSockAddrIn_t); - } - else if (SL_AF_INET6_EUI_48 == from->sa_family ) - { - ((SlSockAddrIn6_t *)from)->sin6_port = Msg.Rsp.IpV6EUI48.port; - sl_Memcpy(((SlSockAddrIn6_t *)from)->sin6_addr._S6_un._S6_u8, Msg.Rsp.IpV6EUI48.address, 6); - } -#ifdef SL_SUPPORT_IPV6 - else if(AF_INET6 == from->sa_family) - { - VERIFY_PROTOCOL(*fromlen >= sizeof(sockaddr_in6)); - - ((sockaddr_in6 *)from)->sin6_port = Msg.Rsp.IpV6.port; - sl_Memcpy(((sockaddr_in6 *)from)->sin6_addr._S6_un._S6_u32, Msg.Rsp.IpV6.address, 16); - *fromlen = sizeof(sockaddr_in6); - } -#endif -#endif - } - - return (_i16)RetVal; -} -#endif - -/*******************************************************************************/ -/* sl_Connect */ -/*******************************************************************************/ -typedef union -{ - _SocketAddrCommand_u Cmd; - _SocketResponse_t Rsp; -}_SlSockConnectMsg_u; - -#if _SL_INCLUDE_FUNC(sl_Connect) -_i16 sl_Connect(_i16 sd, const SlSockAddr_t *addr, _i16 addrlen) -{ - _SlSockConnectMsg_u Msg; - _SlReturnVal_t RetVal; - _SlCmdCtrl_t CmdCtrl = {0, 0, sizeof(_SocketResponse_t)}; - _SocketResponse_t AsyncRsp; - _u8 ObjIdx = MAX_CONCURRENT_ACTIONS; - - - switch(addr->sa_family) - { - case SL_AF_INET : - CmdCtrl.Opcode = SL_OPCODE_SOCKET_CONNECT; - CmdCtrl.TxDescLen = sizeof(_SocketAddrIPv4Command_t); - /* Do nothing - cmd already initialized to this type */ - break; - case SL_AF_INET6_EUI_48: - CmdCtrl.Opcode = SL_OPCODE_SOCKET_CONNECT_V6; - CmdCtrl.TxDescLen = sizeof(_SocketAddrIPv6EUI48Command_t); - break; -#ifdef SL_SUPPORT_IPV6 - case AF_INET6: - CmdCtrl.Opcode = SL_OPCODE_SOCKET_CONNECT_V6; - CmdCtrl.TxDescLen = sizeof(_SocketAddrIPv6Command_t); - break; -#endif - case SL_AF_RF: - default: - return SL_RET_CODE_INVALID_INPUT; - } - - Msg.Cmd.IpV4.lenOrPadding = 0; - Msg.Cmd.IpV4.sd = (_u8)sd; - - _sl_BuildAddress(addr, &Msg.Cmd); - - - ObjIdx = _SlDrvProtectAsyncRespSetting((_u8*)&AsyncRsp, CONNECT_ID, sd & BSD_SOCKET_ID_MASK); - - if (MAX_CONCURRENT_ACTIONS == ObjIdx) - { - return SL_POOL_IS_EMPTY; - } - - /* send the command */ - VERIFY_RET_OK(_SlDrvCmdOp((_SlCmdCtrl_t *)&CmdCtrl, &Msg, NULL)); - VERIFY_PROTOCOL(Msg.Rsp.sd == sd) - - RetVal = Msg.Rsp.statusOrLen; - - if(SL_RET_CODE_OK == RetVal) - { - /* wait for async and get Data Read parameters */ - _SlDrvSyncObjWaitForever(&g_pCB->ObjPool[ObjIdx].SyncObj); - - VERIFY_PROTOCOL(AsyncRsp.sd == sd); - - RetVal = AsyncRsp.statusOrLen; - } - - - - _SlDrvReleasePoolObj(ObjIdx); - return RetVal; -} - -#endif - - -/*******************************************************************************/ -/* _sl_HandleAsync_Connect */ -/*******************************************************************************/ -void _sl_HandleAsync_Connect(void *pVoidBuf) -{ - _SocketResponse_t *pMsgArgs = (_SocketResponse_t *)_SL_RESP_ARGS_START(pVoidBuf); - - _SlDrvProtectionObjLockWaitForever(); - - VERIFY_PROTOCOL((pMsgArgs->sd & BSD_SOCKET_ID_MASK) <= SL_MAX_SOCKETS); - VERIFY_SOCKET_CB(NULL != g_pCB->ObjPool[g_pCB->FunctionParams.AsyncExt.ActionIndex].pRespArgs); - - - ((_SocketResponse_t *)(g_pCB->ObjPool[g_pCB->FunctionParams.AsyncExt.ActionIndex].pRespArgs))->sd = pMsgArgs->sd; - ((_SocketResponse_t *)(g_pCB->ObjPool[g_pCB->FunctionParams.AsyncExt.ActionIndex].pRespArgs))->statusOrLen = pMsgArgs->statusOrLen; - - - _SlDrvSyncObjSignal(&g_pCB->ObjPool[g_pCB->FunctionParams.AsyncExt.ActionIndex].SyncObj); - _SlDrvProtectionObjUnLock(); - return; -} - -/*******************************************************************************/ -/* sl_Send */ -/*******************************************************************************/ -typedef union -{ - _sendRecvCommand_t Cmd; - /* no response for 'sendto' commands*/ -}_SlSendMsg_u; - -const _SlCmdCtrl_t _SlSendCmdCtrl = -{ - SL_OPCODE_SOCKET_SEND, - sizeof(_sendRecvCommand_t), - 0 -}; - -#if _SL_INCLUDE_FUNC(sl_Send) -_i16 sl_Send(_i16 sd, const void *pBuf, _i16 Len, _i16 flags) -{ - _SlSendMsg_u Msg; - _SlCmdExt_t CmdExt; - _u16 ChunkLen; - _i16 RetVal; - _u32 tempVal; - _u8 runSingleChunk = FALSE; - - _SlDrvResetCmdExt(&CmdExt); - CmdExt.TxPayloadLen = Len; - CmdExt.pTxPayload = (_u8 *)pBuf; - - /* Only for RAW transceiver type socket, relay the flags parameter in the 2 bytes (4 byte aligned) before the actual payload */ - if ((sd & SL_SOCKET_PAYLOAD_TYPE_MASK) == SL_SOCKET_PAYLOAD_TYPE_RAW_TRANCEIVER) - { - tempVal = flags; - CmdExt.pRxPayload = (_u8 *)&tempVal; - CmdExt.RxPayloadLen = -4; /* mark as Rx data to send */ - runSingleChunk = TRUE; - } - else - { - CmdExt.pRxPayload = NULL; - } - - ChunkLen = _sl_TruncatePayloadByProtocol(sd,Len); - CmdExt.TxPayloadLen = ChunkLen; - Msg.Cmd.StatusOrLen = ChunkLen; - Msg.Cmd.sd = (_u8)sd; - Msg.Cmd.FamilyAndFlags |= flags & 0x0F; - - do - { - RetVal = _SlDrvDataWriteOp((_u8)sd, (_SlCmdCtrl_t *)&_SlSendCmdCtrl, &Msg, &CmdExt); - if(SL_OS_RET_CODE_OK == RetVal) - { - CmdExt.pTxPayload += ChunkLen; - ChunkLen = (_u8 *)pBuf + Len - CmdExt.pTxPayload; - ChunkLen = _sl_TruncatePayloadByProtocol(sd,ChunkLen); - CmdExt.TxPayloadLen = ChunkLen; - Msg.Cmd.StatusOrLen = ChunkLen; - } - else - { - return RetVal; - } - }while((ChunkLen > 0) && (runSingleChunk==FALSE)); - - return (_i16)Len; -} -#endif - -/*******************************************************************************/ -/* sl_Listen */ -/*******************************************************************************/ -typedef union -{ - _ListenCommand_t Cmd; - _BasicResponse_t Rsp; -}_SlListenMsg_u; - - - -#if _SL_INCLUDE_FUNC(sl_Listen) - -const _SlCmdCtrl_t _SlListenCmdCtrl = -{ - SL_OPCODE_SOCKET_LISTEN, - sizeof(_ListenCommand_t), - sizeof(_BasicResponse_t), -}; - -_i16 sl_Listen(_i16 sd, _i16 backlog) -{ - _SlListenMsg_u Msg; - - Msg.Cmd.sd = (_u8)sd; - Msg.Cmd.backlog = (_u8)backlog; - - VERIFY_RET_OK(_SlDrvCmdOp((_SlCmdCtrl_t *)&_SlListenCmdCtrl, &Msg, NULL)); - - return (_i16)Msg.Rsp.status; -} -#endif - -/*******************************************************************************/ -/* sl_Accept */ -/*******************************************************************************/ -typedef union -{ - _AcceptCommand_t Cmd; - _SocketResponse_t Rsp; -}_SlSockAcceptMsg_u; - - - -#if _SL_INCLUDE_FUNC(sl_Accept) - -const _SlCmdCtrl_t _SlAcceptCmdCtrl = -{ - SL_OPCODE_SOCKET_ACCEPT, - sizeof(_AcceptCommand_t), - sizeof(_BasicResponse_t), -}; - -_i16 sl_Accept(_i16 sd, SlSockAddr_t *addr, SlSocklen_t *addrlen) -{ - _SlSockAcceptMsg_u Msg; - _SlReturnVal_t RetVal; - _SocketAddrResponse_u AsyncRsp; - - _u8 ObjIdx = MAX_CONCURRENT_ACTIONS; - - - Msg.Cmd.sd = (_u8)sd; - Msg.Cmd.family = (sizeof(SlSockAddrIn_t) == *addrlen) ? SL_AF_INET : SL_AF_INET6; - - - ObjIdx = _SlDrvProtectAsyncRespSetting((_u8*)&AsyncRsp, ACCEPT_ID, sd & BSD_SOCKET_ID_MASK ); - - if (MAX_CONCURRENT_ACTIONS == ObjIdx) - { - return SL_POOL_IS_EMPTY; - } - - /* send the command */ - VERIFY_RET_OK(_SlDrvCmdOp((_SlCmdCtrl_t *)&_SlAcceptCmdCtrl, &Msg, NULL)); - VERIFY_PROTOCOL(Msg.Rsp.sd == sd); - - RetVal = Msg.Rsp.statusOrLen; - - if(SL_OS_RET_CODE_OK == RetVal) - { - /* wait for async and get Data Read parameters */ - _SlDrvSyncObjWaitForever(&g_pCB->ObjPool[ObjIdx].SyncObj); - - VERIFY_PROTOCOL(AsyncRsp.IpV4.sd == sd); - - RetVal = AsyncRsp.IpV4.statusOrLen; - if( (NULL != addr) && (NULL != addrlen) ) - { -#if 0 /* Kept for backup */ - _sl_ParseAddress(&AsyncRsp, addr, addrlen); -#else - addr->sa_family = AsyncRsp.IpV4.family; - - if(SL_AF_INET == addr->sa_family) - { - if( *addrlen == sizeof( SlSockAddrIn_t ) ) - { - ((SlSockAddrIn_t *)addr)->sin_port = AsyncRsp.IpV4.port; - ((SlSockAddrIn_t *)addr)->sin_addr.s_addr = AsyncRsp.IpV4.address; - } - else - { - *addrlen = 0; - } - } - else if (SL_AF_INET6_EUI_48 == addr->sa_family ) - { - if( *addrlen == sizeof( SlSockAddrIn6_t ) ) - { - ((SlSockAddrIn6_t *)addr)->sin6_port = AsyncRsp.IpV6EUI48.port ; - /* will be called from here and from _sl_BuildAddress*/ - sl_Memcpy(((SlSockAddrIn6_t *)addr)->sin6_addr._S6_un._S6_u8, AsyncRsp.IpV6EUI48.address, 6); - } - else - { - *addrlen = 0; - } - } -#ifdef SL_SUPPORT_IPV6 - else - { - if( *addrlen == sizeof( sockaddr_in6 ) ) - { - ((sockaddr_in6 *)addr)->sin6_port = AsyncRsp.IpV6.port ; - sl_Memcpy(((sockaddr_in6 *)addr)->sin6_addr._S6_un._S6_u32, AsyncRsp.IpV6.address, 16); - } - else - { - *addrlen = 0; - } - } -#endif -#endif - } - } - - _SlDrvReleasePoolObj(ObjIdx); - return (_i16)RetVal; -} -#endif - - -/*******************************************************************************/ -/* sl_Htonl */ -/*******************************************************************************/ -_u32 sl_Htonl( _u32 val ) -{ - _u32 i = 1; - _i8 *p = (_i8 *)&i; - if (p[0] == 1) /* little endian */ - { - p[0] = ((_i8* )&val)[3]; - p[1] = ((_i8* )&val)[2]; - p[2] = ((_i8* )&val)[1]; - p[3] = ((_i8* )&val)[0]; - return i; - } - else /* big endian */ - { - return val; - } -} - -/*******************************************************************************/ -/* sl_Htonl */ -/*******************************************************************************/ -_u16 sl_Htons( _u16 val ) -{ - _i16 i = 1; - _i8 *p = (_i8 *)&i; - if (p[0] == 1) /* little endian */ - { - p[0] = ((_i8* )&val)[1]; - p[1] = ((_i8* )&val)[0]; - return i; - } - else /* big endian */ - { - return val; - } -} - -/*******************************************************************************/ -/* _sl_HandleAsync_Accept */ -/*******************************************************************************/ -#ifndef SL_TINY_EXT -void _sl_HandleAsync_Accept(void *pVoidBuf) -{ - _SocketAddrResponse_u *pMsgArgs = (_SocketAddrResponse_u *)_SL_RESP_ARGS_START(pVoidBuf); - - _SlDrvProtectionObjLockWaitForever(); - - VERIFY_PROTOCOL(( pMsgArgs->IpV4.sd & BSD_SOCKET_ID_MASK) <= SL_MAX_SOCKETS); - VERIFY_SOCKET_CB(NULL != g_pCB->ObjPool[g_pCB->FunctionParams.AsyncExt.ActionIndex].pRespArgs); - - sl_Memcpy(g_pCB->ObjPool[g_pCB->FunctionParams.AsyncExt.ActionIndex].pRespArgs, pMsgArgs,sizeof(_SocketAddrResponse_u)); - _SlDrvSyncObjSignal(&g_pCB->ObjPool[g_pCB->FunctionParams.AsyncExt.ActionIndex].SyncObj); - - _SlDrvProtectionObjUnLock(); - return; -} - -/*******************************************************************************/ -/* _sl_HandleAsync_Select */ -/*******************************************************************************/ -void _sl_HandleAsync_Select(void *pVoidBuf) -{ - _SelectAsyncResponse_t *pMsgArgs = (_SelectAsyncResponse_t *)_SL_RESP_ARGS_START(pVoidBuf); - - _SlDrvProtectionObjLockWaitForever(); - - VERIFY_SOCKET_CB(NULL != g_pCB->ObjPool[g_pCB->FunctionParams.AsyncExt.ActionIndex].pRespArgs); - - sl_Memcpy(g_pCB->ObjPool[g_pCB->FunctionParams.AsyncExt.ActionIndex].pRespArgs, pMsgArgs, sizeof(_SelectAsyncResponse_t)); - - _SlDrvSyncObjSignal(&g_pCB->ObjPool[g_pCB->FunctionParams.AsyncExt.ActionIndex].SyncObj); - _SlDrvProtectionObjUnLock(); - - return; -} - -#endif - -/*******************************************************************************/ -/* sl_Recv */ -/*******************************************************************************/ -typedef union -{ - _sendRecvCommand_t Cmd; - _SocketResponse_t Rsp; -}_SlRecvMsg_u; - - -#if _SL_INCLUDE_FUNC(sl_Recv) - -const _SlCmdCtrl_t _SlRecvCmdCtrl = -{ - SL_OPCODE_SOCKET_RECV, - sizeof(_sendRecvCommand_t), - sizeof(_SocketResponse_t) -}; - - -_i16 sl_Recv(_i16 sd, void *pBuf, _i16 Len, _i16 flags) -{ - _SlRecvMsg_u Msg; - _SlCmdExt_t CmdExt; - _SlReturnVal_t status; - - _SlDrvResetCmdExt(&CmdExt); - CmdExt.RxPayloadLen = Len; - CmdExt.pRxPayload = (_u8 *)pBuf; - - Msg.Cmd.sd = (_u8)sd; - Msg.Cmd.StatusOrLen = Len; - - /* no size truncation in recv path */ - CmdExt.RxPayloadLen = Msg.Cmd.StatusOrLen; - - Msg.Cmd.FamilyAndFlags = flags & 0x0F; - - status = _SlDrvDataReadOp((_SlSd_t)sd, (_SlCmdCtrl_t *)&_SlRecvCmdCtrl, &Msg, &CmdExt); - if( status != SL_OS_RET_CODE_OK ) - { - return status; - } - - /* if the Device side sends less than expected it is not the Driver's role */ - /* the returned value could be smaller than the requested size */ - return (_i16)Msg.Rsp.statusOrLen; -} -#endif - -/*******************************************************************************/ -/* sl_SetSockOpt */ -/*******************************************************************************/ -typedef union -{ - _setSockOptCommand_t Cmd; - _SocketResponse_t Rsp; -}_SlSetSockOptMsg_u; - -const _SlCmdCtrl_t _SlSetSockOptCmdCtrl = -{ - SL_OPCODE_SOCKET_SETSOCKOPT, - sizeof(_setSockOptCommand_t), - sizeof(_SocketResponse_t) -}; - -#if _SL_INCLUDE_FUNC(sl_SetSockOpt) -_i16 sl_SetSockOpt(_i16 sd, _i16 level, _i16 optname, const void *optval, SlSocklen_t optlen) -{ - _SlSetSockOptMsg_u Msg; - _SlCmdExt_t CmdExt; - - - _SlDrvResetCmdExt(&CmdExt); - CmdExt.TxPayloadLen = optlen; - CmdExt.pTxPayload = (_u8 *)optval; - - Msg.Cmd.sd = (_u8)sd; - Msg.Cmd.level = (_u8)level; - Msg.Cmd.optionLen = (_u8)optlen; - Msg.Cmd.optionName = (_u8)optname; - - VERIFY_RET_OK(_SlDrvCmdOp((_SlCmdCtrl_t *)&_SlSetSockOptCmdCtrl, &Msg, &CmdExt)); - - return (_i16)Msg.Rsp.statusOrLen; -} -#endif - -/*******************************************************************************/ -/* sl_GetSockOpt */ -/*******************************************************************************/ -typedef union -{ - _getSockOptCommand_t Cmd; - _getSockOptResponse_t Rsp; -}_SlGetSockOptMsg_u; - - -#if _SL_INCLUDE_FUNC(sl_GetSockOpt) - -const _SlCmdCtrl_t _SlGetSockOptCmdCtrl = -{ - SL_OPCODE_SOCKET_GETSOCKOPT, - sizeof(_getSockOptCommand_t), - sizeof(_getSockOptResponse_t) -}; - -_i16 sl_GetSockOpt(_i16 sd, _i16 level, _i16 optname, void *optval, SlSocklen_t *optlen) -{ - _SlGetSockOptMsg_u Msg; - _SlCmdExt_t CmdExt; - - if (*optlen == 0) - { - return SL_EZEROLEN; - } - - _SlDrvResetCmdExt(&CmdExt); - CmdExt.RxPayloadLen = *optlen; - CmdExt.pRxPayload = optval; - - Msg.Cmd.sd = (_u8)sd; - Msg.Cmd.level = (_u8)level; - Msg.Cmd.optionLen = (_u8)(*optlen); - Msg.Cmd.optionName = (_u8)optname; - - VERIFY_RET_OK(_SlDrvCmdOp((_SlCmdCtrl_t *)&_SlGetSockOptCmdCtrl, &Msg, &CmdExt)); - - if (CmdExt.RxPayloadLen < CmdExt.ActualRxPayloadLen) - { - *optlen = Msg.Rsp.optionLen; - return SL_ESMALLBUF; - } - else - { - *optlen = (_u8)CmdExt.ActualRxPayloadLen; - } - return (_i16)Msg.Rsp.status; -} -#endif - -/*******************************************************************************/ -/* sl_Select */ -/* ******************************************************************************/ -typedef union -{ - _SelectCommand_t Cmd; - _BasicResponse_t Rsp; -}_SlSelectMsg_u; - - - -#ifndef SL_TINY_EXT -#if _SL_INCLUDE_FUNC(sl_Select) - -const _SlCmdCtrl_t _SlSelectCmdCtrl = -{ - SL_OPCODE_SOCKET_SELECT, - sizeof(_SelectCommand_t), - sizeof(_BasicResponse_t) -}; - - -_i16 sl_Select(_i16 nfds, SlFdSet_t *readsds, SlFdSet_t *writesds, SlFdSet_t *exceptsds, struct SlTimeval_t *timeout) -{ - _SlSelectMsg_u Msg; - _SelectAsyncResponse_t AsyncRsp; - _u8 ObjIdx = MAX_CONCURRENT_ACTIONS; - - Msg.Cmd.nfds = (_u8)nfds; - Msg.Cmd.readFdsCount = 0; - Msg.Cmd.writeFdsCount = 0; - - Msg.Cmd.readFds = 0; - Msg.Cmd.writeFds = 0; - - - if( readsds ) - { - Msg.Cmd.readFds = (_u16)readsds->fd_array[0]; - } - if( writesds ) - { - Msg.Cmd.writeFds = (_u16)writesds->fd_array[0]; - } - if( NULL == timeout ) - { - Msg.Cmd.tv_sec = 0xffff; - Msg.Cmd.tv_usec = 0xffff; - } - else - { - if( 0xffff <= timeout->tv_sec ) - { - Msg.Cmd.tv_sec = 0xffff; - } - else - { - Msg.Cmd.tv_sec = (_u16)timeout->tv_sec; - } - timeout->tv_usec = timeout->tv_usec >> 10; /* convert to milliseconds */ - if( 0xffff <= timeout->tv_usec ) - { - Msg.Cmd.tv_usec = 0xffff; - } - else - { - Msg.Cmd.tv_usec = (_u16)timeout->tv_usec; - } - } - - /* Use Obj to issue the command, if not available try later */ - ObjIdx = _SlDrvProtectAsyncRespSetting((_u8*)&AsyncRsp, SELECT_ID, SL_MAX_SOCKETS); - - if (MAX_CONCURRENT_ACTIONS == ObjIdx) - { - return SL_POOL_IS_EMPTY; - } - - - /* send the command */ - VERIFY_RET_OK(_SlDrvCmdOp((_SlCmdCtrl_t *)&_SlSelectCmdCtrl, &Msg, NULL)); - - if(SL_OS_RET_CODE_OK == (_i16)Msg.Rsp.status) - { - _SlDrvSyncObjWaitForever(&g_pCB->ObjPool[ObjIdx].SyncObj); - - Msg.Rsp.status = AsyncRsp.status; - - if( ((_i16)Msg.Rsp.status) >= 0 ) - { - if( readsds ) - { - readsds->fd_array[0] = AsyncRsp.readFds; - } - if( writesds ) - { - writesds->fd_array[0] = AsyncRsp.writeFds; - } - } - } - - _SlDrvReleasePoolObj(ObjIdx); - return (_i16)Msg.Rsp.status; -} - -/* Select helper functions */ -/*******************************************************************************/ -/* SL_FD_SET */ -/* ******************************************************************************/ -void SL_FD_SET(_i16 fd, SlFdSet_t *fdset) -{ - fdset->fd_array[0] |= (1<< (fd & BSD_SOCKET_ID_MASK)); -} -/*******************************************************************************/ -/* SL_FD_CLR */ -/*******************************************************************************/ -void SL_FD_CLR(_i16 fd, SlFdSet_t *fdset) -{ - fdset->fd_array[0] &= ~(1<< (fd & BSD_SOCKET_ID_MASK)); -} -/*******************************************************************************/ -/* SL_FD_ISSET */ -/*******************************************************************************/ -_i16 SL_FD_ISSET(_i16 fd, SlFdSet_t *fdset) -{ - if( fdset->fd_array[0] & (1<< (fd & BSD_SOCKET_ID_MASK)) ) - { - return 1; - } - return 0; -} -/*******************************************************************************/ -/* SL_FD_ZERO */ -/*******************************************************************************/ -void SL_FD_ZERO(SlFdSet_t *fdset) -{ - fdset->fd_array[0] = 0; -} - -#endif -#endif - - - diff --git a/drivers/cc3100/src/spawn.c b/drivers/cc3100/src/spawn.c deleted file mode 100644 index bb5575818b..0000000000 --- a/drivers/cc3100/src/spawn.c +++ /dev/null @@ -1,197 +0,0 @@ -/* - * spawn.c - CC31xx/CC32xx Host Driver Implementation - * - * Copyright (C) 2014 Texas Instruments Incorporated - http://www.ti.com/ - * - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * - * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the - * distribution. - * - * Neither the name of Texas Instruments Incorporated nor the names of - * its contributors may be used to endorse or promote products derived - * from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * -*/ - - - -/*****************************************************************************/ -/* Include files */ -/*****************************************************************************/ -#include "simplelink.h" - - -#if (defined (SL_PLATFORM_MULTI_THREADED)) && (!defined (SL_PLATFORM_EXTERNAL_SPAWN)) - -#define _SL_MAX_INTERNAL_SPAWN_ENTRIES 10 - -typedef struct _SlInternalSpawnEntry_t -{ - _SlSpawnEntryFunc_t pEntry; - void* pValue; - struct _SlInternalSpawnEntry_t* pNext; -}_SlInternalSpawnEntry_t; - -typedef struct -{ - _SlInternalSpawnEntry_t SpawnEntries[_SL_MAX_INTERNAL_SPAWN_ENTRIES]; - _SlInternalSpawnEntry_t* pFree; - _SlInternalSpawnEntry_t* pWaitForExe; - _SlInternalSpawnEntry_t* pLastInWaitList; - _SlSyncObj_t SyncObj; - _SlLockObj_t LockObj; -}_SlInternalSpawnCB_t; - -_SlInternalSpawnCB_t g_SlInternalSpawnCB; - - -void _SlInternalSpawnTaskEntry() -{ - _i16 i; - _SlInternalSpawnEntry_t* pEntry; - _u8 LastEntry; - - /* create and lock the locking object. lock in order to avoid race condition - on the first creation */ - sl_LockObjCreate(&g_SlInternalSpawnCB.LockObj,"SlSpawnProtect"); - sl_LockObjLock(&g_SlInternalSpawnCB.LockObj,SL_OS_NO_WAIT); - - /* create and clear the sync object */ - sl_SyncObjCreate(&g_SlInternalSpawnCB.SyncObj,"SlSpawnSync"); - sl_SyncObjWait(&g_SlInternalSpawnCB.SyncObj,SL_OS_NO_WAIT); - - g_SlInternalSpawnCB.pFree = &g_SlInternalSpawnCB.SpawnEntries[0]; - g_SlInternalSpawnCB.pWaitForExe = NULL; - g_SlInternalSpawnCB.pLastInWaitList = NULL; - - /* create the link list between the entries */ - for (i=0 ; i<_SL_MAX_INTERNAL_SPAWN_ENTRIES - 1 ; i++) - { - g_SlInternalSpawnCB.SpawnEntries[i].pNext = &g_SlInternalSpawnCB.SpawnEntries[i+1]; - g_SlInternalSpawnCB.SpawnEntries[i].pEntry = NULL; - } - g_SlInternalSpawnCB.SpawnEntries[i].pNext = NULL; - - _SlDrvObjUnLock(&g_SlInternalSpawnCB.LockObj); - - /* here we ready to execute entries */ - - while (TRUE) - { - sl_SyncObjWait(&g_SlInternalSpawnCB.SyncObj,SL_OS_WAIT_FOREVER); - /* go over all entries that already waiting for execution */ - LastEntry = FALSE; - do - { - /* get entry to execute */ - _SlDrvObjLockWaitForever(&g_SlInternalSpawnCB.LockObj); - - pEntry = g_SlInternalSpawnCB.pWaitForExe; - if ( NULL == pEntry ) - { - _SlDrvObjUnLock(&g_SlInternalSpawnCB.LockObj); - break; - } - g_SlInternalSpawnCB.pWaitForExe = pEntry->pNext; - if (pEntry == g_SlInternalSpawnCB.pLastInWaitList) - { - g_SlInternalSpawnCB.pLastInWaitList = NULL; - LastEntry = TRUE; - } - - _SlDrvObjUnLock(&g_SlInternalSpawnCB.LockObj); - - /* pEntry could be null in case that the sync was already set by some - of the entries during execution of earlier entry */ - if (NULL != pEntry) - { - pEntry->pEntry(pEntry->pValue); - /* free the entry */ - - _SlDrvObjLockWaitForever(&g_SlInternalSpawnCB.LockObj); - - pEntry->pNext = g_SlInternalSpawnCB.pFree; - g_SlInternalSpawnCB.pFree = pEntry; - - - if (NULL != g_SlInternalSpawnCB.pWaitForExe) - { - /* new entry received meanwhile */ - LastEntry = FALSE; - } - - _SlDrvObjUnLock(&g_SlInternalSpawnCB.LockObj); - - } - - }while (!LastEntry); - } -} - - -_i16 _SlInternalSpawn(_SlSpawnEntryFunc_t pEntry , void* pValue , _u32 flags) -{ - _i16 Res = 0; - _SlInternalSpawnEntry_t* pSpawnEntry; - - if (NULL == pEntry) - { - Res = -1; - } - else - { - _SlDrvObjLockWaitForever(&g_SlInternalSpawnCB.LockObj); - - pSpawnEntry = g_SlInternalSpawnCB.pFree; - g_SlInternalSpawnCB.pFree = pSpawnEntry->pNext; - - pSpawnEntry->pEntry = pEntry; - pSpawnEntry->pValue = pValue; - pSpawnEntry->pNext = NULL; - - if (NULL == g_SlInternalSpawnCB.pWaitForExe) - { - g_SlInternalSpawnCB.pWaitForExe = pSpawnEntry; - g_SlInternalSpawnCB.pLastInWaitList = pSpawnEntry; - } - else - { - g_SlInternalSpawnCB.pLastInWaitList->pNext = pSpawnEntry; - g_SlInternalSpawnCB.pLastInWaitList = pSpawnEntry; - } - - _SlDrvObjUnLock(&g_SlInternalSpawnCB.LockObj); - - /* this sync is called after releasing the lock object to avoid unnecessary context switches */ - _SlDrvSyncObjSignal(&g_SlInternalSpawnCB.SyncObj); - } - - return Res; -} - - - - - -#endif diff --git a/drivers/cc3100/src/wlan.c b/drivers/cc3100/src/wlan.c deleted file mode 100644 index 59adf02f02..0000000000 --- a/drivers/cc3100/src/wlan.c +++ /dev/null @@ -1,1006 +0,0 @@ -/* -* wlan.c - CC31xx/CC32xx Host Driver Implementation -* -* Copyright (C) 2014 Texas Instruments Incorporated - http://www.ti.com/ -* -* -* Redistribution and use in source and binary forms, with or without -* modification, are permitted provided that the following conditions -* are met: -* -* Redistributions of source code must retain the above copyright -* notice, this list of conditions and the following disclaimer. -* -* Redistributions in binary form must reproduce the above copyright -* notice, this list of conditions and the following disclaimer in the -* documentation and/or other materials provided with the -* distribution. -* -* Neither the name of Texas Instruments Incorporated nor the names of -* its contributors may be used to endorse or promote products derived -* from this software without specific prior written permission. -* -* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -* -*/ - - - -/*****************************************************************************/ -/* Include files */ -/*****************************************************************************/ -#include "simplelink.h" -#include "protocol.h" -#include "driver.h" - -/*****************************************************************************/ -/* Macro declarations */ -/*****************************************************************************/ -#define MAX_SSID_LEN (32) -#define MAX_KEY_LEN (63) -#define MAX_USER_LEN (32) -#define MAX_ANON_USER_LEN (32) -#define MAX_SMART_CONFIG_KEY (16) - - -/***************************************************************************** -sl_WlanConnect -*****************************************************************************/ -typedef struct -{ - _WlanConnectEapCommand_t Args; - _i8 Strings[MAX_SSID_LEN + MAX_KEY_LEN + MAX_USER_LEN + MAX_ANON_USER_LEN]; -}_WlanConnectCmd_t; - -typedef union -{ - _WlanConnectCmd_t Cmd; - _BasicResponse_t Rsp; -}_SlWlanConnectMsg_u; - - -#if _SL_INCLUDE_FUNC(sl_WlanConnect) -_i16 sl_WlanConnect(const _i8* pName,const _i16 NameLen,const _u8 *pMacAddr,const SlSecParams_t* pSecParams ,const SlSecParamsExt_t* pSecExtParams) -{ - _SlWlanConnectMsg_u Msg; - _SlCmdCtrl_t CmdCtrl; - - sl_Memset (&Msg, 0, sizeof(Msg)); - - CmdCtrl.TxDescLen = 0;/* init */ - CmdCtrl.RxDescLen = sizeof(_BasicResponse_t); - - /* verify SSID length */ - VERIFY_PROTOCOL(NameLen <= MAX_SSID_LEN); - /* verify SSID is not NULL */ - if( NULL == pName ) - { - return SL_INVALPARAM; - } - /* update SSID length */ - Msg.Cmd.Args.Common.SsidLen = (_u8)NameLen; - - /* Profile with no security */ - /* Enterprise security profile */ - if (NULL != pSecExtParams) - { - /* Update command opcode */ - CmdCtrl.Opcode = SL_OPCODE_WLAN_WLANCONNECTEAPCOMMAND; - CmdCtrl.TxDescLen += sizeof(_WlanConnectEapCommand_t); - /* copy SSID */ - sl_Memcpy(EAP_SSID_STRING(&Msg), pName, NameLen); - CmdCtrl.TxDescLen += NameLen; - /* Copy password if supplied */ - if ((NULL != pSecParams) && (pSecParams->KeyLen > 0)) - { - /* update security type */ - Msg.Cmd.Args.Common.SecType = pSecParams->Type; - /* verify key length */ - if (pSecParams->KeyLen > MAX_KEY_LEN) - { - return SL_INVALPARAM; - } - /* update key length */ - Msg.Cmd.Args.Common.PasswordLen = pSecParams->KeyLen; - ARG_CHECK_PTR(pSecParams->Key); - /* copy key */ - sl_Memcpy(EAP_PASSWORD_STRING(&Msg), pSecParams->Key, pSecParams->KeyLen); - CmdCtrl.TxDescLen += pSecParams->KeyLen; - } - else - { - Msg.Cmd.Args.Common.PasswordLen = 0; - } - - ARG_CHECK_PTR(pSecExtParams); - /* Update Eap bitmask */ - Msg.Cmd.Args.EapBitmask = pSecExtParams->EapMethod; - /* Update Certificate file ID index - currently not supported */ - Msg.Cmd.Args.CertIndex = pSecExtParams->CertIndex; - /* verify user length */ - if (pSecExtParams->UserLen > MAX_USER_LEN) - { - return SL_INVALPARAM; - } - Msg.Cmd.Args.UserLen = pSecExtParams->UserLen; - /* copy user name (identity) */ - if(pSecExtParams->UserLen > 0) - { - sl_Memcpy(EAP_USER_STRING(&Msg), pSecExtParams->User, pSecExtParams->UserLen); - CmdCtrl.TxDescLen += pSecExtParams->UserLen; - } - /* verify Anonymous user length */ - if (pSecExtParams->AnonUserLen > MAX_ANON_USER_LEN) - { - return SL_INVALPARAM; - } - Msg.Cmd.Args.AnonUserLen = pSecExtParams->AnonUserLen; - /* copy Anonymous user */ - if(pSecExtParams->AnonUserLen > 0) - { - sl_Memcpy(EAP_ANON_USER_STRING(&Msg), pSecExtParams->AnonUser, pSecExtParams->AnonUserLen); - CmdCtrl.TxDescLen += pSecExtParams->AnonUserLen; - } - - } - - /* Regular or open security profile */ - else - { - /* Update command opcode */ - CmdCtrl.Opcode = SL_OPCODE_WLAN_WLANCONNECTCOMMAND; - CmdCtrl.TxDescLen += sizeof(_WlanConnectCommon_t); - /* copy SSID */ - sl_Memcpy(SSID_STRING(&Msg), pName, NameLen); - CmdCtrl.TxDescLen += NameLen; - /* Copy password if supplied */ - if( NULL != pSecParams ) - { - /* update security type */ - Msg.Cmd.Args.Common.SecType = pSecParams->Type; - /* verify key length is valid */ - if (pSecParams->KeyLen > MAX_KEY_LEN) - { - return SL_INVALPARAM; - } - /* update key length */ - Msg.Cmd.Args.Common.PasswordLen = pSecParams->KeyLen; - CmdCtrl.TxDescLen += pSecParams->KeyLen; - /* copy key (could be no key in case of WPS pin) */ - if( NULL != pSecParams->Key ) - { - sl_Memcpy(PASSWORD_STRING(&Msg), pSecParams->Key, pSecParams->KeyLen); - } - } - /* Profile with no security */ - else - { - Msg.Cmd.Args.Common.PasswordLen = 0; - Msg.Cmd.Args.Common.SecType = SL_SEC_TYPE_OPEN; - } - } - /* If BSSID is not null, copy to buffer, otherwise set to 0 */ - if(NULL != pMacAddr) - { - sl_Memcpy(Msg.Cmd.Args.Common.Bssid, pMacAddr, sizeof(Msg.Cmd.Args.Common.Bssid)); - } - else - { - _SlDrvMemZero(Msg.Cmd.Args.Common.Bssid, sizeof(Msg.Cmd.Args.Common.Bssid)); - } - - - VERIFY_RET_OK ( _SlDrvCmdOp(&CmdCtrl, &Msg, NULL)); - - return (_i16)Msg.Rsp.status; -} -#endif - -/*******************************************************************************/ -/* sl_Disconnect */ -/* ******************************************************************************/ -#if _SL_INCLUDE_FUNC(sl_WlanDisconnect) -_i16 sl_WlanDisconnect(void) -{ - return _SlDrvBasicCmd(SL_OPCODE_WLAN_WLANDISCONNECTCOMMAND); -} -#endif - -/******************************************************************************/ -/* sl_PolicySet */ -/******************************************************************************/ -typedef union -{ - _WlanPoliciySetGet_t Cmd; - _BasicResponse_t Rsp; -}_SlPolicyMsg_u; - -#if _SL_INCLUDE_FUNC(sl_WlanPolicySet) - -const _SlCmdCtrl_t _SlPolicySetCmdCtrl = -{ - SL_OPCODE_WLAN_POLICYSETCOMMAND, - sizeof(_WlanPoliciySetGet_t), - sizeof(_BasicResponse_t) -}; - -_i16 sl_WlanPolicySet(const _u8 Type , const _u8 Policy, _u8 *pVal,const _u8 ValLen) -{ - _SlPolicyMsg_u Msg; - _SlCmdExt_t CmdExt; - - - _SlDrvResetCmdExt(&CmdExt); - CmdExt.TxPayloadLen = ValLen; - CmdExt.pTxPayload = (_u8 *)pVal; - - - Msg.Cmd.PolicyType = Type; - Msg.Cmd.PolicyOption = Policy; - Msg.Cmd.PolicyOptionLen = ValLen; - - VERIFY_RET_OK(_SlDrvCmdOp((_SlCmdCtrl_t *)&_SlPolicySetCmdCtrl, &Msg, &CmdExt)); - - return (_i16)Msg.Rsp.status; -} -#endif - - -/******************************************************************************/ -/* sl_PolicyGet */ -/******************************************************************************/ -typedef union -{ - _WlanPoliciySetGet_t Cmd; - _WlanPoliciySetGet_t Rsp; -}_SlPolicyGetMsg_u; - -#if _SL_INCLUDE_FUNC(sl_WlanPolicyGet) - -const _SlCmdCtrl_t _SlPolicyGetCmdCtrl = -{ - SL_OPCODE_WLAN_POLICYGETCOMMAND, - sizeof(_WlanPoliciySetGet_t), - sizeof(_WlanPoliciySetGet_t) -}; - -_i16 sl_WlanPolicyGet(const _u8 Type ,_u8 Policy,_u8 *pVal,_u8 *pValLen) -{ - _SlPolicyGetMsg_u Msg; - _SlCmdExt_t CmdExt; - - if (*pValLen == 0) - { - return SL_EZEROLEN; - } - - _SlDrvResetCmdExt(&CmdExt); - CmdExt.RxPayloadLen = *pValLen; - CmdExt.pRxPayload = pVal; - - Msg.Cmd.PolicyType = Type; - Msg.Cmd.PolicyOption = Policy; - VERIFY_RET_OK(_SlDrvCmdOp((_SlCmdCtrl_t *)&_SlPolicyGetCmdCtrl, &Msg, &CmdExt)); - - - if (CmdExt.RxPayloadLen < CmdExt.ActualRxPayloadLen) - { - *pValLen = Msg.Rsp.PolicyOptionLen; - return SL_ESMALLBUF; - } - else - { - /* no pointer valus, fill the results into _i8 */ - *pValLen = (_u8)CmdExt.ActualRxPayloadLen; - if( 0 == CmdExt.ActualRxPayloadLen ) - { - *pValLen = 1; - pVal[0] = Msg.Rsp.PolicyOption; - } - } - return (_i16)SL_OS_RET_CODE_OK; -} -#endif - - -/*******************************************************************************/ -/* sl_ProfileAdd */ -/*******************************************************************************/ -typedef struct -{ - _WlanAddGetEapProfile_t Args; - _i8 Strings[MAX_SSID_LEN + MAX_KEY_LEN + MAX_USER_LEN + MAX_ANON_USER_LEN]; -}_SlProfileParams_t; - -typedef union -{ - _SlProfileParams_t Cmd; - _BasicResponse_t Rsp; -}_SlProfileAddMsg_u; - - - -#if _SL_INCLUDE_FUNC(sl_WlanProfileAdd) -_i16 sl_WlanProfileAdd(const _i8* pName,const _i16 NameLen,const _u8 *pMacAddr,const SlSecParams_t* pSecParams ,const SlSecParamsExt_t* pSecExtParams,const _u32 Priority,const _u32 Options) -{ - _SlProfileAddMsg_u Msg; - _SlCmdCtrl_t CmdCtrl = {0}; - CmdCtrl.TxDescLen = 0;/* init */ - CmdCtrl.RxDescLen = sizeof(_BasicResponse_t); - - /* update priority */ - Msg.Cmd.Args.Common.Priority = (_u8)Priority; - /* verify SSID is not NULL */ - if( NULL == pName ) - { - return SL_INVALPARAM; - } - /* verify SSID length */ - VERIFY_PROTOCOL(NameLen <= MAX_SSID_LEN); - /* update SSID length */ - Msg.Cmd.Args.Common.SsidLen = (_u8)NameLen; - - - /* Enterprise security profile */ - if (NULL != pSecExtParams) - { - /* Update command opcode */ - CmdCtrl.Opcode = SL_OPCODE_WLAN_EAP_PROFILEADDCOMMAND; - CmdCtrl.TxDescLen += sizeof(_WlanAddGetEapProfile_t); - - /* copy SSID */ - sl_Memcpy(EAP_PROFILE_SSID_STRING(&Msg), pName, NameLen); - CmdCtrl.TxDescLen += NameLen; - - /* Copy password if supplied */ - if ((NULL != pSecParams) && (pSecParams->KeyLen > 0)) - { - /* update security type */ - Msg.Cmd.Args.Common.SecType = pSecParams->Type; - - if( SL_SEC_TYPE_WEP == Msg.Cmd.Args.Common.SecType ) - { - Msg.Cmd.Args.Common.WepKeyId = 0; - } - - /* verify key length */ - if (pSecParams->KeyLen > MAX_KEY_LEN) - { - return SL_INVALPARAM; - } - VERIFY_PROTOCOL(pSecParams->KeyLen <= MAX_KEY_LEN); - /* update key length */ - Msg.Cmd.Args.Common.PasswordLen = pSecParams->KeyLen; - CmdCtrl.TxDescLen += pSecParams->KeyLen; - ARG_CHECK_PTR(pSecParams->Key); - /* copy key */ - sl_Memcpy(EAP_PROFILE_PASSWORD_STRING(&Msg), pSecParams->Key, pSecParams->KeyLen); - } - else - { - Msg.Cmd.Args.Common.PasswordLen = 0; - } - - ARG_CHECK_PTR(pSecExtParams); - /* Update Eap bitmask */ - Msg.Cmd.Args.EapBitmask = pSecExtParams->EapMethod; - /* Update Certificate file ID index - currently not supported */ - Msg.Cmd.Args.CertIndex = pSecExtParams->CertIndex; - /* verify user length */ - if (pSecExtParams->UserLen > MAX_USER_LEN) - { - return SL_INVALPARAM; - } - Msg.Cmd.Args.UserLen = pSecExtParams->UserLen; - /* copy user name (identity) */ - if(pSecExtParams->UserLen > 0) - { - sl_Memcpy(EAP_PROFILE_USER_STRING(&Msg), pSecExtParams->User, pSecExtParams->UserLen); - CmdCtrl.TxDescLen += pSecExtParams->UserLen; - } - - /* verify Anonymous user length (for tunneled) */ - if (pSecExtParams->AnonUserLen > MAX_ANON_USER_LEN) - { - return SL_INVALPARAM; - } - Msg.Cmd.Args.AnonUserLen = pSecExtParams->AnonUserLen; - - /* copy Anonymous user */ - if(pSecExtParams->AnonUserLen > 0) - { - sl_Memcpy(EAP_PROFILE_ANON_USER_STRING(&Msg), pSecExtParams->AnonUser, pSecExtParams->AnonUserLen); - CmdCtrl.TxDescLen += pSecExtParams->AnonUserLen; - } - - } - /* Regular or open security profile */ - else - { - /* Update command opcode */ - CmdCtrl.Opcode = SL_OPCODE_WLAN_PROFILEADDCOMMAND; - /* update commnad length */ - CmdCtrl.TxDescLen += sizeof(_WlanAddGetProfile_t); - - if (NULL != pName) - { - /* copy SSID */ - sl_Memcpy(PROFILE_SSID_STRING(&Msg), pName, NameLen); - CmdCtrl.TxDescLen += NameLen; - } - - /* Copy password if supplied */ - if( NULL != pSecParams ) - { - /* update security type */ - Msg.Cmd.Args.Common.SecType = pSecParams->Type; - - if( SL_SEC_TYPE_WEP == Msg.Cmd.Args.Common.SecType ) - { - Msg.Cmd.Args.Common.WepKeyId = 0; - } - - /* verify key length */ - if (pSecParams->KeyLen > MAX_KEY_LEN) - { - return SL_INVALPARAM; - } - /* update key length */ - Msg.Cmd.Args.Common.PasswordLen = pSecParams->KeyLen; - CmdCtrl.TxDescLen += pSecParams->KeyLen; - /* copy key (could be no key in case of WPS pin) */ - if( NULL != pSecParams->Key ) - { - sl_Memcpy(PROFILE_PASSWORD_STRING(&Msg), pSecParams->Key, pSecParams->KeyLen); - } - } - else - { - Msg.Cmd.Args.Common.SecType = SL_SEC_TYPE_OPEN; - Msg.Cmd.Args.Common.PasswordLen = 0; - } - - } - - - /* If BSSID is not null, copy to buffer, otherwise set to 0 */ - if(NULL != pMacAddr) - { - sl_Memcpy(Msg.Cmd.Args.Common.Bssid, pMacAddr, sizeof(Msg.Cmd.Args.Common.Bssid)); - } - else - { - _SlDrvMemZero(Msg.Cmd.Args.Common.Bssid, sizeof(Msg.Cmd.Args.Common.Bssid)); - } - - VERIFY_RET_OK(_SlDrvCmdOp(&CmdCtrl, &Msg, NULL)); - - return (_i16)Msg.Rsp.status; -} -#endif -/*******************************************************************************/ -/* sl_ProfileGet */ -/*******************************************************************************/ -typedef union -{ - _WlanProfileDelGetCommand_t Cmd; - _SlProfileParams_t Rsp; -}_SlProfileGetMsg_u; - - -#if _SL_INCLUDE_FUNC(sl_WlanProfileGet) - -const _SlCmdCtrl_t _SlProfileGetCmdCtrl = -{ - SL_OPCODE_WLAN_PROFILEGETCOMMAND, - sizeof(_WlanProfileDelGetCommand_t), - sizeof(_SlProfileParams_t) -}; - -_i16 sl_WlanProfileGet(const _i16 Index,_i8* pName, _i16 *pNameLen, _u8 *pMacAddr, SlSecParams_t* pSecParams, SlGetSecParamsExt_t* pEntParams, _u32 *pPriority) -{ - _SlProfileGetMsg_u Msg; - Msg.Cmd.index = (_u8)Index; - - VERIFY_RET_OK(_SlDrvCmdOp((_SlCmdCtrl_t *)&_SlProfileGetCmdCtrl, &Msg, NULL)); - - pSecParams->Type = Msg.Rsp.Args.Common.SecType; - /* since password is not transferred in getprofile, password length should always be zero */ - pSecParams->KeyLen = Msg.Rsp.Args.Common.PasswordLen; - if (NULL != pEntParams) - { - pEntParams->UserLen = Msg.Rsp.Args.UserLen; - /* copy user name */ - if (pEntParams->UserLen > 0) - { - sl_Memcpy(pEntParams->User, EAP_PROFILE_USER_STRING(&Msg), pEntParams->UserLen); - } - pEntParams->AnonUserLen = Msg.Rsp.Args.AnonUserLen; - /* copy anonymous user name */ - if (pEntParams->AnonUserLen > 0) - { - sl_Memcpy(pEntParams->AnonUser, EAP_PROFILE_ANON_USER_STRING(&Msg), pEntParams->AnonUserLen); - } - } - - *pNameLen = Msg.Rsp.Args.Common.SsidLen; - *pPriority = Msg.Rsp.Args.Common.Priority; - - if (NULL != Msg.Rsp.Args.Common.Bssid) - { - sl_Memcpy(pMacAddr, Msg.Rsp.Args.Common.Bssid, sizeof(Msg.Rsp.Args.Common.Bssid)); - } - - sl_Memcpy(pName, EAP_PROFILE_SSID_STRING(&Msg), *pNameLen); - - return (_i16)Msg.Rsp.Args.Common.SecType; - -} -#endif -/*******************************************************************************/ -/* sl_ProfileDel */ -/*******************************************************************************/ -typedef union -{ - _WlanProfileDelGetCommand_t Cmd; - _BasicResponse_t Rsp; -}_SlProfileDelMsg_u; - - -#if _SL_INCLUDE_FUNC(sl_WlanProfileDel) - -const _SlCmdCtrl_t _SlProfileDelCmdCtrl = -{ - SL_OPCODE_WLAN_PROFILEDELCOMMAND, - sizeof(_WlanProfileDelGetCommand_t), - sizeof(_BasicResponse_t) -}; - -_i16 sl_WlanProfileDel(const _i16 Index) -{ - _SlProfileDelMsg_u Msg; - - Msg.Cmd.index = (_u8)Index; - - VERIFY_RET_OK(_SlDrvCmdOp((_SlCmdCtrl_t *)&_SlProfileDelCmdCtrl, &Msg, NULL)); - - return (_i16)Msg.Rsp.status; -} -#endif - - -/******************************************************************************/ -/* sl_WlanGetNetworkList */ -/******************************************************************************/ -typedef union -{ - _WlanGetNetworkListCommand_t Cmd; - _WlanGetNetworkListResponse_t Rsp; -}_SlWlanGetNetworkListMsg_u; - - -#if _SL_INCLUDE_FUNC(sl_WlanGetNetworkList) - -const _SlCmdCtrl_t _SlWlanGetNetworkListCtrl = -{ - SL_OPCODE_WLAN_SCANRESULTSGETCOMMAND, - sizeof(_WlanGetNetworkListCommand_t), - sizeof(_WlanGetNetworkListResponse_t) -}; - -_i16 sl_WlanGetNetworkList(const _u8 Index,const _u8 Count, Sl_WlanNetworkEntry_t *pEntries) -{ - _i16 retVal = 0; - _SlWlanGetNetworkListMsg_u Msg; - _SlCmdExt_t CmdExt; - - if (Count == 0) - { - return SL_EZEROLEN; - } - - _SlDrvResetCmdExt(&CmdExt); - CmdExt.RxPayloadLen = sizeof(Sl_WlanNetworkEntry_t)*(Count); - CmdExt.pRxPayload = (_u8 *)pEntries; - - Msg.Cmd.index = Index; - Msg.Cmd.count = Count; - - VERIFY_RET_OK(_SlDrvCmdOp((_SlCmdCtrl_t *)&_SlWlanGetNetworkListCtrl, &Msg, &CmdExt)); - retVal = Msg.Rsp.status; - - return (_i16)retVal; -} -#endif - - - - - -/******************************************************************************/ -/* RX filters message command response structures */ -/******************************************************************************/ - -/* Set command */ -typedef union -{ - _WlanRxFilterAddCommand_t Cmd; - _WlanRxFilterAddCommandReponse_t Rsp; -}_SlrxFilterAddMsg_u; - - -/* Set command */ -typedef union _SlRxFilterSetMsg_u -{ - _WlanRxFilterSetCommand_t Cmd; - _WlanRxFilterSetCommandReponse_t Rsp; -}_SlRxFilterSetMsg_u; - - -/* Get command */ -typedef union _SlRxFilterGetMsg_u -{ - _WlanRxFilterGetCommand_t Cmd; - _WlanRxFilterGetCommandReponse_t Rsp; -}_SlRxFilterGetMsg_u; - -#if _SL_INCLUDE_FUNC(sl_WlanRxFilterAdd) - -const _SlCmdCtrl_t _SlRxFilterAddtCmdCtrl = -{ - SL_OPCODE_WLAN_WLANRXFILTERADDCOMMAND, - sizeof(_WlanRxFilterAddCommand_t), - sizeof(_WlanRxFilterAddCommandReponse_t) -}; - - -/***************************************************************************** - RX filters -*****************************************************************************/ -SlrxFilterID_t sl_WlanRxFilterAdd( SlrxFilterRuleType_t RuleType, - SlrxFilterFlags_t FilterFlags, - const SlrxFilterRule_t* const Rule, - const SlrxFilterTrigger_t* const Trigger, - const SlrxFilterAction_t* const Action, - SlrxFilterID_t* pFilterId) -{ - - - _SlrxFilterAddMsg_u Msg; - Msg.Cmd.RuleType = RuleType; - /* filterId is zero */ - Msg.Cmd.FilterId = 0; - Msg.Cmd.FilterFlags = FilterFlags; - sl_Memcpy( &(Msg.Cmd.Rule), Rule, sizeof(SlrxFilterRule_t) ); - sl_Memcpy( &(Msg.Cmd.Trigger), Trigger, sizeof(SlrxFilterTrigger_t) ); - sl_Memcpy( &(Msg.Cmd.Action), Action, sizeof(SlrxFilterAction_t) ); - VERIFY_RET_OK(_SlDrvCmdOp((_SlCmdCtrl_t *)&_SlRxFilterAddtCmdCtrl, &Msg, NULL) ); - *pFilterId = Msg.Rsp.FilterId; - return (_i16)Msg.Rsp.Status; - -} -#endif - - - -/*******************************************************************************/ -/* RX filters */ -/*******************************************************************************/ -#if _SL_INCLUDE_FUNC(sl_WlanRxFilterSet) - -const _SlCmdCtrl_t _SlRxFilterSetCmdCtrl = -{ - SL_OPCODE_WLAN_WLANRXFILTERSETCOMMAND, - sizeof(_WlanRxFilterSetCommand_t), - sizeof(_WlanRxFilterSetCommandReponse_t) -}; - -_i16 sl_WlanRxFilterSet(const SLrxFilterOperation_t RxFilterOperation, - const _u8* const pInputBuffer, - _u16 InputbufferLength) -{ - _SlRxFilterSetMsg_u Msg; - _SlCmdExt_t CmdExt; - - - _SlDrvResetCmdExt(&CmdExt); - CmdExt.TxPayloadLen = InputbufferLength; - CmdExt.pTxPayload = (_u8 *)pInputBuffer; - - Msg.Cmd.RxFilterOperation = RxFilterOperation; - Msg.Cmd.InputBufferLength = InputbufferLength; - - - VERIFY_RET_OK(_SlDrvCmdOp((_SlCmdCtrl_t *)&_SlRxFilterSetCmdCtrl, &Msg, &CmdExt) ); - - - return (_i16)Msg.Rsp.Status; -} -#endif - -/******************************************************************************/ -/* RX filters */ -/******************************************************************************/ -#if _SL_INCLUDE_FUNC(sl_WlanRxFilterGet) - -const _SlCmdCtrl_t _SlRxFilterGetCmdCtrl = -{ - SL_OPCODE_WLAN_WLANRXFILTERGETCOMMAND, - sizeof(_WlanRxFilterGetCommand_t), - sizeof(_WlanRxFilterGetCommandReponse_t) -}; - - -_i16 sl_WlanRxFilterGet(const SLrxFilterOperation_t RxFilterOperation, - _u8* pOutputBuffer, - _u16 OutputbufferLength) -{ - _SlRxFilterGetMsg_u Msg; - _SlCmdExt_t CmdExt; - - if (OutputbufferLength == 0) - { - return SL_EZEROLEN; - } - - _SlDrvResetCmdExt(&CmdExt); - CmdExt.RxPayloadLen = OutputbufferLength; - CmdExt.pRxPayload = (_u8 *)pOutputBuffer; - - Msg.Cmd.RxFilterOperation = RxFilterOperation; - Msg.Cmd.OutputBufferLength = OutputbufferLength; - - - VERIFY_RET_OK(_SlDrvCmdOp((_SlCmdCtrl_t *)&_SlRxFilterGetCmdCtrl, &Msg, &CmdExt) ); - - if (CmdExt.RxPayloadLen < CmdExt.ActualRxPayloadLen) - { - return SL_ESMALLBUF; - } - - return (_i16)Msg.Rsp.Status; -} -#endif - -/*******************************************************************************/ -/* sl_WlanRxStatStart */ -/*******************************************************************************/ -#if _SL_INCLUDE_FUNC(sl_WlanRxStatStart) -_i16 sl_WlanRxStatStart(void) -{ - return _SlDrvBasicCmd(SL_OPCODE_WLAN_STARTRXSTATCOMMAND); -} -#endif - -#if _SL_INCLUDE_FUNC(sl_WlanRxStatStop) -_i16 sl_WlanRxStatStop(void) -{ - return _SlDrvBasicCmd(SL_OPCODE_WLAN_STOPRXSTATCOMMAND); -} -#endif - -#if _SL_INCLUDE_FUNC(sl_WlanRxStatGet) -_i16 sl_WlanRxStatGet(SlGetRxStatResponse_t *pRxStat,const _u32 Flags) -{ - _SlCmdCtrl_t CmdCtrl = {SL_OPCODE_WLAN_GETRXSTATCOMMAND, 0, sizeof(SlGetRxStatResponse_t)}; - - _SlDrvMemZero(pRxStat, sizeof(SlGetRxStatResponse_t)); - VERIFY_RET_OK(_SlDrvCmdOp((_SlCmdCtrl_t *)&CmdCtrl, pRxStat, NULL)); - - return 0; -} -#endif - - - -/******************************************************************************/ -/* sl_WlanSmartConfigStop */ -/******************************************************************************/ -#if _SL_INCLUDE_FUNC(sl_WlanSmartConfigStop) -_i16 sl_WlanSmartConfigStop(void) -{ - return _SlDrvBasicCmd(SL_OPCODE_WLAN_SMART_CONFIG_STOP_COMMAND); -} -#endif - - -/******************************************************************************/ -/* sl_WlanSmartConfigStart */ -/******************************************************************************/ - - -typedef struct -{ - _WlanSmartConfigStartCommand_t Args; - _i8 Strings[3 * MAX_SMART_CONFIG_KEY]; /* public key + groupId1 key + groupId2 key */ -}_SlSmartConfigStart_t; - -typedef union -{ - _SlSmartConfigStart_t Cmd; - _BasicResponse_t Rsp; -}_SlSmartConfigStartMsg_u; - -#if _SL_INCLUDE_FUNC(sl_WlanSmartConfigStart) - -const _SlCmdCtrl_t _SlSmartConfigStartCmdCtrl = -{ - SL_OPCODE_WLAN_SMART_CONFIG_START_COMMAND, - sizeof(_SlSmartConfigStart_t), - sizeof(_BasicResponse_t) -}; - -_i16 sl_WlanSmartConfigStart( const _u32 groupIdBitmask, - const _u8 cipher, - const _u8 publicKeyLen, - const _u8 group1KeyLen, - const _u8 group2KeyLen, - const _u8* pPublicKey, - const _u8* pGroup1Key, - const _u8* pGroup2Key) -{ - _SlSmartConfigStartMsg_u Msg; - - Msg.Cmd.Args.groupIdBitmask = (_u8)groupIdBitmask; - Msg.Cmd.Args.cipher = (_u8)cipher; - Msg.Cmd.Args.publicKeyLen = (_u8)publicKeyLen; - Msg.Cmd.Args.group1KeyLen = (_u8)group1KeyLen; - Msg.Cmd.Args.group2KeyLen = (_u8)group2KeyLen; - - /* copy keys (if exist) after command (one after another) */ - sl_Memcpy(SMART_CONFIG_START_PUBLIC_KEY_STRING(&Msg), pPublicKey, publicKeyLen); - sl_Memcpy(SMART_CONFIG_START_GROUP1_KEY_STRING(&Msg), pGroup1Key, group1KeyLen); - sl_Memcpy(SMART_CONFIG_START_GROUP2_KEY_STRING(&Msg), pGroup2Key, group2KeyLen); - - VERIFY_RET_OK(_SlDrvCmdOp((_SlCmdCtrl_t *)&_SlSmartConfigStartCmdCtrl , &Msg, NULL)); - - return (_i16)Msg.Rsp.status; - - -} -#endif - - -/*******************************************************************************/ -/* sl_WlanSetMode */ -/*******************************************************************************/ -typedef union -{ - _WlanSetMode_t Cmd; - _BasicResponse_t Rsp; -}_SlwlanSetModeMsg_u; - -#if _SL_INCLUDE_FUNC(sl_WlanSetMode) - -const _SlCmdCtrl_t _SlWlanSetModeCmdCtrl = -{ - SL_OPCODE_WLAN_SET_MODE, - sizeof(_WlanSetMode_t), - sizeof(_BasicResponse_t) -}; - -/* possible values are: -WLAN_SET_STA_MODE = 1 -WLAN_SET_AP_MODE = 2 -WLAN_SET_P2P_MODE = 3 */ -_i16 sl_WlanSetMode(const _u8 mode) -{ - _SlwlanSetModeMsg_u Msg; - - Msg.Cmd.mode = mode; - - VERIFY_RET_OK(_SlDrvCmdOp((_SlCmdCtrl_t *)&_SlWlanSetModeCmdCtrl , &Msg, NULL)); - - return (_i16)Msg.Rsp.status; -} -#endif - - - - -/*******************************************************************************/ -/* sl_WlanSet */ -/* ******************************************************************************/ -typedef union -{ - _WlanCfgSetGet_t Cmd; - _BasicResponse_t Rsp; -}_SlWlanCfgSetMsg_u; - - -#if _SL_INCLUDE_FUNC(sl_WlanSet) - -const _SlCmdCtrl_t _SlWlanCfgSetCmdCtrl = -{ - SL_OPCODE_WLAN_CFG_SET, - sizeof(_WlanCfgSetGet_t), - sizeof(_BasicResponse_t) -}; - -_i16 sl_WlanSet(const _u16 ConfigId ,const _u16 ConfigOpt,const _u16 ConfigLen,const _u8 *pValues) -{ - _SlWlanCfgSetMsg_u Msg; - _SlCmdExt_t CmdExt; - - _SlDrvResetCmdExt(&CmdExt); - CmdExt.TxPayloadLen = (ConfigLen+3) & (~3); - CmdExt.pTxPayload = (_u8 *)pValues; - - Msg.Cmd.ConfigId = ConfigId; - Msg.Cmd.ConfigLen = ConfigLen; - Msg.Cmd.ConfigOpt = ConfigOpt; - - VERIFY_RET_OK(_SlDrvCmdOp((_SlCmdCtrl_t *)&_SlWlanCfgSetCmdCtrl, &Msg, &CmdExt)); - - return (_i16)Msg.Rsp.status; -} -#endif - - -/******************************************************************************/ -/* sl_WlanGet */ -/******************************************************************************/ -typedef union -{ - _WlanCfgSetGet_t Cmd; - _WlanCfgSetGet_t Rsp; -}_SlWlanCfgMsgGet_u; - -#if _SL_INCLUDE_FUNC(sl_WlanGet) - -const _SlCmdCtrl_t _SlWlanCfgGetCmdCtrl = -{ - SL_OPCODE_WLAN_CFG_GET, - sizeof(_WlanCfgSetGet_t), - sizeof(_WlanCfgSetGet_t) -}; - -_i16 sl_WlanGet(const _u16 ConfigId, _u16 *pConfigOpt,_u16 *pConfigLen, _u8 *pValues) -{ - _SlWlanCfgMsgGet_u Msg; - _SlCmdExt_t CmdExt; - - if (*pConfigLen == 0) - { - return SL_EZEROLEN; - } - - _SlDrvResetCmdExt(&CmdExt); - CmdExt.RxPayloadLen = *pConfigLen; - CmdExt.pRxPayload = (_u8 *)pValues; - - Msg.Cmd.ConfigId = ConfigId; - if( pConfigOpt ) - { - Msg.Cmd.ConfigOpt = (_u16)*pConfigOpt; - } - VERIFY_RET_OK(_SlDrvCmdOp((_SlCmdCtrl_t *)&_SlWlanCfgGetCmdCtrl, &Msg, &CmdExt)); - - if( pConfigOpt ) - { - *pConfigOpt = (_u8)Msg.Rsp.ConfigOpt; - } - if (CmdExt.RxPayloadLen < CmdExt.ActualRxPayloadLen) - { - *pConfigLen = (_u8)CmdExt.RxPayloadLen; - return SL_ESMALLBUF; - } - else - { - *pConfigLen = (_u8)CmdExt.ActualRxPayloadLen; - } - - - return (_i16)Msg.Rsp.Status; -} -#endif diff --git a/drivers/dht/dht.c b/drivers/dht/dht.c deleted file mode 100644 index 5d92ae39a3..0000000000 --- a/drivers/dht/dht.c +++ /dev/null @@ -1,89 +0,0 @@ -/* - * This file is part of the MicroPython project, http://micropython.org/ - * - * The MIT License (MIT) - * - * Copyright (c) 2016 Damien P. George - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ - -#include - -#include "py/runtime.h" -#include "py/mperrno.h" -#include "py/mphal.h" -#include "extmod/machine_pulse.h" -#include "drivers/dht/dht.h" - -STATIC mp_obj_t dht_readinto(mp_obj_t pin_in, mp_obj_t buf_in) { - mp_hal_pin_obj_t pin = mp_hal_get_pin_obj(pin_in); - mp_hal_pin_open_drain(pin); - - mp_buffer_info_t bufinfo; - mp_get_buffer_raise(buf_in, &bufinfo, MP_BUFFER_WRITE); - - if (bufinfo.len < 5) { - mp_raise_ValueError("buffer too small"); - } - - // issue start command - mp_hal_pin_od_high(pin); - mp_hal_delay_ms(250); - mp_hal_pin_od_low(pin); - mp_hal_delay_ms(18); - - mp_uint_t irq_state = mp_hal_quiet_timing_enter(); - - // release the line so the device can respond - mp_hal_pin_od_high(pin); - mp_hal_delay_us_fast(10); - - // wait for device to respond - mp_uint_t ticks = mp_hal_ticks_us(); - while (mp_hal_pin_read(pin) != 0) { - if ((mp_uint_t)(mp_hal_ticks_us() - ticks) > 100) { - goto timeout; - } - } - - // time pulse, should be 80us - ticks = machine_time_pulse_us(pin, 1, 150); - if ((mp_int_t)ticks < 0) { - goto timeout; - } - - // time 40 pulses for data (either 26us or 70us) - uint8_t *buf = bufinfo.buf; - for (int i = 0; i < 40; ++i) { - ticks = machine_time_pulse_us(pin, 1, 100); - if ((mp_int_t)ticks < 0) { - goto timeout; - } - buf[i / 8] = (buf[i / 8] << 1) | (ticks > 48); - } - - mp_hal_quiet_timing_exit(irq_state); - return mp_const_none; - -timeout: - mp_hal_quiet_timing_exit(irq_state); - mp_raise_OSError(MP_ETIMEDOUT); -} -MP_DEFINE_CONST_FUN_OBJ_2(dht_readinto_obj, dht_readinto); diff --git a/drivers/dht/dht.h b/drivers/dht/dht.h deleted file mode 100644 index 883e077961..0000000000 --- a/drivers/dht/dht.h +++ /dev/null @@ -1,8 +0,0 @@ -#ifndef MICROPY_INCLUDED_DRIVERS_DHT_DHT_H -#define MICROPY_INCLUDED_DRIVERS_DHT_DHT_H - -#include "py/obj.h" - -MP_DECLARE_CONST_FUN_OBJ_2(dht_readinto_obj); - -#endif // MICROPY_INCLUDED_DRIVERS_DHT_DHT_H diff --git a/drivers/display/lcd160cr.py b/drivers/display/lcd160cr.py deleted file mode 100644 index dd9ab9985b..0000000000 --- a/drivers/display/lcd160cr.py +++ /dev/null @@ -1,474 +0,0 @@ -# Driver for official MicroPython LCD160CR display -# MIT license; Copyright (c) 2017 Damien P. George - -from micropython import const -from utime import sleep_ms -from ustruct import calcsize, pack_into -import uerrno, machine - -# for set_orient -PORTRAIT = const(0) -LANDSCAPE = const(1) -PORTRAIT_UPSIDEDOWN = const(2) -LANDSCAPE_UPSIDEDOWN = const(3) - -# for set_startup_deco; can be or'd -STARTUP_DECO_NONE = const(0) -STARTUP_DECO_MLOGO = const(1) -STARTUP_DECO_INFO = const(2) - -_uart_baud_table = { - 2400: 0, - 4800: 1, - 9600: 2, - 19200: 3, - 38400: 4, - 57600: 5, - 115200: 6, - 230400: 7, - 460800: 8, -} - -class LCD160CR: - def __init__(self, connect=None, *, pwr=None, i2c=None, spi=None, i2c_addr=98): - if connect in ('X', 'Y', 'XY', 'YX'): - i = connect[-1] - j = connect[0] - y = j + '4' - elif connect == 'C': - i = 2 - j = 2 - y = 'A7' - else: - if pwr is None or i2c is None or spi is None: - raise ValueError('must specify valid "connect" or all of "pwr", "i2c" and "spi"') - - if pwr is None: - pwr = machine.Pin(y, machine.Pin.OUT) - if i2c is None: - i2c = machine.I2C(i, freq=1000000) - if spi is None: - spi = machine.SPI(j, baudrate=13500000, polarity=0, phase=0) - - if not pwr.value(): - pwr(1) - sleep_ms(10) - # else: - # alread have power - # lets be optimistic... - - # set connections - self.pwr = pwr - self.i2c = i2c - self.spi = spi - self.i2c_addr = i2c_addr - - # create temp buffers and memoryviews - self.buf16 = bytearray(16) - self.buf19 = bytearray(19) - self.buf = [None] * 10 - for i in range(1, 10): - self.buf[i] = memoryview(self.buf16)[0:i] - self.buf1 = self.buf[1] - self.array4 = [0, 0, 0, 0] - - # set default orientation and window - self.set_orient(PORTRAIT) - self._fcmd2b('= n: - self.i2c.readfrom_into(self.i2c_addr, buf) - return - t -= 1 - sleep_ms(1) - raise OSError(uerrno.ETIMEDOUT) - - def oflush(self, n=255): - t = 5000 - while t: - self.i2c.readfrom_into(self.i2c_addr + 1, self.buf1) - r = self.buf1[0] - if r >= n: - return - t -= 1 - machine.idle() - raise OSError(uerrno.ETIMEDOUT) - - def iflush(self): - t = 5000 - while t: - self.i2c.readfrom_into(self.i2c_addr, self.buf16) - if self.buf16[0] == 0: - return - t -= 1 - sleep_ms(1) - raise OSError(uerrno.ETIMEDOUT) - - #### MISC METHODS #### - - @staticmethod - def rgb(r, g, b): - return ((b & 0xf8) << 8) | ((g & 0xfc) << 3) | (r >> 3) - - @staticmethod - def clip_line(c, w, h): - while True: - ca = ce = 0 - if c[1] < 0: - ca |= 8 - elif c[1] > h: - ca |= 4 - if c[0] < 0: - ca |= 1 - elif c[0] > w: - ca |= 2 - if c[3] < 0: - ce |= 8 - elif c[3] > h: - ce |= 4 - if c[2] < 0: - ce |= 1 - elif c[2] > w: - ce |= 2 - if ca & ce: - return False - elif ca | ce: - ca |= ce - if ca & 1: - if c[2] < c[0]: - c[0], c[2] = c[2], c[0] - c[1], c[3] = c[3], c[1] - c[1] += ((-c[0]) * (c[3] - c[1])) // (c[2] - c[0]) - c[0] = 0 - elif ca & 2: - if c[2] < c[0]: - c[0], c[2] = c[2], c[0] - c[1], c[3] = c[3], c[1] - c[3] += ((w - 1 - c[2]) * (c[3] - c[1])) // (c[2] - c[0]) - c[2] = w - 1 - elif ca & 4: - if c[0] == c[2]: - if c[1] >= h: - c[1] = h - 1 - if c[3] >= h: - c[3] = h - 1 - else: - if c[3] < c[1]: - c[0], c[2] = c[2], c[0] - c[1], c[3] = c[3], c[1] - c[2] += ((h - 1 - c[3]) * (c[2] - c[0])) // (c[3] - c[1]) - c[3] = h - 1 - else: - if c[0] == c[2]: - if c[1] < 0: - c[1] = 0 - if c[3] < 0: - c[3] = 0 - else: - if c[3] < c[1]: - c[0], c[2] = c[2], c[0] - c[1], c[3] = c[3], c[1] - c[0] += ((-c[1]) * (c[2] - c[0])) // (c[3] - c[1]) - c[1] = 0 - else: - return True - - #### SETUP COMMANDS #### - - def set_power(self, on): - self.pwr(on) - sleep_ms(15) - - def set_orient(self, orient): - self._fcmd2('= 2: - self.i2c.readfrom_into(self.i2c_addr, self.buf[3]) - return self.buf[3][1] | self.buf[3][2] << 8 - t -= 1 - sleep_ms(1) - raise OSError(uerrno.ETIMEDOUT) - - def get_line(self, x, y, buf): - l = len(buf) // 2 - self._fcmd2b('= l: - self.i2c.readfrom_into(self.i2c_addr, buf) - return - t -= 1 - sleep_ms(1) - raise OSError(uerrno.ETIMEDOUT) - - def screen_dump(self, buf, x=0, y=0, w=None, h=None): - if w is None: - w = self.w - x - if h is None: - h = self.h - y - if w <= 127: - line = bytearray(2 * w + 1) - line2 = None - else: - # split line if more than 254 bytes needed - buflen = (w + 1) // 2 - line = bytearray(2 * buflen + 1) - line2 = memoryview(line)[:2 * (w - buflen) + 1] - for i in range(min(len(buf) // (2 * w), h)): - ix = i * w * 2 - self.get_line(x, y + i, line) - buf[ix:ix + len(line) - 1] = memoryview(line)[1:] - ix += len(line) - 1 - if line2: - self.get_line(x + buflen, y + i, line2) - buf[ix:ix + len(line2) - 1] = memoryview(line2)[1:] - ix += len(line2) - 1 - - def screen_load(self, buf): - l = self.w * self.h * 2+2 - self._fcmd2b('= 0x200: - self._send(ar[n:n + 0x200]) - n += 0x200 - else: - self._send(ar[n:]) - while n < self.w * self.h * 2: - self._send(b'\x00') - n += 1 - - #### TEXT COMMANDS #### - - def set_pos(self, x, y): - self._fcmd2('= self.w or y >= self.h: - return - elif x < 0 or y < 0: - left = top = True - if x < 0: - left = False - w += x - x = 0 - if y < 0: - top = False - h += y - y = 0 - if cmd == 0x51 or cmd == 0x72: - # draw interior - self._fcmd2b('> 7 != 0 - - def get_touch(self): - self._send(b'\x02T') # implicit LCD output flush - b = self.buf[4] - self._waitfor(3, b) - return b[1] >> 7, b[2], b[3] - - #### ADVANCED COMMANDS #### - - def set_spi_win(self, x, y, w, h): - pack_into(' 32: - raise ValueError('length must be 32 or less') - self._fcmd2(' 0xffff: - raise ValueError('length must be 65535 or less') - self.oflush() - self._fcmd2(' 0: - s = '%6.3fV' % data[i] - else: - s = '%5.1f°C' % data[i] - if lcd.h == 160: - lcd.set_font(1, bold=0, scale=1) - else: - lcd.set_font(1, bold=0, scale=1, trans=1) - lcd.set_pos(45, lcd.h-60 + i * 16) - lcd.write(s) - -def test_features(lcd, orient=lcd160cr.PORTRAIT): - # if we run on pyboard then use ADC and RTC features - try: - import pyb - adc = pyb.ADCAll(12, 0xf0000) - rtc = pyb.RTC() - except: - adc = None - rtc = None - - # set orientation and clear screen - lcd = get_lcd(lcd) - lcd.set_orient(orient) - lcd.set_pen(0, 0) - lcd.erase() - - # create M-logo - mlogo = framebuf.FrameBuffer(bytearray(17 * 17 * 2), 17, 17, framebuf.RGB565) - mlogo.fill(0) - mlogo.fill_rect(1, 1, 15, 15, 0xffffff) - mlogo.vline(4, 4, 12, 0) - mlogo.vline(8, 1, 12, 0) - mlogo.vline(12, 4, 12, 0) - mlogo.vline(14, 13, 2, 0) - - # create inline framebuf - offx = 14 - offy = 19 - w = 100 - h = 75 - fbuf = framebuf.FrameBuffer(bytearray(w * h * 2), w, h, framebuf.RGB565) - lcd.set_spi_win(offx, offy, w, h) - - # initialise loop parameters - tx = ty = 0 - t0 = time.ticks_us() - - for i in range(300): - # update position of cross-hair - t, tx2, ty2 = lcd.get_touch() - if t: - tx2 -= offx - ty2 -= offy - if tx2 >= 0 and ty2 >= 0 and tx2 < w and ty2 < h: - tx, ty = tx2, ty2 - else: - tx = (tx + 1) % w - ty = (ty + 1) % h - - # create and show the inline framebuf - fbuf.fill(lcd.rgb(128 + int(64 * math.cos(0.1 * i)), 128, 192)) - fbuf.line(w // 2, h // 2, - w // 2 + int(40 * math.cos(0.2 * i)), - h // 2 + int(40 * math.sin(0.2 * i)), - lcd.rgb(128, 255, 64)) - fbuf.hline(0, ty, w, lcd.rgb(64, 64, 64)) - fbuf.vline(tx, 0, h, lcd.rgb(64, 64, 64)) - fbuf.rect(tx - 3, ty - 3, 7, 7, lcd.rgb(64, 64, 64)) - for phase in (-0.2, 0, 0.2): - x = w // 2 - 8 + int(50 * math.cos(0.05 * i + phase)) - y = h // 2 - 8 + int(32 * math.sin(0.05 * i + phase)) - fbuf.blit(mlogo, x, y) - for j in range(-3, 3): - fbuf.text('MicroPython', - 5, h // 2 + 9 * j + int(20 * math.sin(0.1 * (i + j))), - lcd.rgb(128 + 10 * j, 0, 128 - 10 * j)) - lcd.show_framebuf(fbuf) - - # show results from the ADC - if adc: - show_adc(lcd, adc) - - # show the time - if rtc: - lcd.set_pos(2, 0) - lcd.set_font(1) - t = rtc.datetime() - lcd.write('%4d-%02d-%02d %2d:%02d:%02d.%01d' % (t[0], t[1], t[2], t[4], t[5], t[6], t[7] // 100000)) - - # compute the frame rate - t1 = time.ticks_us() - dt = time.ticks_diff(t1, t0) - t0 = t1 - - # show the frame rate - lcd.set_pos(2, 9) - lcd.write('%.2f fps' % (1000000 / dt)) - -def test_mandel(lcd, orient=lcd160cr.PORTRAIT): - # set orientation and clear screen - lcd = get_lcd(lcd) - lcd.set_orient(orient) - lcd.set_pen(0, 0xffff) - lcd.erase() - - # function to compute Mandelbrot pixels - def in_set(c): - z = 0 - for i in range(32): - z = z * z + c - if abs(z) > 100: - return i - return 0 - - # cache width and height of LCD - w = lcd.w - h = lcd.h - - # create the buffer for each line and set SPI parameters - line = bytearray(w * 2) - lcd.set_spi_win(0, 0, w, h) - spi = lcd.fast_spi() - - # draw the Mandelbrot set line-by-line - hh = ((h - 1) / 3.2) - ww = ((w - 1) / 2.4) - for v in range(h): - for u in range(w): - c = in_set((v / hh - 2.3) + (u / ww - 1.2) * 1j) - if c < 16: - rgb = c << 12 | c << 6 - else: - rgb = 0xf800 | c << 6 - line[2 * u] = rgb - line[2 * u + 1] = rgb >> 8 - spi.write(line) - -def test_all(lcd, orient=lcd160cr.PORTRAIT): - lcd = get_lcd(lcd) - test_features(lcd, orient) - test_mandel(lcd, orient) - -print('To run all tests: test_all()') -print('Individual tests are: test_features, test_mandel') -print(' argument should be a connection, eg "X", or an LCD160CR object') diff --git a/drivers/display/ssd1306.py b/drivers/display/ssd1306.py deleted file mode 100644 index 53bcb0d2de..0000000000 --- a/drivers/display/ssd1306.py +++ /dev/null @@ -1,161 +0,0 @@ -# MicroPython SSD1306 OLED driver, I2C and SPI interfaces - -from micropython import const -import time -import framebuf - - -# register definitions -SET_CONTRAST = const(0x81) -SET_ENTIRE_ON = const(0xa4) -SET_NORM_INV = const(0xa6) -SET_DISP = const(0xae) -SET_MEM_ADDR = const(0x20) -SET_COL_ADDR = const(0x21) -SET_PAGE_ADDR = const(0x22) -SET_DISP_START_LINE = const(0x40) -SET_SEG_REMAP = const(0xa0) -SET_MUX_RATIO = const(0xa8) -SET_COM_OUT_DIR = const(0xc0) -SET_DISP_OFFSET = const(0xd3) -SET_COM_PIN_CFG = const(0xda) -SET_DISP_CLK_DIV = const(0xd5) -SET_PRECHARGE = const(0xd9) -SET_VCOM_DESEL = const(0xdb) -SET_CHARGE_PUMP = const(0x8d) - - -class SSD1306: - def __init__(self, width, height, external_vcc): - self.width = width - self.height = height - self.external_vcc = external_vcc - self.pages = self.height // 8 - self.buffer = bytearray(self.pages * self.width) - self.framebuf = framebuf.FrameBuffer(self.buffer, self.width, self.height, framebuf.MVLSB) - self.poweron() - self.init_display() - - def init_display(self): - for cmd in ( - SET_DISP | 0x00, # off - # address setting - SET_MEM_ADDR, 0x00, # horizontal - # resolution and layout - SET_DISP_START_LINE | 0x00, - SET_SEG_REMAP | 0x01, # column addr 127 mapped to SEG0 - SET_MUX_RATIO, self.height - 1, - SET_COM_OUT_DIR | 0x08, # scan from COM[N] to COM0 - SET_DISP_OFFSET, 0x00, - SET_COM_PIN_CFG, 0x02 if self.height == 32 else 0x12, - # timing and driving scheme - SET_DISP_CLK_DIV, 0x80, - SET_PRECHARGE, 0x22 if self.external_vcc else 0xf1, - SET_VCOM_DESEL, 0x30, # 0.83*Vcc - # display - SET_CONTRAST, 0xff, # maximum - SET_ENTIRE_ON, # output follows RAM contents - SET_NORM_INV, # not inverted - # charge pump - SET_CHARGE_PUMP, 0x10 if self.external_vcc else 0x14, - SET_DISP | 0x01): # on - self.write_cmd(cmd) - self.fill(0) - self.show() - - def poweroff(self): - self.write_cmd(SET_DISP | 0x00) - - def contrast(self, contrast): - self.write_cmd(SET_CONTRAST) - self.write_cmd(contrast) - - def invert(self, invert): - self.write_cmd(SET_NORM_INV | (invert & 1)) - - def show(self): - x0 = 0 - x1 = self.width - 1 - if self.width == 64: - # displays with width of 64 pixels are shifted by 32 - x0 += 32 - x1 += 32 - self.write_cmd(SET_COL_ADDR) - self.write_cmd(x0) - self.write_cmd(x1) - self.write_cmd(SET_PAGE_ADDR) - self.write_cmd(0) - self.write_cmd(self.pages - 1) - self.write_data(self.buffer) - - def fill(self, col): - self.framebuf.fill(col) - - def pixel(self, x, y, col): - self.framebuf.pixel(x, y, col) - - def scroll(self, dx, dy): - self.framebuf.scroll(dx, dy) - - def text(self, string, x, y, col=1): - self.framebuf.text(string, x, y, col) - - -class SSD1306_I2C(SSD1306): - def __init__(self, width, height, i2c, addr=0x3c, external_vcc=False): - self.i2c = i2c - self.addr = addr - self.temp = bytearray(2) - super().__init__(width, height, external_vcc) - - def write_cmd(self, cmd): - self.temp[0] = 0x80 # Co=1, D/C#=0 - self.temp[1] = cmd - self.i2c.writeto(self.addr, self.temp) - - def write_data(self, buf): - self.temp[0] = self.addr << 1 - self.temp[1] = 0x40 # Co=0, D/C#=1 - self.i2c.start() - self.i2c.write(self.temp) - self.i2c.write(buf) - self.i2c.stop() - - def poweron(self): - pass - - -class SSD1306_SPI(SSD1306): - def __init__(self, width, height, spi, dc, res, cs, external_vcc=False): - self.rate = 10 * 1024 * 1024 - dc.init(dc.OUT, value=0) - res.init(res.OUT, value=0) - cs.init(cs.OUT, value=1) - self.spi = spi - self.dc = dc - self.res = res - self.cs = cs - super().__init__(width, height, external_vcc) - - def write_cmd(self, cmd): - self.spi.init(baudrate=self.rate, polarity=0, phase=0) - self.cs(1) - self.dc(0) - self.cs(0) - self.spi.write(bytearray([cmd])) - self.cs(1) - - def write_data(self, buf): - self.spi.init(baudrate=self.rate, polarity=0, phase=0) - self.cs(1) - self.dc(1) - self.cs(0) - self.spi.write(buf) - self.cs(1) - - def poweron(self): - self.res(1) - time.sleep_ms(1) - self.res(0) - time.sleep_ms(10) - self.res(1) diff --git a/drivers/memory/spiflash.c b/drivers/memory/spiflash.c deleted file mode 100644 index 214610e0a2..0000000000 --- a/drivers/memory/spiflash.c +++ /dev/null @@ -1,200 +0,0 @@ -/* - * This file is part of the MicroPython project, http://micropython.org/ - * - * The MIT License (MIT) - * - * Copyright (c) 2016-2017 Damien P. George - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ - -#include -#include - -#include "py/mperrno.h" -#include "py/mphal.h" -#include "extmod/machine_spi.h" -#include "drivers/memory/spiflash.h" - -#define CMD_WRITE (0x02) -#define CMD_READ (0x03) -#define CMD_WRDI (0x04) -#define CMD_RDSR (0x05) -#define CMD_WREN (0x06) -#define CMD_SEC_ERASE (0x20) -#define WAIT_SR_TIMEOUT (1000000) - -#define PAGE_SIZE (256) // maximum bytes we can write in one SPI transfer -#define SECTOR_SIZE (4096) // size of erase sector - -// Note: this code is not reentrant with this shared buffer -STATIC uint8_t buf[SECTOR_SIZE]; - -void mp_spiflash_init(mp_spiflash_t *self) { - mp_hal_pin_write(self->cs, 1); - mp_hal_pin_output(self->cs); - mp_hal_pin_write(self->spi.sck, 0); - mp_hal_pin_output(self->spi.sck); - mp_hal_pin_output(self->spi.mosi); - mp_hal_pin_input(self->spi.miso); -} - -STATIC void mp_spiflash_acquire_bus(mp_spiflash_t *self) { - // can be used for actions needed to acquire bus - (void)self; -} - -STATIC void mp_spiflash_release_bus(mp_spiflash_t *self) { - // can be used for actions needed to release bus - (void)self; -} - -STATIC void mp_spiflash_transfer(mp_spiflash_t *self, size_t len, const uint8_t *src, uint8_t *dest) { - mp_machine_soft_spi_transfer(&self->spi.base, len, src, dest); -} - -STATIC int mp_spiflash_wait_sr(mp_spiflash_t *self, uint8_t mask, uint8_t val, uint32_t timeout) { - uint8_t cmd[1] = {CMD_RDSR}; - mp_hal_pin_write(self->cs, 0); - mp_spiflash_transfer(self, 1, cmd, NULL); - for (; timeout; --timeout) { - mp_spiflash_transfer(self, 1, cmd, cmd); - if ((cmd[0] & mask) == val) { - break; - } - } - mp_hal_pin_write(self->cs, 1); - if ((cmd[0] & mask) == val) { - return 0; // success - } else if (timeout == 0) { - return -MP_ETIMEDOUT; - } else { - return -MP_EIO; - } -} - -STATIC int mp_spiflash_wait_wel1(mp_spiflash_t *self) { - return mp_spiflash_wait_sr(self, 2, 2, WAIT_SR_TIMEOUT); -} - -STATIC int mp_spiflash_wait_wip0(mp_spiflash_t *self) { - return mp_spiflash_wait_sr(self, 1, 0, WAIT_SR_TIMEOUT); -} - -STATIC void mp_spiflash_write_cmd(mp_spiflash_t *self, uint8_t cmd) { - mp_hal_pin_write(self->cs, 0); - mp_spiflash_transfer(self, 1, &cmd, NULL); - mp_hal_pin_write(self->cs, 1); -} - -STATIC int mp_spiflash_erase_sector(mp_spiflash_t *self, uint32_t addr) { - // enable writes - mp_spiflash_write_cmd(self, CMD_WREN); - - // wait WEL=1 - int ret = mp_spiflash_wait_wel1(self); - if (ret != 0) { - return ret; - } - - // erase the sector - mp_hal_pin_write(self->cs, 0); - uint8_t cmd[4] = {CMD_SEC_ERASE, addr >> 16, addr >> 8, addr}; - mp_spiflash_transfer(self, 4, cmd, NULL); - mp_hal_pin_write(self->cs, 1); - - // wait WIP=0 - return mp_spiflash_wait_wip0(self); -} - -STATIC int mp_spiflash_write_page(mp_spiflash_t *self, uint32_t addr, const uint8_t *src) { - // enable writes - mp_spiflash_write_cmd(self, CMD_WREN); - - // wait WEL=1 - int ret = mp_spiflash_wait_wel1(self); - if (ret != 0) { - return ret; - } - - // write the page - mp_hal_pin_write(self->cs, 0); - uint8_t cmd[4] = {CMD_WRITE, addr >> 16, addr >> 8, addr}; - mp_spiflash_transfer(self, 4, cmd, NULL); - mp_spiflash_transfer(self, PAGE_SIZE, src, NULL); - mp_hal_pin_write(self->cs, 1); - - // wait WIP=0 - return mp_spiflash_wait_wip0(self); -} - -void mp_spiflash_read(mp_spiflash_t *self, uint32_t addr, size_t len, uint8_t *dest) { - mp_spiflash_acquire_bus(self); - uint8_t cmd[4] = {CMD_READ, addr >> 16, addr >> 8, addr}; - mp_hal_pin_write(self->cs, 0); - mp_spiflash_transfer(self, 4, cmd, NULL); - mp_spiflash_transfer(self, len, dest, dest); - mp_hal_pin_write(self->cs, 1); - mp_spiflash_release_bus(self); -} - -int mp_spiflash_write(mp_spiflash_t *self, uint32_t addr, size_t len, const uint8_t *src) { - // TODO optimise so we don't need to erase multiple times for successive writes to a sector - - // align to 4096 sector - uint32_t offset = addr & 0xfff; - addr = (addr >> 12) << 12; - - // restriction for now, so we don't need to erase multiple pages - if (offset + len > sizeof(buf)) { - printf("mp_spiflash_write: len is too large\n"); - return -MP_EIO; - } - - mp_spiflash_acquire_bus(self); - - // read sector - uint8_t cmd[4] = {CMD_READ, addr >> 16, addr >> 8, addr}; - mp_hal_pin_write(self->cs, 0); - mp_spiflash_transfer(self, 4, cmd, NULL); - mp_spiflash_transfer(self, SECTOR_SIZE, buf, buf); - mp_hal_pin_write(self->cs, 1); - - // erase sector - int ret = mp_spiflash_erase_sector(self, addr); - if (ret != 0) { - mp_spiflash_release_bus(self); - return ret; - } - - // copy new block into buffer - memcpy(buf + offset, src, len); - - // write sector in pages of 256 bytes - for (int i = 0; i < SECTOR_SIZE; i += 256) { - ret = mp_spiflash_write_page(self, addr + i, buf + i); - if (ret != 0) { - mp_spiflash_release_bus(self); - return ret; - } - } - - mp_spiflash_release_bus(self); - return 0; // success -} diff --git a/drivers/memory/spiflash.h b/drivers/memory/spiflash.h deleted file mode 100644 index 967352b04e..0000000000 --- a/drivers/memory/spiflash.h +++ /dev/null @@ -1,41 +0,0 @@ -/* - * This file is part of the MicroPython project, http://micropython.org/ - * - * The MIT License (MIT) - * - * Copyright (c) 2016 Damien P. George - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -#ifndef MICROPY_INCLUDED_DRIVERS_MEMORY_SPIFLASH_H -#define MICROPY_INCLUDED_DRIVERS_MEMORY_SPIFLASH_H - -#include "extmod/machine_spi.h" - -typedef struct _mp_spiflash_t { - mp_hal_pin_obj_t cs; - // TODO replace with generic SPI object - mp_machine_soft_spi_obj_t spi; -} mp_spiflash_t; - -void mp_spiflash_init(mp_spiflash_t *self); -void mp_spiflash_read(mp_spiflash_t *self, uint32_t addr, size_t len, uint8_t *dest); -int mp_spiflash_write(mp_spiflash_t *self, uint32_t addr, size_t len, const uint8_t *src); - -#endif // MICROPY_INCLUDED_DRIVERS_MEMORY_SPIFLASH_H diff --git a/drivers/nrf24l01/nrf24l01.py b/drivers/nrf24l01/nrf24l01.py deleted file mode 100644 index 7274a79278..0000000000 --- a/drivers/nrf24l01/nrf24l01.py +++ /dev/null @@ -1,252 +0,0 @@ -"""NRF24L01 driver for MicroPython -""" - -from micropython import const -import utime - -# nRF24L01+ registers -CONFIG = const(0x00) -EN_RXADDR = const(0x02) -SETUP_AW = const(0x03) -SETUP_RETR = const(0x04) -RF_CH = const(0x05) -RF_SETUP = const(0x06) -STATUS = const(0x07) -RX_ADDR_P0 = const(0x0a) -TX_ADDR = const(0x10) -RX_PW_P0 = const(0x11) -FIFO_STATUS = const(0x17) -DYNPD = const(0x1c) - -# CONFIG register -EN_CRC = const(0x08) # enable CRC -CRCO = const(0x04) # CRC encoding scheme; 0=1 byte, 1=2 bytes -PWR_UP = const(0x02) # 1=power up, 0=power down -PRIM_RX = const(0x01) # RX/TX control; 0=PTX, 1=PRX - -# RF_SETUP register -POWER_0 = const(0x00) # -18 dBm -POWER_1 = const(0x02) # -12 dBm -POWER_2 = const(0x04) # -6 dBm -POWER_3 = const(0x06) # 0 dBm -SPEED_1M = const(0x00) -SPEED_2M = const(0x08) -SPEED_250K = const(0x20) - -# STATUS register -RX_DR = const(0x40) # RX data ready; write 1 to clear -TX_DS = const(0x20) # TX data sent; write 1 to clear -MAX_RT = const(0x10) # max retransmits reached; write 1 to clear - -# FIFO_STATUS register -RX_EMPTY = const(0x01) # 1 if RX FIFO is empty - -# constants for instructions -R_RX_PL_WID = const(0x60) # read RX payload width -R_RX_PAYLOAD = const(0x61) # read RX payload -W_TX_PAYLOAD = const(0xa0) # write TX payload -FLUSH_TX = const(0xe1) # flush TX FIFO -FLUSH_RX = const(0xe2) # flush RX FIFO -NOP = const(0xff) # use to read STATUS register - -class NRF24L01: - def __init__(self, spi, cs, ce, channel=46, payload_size=16): - assert payload_size <= 32 - - self.buf = bytearray(1) - - # store the pins - self.spi = spi - self.cs = cs - self.ce = ce - - # init the SPI bus and pins - self.init_spi(4000000) - cs.init(cs.OUT, value=1) - ce.init(ce.OUT, value=0) - - # reset everything - self.ce(0) - self.cs(1) - self.payload_size = payload_size - self.pipe0_read_addr = None - utime.sleep_ms(5) - - # set address width to 5 bytes and check for device present - self.reg_write(SETUP_AW, 0b11) - if self.reg_read(SETUP_AW) != 0b11: - raise OSError("nRF24L01+ Hardware not responding") - - # disable dynamic payloads - self.reg_write(DYNPD, 0) - - # auto retransmit delay: 1750us - # auto retransmit count: 8 - self.reg_write(SETUP_RETR, (6 << 4) | 8) - - # set rf power and speed - self.set_power_speed(POWER_3, SPEED_250K) # Best for point to point links - - # init CRC - self.set_crc(2) - - # clear status flags - self.reg_write(STATUS, RX_DR | TX_DS | MAX_RT) - - # set channel - self.set_channel(channel) - - # flush buffers - self.flush_rx() - self.flush_tx() - - def init_spi(self, baudrate): - try: - master = self.spi.MASTER - except AttributeError: - self.spi.init(baudrate=baudrate, polarity=0, phase=0) - else: - self.spi.init(master, baudrate=baudrate, polarity=0, phase=0) - - def reg_read(self, reg): - self.cs(0) - self.spi.readinto(self.buf, reg) - self.spi.readinto(self.buf) - self.cs(1) - return self.buf[0] - - def reg_write_bytes(self, reg, buf): - self.cs(0) - self.spi.readinto(self.buf, 0x20 | reg) - self.spi.write(buf) - self.cs(1) - return self.buf[0] - - def reg_write(self, reg, value): - self.cs(0) - self.spi.readinto(self.buf, 0x20 | reg) - ret = self.buf[0] - self.spi.readinto(self.buf, value) - self.cs(1) - return ret - - def flush_rx(self): - self.cs(0) - self.spi.readinto(self.buf, FLUSH_RX) - self.cs(1) - - def flush_tx(self): - self.cs(0) - self.spi.readinto(self.buf, FLUSH_TX) - self.cs(1) - - # power is one of POWER_x defines; speed is one of SPEED_x defines - def set_power_speed(self, power, speed): - setup = self.reg_read(RF_SETUP) & 0b11010001 - self.reg_write(RF_SETUP, setup | power | speed) - - # length in bytes: 0, 1 or 2 - def set_crc(self, length): - config = self.reg_read(CONFIG) & ~(CRCO | EN_CRC) - if length == 0: - pass - elif length == 1: - config |= EN_CRC - else: - config |= EN_CRC | CRCO - self.reg_write(CONFIG, config) - - def set_channel(self, channel): - self.reg_write(RF_CH, min(channel, 125)) - - # address should be a bytes object 5 bytes long - def open_tx_pipe(self, address): - assert len(address) == 5 - self.reg_write_bytes(RX_ADDR_P0, address) - self.reg_write_bytes(TX_ADDR, address) - self.reg_write(RX_PW_P0, self.payload_size) - - # address should be a bytes object 5 bytes long - # pipe 0 and 1 have 5 byte address - # pipes 2-5 use same 4 most-significant bytes as pipe 1, plus 1 extra byte - def open_rx_pipe(self, pipe_id, address): - assert len(address) == 5 - assert 0 <= pipe_id <= 5 - if pipe_id == 0: - self.pipe0_read_addr = address - if pipe_id < 2: - self.reg_write_bytes(RX_ADDR_P0 + pipe_id, address) - else: - self.reg_write(RX_ADDR_P0 + pipe_id, address[0]) - self.reg_write(RX_PW_P0 + pipe_id, self.payload_size) - self.reg_write(EN_RXADDR, self.reg_read(EN_RXADDR) | (1 << pipe_id)) - - def start_listening(self): - self.reg_write(CONFIG, self.reg_read(CONFIG) | PWR_UP | PRIM_RX) - self.reg_write(STATUS, RX_DR | TX_DS | MAX_RT) - - if self.pipe0_read_addr is not None: - self.reg_write_bytes(RX_ADDR_P0, self.pipe0_read_addr) - - self.flush_rx() - self.flush_tx() - self.ce(1) - utime.sleep_us(130) - - def stop_listening(self): - self.ce(0) - self.flush_tx() - self.flush_rx() - - # returns True if any data available to recv - def any(self): - return not bool(self.reg_read(FIFO_STATUS) & RX_EMPTY) - - def recv(self): - # get the data - self.cs(0) - self.spi.readinto(self.buf, R_RX_PAYLOAD) - buf = self.spi.read(self.payload_size) - self.cs(1) - # clear RX ready flag - self.reg_write(STATUS, RX_DR) - - return buf - - # blocking wait for tx complete - def send(self, buf, timeout=500): - send_nonblock = self.send_start(buf) - start = utime.ticks_ms() - result = None - while result is None and utime.ticks_diff(utime.ticks_ms(), start) < timeout: - result = self.send_done() # 1 == success, 2 == fail - if result == 2: - raise OSError("send failed") - - # non-blocking tx - def send_start(self, buf): - # power up - self.reg_write(CONFIG, (self.reg_read(CONFIG) | PWR_UP) & ~PRIM_RX) - utime.sleep_us(150) - # send the data - self.cs(0) - self.spi.readinto(self.buf, W_TX_PAYLOAD) - self.spi.write(buf) - if len(buf) < self.payload_size: - self.spi.write(b'\x00' * (self.payload_size - len(buf))) # pad out data - self.cs(1) - - # enable the chip so it can send the data - self.ce(1) - utime.sleep_us(15) # needs to be >10us - self.ce(0) - - # returns None if send still in progress, 1 for success, 2 for fail - def send_done(self): - if not (self.reg_read(STATUS) & (TX_DS | MAX_RT)): - return None # tx not finished - - # either finished or failed: get and clear status flags, power down - status = self.reg_write(STATUS, RX_DR | TX_DS | MAX_RT) - self.reg_write(CONFIG, self.reg_read(CONFIG) & ~PWR_UP) - return 1 if status & TX_DS else 2 diff --git a/drivers/nrf24l01/nrf24l01test.py b/drivers/nrf24l01/nrf24l01test.py deleted file mode 100644 index a25194d387..0000000000 --- a/drivers/nrf24l01/nrf24l01test.py +++ /dev/null @@ -1,100 +0,0 @@ -"""Test for nrf24l01 module.""" - -import struct -import pyb -from pyb import Pin, SPI -from nrf24l01 import NRF24L01 - -pipes = (b'\xf0\xf0\xf0\xf0\xe1', b'\xf0\xf0\xf0\xf0\xd2') - -def master(): - nrf = NRF24L01(SPI(2), Pin('Y5'), Pin('Y4'), payload_size=8) - - nrf.open_tx_pipe(pipes[0]) - nrf.open_rx_pipe(1, pipes[1]) - nrf.start_listening() - - num_needed = 16 - num_successes = 0 - num_failures = 0 - led_state = 0 - - print('NRF24L01 master mode, sending %d packets...' % num_needed) - - while num_successes < num_needed and num_failures < num_needed: - # stop listening and send packet - nrf.stop_listening() - millis = pyb.millis() - led_state = max(1, (led_state << 1) & 0x0f) - print('sending:', millis, led_state) - try: - nrf.send(struct.pack('ii', millis, led_state)) - except OSError: - pass - - # start listening again - nrf.start_listening() - - # wait for response, with 250ms timeout - start_time = pyb.millis() - timeout = False - while not nrf.any() and not timeout: - if pyb.elapsed_millis(start_time) > 250: - timeout = True - - if timeout: - print('failed, response timed out') - num_failures += 1 - - else: - # recv packet - got_millis, = struct.unpack('i', nrf.recv()) - - # print response and round-trip delay - print('got response:', got_millis, '(delay', pyb.millis() - got_millis, 'ms)') - num_successes += 1 - - # delay then loop - pyb.delay(250) - - print('master finished sending; successes=%d, failures=%d' % (num_successes, num_failures)) - -def slave(): - nrf = NRF24L01(SPI(2), Pin('Y5'), Pin('Y4'), payload_size=8) - - nrf.open_tx_pipe(pipes[1]) - nrf.open_rx_pipe(1, pipes[0]) - nrf.start_listening() - - print('NRF24L01 slave mode, waiting for packets... (ctrl-C to stop)') - - while True: - pyb.wfi() - if nrf.any(): - while nrf.any(): - buf = nrf.recv() - millis, led_state = struct.unpack('ii', buf) - print('received:', millis, led_state) - for i in range(4): - if led_state & (1 << i): - pyb.LED(i + 1).on() - else: - pyb.LED(i + 1).off() - pyb.delay(15) - - nrf.stop_listening() - try: - nrf.send(struct.pack('i', millis)) - except OSError: - pass - print('sent response') - nrf.start_listening() - -print('NRF24L01 test module loaded') -print('NRF24L01 pinout for test:') -print(' CE on Y4') -print(' CSN on Y5') -print(' SCK on Y6') -print(' MISO on Y7') -print(' MOSI on Y8') -print('run nrf24l01test.slave() on slave, then nrf24l01test.master() on master') diff --git a/drivers/onewire/ds18x20.py b/drivers/onewire/ds18x20.py deleted file mode 100644 index bf06094835..0000000000 --- a/drivers/onewire/ds18x20.py +++ /dev/null @@ -1,51 +0,0 @@ -# DS18x20 temperature sensor driver for MicroPython. -# MIT license; Copyright (c) 2016 Damien P. George - -from micropython import const - -_CONVERT = const(0x44) -_RD_SCRATCH = const(0xbe) -_WR_SCRATCH = const(0x4e) - -class DS18X20: - def __init__(self, onewire): - self.ow = onewire - self.buf = bytearray(9) - - def scan(self): - return [rom for rom in self.ow.scan() if rom[0] == 0x10 or rom[0] == 0x28] - - def convert_temp(self): - self.ow.reset(True) - self.ow.writebyte(self.ow.SKIP_ROM) - self.ow.writebyte(_CONVERT) - - def read_scratch(self, rom): - self.ow.reset(True) - self.ow.select_rom(rom) - self.ow.writebyte(_RD_SCRATCH) - self.ow.readinto(self.buf) - if self.ow.crc8(self.buf): - raise Exception('CRC error') - return self.buf - - def write_scratch(self, rom, buf): - self.ow.reset(True) - self.ow.select_rom(rom) - self.ow.writebyte(_WR_SCRATCH) - self.ow.write(buf) - - def read_temp(self, rom): - buf = self.read_scratch(rom) - if rom[0] == 0x10: - if buf[1]: - t = buf[0] >> 1 | 0x80 - t = -((~t + 1) & 0xff) - else: - t = buf[0] >> 1 - return t - 0.25 + (buf[7] - buf[6]) / buf[7] - else: - t = buf[1] << 8 | buf[0] - if t & 0x8000: # sign bit set - t = -((t ^ 0xffff) + 1) - return t / 16 diff --git a/drivers/onewire/onewire.py b/drivers/onewire/onewire.py deleted file mode 100644 index 3309ba0d27..0000000000 --- a/drivers/onewire/onewire.py +++ /dev/null @@ -1,91 +0,0 @@ -# 1-Wire driver for MicroPython -# MIT license; Copyright (c) 2016 Damien P. George - -from micropython import const -import _onewire as _ow - -class OneWireError(Exception): - pass - -class OneWire: - SEARCH_ROM = const(0xf0) - MATCH_ROM = const(0x55) - SKIP_ROM = const(0xcc) - - def __init__(self, pin): - self.pin = pin - self.pin.init(pin.OPEN_DRAIN, pin.PULL_UP) - - def reset(self, required=False): - reset = _ow.reset(self.pin) - if required and not reset: - raise OneWireError - return reset - - def readbit(self): - return _ow.readbit(self.pin) - - def readbyte(self): - return _ow.readbyte(self.pin) - - def readinto(self, buf): - for i in range(len(buf)): - buf[i] = _ow.readbyte(self.pin) - - def writebit(self, value): - return _ow.writebit(self.pin, value) - - def writebyte(self, value): - return _ow.writebyte(self.pin, value) - - def write(self, buf): - for b in buf: - _ow.writebyte(self.pin, b) - - def select_rom(self, rom): - self.reset() - self.writebyte(MATCH_ROM) - self.write(rom) - - def scan(self): - devices = [] - diff = 65 - rom = False - for i in range(0xff): - rom, diff = self._search_rom(rom, diff) - if rom: - devices += [rom] - if diff == 0: - break - return devices - - def _search_rom(self, l_rom, diff): - if not self.reset(): - return None, 0 - self.writebyte(SEARCH_ROM) - if not l_rom: - l_rom = bytearray(8) - rom = bytearray(8) - next_diff = 0 - i = 64 - for byte in range(8): - r_b = 0 - for bit in range(8): - b = self.readbit() - if self.readbit(): - if b: # there are no devices or there is an error on the bus - return None, 0 - else: - if not b: # collision, two devices with different bit meaning - if diff > i or ((l_rom[byte] & (1 << bit)) and diff != i): - b = 1 - next_diff = i - self.writebit(b) - if b: - r_b |= 1 << bit - i -= 1 - rom[byte] = r_b - return rom, next_diff - - def crc8(self, data): - return _ow.crc8(data) diff --git a/drivers/sdcard/sdcard.py b/drivers/sdcard/sdcard.py deleted file mode 100644 index 75a0c501ee..0000000000 --- a/drivers/sdcard/sdcard.py +++ /dev/null @@ -1,272 +0,0 @@ -""" -MicroPython driver for SD cards using SPI bus. - -Requires an SPI bus and a CS pin. Provides readblocks and writeblocks -methods so the device can be mounted as a filesystem. - -Example usage on pyboard: - - import pyb, sdcard, os - sd = sdcard.SDCard(pyb.SPI(1), pyb.Pin.board.X5) - pyb.mount(sd, '/sd2') - os.listdir('/') - -Example usage on ESP8266: - - import machine, sdcard, os - sd = sdcard.SDCard(machine.SPI(0), machine.Pin(15)) - os.umount() - os.VfsFat(sd, "") - os.listdir() - -""" - -from micropython import const -import time - - -_CMD_TIMEOUT = const(100) - -_R1_IDLE_STATE = const(1 << 0) -#R1_ERASE_RESET = const(1 << 1) -_R1_ILLEGAL_COMMAND = const(1 << 2) -#R1_COM_CRC_ERROR = const(1 << 3) -#R1_ERASE_SEQUENCE_ERROR = const(1 << 4) -#R1_ADDRESS_ERROR = const(1 << 5) -#R1_PARAMETER_ERROR = const(1 << 6) -_TOKEN_CMD25 = const(0xfc) -_TOKEN_STOP_TRAN = const(0xfd) -_TOKEN_DATA = const(0xfe) - - -class SDCard: - def __init__(self, spi, cs): - self.spi = spi - self.cs = cs - - self.cmdbuf = bytearray(6) - self.dummybuf = bytearray(512) - for i in range(512): - self.dummybuf[i] = 0xff - self.dummybuf_memoryview = memoryview(self.dummybuf) - - # initialise the card - self.init_card() - - def init_spi(self, baudrate): - try: - master = self.spi.MASTER - except AttributeError: - # on ESP8266 - self.spi.init(baudrate=baudrate, phase=0, polarity=0) - else: - # on pyboard - self.spi.init(master, baudrate=baudrate, phase=0, polarity=0) - - def init_card(self): - # init CS pin - self.cs.init(self.cs.OUT, value=1) - - # init SPI bus; use low data rate for initialisation - self.init_spi(100000) - - # clock card at least 100 cycles with cs high - for i in range(16): - self.spi.write(b'\xff') - - # CMD0: init card; should return _R1_IDLE_STATE (allow 5 attempts) - for _ in range(5): - if self.cmd(0, 0, 0x95) == _R1_IDLE_STATE: - break - else: - raise OSError("no SD card") - - # CMD8: determine card version - r = self.cmd(8, 0x01aa, 0x87, 4) - if r == _R1_IDLE_STATE: - self.init_card_v2() - elif r == (_R1_IDLE_STATE | _R1_ILLEGAL_COMMAND): - self.init_card_v1() - else: - raise OSError("couldn't determine SD card version") - - # get the number of sectors - # CMD9: response R2 (R1 byte + 16-byte block read) - if self.cmd(9, 0, 0, 0, False) != 0: - raise OSError("no response from SD card") - csd = bytearray(16) - self.readinto(csd) - if csd[0] & 0xc0 != 0x40: - raise OSError("SD card CSD format not supported") - self.sectors = ((csd[8] << 8 | csd[9]) + 1) * 2014 - #print('sectors', self.sectors) - - # CMD16: set block length to 512 bytes - if self.cmd(16, 512, 0) != 0: - raise OSError("can't set 512 block size") - - # set to high data rate now that it's initialised - self.init_spi(1320000) - - def init_card_v1(self): - for i in range(_CMD_TIMEOUT): - self.cmd(55, 0, 0) - if self.cmd(41, 0, 0) == 0: - self.cdv = 512 - #print("[SDCard] v1 card") - return - raise OSError("timeout waiting for v1 card") - - def init_card_v2(self): - for i in range(_CMD_TIMEOUT): - time.sleep_ms(50) - self.cmd(58, 0, 0, 4) - self.cmd(55, 0, 0) - if self.cmd(41, 0x40000000, 0) == 0: - self.cmd(58, 0, 0, 4) - self.cdv = 1 - #print("[SDCard] v2 card") - return - raise OSError("timeout waiting for v2 card") - - def cmd(self, cmd, arg, crc, final=0, release=True): - self.cs(0) - - # create and send the command - buf = self.cmdbuf - buf[0] = 0x40 | cmd - buf[1] = arg >> 24 - buf[2] = arg >> 16 - buf[3] = arg >> 8 - buf[4] = arg - buf[5] = crc - self.spi.write(buf) - - # wait for the response (response[7] == 0) - for i in range(_CMD_TIMEOUT): - response = self.spi.read(1, 0xff)[0] - if not (response & 0x80): - # this could be a big-endian integer that we are getting here - for j in range(final): - self.spi.write(b'\xff') - if release: - self.cs(1) - self.spi.write(b'\xff') - return response - - # timeout - self.cs(1) - self.spi.write(b'\xff') - return -1 - - def cmd_nodata(self, cmd): - self.spi.write(cmd) - self.spi.read(1, 0xff) # ignore stuff byte - for _ in range(_CMD_TIMEOUT): - if self.spi.read(1, 0xff)[0] == 0xff: - self.cs(1) - self.spi.write(b'\xff') - return 0 # OK - self.cs(1) - self.spi.write(b'\xff') - return 1 # timeout - - def readinto(self, buf): - self.cs(0) - - # read until start byte (0xff) - while self.spi.read(1, 0xff)[0] != 0xfe: - pass - - # read data - mv = self.dummybuf_memoryview[:len(buf)] - self.spi.write_readinto(mv, buf) - - # read checksum - self.spi.write(b'\xff') - self.spi.write(b'\xff') - - self.cs(1) - self.spi.write(b'\xff') - - def write(self, token, buf): - self.cs(0) - - # send: start of block, data, checksum - self.spi.read(1, token) - self.spi.write(buf) - self.spi.write(b'\xff') - self.spi.write(b'\xff') - - # check the response - if (self.spi.read(1, 0xff)[0] & 0x1f) != 0x05: - self.cs(1) - self.spi.write(b'\xff') - return - - # wait for write to finish - while self.spi.read(1, 0xff)[0] == 0: - pass - - self.cs(1) - self.spi.write(b'\xff') - - def write_token(self, token): - self.cs(0) - self.spi.read(1, token) - self.spi.write(b'\xff') - # wait for write to finish - while self.spi.read(1, 0xff)[0] == 0x00: - pass - - self.cs(1) - self.spi.write(b'\xff') - - def count(self): - return self.sectors - - def readblocks(self, block_num, buf): - nblocks, err = divmod(len(buf), 512) - assert nblocks and not err, 'Buffer length is invalid' - if nblocks == 1: - # CMD17: set read address for single block - if self.cmd(17, block_num * self.cdv, 0) != 0: - return 1 - # receive the data - self.readinto(buf) - else: - # CMD18: set read address for multiple blocks - if self.cmd(18, block_num * self.cdv, 0) != 0: - return 1 - offset = 0 - mv = memoryview(buf) - while nblocks: - self.readinto(mv[offset : offset + 512]) - offset += 512 - nblocks -= 1 - return self.cmd_nodata(b'\x0c') # cmd 12 - return 0 - - def writeblocks(self, block_num, buf): - nblocks, err = divmod(len(buf), 512) - assert nblocks and not err, 'Buffer length is invalid' - if nblocks == 1: - # CMD24: set write address for single block - if self.cmd(24, block_num * self.cdv, 0) != 0: - return 1 - - # send the data - self.write(_TOKEN_DATA, buf) - else: - # CMD25: set write address for first block - if self.cmd(25, block_num * self.cdv, 0) != 0: - return 1 - # send the data - offset = 0 - mv = memoryview(buf) - while nblocks: - self.write(_TOKEN_CMD25, mv[offset : offset + 512]) - offset += 512 - nblocks -= 1 - self.write_token(_TOKEN_STOP_TRAN) - return 0 diff --git a/drivers/sdcard/sdtest.py b/drivers/sdcard/sdtest.py deleted file mode 100644 index 438baa245d..0000000000 --- a/drivers/sdcard/sdtest.py +++ /dev/null @@ -1,57 +0,0 @@ -# Test for sdcard block protocol -# Peter hinch 30th Jan 2016 -import os, sdcard, pyb - -def sdtest(): - sd = sdcard.SDCard(pyb.SPI(1), pyb.Pin.board.X21) # Compatible with PCB - pyb.mount(sd, '/fc') - print('Filesystem check') - print(os.listdir('/fc')) - - line = 'abcdefghijklmnopqrstuvwxyz\n' - lines = line * 200 # 5400 chars - short = '1234567890\n' - - fn = '/fc/rats.txt' - print() - print('Multiple block read/write') - with open(fn,'w') as f: - n = f.write(lines) - print(n, 'bytes written') - n = f.write(short) - print(n, 'bytes written') - n = f.write(lines) - print(n, 'bytes written') - - with open(fn,'r') as f: - result1 = f.read() - print(len(result1), 'bytes read') - - fn = '/fc/rats1.txt' - print() - print('Single block read/write') - with open(fn,'w') as f: - n = f.write(short) # one block - print(n, 'bytes written') - - with open(fn,'r') as f: - result2 = f.read() - print(len(result2), 'bytes read') - - pyb.mount(None, '/fc') - - print() - print('Verifying data read back') - success = True - if result1 == ''.join((lines, short, lines)): - print('Large file Pass') - else: - print('Large file Fail') - success = False - if result2 == short: - print('Small file Pass') - else: - print('Small file Fail') - success = False - print() - print('Tests', 'passed' if success else 'failed') diff --git a/drivers/wiznet5k/README.md b/drivers/wiznet5k/README.md deleted file mode 100644 index 88f25a2b8d..0000000000 --- a/drivers/wiznet5k/README.md +++ /dev/null @@ -1,6 +0,0 @@ -This is the driver for the WIZnet5x00 series of Ethernet controllers. - -Adapted for MicroPython. - -Original source: https://github.com/Wiznet/W5500_EVB/tree/master/ioLibrary -Taken on: 30 August 2014 diff --git a/drivers/wiznet5k/ethernet/socket.c b/drivers/wiznet5k/ethernet/socket.c deleted file mode 100644 index 129473ad4d..0000000000 --- a/drivers/wiznet5k/ethernet/socket.c +++ /dev/null @@ -1,723 +0,0 @@ -//***************************************************************************** -// -//! \file socket.c -//! \brief SOCKET APIs Implements file. -//! \details SOCKET APIs like as Berkeley Socket APIs. -//! \version 1.0.3 -//! \date 2013/10/21 -//! \par Revision history -//! <2014/05/01> V1.0.3. Refer to M20140501 -//! 1. Implicit type casting -> Explicit type casting. -//! 2. replace 0x01 with PACK_REMAINED in recvfrom() -//! 3. Validation a destination ip in connect() & sendto(): -//! It occurs a fatal error on converting unint32 address if uint8* addr parameter is not aligned by 4byte address. -//! Copy 4 byte addr value into temporary uint32 variable and then compares it. -//! <2013/12/20> V1.0.2 Refer to M20131220 -//! Remove Warning. -//! <2013/11/04> V1.0.1 2nd Release. Refer to "20131104". -//! In sendto(), Add to clear timeout interrupt status (Sn_IR_TIMEOUT) -//! <2013/10/21> 1st Release -//! \author MidnightCow -//! \copyright -//! -//! Copyright (c) 2013, WIZnet Co., LTD. -//! All rights reserved. -//! -//! Redistribution and use in source and binary forms, with or without -//! modification, are permitted provided that the following conditions -//! are met: -//! -//! * Redistributions of source code must retain the above copyright -//! notice, this list of conditions and the following disclaimer. -//! * Redistributions in binary form must reproduce the above copyright -//! notice, this list of conditions and the following disclaimer in the -//! documentation and/or other materials provided with the distribution. -//! * Neither the name of the nor the names of its -//! contributors may be used to endorse or promote products derived -//! from this software without specific prior written permission. -//! -//! THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" -//! AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -//! IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE -//! ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE -//! LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR -//! CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF -//! SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS -//! INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN -//! CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) -//! ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF -//! THE POSSIBILITY OF SUCH DAMAGE. -// -//***************************************************************************** - -#include - -#include "socket.h" - -extern void HAL_Delay(uint32_t); - -#define SOCK_ANY_PORT_NUM 0xC000; - -static uint16_t sock_any_port = SOCK_ANY_PORT_NUM; -static uint16_t sock_io_mode = 0; -static uint16_t sock_is_sending = 0; -static uint16_t sock_remained_size[_WIZCHIP_SOCK_NUM_] = {0,0,}; -static uint8_t sock_pack_info[_WIZCHIP_SOCK_NUM_] = {0,}; - -#if _WIZCHIP_ == 5200 - static uint16_t sock_next_rd[_WIZCHIP_SOCK_NUM_] ={0,}; -#endif - -#define CHECK_SOCKNUM() \ - do{ \ - if(sn > _WIZCHIP_SOCK_NUM_) return SOCKERR_SOCKNUM; \ - }while(0); \ - -#define CHECK_SOCKMODE(mode) \ - do{ \ - if((getSn_MR(sn) & 0x0F) != mode) return SOCKERR_SOCKMODE; \ - }while(0); \ - -#define CHECK_SOCKINIT() \ - do{ \ - if((getSn_SR(sn) != SOCK_INIT)) return SOCKERR_SOCKINIT; \ - }while(0); \ - -#define CHECK_SOCKDATA() \ - do{ \ - if(len == 0) return SOCKERR_DATALEN; \ - }while(0); \ - -void WIZCHIP_EXPORT(socket_reset)(void) { - sock_any_port = SOCK_ANY_PORT_NUM; - sock_io_mode = 0; - sock_is_sending = 0; - /* - memset(sock_remained_size, 0, _WIZCHIP_SOCK_NUM_ * sizeof(uint16_t)); - memset(sock_pack_info, 0, _WIZCHIP_SOCK_NUM_ * sizeof(uint8_t)); - */ - -#if _WIZCHIP_ == 5200 - memset(sock_next_rd, 0, _WIZCHIP_SOCK_NUM_ * sizeof(uint16_t)); -#endif -} - -int8_t WIZCHIP_EXPORT(socket)(uint8_t sn, uint8_t protocol, uint16_t port, uint8_t flag) -{ - CHECK_SOCKNUM(); - switch(protocol) - { - case Sn_MR_TCP : - case Sn_MR_UDP : - case Sn_MR_MACRAW : - break; - #if ( _WIZCHIP_ < 5200 ) - case Sn_MR_IPRAW : - case Sn_MR_PPPoE : - break; - #endif - default : - return SOCKERR_SOCKMODE; - } - if((flag & 0x06) != 0) return SOCKERR_SOCKFLAG; -#if _WIZCHIP_ == 5200 - if(flag & 0x10) return SOCKERR_SOCKFLAG; -#endif - - if(flag != 0) - { - switch(protocol) - { - case Sn_MR_TCP: - if((flag & (SF_TCP_NODELAY|SF_IO_NONBLOCK))==0) return SOCKERR_SOCKFLAG; - break; - case Sn_MR_UDP: - if(flag & SF_IGMP_VER2) - { - if((flag & SF_MULTI_ENABLE)==0) return SOCKERR_SOCKFLAG; - } - #if _WIZCHIP_ == 5500 - if(flag & SF_UNI_BLOCK) - { - if((flag & SF_MULTI_ENABLE) == 0) return SOCKERR_SOCKFLAG; - } - #endif - break; - default: - break; - } - } - WIZCHIP_EXPORT(close)(sn); - setSn_MR(sn, (protocol | (flag & 0xF0))); - if(!port) - { - port = sock_any_port++; - if(sock_any_port == 0xFFF0) sock_any_port = SOCK_ANY_PORT_NUM; - } - setSn_PORT(sn,port); - setSn_CR(sn,Sn_CR_OPEN); - while(getSn_CR(sn)); - sock_io_mode |= ((flag & SF_IO_NONBLOCK) << sn); - sock_is_sending &= ~(1< freesize) len = freesize; // check size not to exceed MAX size. - while(1) - { - freesize = getSn_TX_FSR(sn); - tmp = getSn_SR(sn); - if ((tmp != SOCK_ESTABLISHED) && (tmp != SOCK_CLOSE_WAIT)) - { - WIZCHIP_EXPORT(close)(sn); - return SOCKERR_SOCKSTATUS; - } - if( (sock_io_mode & (1< freesize) ) return SOCK_BUSY; - if(len <= freesize) break; - } - wiz_send_data(sn, buf, len); - #if _WIZCHIP_ == 5200 - sock_next_rd[sn] = getSn_TX_RD(sn) + len; - #endif - setSn_CR(sn,Sn_CR_SEND); - /* wait to process the command... */ - while(getSn_CR(sn)); - sock_is_sending |= (1 << sn); - return len; -} - - -int32_t WIZCHIP_EXPORT(recv)(uint8_t sn, uint8_t * buf, uint16_t len) -{ - uint8_t tmp = 0; - uint16_t recvsize = 0; - CHECK_SOCKNUM(); - CHECK_SOCKMODE(Sn_MR_TCP); - CHECK_SOCKDATA(); - - recvsize = getSn_RxMAX(sn); - if(recvsize < len) len = recvsize; - while(1) - { - recvsize = getSn_RX_RSR(sn); - tmp = getSn_SR(sn); - if (tmp != SOCK_ESTABLISHED) - { - if(tmp == SOCK_CLOSE_WAIT) - { - if(recvsize != 0) break; - else if(getSn_TX_FSR(sn) == getSn_TxMAX(sn)) - { - // dpgeorge: Getting here seems to be an orderly shutdown of the - // socket, and trying to get POSIX behaviour we return 0 because: - // "If no messages are available to be received and the peer has per†- // formed an orderly shutdown, recv() shall return 0". - // TODO this return value clashes with SOCK_BUSY in non-blocking mode. - WIZCHIP_EXPORT(close)(sn); - return 0; - } - } - else - { - WIZCHIP_EXPORT(close)(sn); - return SOCKERR_SOCKSTATUS; - } - } - if((sock_io_mode & (1< freesize) len = freesize; // check size not to exceed MAX size. - while(1) - { - freesize = getSn_TX_FSR(sn); - if(getSn_SR(sn) == SOCK_CLOSED) return SOCKERR_SOCKCLOSED; - if( (sock_io_mode & (1< freesize) ) return SOCK_BUSY; - if(len <= freesize) break; - HAL_Delay(1); - }; - wiz_send_data(sn, buf, len); - - #if _WIZCHIP_ == 5200 // for W5200 ARP errata - setSUBR(wizchip_getsubn()); - #endif - - setSn_CR(sn,Sn_CR_SEND); - /* wait to process the command... */ - while(getSn_CR(sn)); - while(1) - { - tmp = getSn_IR(sn); - if(tmp & Sn_IR_SENDOK) - { - setSn_IR(sn, Sn_IR_SENDOK); - break; - } - //M:20131104 - //else if(tmp & Sn_IR_TIMEOUT) return SOCKERR_TIMEOUT; - else if(tmp & Sn_IR_TIMEOUT) - { - setSn_IR(sn, Sn_IR_TIMEOUT); - #if _WIZCHIP_ == 5200 // for W5200 ARP errata - setSUBR((uint8_t*)"\x00\x00\x00\x00"); - #endif - return SOCKERR_TIMEOUT; - } - //////////// - HAL_Delay(1); - } - #if _WIZCHIP_ == 5200 // for W5200 ARP errata - setSUBR((uint8_t*)"\x00\x00\x00\x00"); - #endif - return len; -} - - - -int32_t WIZCHIP_EXPORT(recvfrom)(uint8_t sn, uint8_t * buf, uint16_t len, uint8_t * addr, uint16_t *port) -{ - uint8_t mr; - uint8_t head[8]; - uint16_t pack_len=0; - - CHECK_SOCKNUM(); - //CHECK_SOCKMODE(Sn_MR_UDP); - switch((mr=getSn_MR(sn)) & 0x0F) - { - case Sn_MR_UDP: - case Sn_MR_MACRAW: - break; - #if ( _WIZCHIP_ < 5200 ) - case Sn_MR_IPRAW: - case Sn_MR_PPPoE: - break; - #endif - default: - return SOCKERR_SOCKMODE; - } - CHECK_SOCKDATA(); - if(sock_remained_size[sn] == 0) - { - while(1) - { - pack_len = getSn_RX_RSR(sn); - if(getSn_SR(sn) == SOCK_CLOSED) return SOCKERR_SOCKCLOSED; - if( (sock_io_mode & (1< 1514) - { - WIZCHIP_EXPORT(close)(sn); - return SOCKFATAL_PACKLEN; - } - sock_pack_info[sn] = PACK_FIRST; - } - if(len < sock_remained_size[sn]) pack_len = len; - else pack_len = sock_remained_size[sn]; - wiz_recv_data(sn,buf,pack_len); - break; - #if ( _WIZCHIP_ < 5200 ) - case Sn_MR_IPRAW: - if(sock_remained_size[sn] == 0) - { - wiz_recv_data(sn, head, 6); - setSn_CR(sn,Sn_CR_RECV); - while(getSn_CR(sn)); - addr[0] = head[0]; - addr[1] = head[1]; - addr[2] = head[2]; - addr[3] = head[3]; - sock_remained_size[sn] = head[4]; - sock_remaiend_size[sn] = (sock_remained_size[sn] << 8) + head[5]; - sock_pack_info[sn] = PACK_FIRST; - } - // - // Need to packet length check - // - if(len < sock_remained_size[sn]) pack_len = len; - else pack_len = sock_remained_size[sn]; - wiz_recv_data(sn, buf, pack_len); // data copy. - break; - #endif - default: - wiz_recv_ignore(sn, pack_len); // data copy. - sock_remained_size[sn] = pack_len; - break; - } - setSn_CR(sn,Sn_CR_RECV); - /* wait to process the command... */ - while(getSn_CR(sn)) ; - sock_remained_size[sn] -= pack_len; - //M20140501 : replace 0x01 with PACK_REMAINED - //if(sock_remained_size[sn] != 0) sock_pack_info[sn] |= 0x01; - if(sock_remained_size[sn] != 0) sock_pack_info[sn] |= PACK_REMAINED; - // - return pack_len; -} - - -int8_t WIZCHIP_EXPORT(ctlsocket)(uint8_t sn, ctlsock_type cstype, void* arg) -{ - uint8_t tmp = 0; - CHECK_SOCKNUM(); - switch(cstype) - { - case CS_SET_IOMODE: - tmp = *((uint8_t*)arg); - if(tmp == SOCK_IO_NONBLOCK) sock_io_mode |= (1< explict type casting - //*((uint8_t*)arg) = (sock_io_mode >> sn) & 0x0001; - *((uint8_t*)arg) = (uint8_t)((sock_io_mode >> sn) & 0x0001); - // - break; - case CS_GET_MAXTXBUF: - *((uint16_t*)arg) = getSn_TxMAX(sn); - break; - case CS_GET_MAXRXBUF: - *((uint16_t*)arg) = getSn_RxMAX(sn); - break; - case CS_CLR_INTERRUPT: - if( (*(uint8_t*)arg) > SIK_ALL) return SOCKERR_ARG; - setSn_IR(sn,*(uint8_t*)arg); - break; - case CS_GET_INTERRUPT: - *((uint8_t*)arg) = getSn_IR(sn); - break; - case CS_SET_INTMASK: - if( (*(uint8_t*)arg) > SIK_ALL) return SOCKERR_ARG; - setSn_IMR(sn,*(uint8_t*)arg); - break; - case CS_GET_INTMASK: - *((uint8_t*)arg) = getSn_IMR(sn); - default: - return SOCKERR_ARG; - } - return SOCK_OK; -} - -int8_t WIZCHIP_EXPORT(setsockopt)(uint8_t sn, sockopt_type sotype, void* arg) -{ - // M20131220 : Remove warning - //uint8_t tmp; - CHECK_SOCKNUM(); - switch(sotype) - { - case SO_TTL: - setSn_TTL(sn,*(uint8_t*)arg); - break; - case SO_TOS: - setSn_TOS(sn,*(uint8_t*)arg); - break; - case SO_MSS: - setSn_MSSR(sn,*(uint16_t*)arg); - break; - case SO_DESTIP: - setSn_DIPR(sn, (uint8_t*)arg); - break; - case SO_DESTPORT: - setSn_DPORT(sn, *(uint16_t*)arg); - break; -#if _WIZCHIP_ != 5100 - case SO_KEEPALIVESEND: - CHECK_SOCKMODE(Sn_MR_TCP); - #if _WIZCHIP_ > 5200 - if(getSn_KPALVTR(sn) != 0) return SOCKERR_SOCKOPT; - #endif - setSn_CR(sn,Sn_CR_SEND_KEEP); - while(getSn_CR(sn) != 0) - { - // M20131220 - //if ((tmp = getSn_IR(sn)) & Sn_IR_TIMEOUT) - if (getSn_IR(sn) & Sn_IR_TIMEOUT) - { - setSn_IR(sn, Sn_IR_TIMEOUT); - return SOCKERR_TIMEOUT; - } - } - break; - #if _WIZCHIP_ > 5200 - case SO_KEEPALIVEAUTO: - CHECK_SOCKMODE(Sn_MR_TCP); - setSn_KPALVTR(sn,*(uint8_t*)arg); - break; - #endif -#endif - default: - return SOCKERR_ARG; - } - return SOCK_OK; -} - -int8_t WIZCHIP_EXPORT(getsockopt)(uint8_t sn, sockopt_type sotype, void* arg) -{ - CHECK_SOCKNUM(); - switch(sotype) - { - case SO_FLAG: - *(uint8_t*)arg = getSn_MR(sn) & 0xF0; - break; - case SO_TTL: - *(uint8_t*) arg = getSn_TTL(sn); - break; - case SO_TOS: - *(uint8_t*) arg = getSn_TOS(sn); - break; - case SO_MSS: - *(uint8_t*) arg = getSn_MSSR(sn); - case SO_DESTIP: - getSn_DIPR(sn, (uint8_t*)arg); - break; - case SO_DESTPORT: - *(uint16_t*) arg = getSn_DPORT(sn); - break; - #if _WIZCHIP_ > 5200 - case SO_KEEPALIVEAUTO: - CHECK_SOCKMODE(Sn_MR_TCP); - *(uint16_t*) arg = getSn_KPALVTR(sn); - break; - #endif - case SO_SENDBUF: - *(uint16_t*) arg = getSn_TX_FSR(sn); - case SO_RECVBUF: - *(uint16_t*) arg = getSn_RX_RSR(sn); - case SO_STATUS: - *(uint8_t*) arg = getSn_SR(sn); - break; - case SO_REMAINSIZE: - if(getSn_MR(sn) == Sn_MR_TCP) - *(uint16_t*)arg = getSn_RX_RSR(sn); - else - *(uint16_t*)arg = sock_remained_size[sn]; - break; - case SO_PACKINFO: - CHECK_SOCKMODE(Sn_MR_TCP); - *(uint8_t*)arg = sock_pack_info[sn]; - break; - default: - return SOCKERR_SOCKOPT; - } - return SOCK_OK; -} diff --git a/drivers/wiznet5k/ethernet/socket.h b/drivers/wiznet5k/ethernet/socket.h deleted file mode 100644 index 2f03a34eba..0000000000 --- a/drivers/wiznet5k/ethernet/socket.h +++ /dev/null @@ -1,472 +0,0 @@ -//***************************************************************************** -// -//! \file socket.h -//! \brief SOCKET APIs Header file. -//! \details SOCKET APIs like as berkeley socket api. -//! \version 1.0.2 -//! \date 2013/10/21 -//! \par Revision history -//! <2014/05/01> V1.0.2. Refer to M20140501 -//! 1. Modify the comment : SO_REMAINED -> PACK_REMAINED -//! 2. Add the comment as zero byte udp data reception in getsockopt(). -//! <2013/10/21> 1st Release -//! \author MidnightCow -//! \copyright -//! -//! Copyright (c) 2013, WIZnet Co., LTD. -//! All rights reserved. -//! -//! Redistribution and use in source and binary forms, with or without -//! modification, are permitted provided that the following conditions -//! are met: -//! -//! * Redistributions of source code must retain the above copyright -//! notice, this list of conditions and the following disclaimer. -//! * Redistributions in binary form must reproduce the above copyright -//! notice, this list of conditions and the following disclaimer in the -//! documentation and/or other materials provided with the distribution. -//! * Neither the name of the nor the names of its -//! contributors may be used to endorse or promote products derived -//! from this software without specific prior written permission. -//! -//! THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" -//! AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -//! IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE -//! ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE -//! LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR -//! CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF -//! SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS -//! INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN -//! CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) -//! ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF -//! THE POSSIBILITY OF SUCH DAMAGE. -// -//***************************************************************************** -/** - * @defgroup WIZnet_socket_APIs 1. WIZnet socket APIs - * @brief WIZnet socket APIs are based on Berkeley socket APIs, thus it has much similar name and interface. - * But there is a little bit of difference. - * @details - * Comparison between WIZnet and Berkeley SOCKET APIs - * - * - * - * - * - * - * - * - * - * - * - * - *
API WIZnet Berkeley
socket() O O
bind() X O
listen() O O
connect() O O
accept() X O
recv() O O
send() O O
recvfrom() O O
sendto() O O
closesocket() O
close() & disconnect()
O
- * There are @b bind() and @b accept() functions in @b Berkeley SOCKET API but, - * not in @b WIZnet SOCKET API. Because socket() of WIZnet is not only creating a SOCKET but also binding a local port number, - * and listen() of WIZnet is not only listening to connection request from client but also accepting the connection request. \n - * When you program "TCP SERVER" with Berkeley SOCKET API, you can use only one listen port. - * When the listen SOCKET accepts a connection request from a client, it keeps listening. - * After accepting the connection request, a new SOCKET is created and the new SOCKET is used in communication with the client. \n - * Following figure shows network flow diagram by Berkeley SOCKET API. - * @image html Berkeley_SOCKET.jpg "" - * But, When you program "TCP SERVER" with WIZnet SOCKET API, you can use as many as 8 listen SOCKET with same port number. \n - * Because there's no accept() in WIZnet SOCKET APIs, when the listen SOCKET accepts a connection request from a client, - * it is changed in order to communicate with the client. - * And the changed SOCKET is not listening any more and is dedicated for communicating with the client. \n - * If there're many listen SOCKET with same listen port number and a client requests a connection, - * the SOCKET which has the smallest SOCKET number accepts the request and is changed as communication SOCKET. \n - * Following figure shows network flow diagram by WIZnet SOCKET API. - * @image html WIZnet_SOCKET.jpg "" - */ -#ifndef _WIZCHIP_SOCKET_H_ -#define _WIZCHIP_SOCKET_H_ - -// use this macro for exported names to avoid name clashes -#define WIZCHIP_EXPORT(name) wizchip_ ## name - -#include "wizchip_conf.h" - -#define SOCKET uint8_t ///< SOCKET type define for legacy driver - -#define SOCK_OK 1 ///< Result is OK about socket process. -#define SOCK_BUSY 0 ///< Socket is busy on processing the operation. Valid only Non-block IO Mode. -#define SOCK_FATAL -1000 ///< Result is fatal error about socket process. - -#define SOCK_ERROR 0 -#define SOCKERR_SOCKNUM (SOCK_ERROR - 1) ///< Invalid socket number -#define SOCKERR_SOCKOPT (SOCK_ERROR - 2) ///< Invalid socket option -#define SOCKERR_SOCKINIT (SOCK_ERROR - 3) ///< Socket is not initialized -#define SOCKERR_SOCKCLOSED (SOCK_ERROR - 4) ///< Socket unexpectedly closed. -#define SOCKERR_SOCKMODE (SOCK_ERROR - 5) ///< Invalid socket mode for socket operation. -#define SOCKERR_SOCKFLAG (SOCK_ERROR - 6) ///< Invalid socket flag -#define SOCKERR_SOCKSTATUS (SOCK_ERROR - 7) ///< Invalid socket status for socket operation. -#define SOCKERR_ARG (SOCK_ERROR - 10) ///< Invalid argument. -#define SOCKERR_PORTZERO (SOCK_ERROR - 11) ///< Port number is zero -#define SOCKERR_IPINVALID (SOCK_ERROR - 12) ///< Invalid IP address -#define SOCKERR_TIMEOUT (SOCK_ERROR - 13) ///< Timeout occurred -#define SOCKERR_DATALEN (SOCK_ERROR - 14) ///< Data length is zero or greater than buffer max size. -#define SOCKERR_BUFFER (SOCK_ERROR - 15) ///< Socket buffer is not enough for data communication. - -#define SOCKFATAL_PACKLEN (SOCK_FATAL - 1) ///< Invalid packet length. Fatal Error. - -/* - * SOCKET FLAG - */ -#define SF_ETHER_OWN (Sn_MR_MFEN) ///< In \ref Sn_MR_MACRAW, Receive only the packet as broadcast, multicast and own packet -#define SF_IGMP_VER2 (Sn_MR_MC) ///< In \ref Sn_MR_UDP with \ref SF_MULTI_ENABLE, Select IGMP version 2. -#define SF_TCP_NODELAY (Sn_MR_ND) ///< In \ref Sn_MR_TCP, Use to nodelayed ack. -#define SF_MULTI_ENABLE (Sn_MR_MULTI) ///< In \ref Sn_MR_UDP, Enable multicast mode. - -#if _WIZCHIP_ == 5500 - #define SF_BROAD_BLOCK (Sn_MR_BCASTB) ///< In \ref Sn_MR_UDP or \ref Sn_MR_MACRAW, Block broadcast packet. Valid only in W5500 - #define SF_MULTI_BLOCK (Sn_MR_MMB) ///< In \ref Sn_MR_MACRAW, Block multicast packet. Valid only in W5500 - #define SF_IPv6_BLOCK (Sn_MR_MIP6B) ///< In \ref Sn_MR_MACRAW, Block IPv6 packet. Valid only in W5500 - #define SF_UNI_BLOCK (Sn_MR_UCASTB) ///< In \ref Sn_MR_UDP with \ref SF_MULTI_ENABLE. Valid only in W5500 -#endif - -#define SF_IO_NONBLOCK 0x01 ///< Socket nonblock io mode. It used parameter in \ref socket(). - -/* - * UDP & MACRAW Packet Infomation - */ -#define PACK_FIRST 0x80 ///< In Non-TCP packet, It indicates to start receiving a packet. -#define PACK_REMAINED 0x01 ///< In Non-TCP packet, It indicates to remain a packet to be received. -#define PACK_COMPLETED 0x00 ///< In Non-TCP packet, It indicates to complete to receive a packet. - -// resets all global state associated with the socket interface -void WIZCHIP_EXPORT(socket_reset)(void); - -/** - * @ingroup WIZnet_socket_APIs - * @brief Open a socket. - * @details Initializes the socket with 'sn' passed as parameter and open. - * - * @param sn Socket number. It should be 0 ~ @ref \_WIZCHIP_SOCK_NUM_. - * @param protocol Protocol type to operate such as TCP, UDP and MACRAW. - * @param port Port number to be bined. - * @param flag Socket flags as \ref SF_ETHER_OWN, \ref SF_IGMP_VER2, \ref SF_TCP_NODELAY, \ref SF_MULTI_ENABLE, \ref SF_IO_NONBLOCK and so on.\n - * Valid flags only in W5500 : @ref SF_BROAD_BLOCK, @ref SF_MULTI_BLOCK, @ref SF_IPv6_BLOCK, and @ref SF_UNI_BLOCK. - * @sa Sn_MR - * - * @return @b Success : The socket number @b 'sn' passed as parameter\n - * @b Fail :\n @ref SOCKERR_SOCKNUM - Invalid socket number\n - * @ref SOCKERR_SOCKMODE - Not support socket mode as TCP, UDP, and so on. \n - * @ref SOCKERR_SOCKFLAG - Invaild socket flag. - */ -int8_t WIZCHIP_EXPORT(socket)(uint8_t sn, uint8_t protocol, uint16_t port, uint8_t flag); - -/** - * @ingroup WIZnet_socket_APIs - * @brief Close a socket. - * @details It closes the socket with @b'sn' passed as parameter. - * - * @param sn Socket number. It should be 0 ~ @ref \_WIZCHIP_SOCK_NUM_. - * - * @return @b Success : @ref SOCK_OK \n - * @b Fail : @ref SOCKERR_SOCKNUM - Invalid socket number - */ -int8_t WIZCHIP_EXPORT(close)(uint8_t sn); - -/** - * @ingroup WIZnet_socket_APIs - * @brief Listen to a connection request from a client. - * @details It is listening to a connection request from a client. - * If connection request is accepted successfully, the connection is established. Socket sn is used in passive(server) mode. - * - * @param sn Socket number. It should be 0 ~ @ref \_WIZCHIP_SOCK_NUM_. - * @return @b Success : @ref SOCK_OK \n - * @b Fail :\n @ref SOCKERR_SOCKINIT - Socket is not initialized \n - * @ref SOCKERR_SOCKCLOSED - Socket closed unexpectedly. - */ -int8_t WIZCHIP_EXPORT(listen)(uint8_t sn); - -/** - * @ingroup WIZnet_socket_APIs - * @brief Try to connect a server. - * @details It requests connection to the server with destination IP address and port number passed as parameter.\n - * @note It is valid only in TCP client mode. - * In block io mode, it does not return until connection is completed. - * In Non-block io mode, it return @ref SOCK_BUSY immediately. - * - * @param sn Socket number. It should be 0 ~ @ref \_WIZCHIP_SOCK_NUM_. - * @param addr Pointer variable of destination IP address. It should be allocated 4 bytes. - * @param port Destination port number. - * - * @return @b Success : @ref SOCK_OK \n - * @b Fail :\n @ref SOCKERR_SOCKNUM - Invalid socket number\n - * @ref SOCKERR_SOCKMODE - Invalid socket mode\n - * @ref SOCKERR_SOCKINIT - Socket is not initialized\n - * @ref SOCKERR_IPINVALID - Wrong server IP address\n - * @ref SOCKERR_PORTZERO - Server port zero\n - * @ref SOCKERR_TIMEOUT - Timeout occurred during request connection\n - * @ref SOCK_BUSY - In non-block io mode, it returned immediately\n - */ -int8_t WIZCHIP_EXPORT(connect)(uint8_t sn, uint8_t * addr, uint16_t port); - -/** - * @ingroup WIZnet_socket_APIs - * @brief Try to disconnect a connection socket. - * @details It sends request message to disconnect the TCP socket 'sn' passed as parameter to the server or client. - * @note It is valid only in TCP server or client mode. \n - * In block io mode, it does not return until disconnection is completed. \n - * In Non-block io mode, it return @ref SOCK_BUSY immediately. \n - - * @param sn Socket number. It should be 0 ~ @ref \_WIZCHIP_SOCK_NUM_. - * @return @b Success : @ref SOCK_OK \n - * @b Fail :\n @ref SOCKERR_SOCKNUM - Invalid socket number \n - * @ref SOCKERR_SOCKMODE - Invalid operation in the socket \n - * @ref SOCKERR_TIMEOUT - Timeout occurred \n - * @ref SOCK_BUSY - Socket is busy. - */ -int8_t WIZCHIP_EXPORT(disconnect)(uint8_t sn); - -/** - * @ingroup WIZnet_socket_APIs - * @brief Send data to the connected peer in TCP socket. - * @details It is used to send outgoing data to the connected socket. - * @note It is valid only in TCP server or client mode. It can't send data greater than socket buffer size. \n - * In block io mode, It doesn't return until data send is completed - socket buffer size is greater than data. \n - * In non-block io mode, It return @ref SOCK_BUSY immediately when socket buffer is not enough. \n - * @param sn Socket number. It should be 0 ~ @ref \_WIZCHIP_SOCK_NUM_. - * @param buf Pointer buffer containing data to be sent. - * @param len The byte length of data in buf. - * @return @b Success : The sent data size \n - * @b Fail : \n @ref SOCKERR_SOCKSTATUS - Invalid socket status for socket operation \n - * @ref SOCKERR_TIMEOUT - Timeout occurred \n - * @ref SOCKERR_SOCKMODE - Invalid operation in the socket \n - * @ref SOCKERR_SOCKNUM - Invalid socket number \n - * @ref SOCKERR_DATALEN - zero data length \n - * @ref SOCK_BUSY - Socket is busy. - */ -int32_t WIZCHIP_EXPORT(send)(uint8_t sn, uint8_t * buf, uint16_t len); - -/** - * @ingroup WIZnet_socket_APIs - * @brief Receive data from the connected peer. - * @details It is used to read incoming data from the connected socket.\n - * It waits for data as much as the application wants to receive. - * @note It is valid only in TCP server or client mode. It can't receive data greater than socket buffer size. \n - * In block io mode, it doesn't return until data reception is completed - data is filled as len in socket buffer. \n - * In non-block io mode, it return @ref SOCK_BUSY immediately when len is greater than data size in socket buffer. \n - * - * @param sn Socket number. It should be 0 ~ @ref \_WIZCHIP_SOCK_NUM_. - * @param buf Pointer buffer to read incoming data. - * @param len The max data length of data in buf. - * @return @b Success : The real received data size \n - * @b Fail :\n - * @ref SOCKERR_SOCKSTATUS - Invalid socket status for socket operation \n - * @ref SOCKERR_SOCKMODE - Invalid operation in the socket \n - * @ref SOCKERR_SOCKNUM - Invalid socket number \n - * @ref SOCKERR_DATALEN - zero data length \n - * @ref SOCK_BUSY - Socket is busy. - */ -int32_t WIZCHIP_EXPORT(recv)(uint8_t sn, uint8_t * buf, uint16_t len); - -/** - * @ingroup WIZnet_socket_APIs - * @brief Sends datagram to the peer with destination IP address and port number passed as parameter. - * @details It sends datagram of UDP or MACRAW to the peer with destination IP address and port number passed as parameter.\n - * Even if the connectionless socket has been previously connected to a specific address, - * the address and port number parameters override the destination address for that particular datagram only. - * @note In block io mode, It doesn't return until data send is completed - socket buffer size is greater than len. - * In non-block io mode, It return @ref SOCK_BUSY immediately when socket buffer is not enough. - * - * @param sn Socket number. It should be 0 ~ @ref \_WIZCHIP_SOCK_NUM_. - * @param buf Pointer buffer to send outgoing data. - * @param len The byte length of data in buf. - * @param addr Pointer variable of destination IP address. It should be allocated 4 bytes. - * @param port Destination port number. - * - * @return @b Success : The sent data size \n - * @b Fail :\n @ref SOCKERR_SOCKNUM - Invalid socket number \n - * @ref SOCKERR_SOCKMODE - Invalid operation in the socket \n - * @ref SOCKERR_SOCKSTATUS - Invalid socket status for socket operation \n - * @ref SOCKERR_DATALEN - zero data length \n - * @ref SOCKERR_IPINVALID - Wrong server IP address\n - * @ref SOCKERR_PORTZERO - Server port zero\n - * @ref SOCKERR_SOCKCLOSED - Socket unexpectedly closed \n - * @ref SOCKERR_TIMEOUT - Timeout occurred \n - * @ref SOCK_BUSY - Socket is busy. - */ -int32_t WIZCHIP_EXPORT(sendto)(uint8_t sn, uint8_t * buf, uint16_t len, uint8_t * addr, uint16_t port); - -/** - * @ingroup WIZnet_socket_APIs - * @brief Receive datagram of UDP or MACRAW - * @details This function is an application I/F function which is used to receive the data in other then TCP mode. \n - * This function is used to receive UDP and MAC_RAW mode, and handle the header as well. - * This function can divide to received the packet data. - * On the MACRAW SOCKET, the addr and port parameters are ignored. - * @note In block io mode, it doesn't return until data reception is completed - data is filled as len in socket buffer - * In non-block io mode, it return @ref SOCK_BUSY immediately when len is greater than data size in socket buffer. - * - * @param sn Socket number. It should be 0 ~ @ref \_WIZCHIP_SOCK_NUM_. - * @param buf Pointer buffer to read incoming data. - * @param len The max data length of data in buf. - * When the received packet size <= len, receives data as packet sized. - * When others, receives data as len. - * @param addr Pointer variable of destination IP address. It should be allocated 4 bytes. - * It is valid only when the first call recvfrom for receiving the packet. - * When it is valid, @ref packinfo[7] should be set as '1' after call @ref getsockopt(sn, SO_PACKINFO, &packinfo). - * @param port Pointer variable of destination port number. - * It is valid only when the first call recvform for receiving the packet. -* When it is valid, @ref packinfo[7] should be set as '1' after call @ref getsockopt(sn, SO_PACKINFO, &packinfo). - * - * @return @b Success : This function return real received data size for success.\n - * @b Fail : @ref SOCKERR_DATALEN - zero data length \n - * @ref SOCKERR_SOCKMODE - Invalid operation in the socket \n - * @ref SOCKERR_SOCKNUM - Invalid socket number \n - * @ref SOCKBUSY - Socket is busy. - */ -int32_t WIZCHIP_EXPORT(recvfrom)(uint8_t sn, uint8_t * buf, uint16_t len, uint8_t * addr, uint16_t *port); - - -///////////////////////////// -// SOCKET CONTROL & OPTION // -///////////////////////////// -#define SOCK_IO_BLOCK 0 ///< Socket Block IO Mode in @ref setsockopt(). -#define SOCK_IO_NONBLOCK 1 ///< Socket Non-block IO Mode in @ref setsockopt(). - -/** - * @defgroup DATA_TYPE DATA TYPE - */ - -/** - * @ingroup DATA_TYPE - * @brief The kind of Socket Interrupt. - * @sa Sn_IR, Sn_IMR, setSn_IR(), getSn_IR(), setSn_IMR(), getSn_IMR() - */ -typedef enum -{ - SIK_CONNECTED = (1 << 0), ///< connected - SIK_DISCONNECTED = (1 << 1), ///< disconnected - SIK_RECEIVED = (1 << 2), ///< data received - SIK_TIMEOUT = (1 << 3), ///< timeout occurred - SIK_SENT = (1 << 4), ///< send ok - SIK_ALL = 0x1F, ///< all interrupt -}sockint_kind; - -/** - * @ingroup DATA_TYPE - * @brief The type of @ref ctlsocket(). - */ -typedef enum -{ - CS_SET_IOMODE, ///< set socket IO mode with @ref SOCK_IO_BLOCK or @ref SOCK_IO_NONBLOCK - CS_GET_IOMODE, ///< get socket IO mode - CS_GET_MAXTXBUF, ///< get the size of socket buffer allocated in TX memory - CS_GET_MAXRXBUF, ///< get the size of socket buffer allocated in RX memory - CS_CLR_INTERRUPT, ///< clear the interrupt of socket with @ref sockint_kind - CS_GET_INTERRUPT, ///< get the socket interrupt. refer to @ref sockint_kind - CS_SET_INTMASK, ///< set the interrupt mask of socket with @ref sockint_kind - CS_GET_INTMASK ///< get the masked interrupt of socket. refer to @ref sockint_kind -}ctlsock_type; - - -/** - * @ingroup DATA_TYPE - * @brief The type of socket option in @ref setsockopt() or @ref getsockopt() - */ -typedef enum -{ - SO_FLAG, ///< Valid only in getsockopt(), For set flag of socket refer to flag in @ref socket(). - SO_TTL, ///< Set/Get TTL. @ref Sn_TTL ( @ref setSn_TTL(), @ref getSn_TTL() ) - SO_TOS, ///< Set/Get TOS. @ref Sn_TOS ( @ref setSn_TOS(), @ref getSn_TOS() ) - SO_MSS, ///< Set/Get MSS. @ref Sn_MSSR ( @ref setSn_MSSR(), @ref getSn_MSSR() ) - SO_DESTIP, ///< Set/Get the destination IP address. @ref Sn_DIPR ( @ref setSn_DIPR(), @ref getSn_DIPR() ) - SO_DESTPORT, ///< Set/Get the destination Port number. @ref Sn_DPORT ( @ref setSn_DPORT(), @ref getSn_DPORT() ) -#if _WIZCHIP_ != 5100 - SO_KEEPALIVESEND, ///< Valid only in setsockopt. Manually send keep-alive packet in TCP mode - #if _WIZCHIP_ > 5200 - SO_KEEPALIVEAUTO, ///< Set/Get keep-alive auto transmission timer in TCP mode - #endif -#endif - SO_SENDBUF, ///< Valid only in getsockopt. Get the free data size of Socekt TX buffer. @ref Sn_TX_FSR, @ref getSn_TX_FSR() - SO_RECVBUF, ///< Valid only in getsockopt. Get the received data size in socket RX buffer. @ref Sn_RX_RSR, @ref getSn_RX_RSR() - SO_STATUS, ///< Valid only in getsockopt. Get the socket status. @ref Sn_SR, @ref getSn_SR() - SO_REMAINSIZE, ///< Valid only in getsockopt. Get the remained packet size in other then TCP mode. - SO_PACKINFO ///< Valid only in getsockopt. Get the packet information as @ref PACK_FIRST, @ref PACK_REMAINED, and @ref PACK_COMPLETED in other then TCP mode. -}sockopt_type; - -/** - * @ingroup WIZnet_socket_APIs - * @brief Control socket. - * @details Control IO mode, Interrupt & Mask of socket and get the socket buffer information. - * Refer to @ref ctlsock_type. - * @param sn socket number - * @param cstype type of control socket. refer to @ref ctlsock_type. - * @param arg Data type and value is determined according to @ref ctlsock_type. \n - * - * - * - * - * - *
@b cstype @b data type@b value
@ref CS_SET_IOMODE \n @ref CS_GET_IOMODE uint8_t @ref SOCK_IO_BLOCK @ref SOCK_IO_NONBLOCK
@ref CS_GET_MAXTXBUF \n @ref CS_GET_MAXRXBUF uint16_t 0 ~ 16K
@ref CS_CLR_INTERRUPT \n @ref CS_GET_INTERRUPT \n @ref CS_SET_INTMASK \n @ref CS_GET_INTMASK @ref sockint_kind @ref SIK_CONNECTED, etc.
- * @return @b Success @ref SOCK_OK \n - * @b fail @ref SOCKERR_ARG - Invalid argument\n - */ -int8_t WIZCHIP_EXPORT(ctlsocket)(uint8_t sn, ctlsock_type cstype, void* arg); - -/** - * @ingroup WIZnet_socket_APIs - * @brief set socket options - * @details Set socket option like as TTL, MSS, TOS, and so on. Refer to @ref sockopt_type. - * - * @param sn socket number - * @param sotype socket option type. refer to @ref sockopt_type - * @param arg Data type and value is determined according to sotype. \n - * - * - * - * - * - * - * - * - * - *
@b sotype @b data type@b value
@ref SO_TTL uint8_t 0 ~ 255
@ref SO_TOS uint8_t 0 ~ 255
@ref SO_MSS uint16_t 0 ~ 65535
@ref SO_DESTIP uint8_t[4]
@ref SO_DESTPORT uint16_t 0 ~ 65535
@ref SO_KEEPALIVESEND null null
@ref SO_KEEPALIVEAUTO uint8_t 0 ~ 255
- * @return - * - @b Success : @ref SOCK_OK \n - * - @b Fail - * - @ref SOCKERR_SOCKNUM - Invalid Socket number \n - * - @ref SOCKERR_SOCKMODE - Invalid socket mode \n - * - @ref SOCKERR_SOCKOPT - Invalid socket option or its value \n - * - @ref SOCKERR_TIMEOUT - Timeout occurred when sending keep-alive packet \n - */ -int8_t WIZCHIP_EXPORT(setsockopt)(uint8_t sn, sockopt_type sotype, void* arg); - -/** - * @ingroup WIZnet_socket_APIs - * @brief get socket options - * @details Get socket option like as FLAG, TTL, MSS, and so on. Refer to @ref sockopt_type - * @param sn socket number - * @param sotype socket option type. refer to @ref sockopt_type - * @param arg Data type and value is determined according to sotype. \n - * - * - * - * - * - * - * - * - * - * - * - * - * - *
@b sotype @b data type@b value
@ref SO_FLAG uint8_t @ref SF_ETHER_OWN, etc...
@ref SO_TOS uint8_t 0 ~ 255
@ref SO_MSS uint16_t 0 ~ 65535
@ref SO_DESTIP uint8_t[4]
@ref SO_DESTPORT uint16_t
@ref SO_KEEPALIVEAUTO uint8_t 0 ~ 255
@ref SO_SENDBUF uint16_t 0 ~ 65535
@ref SO_RECVBUF uint16_t 0 ~ 65535
@ref SO_STATUS uint8_t @ref SOCK_ESTABLISHED, etc..
@ref SO_REMAINSIZE uint16_t 0~ 65535
@ref SO_PACKINFO uint8_t @ref PACK_FIRST, etc...
- * @return - * - @b Success : @ref SOCK_OK \n - * - @b Fail - * - @ref SOCKERR_SOCKNUM - Invalid Socket number \n - * - @ref SOCKERR_SOCKOPT - Invalid socket option or its value \n - * - @ref SOCKERR_SOCKMODE - Invalid socket mode \n - * @note - * The option as PACK_REMAINED and SO_PACKINFO is valid only in NON-TCP mode and after call @ref recvfrom(). \n - * When SO_PACKINFO value is PACK_FIRST and the return value of recvfrom() is zero, - * This means the zero byte UDP data(UDP Header only) received. - */ -int8_t WIZCHIP_EXPORT(getsockopt)(uint8_t sn, sockopt_type sotype, void* arg); - -#endif // _WIZCHIP_SOCKET_H_ diff --git a/drivers/wiznet5k/ethernet/w5200/w5200.c b/drivers/wiznet5k/ethernet/w5200/w5200.c deleted file mode 100644 index 8c3780792e..0000000000 --- a/drivers/wiznet5k/ethernet/w5200/w5200.c +++ /dev/null @@ -1,206 +0,0 @@ -// dpgeorge: this file taken from w5500/w5500.c and adapted to W5200 - -//***************************************************************************** -// -//! \file w5500.c -//! \brief W5500 HAL Interface. -//! \version 1.0.1 -//! \date 2013/10/21 -//! \par Revision history -//! <2014/05/01> V1.0.2 -//! 1. Implicit type casting -> Explicit type casting. Refer to M20140501 -//! Fixed the problem on porting into under 32bit MCU -//! Issued by Mathias ClauBen, wizwiki forum ID Think01 and bobh -//! Thank for your interesting and serious advices. -//! <2013/10/21> 1st Release -//! <2013/12/20> V1.0.1 -//! 1. Remove warning -//! 2. WIZCHIP_READ_BUF WIZCHIP_WRITE_BUF in case _WIZCHIP_IO_MODE_SPI_FDM_ -//! for loop optimized(removed). refer to M20131220 -//! \author MidnightCow -//! \copyright -//! -//! Copyright (c) 2013, WIZnet Co., LTD. -//! All rights reserved. -//! -//! Redistribution and use in source and binary forms, with or without -//! modification, are permitted provided that the following conditions -//! are met: -//! -//! * Redistributions of source code must retain the above copyright -//! notice, this list of conditions and the following disclaimer. -//! * Redistributions in binary form must reproduce the above copyright -//! notice, this list of conditions and the following disclaimer in the -//! documentation and/or other materials provided with the distribution. -//! * Neither the name of the nor the names of its -//! contributors may be used to endorse or promote products derived -//! from this software without specific prior written permission. -//! -//! THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" -//! AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -//! IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE -//! ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE -//! LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR -//! CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF -//! SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS -//! INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN -//! CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) -//! ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF -//! THE POSSIBILITY OF SUCH DAMAGE. -// -//***************************************************************************** - -#include "w5200.h" - -#define SMASK (0x7ff) /* tx buffer mask */ -#define RMASK (0x7ff) /* rx buffer mask */ -#define SSIZE (2048) /* max tx buffer size */ -#define RSIZE (2048) /* max rx buffer size */ - -#define TXBUF_BASE (0x8000) -#define RXBUF_BASE (0xc000) -#define SBASE(sn) (TXBUF_BASE + SSIZE * (sn)) /* tx buffer base for socket sn */ -#define RBASE(sn) (RXBUF_BASE + RSIZE * (sn)) /* rx buffer base for socket sn */ - -uint8_t WIZCHIP_READ(uint32_t AddrSel) { - WIZCHIP_CRITICAL_ENTER(); - WIZCHIP.CS._select(); - - uint8_t spi_data[4] = { - AddrSel >> 8, - AddrSel, - 0x00, - 0x01, - }; - WIZCHIP.IF.SPI._write_bytes(spi_data, 4); - uint8_t ret; - WIZCHIP.IF.SPI._read_bytes(&ret, 1); - - WIZCHIP.CS._deselect(); - WIZCHIP_CRITICAL_EXIT(); - - return ret; -} - -void WIZCHIP_WRITE(uint32_t AddrSel, uint8_t wb) { - WIZCHIP_CRITICAL_ENTER(); - WIZCHIP.CS._select(); - - uint8_t spi_data[5] = { - AddrSel >> 8, - AddrSel, - 0x80, - 0x01, - wb, - }; - WIZCHIP.IF.SPI._write_bytes(spi_data, 5); - - WIZCHIP.CS._deselect(); - WIZCHIP_CRITICAL_EXIT(); -} - -void WIZCHIP_READ_BUF(uint32_t AddrSel, uint8_t* pBuf, uint16_t len) { - WIZCHIP_CRITICAL_ENTER(); - WIZCHIP.CS._select(); - - uint8_t spi_data[4] = { - AddrSel >> 8, - AddrSel, - 0x00 | ((len >> 8) & 0x7f), - len & 0xff, - }; - WIZCHIP.IF.SPI._write_bytes(spi_data, 4); - WIZCHIP.IF.SPI._read_bytes(pBuf, len); - - WIZCHIP.CS._deselect(); - WIZCHIP_CRITICAL_EXIT(); -} - -void WIZCHIP_WRITE_BUF(uint32_t AddrSel, uint8_t* pBuf, uint16_t len) { - WIZCHIP_CRITICAL_ENTER(); - WIZCHIP.CS._select(); - - uint8_t spi_data[4] = { - AddrSel >> 8, - AddrSel, - 0x80 | ((len >> 8) & 0x7f), - len & 0xff, - }; - WIZCHIP.IF.SPI._write_bytes(spi_data, 4); - WIZCHIP.IF.SPI._write_bytes(pBuf, len); - - WIZCHIP.CS._deselect(); - WIZCHIP_CRITICAL_EXIT(); -} - -uint16_t getSn_TX_FSR(uint8_t sn) { - uint16_t val = 0, val1 = 0; - do { - val1 = (WIZCHIP_READ(Sn_TX_FSR(sn)) << 8) | WIZCHIP_READ(Sn_TX_FSR(sn) + 1); - if (val1 != 0) { - val = (WIZCHIP_READ(Sn_TX_FSR(sn)) << 8) | WIZCHIP_READ(Sn_TX_FSR(sn) + 1); - } - } while (val != val1); - return val; -} - -uint16_t getSn_RX_RSR(uint8_t sn) { - uint16_t val = 0, val1 = 0; - do { - val1 = (WIZCHIP_READ(Sn_RX_RSR(sn)) << 8) | WIZCHIP_READ(Sn_RX_RSR(sn) + 1); - if (val1 != 0) { - val = (WIZCHIP_READ(Sn_RX_RSR(sn)) << 8) | WIZCHIP_READ(Sn_RX_RSR(sn) + 1); - } - } while (val != val1); - return val; -} - -void wiz_send_data(uint8_t sn, uint8_t *wizdata, uint16_t len) { - if (len == 0) { - return; - } - - uint16_t ptr = getSn_TX_WR(sn); - uint16_t offset = ptr & SMASK; - uint32_t addr = offset + SBASE(sn); - - if (offset + len > SSIZE) { - // implement wrap-around circular buffer - uint16_t size = SSIZE - offset; - WIZCHIP_WRITE_BUF(addr, wizdata, size); - WIZCHIP_WRITE_BUF(SBASE(sn), wizdata + size, len - size); - } else { - WIZCHIP_WRITE_BUF(addr, wizdata, len); - } - - ptr += len; - setSn_TX_WR(sn, ptr); -} - -void wiz_recv_data(uint8_t sn, uint8_t *wizdata, uint16_t len) { - if (len == 0) { - return; - } - - uint16_t ptr = getSn_RX_RD(sn); - uint16_t offset = ptr & RMASK; - uint16_t addr = RBASE(sn) + offset; - - if (offset + len > RSIZE) { - // implement wrap-around circular buffer - uint16_t size = RSIZE - offset; - WIZCHIP_READ_BUF(addr, wizdata, size); - WIZCHIP_READ_BUF(RBASE(sn), wizdata + size, len - size); - } else { - WIZCHIP_READ_BUF(addr, wizdata, len); - } - - ptr += len; - setSn_RX_RD(sn, ptr); -} - -void wiz_recv_ignore(uint8_t sn, uint16_t len) { - uint16_t ptr = getSn_RX_RD(sn); - ptr += len; - setSn_RX_RD(sn, ptr); -} diff --git a/drivers/wiznet5k/ethernet/w5200/w5200.h b/drivers/wiznet5k/ethernet/w5200/w5200.h deleted file mode 100644 index 63561940f8..0000000000 --- a/drivers/wiznet5k/ethernet/w5200/w5200.h +++ /dev/null @@ -1,2092 +0,0 @@ -// dpgeorge: this file taken from w5500/w5500.h and adapted to W5200 - -//***************************************************************************** -// -//! \file w5500.h -//! \brief W5500 HAL Header File. -//! \version 1.0.0 -//! \date 2013/10/21 -//! \par Revision history -//! <2013/10/21> 1st Release -//! \author MidnightCow -//! \copyright -//! -//! Copyright (c) 2013, WIZnet Co., LTD. -//! All rights reserved. -//! -//! Redistribution and use in source and binary forms, with or without -//! modification, are permitted provided that the following conditions -//! are met: -//! -//! * Redistributions of source code must retain the above copyright -//! notice, this list of conditions and the following disclaimer. -//! * Redistributions in binary form must reproduce the above copyright -//! notice, this list of conditions and the following disclaimer in the -//! documentation and/or other materials provided with the distribution. -//! * Neither the name of the nor the names of its -//! contributors may be used to endorse or promote products derived -//! from this software without specific prior written permission. -//! -//! THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" -//! AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -//! IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE -//! ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE -//! LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR -//! CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF -//! SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS -//! INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN -//! CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) -//! ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF -//! THE POSSIBILITY OF SUCH DAMAGE. -// -//***************************************************************************** - -#ifndef _W5200_H_ -#define _W5200_H_ - -#include -#include "../wizchip_conf.h" -//#include "board.h" - -#define _W5200_IO_BASE_ 0x00000000 - -#define WIZCHIP_CREG_ADDR(addr) (_W5200_IO_BASE_ + (addr)) - -#define WIZCHIP_CH_BASE (0x4000) -#define WIZCHIP_CH_SIZE (0x100) -#define WIZCHIP_SREG_ADDR(sn, addr) (_W5200_IO_BASE_ + WIZCHIP_CH_BASE + (sn) * WIZCHIP_CH_SIZE + (addr)) - -////////////////////////////// -//-------------------------- defgroup --------------------------------- -/** - * @defgroup W5500 W5500 - * - * @brief WHIZCHIP register defines and I/O functions of @b W5500. - * - * - @ref WIZCHIP_register : @ref Common_register_group and @ref Socket_register_group - * - @ref WIZCHIP_IO_Functions : @ref Basic_IO_function, @ref Common_register_access_function and @ref Socket_register_access_function - */ - - -/** - * @defgroup WIZCHIP_register WIZCHIP register - * @ingroup W5500 - * - * @brief WHIZCHIP register defines register group of @b W5500. - * - * - @ref Common_register_group : Common register group - * - @ref Socket_register_group : \c SOCKET n register group - */ - - -/** - * @defgroup WIZCHIP_IO_Functions WIZCHIP I/O functions - * @ingroup W5500 - * - * @brief This supports the basic I/O functions for @ref WIZCHIP_register. - * - * - Basic I/O function \n - * WIZCHIP_READ(), WIZCHIP_WRITE(), WIZCHIP_READ_BUF(), WIZCHIP_WRITE_BUF() \n\n - * - * - @ref Common_register_group access functions \n - * -# @b Mode \n - * getMR(), setMR() - * -# @b Interrupt \n - * getIR(), setIR(), getIMR(), setIMR(), getSIR(), setSIR(), getSIMR(), setSIMR(), getINTLEVEL(), setINTLEVEL() - * -# Network Information \n - * getSHAR(), setSHAR(), getGAR(), setGAR(), getSUBR(), setSUBR(), getSIPR(), setSIPR() - * -# @b Retransmission \n - * getRCR(), setRCR(), getRTR(), setRTR() - * -# @b PPPoE \n - * getPTIMER(), setPTIMER(), getPMAGIC(), getPMAGIC(), getPSID(), setPSID(), getPHAR(), setPHAR(), getPMRU(), setPMRU() - * -# ICMP packet \n - * getUIPR(), getUPORTR() - * -# @b etc. \n - * getPHYCFGR(), setPHYCFGR(), getVERSIONR() \n\n - * - * - \ref Socket_register_group access functions \n - * -# SOCKET control \n - * getSn_MR(), setSn_MR(), getSn_CR(), setSn_CR(), getSn_IMR(), setSn_IMR(), getSn_IR(), setSn_IR() - * -# SOCKET information \n - * getSn_SR(), getSn_DHAR(), setSn_DHAR(), getSn_PORT(), setSn_PORT(), getSn_DIPR(), setSn_DIPR(), getSn_DPORT(), setSn_DPORT() - * getSn_MSSR(), setSn_MSSR() - * -# SOCKET communication \n - * getSn_RXBUF_SIZE(), setSn_RXBUF_SIZE(), getSn_TXBUF_SIZE(), setSn_TXBUF_SIZE() \n - * getSn_TX_RD(), getSn_TX_WR(), setSn_TX_WR() \n - * getSn_RX_RD(), setSn_RX_RD(), getSn_RX_WR() \n - * getSn_TX_FSR(), getSn_RX_RSR(), getSn_KPALVTR(), setSn_KPALVTR() - * -# IP header field \n - * getSn_FRAG(), setSn_FRAG(), getSn_TOS(), setSn_TOS() \n - * getSn_TTL(), setSn_TTL() - */ - - - -/** - * @defgroup Common_register_group Common register - * @ingroup WIZCHIP_register - * - * @brief Common register group\n - * It set the basic for the networking\n - * It set the configuration such as interrupt, network information, ICMP, etc. - * @details - * @sa MR : Mode register. - * @sa GAR, SUBR, SHAR, SIPR - * @sa INTLEVEL, IR, IMR, SIR, SIMR : Interrupt. - * @sa RTR, RCR : Data retransmission. - * @sa PTIMER, PMAGIC, PHAR, PSID, PMRU : PPPoE. - * @sa UIPR, UPORTR : ICMP message. - * @sa PHYCFGR, VERSIONR : etc. - */ - - - -/** - * @defgroup Socket_register_group Socket register - * @ingroup WIZCHIP_register - * - * @brief Socket register group.\n - * Socket register configures and control SOCKETn which is necessary to data communication. - * @details - * @sa Sn_MR, Sn_CR, Sn_IR, Sn_IMR : SOCKETn Control - * @sa Sn_SR, Sn_PORT, Sn_DHAR, Sn_DIPR, Sn_DPORT : SOCKETn Information - * @sa Sn_MSSR, Sn_TOS, Sn_TTL, Sn_KPALVTR, Sn_FRAG : Internet protocol. - * @sa Sn_RXBUF_SIZE, Sn_TXBUF_SIZE, Sn_TX_FSR, Sn_TX_RD, Sn_TX_WR, Sn_RX_RSR, Sn_RX_RD, Sn_RX_WR : Data communication - */ - - - - /** - * @defgroup Basic_IO_function Basic I/O function - * @ingroup WIZCHIP_IO_Functions - * @brief These are basic input/output functions to read values from register or write values to register. - */ - -/** - * @defgroup Common_register_access_function Common register access functions - * @ingroup WIZCHIP_IO_Functions - * @brief These are functions to access common registers. - */ - -/** - * @defgroup Socket_register_access_function Socket register access functions - * @ingroup WIZCHIP_IO_Functions - * @brief These are functions to access socket registers. - */ - -//------------------------------- defgroup end -------------------------------------------- -//----------------------------- W5500 Common Registers IOMAP ----------------------------- -/** - * @ingroup Common_register_group - * @brief Mode Register address(R/W)\n - * @ref MR is used for S/W reset, ping block mode, PPPoE mode and etc. - * @details Each bit of @ref MR defined as follows. - * - * - * - *
7 6 5 4 3 2 1 0
RST Reserved WOL PB PPPoE Reserved FARP Reserved
- * - \ref MR_RST : Reset - * - \ref MR_WOL : Wake on LAN - * - \ref MR_PB : Ping block - * - \ref MR_PPPOE : PPPoE mode - * - \ref MR_FARP : Force ARP mode - */ -#define MR WIZCHIP_CREG_ADDR(0x0000) - -/** - * @ingroup Common_register_group - * @brief Gateway IP Register address(R/W) - * @details @ref GAR configures the default gateway address. - */ -#define GAR WIZCHIP_CREG_ADDR(0x0001) - -/** - * @ingroup Common_register_group - * @brief Subnet mask Register address(R/W) - * @details @ref SUBR configures the subnet mask address. - */ -#define SUBR WIZCHIP_CREG_ADDR(0x0005) - -/** - * @ingroup Common_register_group - * @brief Source MAC Register address(R/W) - * @details @ref SHAR configures the source hardware address. - */ -#define SHAR WIZCHIP_CREG_ADDR(0x0009) - -/** - * @ingroup Common_register_group - * @brief Source IP Register address(R/W) - * @details @ref SIPR configures the source IP address. - */ -#define SIPR WIZCHIP_CREG_ADDR(0x000f) - -/** - * @ingroup Common_register_group - * @brief Set Interrupt low level timer register address(R/W) - * @details @ref INTLEVEL configures the Interrupt Assert Time. - */ -//#define INTLEVEL (_W5500_IO_BASE_ + (0x0013 << 8) + (WIZCHIP_CREG_BLOCK << 3)) - -/** - * @ingroup Common_register_group - * @brief Interrupt Register(R/W) - * @details @ref IR indicates the interrupt status. Each bit of @ref IR will be still until the bit will be written to by the host. - * If @ref IR is not equal to x00 INTn PIN is asserted to low until it is x00\n\n - * Each bit of @ref IR defined as follows. - * - * - * - *
7 6 5 4 3 2 1 0
CONFLICT UNREACH PPPoE MP Reserved Reserved Reserved Reserved
- * - \ref IR_CONFLICT : IP conflict - * - \ref IR_UNREACH : Destination unreachable - * - \ref IR_PPPoE : PPPoE connection close - * - \ref IR_MP : Magic packet - */ -#define IR WIZCHIP_CREG_ADDR(0x0015) - -/** - * @ingroup Common_register_group - * @brief Interrupt mask register(R/W) - * @details @ref IMR is used to mask interrupts. Each bit of @ref IMR corresponds to each bit of @ref IR. - * When a bit of @ref IMR is and the corresponding bit of @ref IR is an interrupt will be issued. In other words, - * if a bit of @ref IMR is an interrupt will not be issued even if the corresponding bit of @ref IR is \n\n - * Each bit of @ref IMR defined as the following. - * - * - * - *
7 6 5 4 3 2 1 0
IM_IR7 IM_IR6 IM_IR5 IM_IR4 Reserved Reserved Reserved Reserved
- * - \ref IM_IR7 : IP Conflict Interrupt Mask - * - \ref IM_IR6 : Destination unreachable Interrupt Mask - * - \ref IM_IR5 : PPPoE Close Interrupt Mask - * - \ref IM_IR4 : Magic Packet Interrupt Mask - */ -#define IMR WIZCHIP_CREG_ADDR(0x0016) - -/** - * @ingroup Common_register_group - * @brief Socket Interrupt Register(R/W) - * @details @ref SIR indicates the interrupt status of Socket.\n - * Each bit of @ref SIR be still until @ref Sn_IR is cleared by the host.\n - * If @ref Sn_IR is not equal to x00 the n-th bit of @ref SIR is and INTn PIN is asserted until @ref SIR is x00 */ -//#define SIR (_W5500_IO_BASE_ + (0x0017 << 8) + (WIZCHIP_CREG_BLOCK << 3)) - -/** - * @ingroup Common_register_group - * @brief Socket Interrupt Mask Register(R/W) - * @details Each bit of @ref SIMR corresponds to each bit of @ref SIR. - * When a bit of @ref SIMR is and the corresponding bit of @ref SIR is Interrupt will be issued. - * In other words, if a bit of @ref SIMR is an interrupt will be not issued even if the corresponding bit of @ref SIR is - */ -//#define SIMR (_W5500_IO_BASE_ + (0x0018 << 8) + (WIZCHIP_CREG_BLOCK << 3)) - -/** - * @ingroup Common_register_group - * @brief Timeout register address( 1 is 100us )(R/W) - * @details @ref RTR configures the retransmission timeout period. The unit of timeout period is 100us and the default of @ref RTR is x07D0or 000 - * And so the default timeout period is 200ms(100us X 2000). During the time configured by @ref RTR, W5500 waits for the peer response - * to the packet that is transmitted by \ref Sn_CR (CONNECT, DISCON, CLOSE, SEND, SEND_MAC, SEND_KEEP command). - * If the peer does not respond within the @ref RTR time, W5500 retransmits the packet or issues timeout. - */ -#define RTR WIZCHIP_CREG_ADDR(0x0017) - -/** - * @ingroup Common_register_group - * @brief Retry count register(R/W) - * @details @ref RCR configures the number of time of retransmission. - * When retransmission occurs as many as ref RCR+1 Timeout interrupt is issued (@ref Sn_IR[TIMEOUT] = . - */ -#define RCR WIZCHIP_CREG_ADDR(0x0019) - -/** - * @ingroup Common_register_group - * @brief PPP LCP Request Timer register in PPPoE mode(R/W) - * @details @ref PTIMER configures the time for sending LCP echo request. The unit of time is 25ms. - */ -#define PTIMER WIZCHIP_CREG_ADDR(0x0028) - -/** - * @ingroup Common_register_group - * @brief PPP LCP Magic number register in PPPoE mode(R/W) - * @details @ref PMAGIC configures the 4bytes magic number to be used in LCP negotiation. - */ -#define PMAGIC WIZCHIP_CREG_ADDR(0x0029) - -/** - * @ingroup Common_register_group - * @brief PPP Destination MAC Register address(R/W) - * @details @ref PHAR configures the PPPoE server hardware address that is acquired during PPPoE connection process. - */ -//#define PHAR (_W5500_IO_BASE_ + (0x001E << 8) + (WIZCHIP_CREG_BLOCK << 3)) - -/** - * @ingroup Common_register_group - * @brief PPP Session Identification Register(R/W) - * @details @ref PSID configures the PPPoE sever session ID acquired during PPPoE connection process. - */ -//#define PSID (_W5500_IO_BASE_ + (0x0024 << 8) + (WIZCHIP_CREG_BLOCK << 3)) - -/** - * @ingroup Common_register_group - * @brief PPP Maximum Segment Size(MSS) register(R/W) - * @details @ref PMRU configures the maximum receive unit of PPPoE. - */ -//#define PMRU (_W5500_IO_BASE_ + (0x0026 << 8) + (WIZCHIP_CREG_BLOCK << 3)) - -/** - * @ingroup Common_register_group - * @brief Unreachable IP register address in UDP mode(R) - * @details W5500 receives an ICMP packet(Destination port unreachable) when data is sent to a port number - * which socket is not open and @ref UNREACH bit of @ref IR becomes and @ref UIPR & @ref UPORTR indicates - * the destination IP address & port number respectively. - */ -//#define UIPR (_W5500_IO_BASE_ + (0x002a << 8) + (WIZCHIP_CREG_BLOCK << 3)) - -/** - * @ingroup Common_register_group - * @brief Unreachable Port register address in UDP mode(R) - * @details W5500 receives an ICMP packet(Destination port unreachable) when data is sent to a port number - * which socket is not open and @ref UNREACH bit of @ref IR becomes and @ref UIPR & @ref UPORTR - * indicates the destination IP address & port number respectively. - */ -//#define UPORTR (_W5500_IO_BASE_ + (0x002e << 8) + (WIZCHIP_CREG_BLOCK << 3)) - -/** - * @ingroup Common_register_group - * @brief PHY Status Register(R/W) - * @details @ref PHYCFGR configures PHY operation mode and resets PHY. In addition, @ref PHYCFGR indicates the status of PHY such as duplex, Speed, Link. - */ -//#define PHYCFGR (_W5500_IO_BASE_ + (0x002E << 8) + (WIZCHIP_CREG_BLOCK << 3)) -#define PHYSTATUS WIZCHIP_CREG_ADDR(0x0035) - -// Reserved (_W5500_IO_BASE_ + (0x002F << 8) + (WIZCHIP_CREG_BLOCK << 3)) -// Reserved (_W5500_IO_BASE_ + (0x0030 << 8) + (WIZCHIP_CREG_BLOCK << 3)) -// Reserved (_W5500_IO_BASE_ + (0x0031 << 8) + (WIZCHIP_CREG_BLOCK << 3)) -// Reserved (_W5500_IO_BASE_ + (0x0032 << 8) + (WIZCHIP_CREG_BLOCK << 3)) -// Reserved (_W5500_IO_BASE_ + (0x0033 << 8) + (WIZCHIP_CREG_BLOCK << 3)) -// Reserved (_W5500_IO_BASE_ + (0x0034 << 8) + (WIZCHIP_CREG_BLOCK << 3)) -// Reserved (_W5500_IO_BASE_ + (0x0035 << 8) + (WIZCHIP_CREG_BLOCK << 3)) -// Reserved (_W5500_IO_BASE_ + (0x0036 << 8) + (WIZCHIP_CREG_BLOCK << 3)) -// Reserved (_W5500_IO_BASE_ + (0x0037 << 8) + (WIZCHIP_CREG_BLOCK << 3)) -// Reserved (_W5500_IO_BASE_ + (0x0038 << 8) + (WIZCHIP_CREG_BLOCK << 3)) - -/** - * @ingroup Common_register_group - * @brief chip version register address(R) - * @details @ref VERSIONR always indicates the W5500 version as @b 0x04. - */ -//#define VERSIONR (_W5200_IO_BASE_ + (0x0039 << 8) + (WIZCHIP_CREG_BLOCK << 3)) - - -//----------------------------- W5500 Socket Registers IOMAP ----------------------------- -/** - * @ingroup Socket_register_group - * @brief socket Mode register(R/W) - * @details @ref Sn_MR configures the option or protocol type of Socket n.\n\n - * Each bit of @ref Sn_MR defined as the following. - * - * - * - *
7 6 5 4 3 2 1 0
MULTI/MFEN BCASTB ND/MC/MMB UCASTB/MIP6B Protocol[3] Protocol[2] Protocol[1] Protocol[0]
- * - @ref Sn_MR_MULTI : Support UDP Multicasting - * - @ref Sn_MR_BCASTB : Broadcast block in UDP Multicasting - * - @ref Sn_MR_ND : No Delayed Ack(TCP) flag - * - @ref Sn_MR_MC : IGMP version used in UDP mulitcasting - * - @ref Sn_MR_MMB : Multicast Blocking in @ref Sn_MR_MACRAW mode - * - @ref Sn_MR_UCASTB : Unicast Block in UDP Multicating - * - @ref Sn_MR_MIP6B : IPv6 packet Blocking in @ref Sn_MR_MACRAW mode - * - Protocol - * - * - * - * - * - * - *
Protocol[3] Protocol[2] Protocol[1] Protocol[0] @b Meaning
0 0 0 0 Closed
0 0 0 1 TCP
0 0 1 0 UDP
0 1 0 0 MACRAW
- * - @ref Sn_MR_MACRAW : MAC LAYER RAW SOCK \n - * - @ref Sn_MR_UDP : UDP - * - @ref Sn_MR_TCP : TCP - * - @ref Sn_MR_CLOSE : Unused socket - * @note MACRAW mode should be only used in Socket 0. - */ -#define Sn_MR(N) WIZCHIP_SREG_ADDR(N, 0x0000) - -/** - * @ingroup Socket_register_group - * @brief Socket command register(R/W) - * @details This is used to set the command for Socket n such as OPEN, CLOSE, CONNECT, LISTEN, SEND, and RECEIVE.\n - * After W5500 accepts the command, the @ref Sn_CR register is automatically cleared to 0x00. - * Even though @ref Sn_CR is cleared to 0x00, the command is still being processed.\n - * To check whether the command is completed or not, please check the @ref Sn_IR or @ref Sn_SR. - * - @ref Sn_CR_OPEN : Initialize or open socket. - * - @ref Sn_CR_LISTEN : Wait connection request in TCP mode(Server mode) - * - @ref Sn_CR_CONNECT : Send connection request in TCP mode(Client mode) - * - @ref Sn_CR_DISCON : Send closing request in TCP mode. - * - @ref Sn_CR_CLOSE : Close socket. - * - @ref Sn_CR_SEND : Update TX buffer pointer and send data. - * - @ref Sn_CR_SEND_MAC : Send data with MAC address, so without ARP process. - * - @ref Sn_CR_SEND_KEEP : Send keep alive message. - * - @ref Sn_CR_RECV : Update RX buffer pointer and receive data. - */ -#define Sn_CR(N) WIZCHIP_SREG_ADDR(N, 0x0001) - -/** - * @ingroup Socket_register_group - * @brief Socket interrupt register(R) - * @details @ref Sn_IR indicates the status of Socket Interrupt such as establishment, termination, receiving data, timeout).\n - * When an interrupt occurs and the corresponding bit of @ref Sn_IMR is the corresponding bit of @ref Sn_IR becomes \n - * In order to clear the @ref Sn_IR bit, the host should write the bit to \n - * - * - * - *
7 6 5 4 3 2 1 0
Reserved Reserved Reserved SEND_OK TIMEOUT RECV DISCON CON
- * - \ref Sn_IR_SENDOK : SEND_OK Interrupt - * - \ref Sn_IR_TIMEOUT : TIMEOUT Interrupt - * - \ref Sn_IR_RECV : RECV Interrupt - * - \ref Sn_IR_DISCON : DISCON Interrupt - * - \ref Sn_IR_CON : CON Interrupt - */ -#define Sn_IR(N) WIZCHIP_SREG_ADDR(N, 0x0002) - -/** - * @ingroup Socket_register_group - * @brief Socket status register(R) - * @details @ref Sn_SR indicates the status of Socket n.\n - * The status of Socket n is changed by @ref Sn_CR or some special control packet as SYN, FIN packet in TCP. - * @par Normal status - * - @ref SOCK_CLOSED : Closed - * - @ref SOCK_INIT : Initiate state - * - @ref SOCK_LISTEN : Listen state - * - @ref SOCK_ESTABLISHED : Success to connect - * - @ref SOCK_CLOSE_WAIT : Closing state - * - @ref SOCK_UDP : UDP socket - * - @ref SOCK_MACRAW : MAC raw mode socket - *@par Temporary status during changing the status of Socket n. - * - @ref SOCK_SYNSENT : This indicates Socket n sent the connect-request packet (SYN packet) to a peer. - * - @ref SOCK_SYNRECV : It indicates Socket n successfully received the connect-request packet (SYN packet) from a peer. - * - @ref SOCK_FIN_WAIT : Connection state - * - @ref SOCK_CLOSING : Closing state - * - @ref SOCK_TIME_WAIT : Closing state - * - @ref SOCK_LAST_ACK : Closing state - */ -#define Sn_SR(N) WIZCHIP_SREG_ADDR(N, 0x0003) - -/** - * @ingroup Socket_register_group - * @brief source port register(R/W) - * @details @ref Sn_PORT configures the source port number of Socket n. - * It is valid when Socket n is used in TCP/UPD mode. It should be set before OPEN command is ordered. - */ -#define Sn_PORT(N) WIZCHIP_SREG_ADDR(N, 0x0004) - -/** - * @ingroup Socket_register_group - * @brief Peer MAC register address(R/W) - * @details @ref Sn_DHAR configures the destination hardware address of Socket n when using SEND_MAC command in UDP mode or - * it indicates that it is acquired in ARP-process by CONNECT/SEND command. - */ -#define Sn_DHAR(N) WIZCHIP_SREG_ADDR(N, 0x0006) - -/** - * @ingroup Socket_register_group - * @brief Peer IP register address(R/W) - * @details @ref Sn_DIPR configures or indicates the destination IP address of Socket n. It is valid when Socket n is used in TCP/UDP mode. - * In TCP client mode, it configures an IP address of �TCP serverbefore CONNECT command. - * In TCP server mode, it indicates an IP address of �TCP clientafter successfully establishing connection. - * In UDP mode, it configures an IP address of peer to be received the UDP packet by SEND or SEND_MAC command. - */ -#define Sn_DIPR(N) WIZCHIP_SREG_ADDR(N, 0x000c) - -/** - * @ingroup Socket_register_group - * @brief Peer port register address(R/W) - * @details @ref Sn_DPORT configures or indicates the destination port number of Socket n. It is valid when Socket n is used in TCP/UDP mode. - * In �TCP clientmode, it configures the listen port number of �TCP serverbefore CONNECT command. - * In �TCP Servermode, it indicates the port number of TCP client after successfully establishing connection. - * In UDP mode, it configures the port number of peer to be transmitted the UDP packet by SEND/SEND_MAC command. - */ -#define Sn_DPORT(N) WIZCHIP_SREG_ADDR(N, 0x0010) - -/** - * @ingroup Socket_register_group - * @brief Maximum Segment Size(Sn_MSSR0) register address(R/W) - * @details @ref Sn_MSSR configures or indicates the MTU(Maximum Transfer Unit) of Socket n. - */ -#define Sn_MSSR(N) WIZCHIP_SREG_ADDR(N, 0x0012) - -// Reserved (_W5500_IO_BASE_ + (0x0014 << 8) + (WIZCHIP_SREG_BLOCK(N) << 3)) - -/** - * @ingroup Socket_register_group - * @brief IP Type of Service(TOS) Register(R/W) - * @details @ref Sn_TOS configures the TOS(Type Of Service field in IP Header) of Socket n. - * It is set before OPEN command. - */ -#define Sn_TOS(N) WIZCHIP_SREG_ADDR(N, 0x0015) -/** - * @ingroup Socket_register_group - * @brief IP Time to live(TTL) Register(R/W) - * @details @ref Sn_TTL configures the TTL(Time To Live field in IP header) of Socket n. - * It is set before OPEN command. - */ -#define Sn_TTL(N) WIZCHIP_SREG_ADDR(N, 0x0016) -// Reserved (_W5500_IO_BASE_ + (0x0017 << 8) + (WIZCHIP_SREG_BLOCK(N) << 3)) -// Reserved (_W5500_IO_BASE_ + (0x0018 << 8) + (WIZCHIP_SREG_BLOCK(N) << 3)) -// Reserved (_W5500_IO_BASE_ + (0x0019 << 8) + (WIZCHIP_SREG_BLOCK(N) << 3)) -// Reserved (_W5500_IO_BASE_ + (0x001A << 8) + (WIZCHIP_SREG_BLOCK(N) << 3)) -// Reserved (_W5500_IO_BASE_ + (0x001B << 8) + (WIZCHIP_SREG_BLOCK(N) << 3)) -// Reserved (_W5500_IO_BASE_ + (0x001C << 8) + (WIZCHIP_SREG_BLOCK(N) << 3)) -// Reserved (_W5500_IO_BASE_ + (0x001D << 8) + (WIZCHIP_SREG_BLOCK(N) << 3)) - -/** - * @ingroup Socket_register_group - * @brief Receive memory size register(R/W) - * @details @ref Sn_RXBUF_SIZE configures the RX buffer block size of Socket n. - * Socket n RX Buffer Block size can be configured with 1,2,4,8, and 16 Kbytes. - * If a different size is configured, the data cannot be normally received from a peer. - * Although Socket n RX Buffer Block size is initially configured to 2Kbytes, - * user can re-configure its size using @ref Sn_RXBUF_SIZE. The total sum of @ref Sn_RXBUF_SIZE can not be exceed 16Kbytes. - * When exceeded, the data reception error is occurred. - */ -#define Sn_RXBUF_SIZE(N) WIZCHIP_SREG_ADDR(N, 0x001e) - -/** - * @ingroup Socket_register_group - * @brief Transmit memory size register(R/W) - * @details @ref Sn_TXBUF_SIZE configures the TX buffer block size of Socket n. Socket n TX Buffer Block size can be configured with 1,2,4,8, and 16 Kbytes. - * If a different size is configured, the data can�t be normally transmitted to a peer. - * Although Socket n TX Buffer Block size is initially configured to 2Kbytes, - * user can be re-configure its size using @ref Sn_TXBUF_SIZE. The total sum of @ref Sn_TXBUF_SIZE can not be exceed 16Kbytes. - * When exceeded, the data transmission error is occurred. - */ -#define Sn_TXBUF_SIZE(N) WIZCHIP_SREG_ADDR(N, 0x001f) - -/** - * @ingroup Socket_register_group - * @brief Transmit free memory size register(R) - * @details @ref Sn_TX_FSR indicates the free size of Socket n TX Buffer Block. It is initialized to the configured size by @ref Sn_TXBUF_SIZE. - * Data bigger than @ref Sn_TX_FSR should not be saved in the Socket n TX Buffer because the bigger data overwrites the previous saved data not yet sent. - * Therefore, check before saving the data to the Socket n TX Buffer, and if data is equal or smaller than its checked size, - * transmit the data with SEND/SEND_MAC command after saving the data in Socket n TX buffer. But, if data is bigger than its checked size, - * transmit the data after dividing into the checked size and saving in the Socket n TX buffer. - */ -#define Sn_TX_FSR(N) WIZCHIP_SREG_ADDR(N, 0x0020) - -/** - * @ingroup Socket_register_group - * @brief Transmit memory read pointer register address(R) - * @details @ref Sn_TX_RD is initialized by OPEN command. However, if Sn_MR(P[3:0]) is TCP mode(001, it is re-initialized while connecting with TCP. - * After its initialization, it is auto-increased by SEND command. - * SEND command transmits the saved data from the current @ref Sn_TX_RD to the @ref Sn_TX_WR in the Socket n TX Buffer. - * After transmitting the saved data, the SEND command increases the @ref Sn_TX_RD as same as the @ref Sn_TX_WR. - * If its increment value exceeds the maximum value 0xFFFF, (greater than 0x10000 and the carry bit occurs), - * then the carry bit is ignored and will automatically update with the lower 16bits value. - */ -#define Sn_TX_RD(N) WIZCHIP_SREG_ADDR(N, 0x0022) - -/** - * @ingroup Socket_register_group - * @brief Transmit memory write pointer register address(R/W) - * @details @ref Sn_TX_WR is initialized by OPEN command. However, if Sn_MR(P[3:0]) is TCP mode(001, it is re-initialized while connecting with TCP.\n - * It should be read or be updated like as follows.\n - * 1. Read the starting address for saving the transmitting data.\n - * 2. Save the transmitting data from the starting address of Socket n TX buffer.\n - * 3. After saving the transmitting data, update @ref Sn_TX_WR to the increased value as many as transmitting data size. - * If the increment value exceeds the maximum value 0xFFFF(greater than 0x10000 and the carry bit occurs), - * then the carry bit is ignored and will automatically update with the lower 16bits value.\n - * 4. Transmit the saved data in Socket n TX Buffer by using SEND/SEND command - */ -#define Sn_TX_WR(N) WIZCHIP_SREG_ADDR(N, 0x0024) - -/** - * @ingroup Socket_register_group - * @brief Received data size register(R) - * @details @ref Sn_RX_RSR indicates the data size received and saved in Socket n RX Buffer. - * @ref Sn_RX_RSR does not exceed the @ref Sn_RXBUF_SIZE and is calculated as the difference between - * �Socket n RX Write Pointer (@ref Sn_RX_WR)and �Socket n RX Read Pointer (@ref Sn_RX_RD) - */ -#define Sn_RX_RSR(N) WIZCHIP_SREG_ADDR(N, 0x0026) - -/** - * @ingroup Socket_register_group - * @brief Read point of Receive memory(R/W) - * @details @ref Sn_RX_RD is initialized by OPEN command. Make sure to be read or updated as follows.\n - * 1. Read the starting save address of the received data.\n - * 2. Read data from the starting address of Socket n RX Buffer.\n - * 3. After reading the received data, Update @ref Sn_RX_RD to the increased value as many as the reading size. - * If the increment value exceeds the maximum value 0xFFFF, that is, is greater than 0x10000 and the carry bit occurs, - * update with the lower 16bits value ignored the carry bit.\n - * 4. Order RECV command is for notifying the updated @ref Sn_RX_RD to W5500. - */ -#define Sn_RX_RD(N) WIZCHIP_SREG_ADDR(N, 0x0028) - -/** - * @ingroup Socket_register_group - * @brief Write point of Receive memory(R) - * @details @ref Sn_RX_WR is initialized by OPEN command and it is auto-increased by the data reception. - * If the increased value exceeds the maximum value 0xFFFF, (greater than 0x10000 and the carry bit occurs), - * then the carry bit is ignored and will automatically update with the lower 16bits value. - */ -#define Sn_RX_WR(N) WIZCHIP_SREG_ADDR(N, 0x002a) - -/** - * @ingroup Socket_register_group - * @brief socket interrupt mask register(R) - * @details @ref Sn_IMR masks the interrupt of Socket n. - * Each bit corresponds to each bit of @ref Sn_IR. When a Socket n Interrupt is occurred and the corresponding bit of @ref Sn_IMR is - * the corresponding bit of @ref Sn_IR becomes When both the corresponding bit of @ref Sn_IMR and @ref Sn_IR are and the n-th bit of @ref IR is - * Host is interrupted by asserted INTn PIN to low. - */ -//#define Sn_IMR(N) (_W5500_IO_BASE_ + (0x002C << 8) + (WIZCHIP_SREG_BLOCK(N) << 3)) - -/** - * @ingroup Socket_register_group - * @brief Fragment field value in IP header register(R/W) - * @details @ref Sn_FRAG configures the FRAG(Fragment field in IP header). - */ -//#define Sn_FRAG(N) (_W5500_IO_BASE_ + (0x002D << 8) + (WIZCHIP_SREG_BLOCK(N) << 3)) - -/** - * @ingroup Socket_register_group - * @brief Keep Alive Timer register(R/W) - * @details @ref Sn_KPALVTR configures the transmitting timer of �KEEP ALIVE(KA)packet of SOCKETn. It is valid only in TCP mode, - * and ignored in other modes. The time unit is 5s. - * KA packet is transmittable after @ref Sn_SR is changed to SOCK_ESTABLISHED and after the data is transmitted or received to/from a peer at least once. - * In case of '@ref Sn_KPALVTR > 0', W5500 automatically transmits KA packet after time-period for checking the TCP connection (Auto-keepalive-process). - * In case of '@ref Sn_KPALVTR = 0', Auto-keep-alive-process will not operate, - * and KA packet can be transmitted by SEND_KEEP command by the host (Manual-keep-alive-process). - * Manual-keep-alive-process is ignored in case of '@ref Sn_KPALVTR > 0'. - */ -//#define Sn_KPALVTR(N) (_W5500_IO_BASE_ + (0x002F << 8) + (WIZCHIP_SREG_BLOCK(N) << 3)) - -//#define Sn_TSR(N) (_W5500_IO_BASE_ + (0x0030 << 8) + (WIZCHIP_SREG_BLOCK(N) << 3)) - - -//----------------------------- W5500 Register values ----------------------------- - -/* MODE register values */ -/** - * @brief Reset - * @details If this bit is All internal registers will be initialized. It will be automatically cleared as after S/W reset. - */ -#define MR_RST 0x80 - -/** - * @brief Wake on LAN - * @details 0 : Disable WOL mode\n - * 1 : Enable WOL mode\n - * If WOL mode is enabled and the received magic packet over UDP has been normally processed, the Interrupt PIN (INTn) asserts to low. - * When using WOL mode, the UDP Socket should be opened with any source port number. (Refer to Socket n Mode Register (@ref Sn_MR) for opening Socket.) - * @note The magic packet over UDP supported by W5500 consists of 6 bytes synchronization stream (xFFFFFFFFFFFF and - * 16 times Target MAC address stream in UDP payload. The options such like password are ignored. You can use any UDP source port number for WOL mode. - */ -#define MR_WOL 0x20 - -/** - * @brief Ping block - * @details 0 : Disable Ping block\n - * 1 : Enable Ping block\n - * If the bit is it blocks the response to a ping request. - */ -#define MR_PB 0x10 - -/** - * @brief Enable PPPoE - * @details 0 : DisablePPPoE mode\n - * 1 : EnablePPPoE mode\n - * If you use ADSL, this bit should be - */ -#define MR_PPPOE 0x08 - -/** - * @brief Enable UDP_FORCE_ARP CHECHK - * @details 0 : Disable Force ARP mode\n - * 1 : Enable Force ARP mode\n - * In Force ARP mode, It forces on sending ARP Request whenever data is sent. - */ -#define MR_FARP 0x02 - -/* IR register values */ -/** - * @brief Check IP conflict. - * @details Bit is set as when own source IP address is same with the sender IP address in the received ARP request. - */ -#define IR_CONFLICT 0x80 - -/** - * @brief Get the destination unreachable message in UDP sending. - * @details When receiving the ICMP (Destination port unreachable) packet, this bit is set as - * When this bit is Destination Information such as IP address and Port number may be checked with the corresponding @ref UIPR & @ref UPORTR. - */ -#define IR_UNREACH 0x40 - -/** - * @brief Get the PPPoE close message. - * @details When PPPoE is disconnected during PPPoE mode, this bit is set. - */ -#define IR_PPPoE 0x20 - -/** - * @brief Get the magic packet interrupt. - * @details When WOL mode is enabled and receives the magic packet over UDP, this bit is set. - */ -#define IR_MP 0x10 - - -/* PHYCFGR register value */ -#define PHYCFGR_RST ~(1<<7) //< For PHY reset, must operate AND mask. -#define PHYCFGR_OPMD (1<<6) // Configre PHY with OPMDC value -#define PHYCFGR_OPMDC_ALLA (7<<3) -#define PHYCFGR_OPMDC_PDOWN (6<<3) -#define PHYCFGR_OPMDC_NA (5<<3) -#define PHYCFGR_OPMDC_100FA (4<<3) -#define PHYCFGR_OPMDC_100F (3<<3) -#define PHYCFGR_OPMDC_100H (2<<3) -#define PHYCFGR_OPMDC_10F (1<<3) -#define PHYCFGR_OPMDC_10H (0<<3) -#define PHYCFGR_DPX_FULL (1<<2) -#define PHYCFGR_DPX_HALF (0<<2) -#define PHYCFGR_SPD_100 (1<<1) -#define PHYCFGR_SPD_10 (0<<1) -#define PHYCFGR_LNK_ON (1<<0) -#define PHYCFGR_LNK_OFF (0<<0) - -// PHYSTATUS register -#define PHYSTATUS_POWERDOWN (0x08) -#define PHYSTATUS_LINK (0x20) - -/* IMR register values */ -/** - * @brief IP Conflict Interrupt Mask. - * @details 0: Disable IP Conflict Interrupt\n - * 1: Enable IP Conflict Interrupt - */ -#define IM_IR7 0x80 - -/** - * @brief Destination unreachable Interrupt Mask. - * @details 0: Disable Destination unreachable Interrupt\n - * 1: Enable Destination unreachable Interrupt - */ -#define IM_IR6 0x40 - -/** - * @brief PPPoE Close Interrupt Mask. - * @details 0: Disable PPPoE Close Interrupt\n - * 1: Enable PPPoE Close Interrupt - */ -#define IM_IR5 0x20 - -/** - * @brief Magic Packet Interrupt Mask. - * @details 0: Disable Magic Packet Interrupt\n - * 1: Enable Magic Packet Interrupt - */ -#define IM_IR4 0x10 - -/* Sn_MR Default values */ -/** - * @brief Support UDP Multicasting - * @details 0 : disable Multicasting\n - * 1 : enable Multicasting\n - * This bit is applied only during UDP mode(P[3:0] = 010.\n - * To use multicasting, @ref Sn_DIPR & @ref Sn_DPORT should be respectively configured with the multicast group IP address & port number - * before Socket n is opened by OPEN command of @ref Sn_CR. - */ -#define Sn_MR_MULTI 0x80 - -/** - * @brief Broadcast block in UDP Multicasting. - * @details 0 : disable Broadcast Blocking\n - * 1 : enable Broadcast Blocking\n - * This bit blocks to receive broadcasting packet during UDP mode(P[3:0] = 010.\m - * In addition, This bit does when MACRAW mode(P[3:0] = 100 - */ -//#define Sn_MR_BCASTB 0x40 - -/** - * @brief No Delayed Ack(TCP), Multicast flag - * @details 0 : Disable No Delayed ACK option\n - * 1 : Enable No Delayed ACK option\n - * This bit is applied only during TCP mode (P[3:0] = 001.\n - * When this bit is It sends the ACK packet without delay as soon as a Data packet is received from a peer.\n - * When this bit is It sends the ACK packet after waiting for the timeout time configured by @ref RTR. - */ -#define Sn_MR_ND 0x20 - -/** - * @brief Unicast Block in UDP Multicasting - * @details 0 : disable Unicast Blocking\n - * 1 : enable Unicast Blocking\n - * This bit blocks receiving the unicast packet during UDP mode(P[3:0] = 010 and MULTI = - */ -//#define Sn_MR_UCASTB 0x10 - -/** - * @brief MAC LAYER RAW SOCK - * @details This configures the protocol mode of Socket n. - * @note MACRAW mode should be only used in Socket 0. - */ -#define Sn_MR_MACRAW 0x04 - -#define Sn_MR_IPRAW 0x03 /**< IP LAYER RAW SOCK */ - -/** - * @brief UDP - * @details This configures the protocol mode of Socket n. - */ -#define Sn_MR_UDP 0x02 - -/** - * @brief TCP - * @details This configures the protocol mode of Socket n. - */ -#define Sn_MR_TCP 0x01 - -/** - * @brief Unused socket - * @details This configures the protocol mode of Socket n. - */ -#define Sn_MR_CLOSE 0x00 - -/* Sn_MR values used with Sn_MR_MACRAW */ -/** - * @brief MAC filter enable in @ref Sn_MR_MACRAW mode - * @details 0 : disable MAC Filtering\n - * 1 : enable MAC Filtering\n - * This bit is applied only during MACRAW mode(P[3:0] = 100.\n - * When set as W5500 can only receive broadcasting packet or packet sent to itself. - * When this bit is W5500 can receive all packets on Ethernet. - * If user wants to implement Hybrid TCP/IP stack, - * it is recommended that this bit is set as for reducing host overhead to process the all received packets. - */ -#define Sn_MR_MFEN Sn_MR_MULTI - -/** - * @brief Multicast Blocking in @ref Sn_MR_MACRAW mode - * @details 0 : using IGMP version 2\n - * 1 : using IGMP version 1\n - * This bit is applied only during UDP mode(P[3:0] = 010 and MULTI = - * It configures the version for IGMP messages (Join/Leave/Report). - */ -#define Sn_MR_MMB Sn_MR_ND - -/** - * @brief IPv6 packet Blocking in @ref Sn_MR_MACRAW mode - * @details 0 : disable IPv6 Blocking\n - * 1 : enable IPv6 Blocking\n - * This bit is applied only during MACRAW mode (P[3:0] = 100. It blocks to receiving the IPv6 packet. - */ -#define Sn_MR_MIP6B Sn_MR_UCASTB - -/* Sn_MR value used with Sn_MR_UDP & Sn_MR_MULTI */ -/** - * @brief IGMP version used in UDP mulitcasting - * @details 0 : disable Multicast Blocking\n - * 1 : enable Multicast Blocking\n - * This bit is applied only when MACRAW mode(P[3:0] = 100. It blocks to receive the packet with multicast MAC address. - */ -#define Sn_MR_MC Sn_MR_ND - -/* Sn_MR alternate values */ -/** - * @brief For Berkeley Socket API - */ -#define SOCK_STREAM Sn_MR_TCP - -/** - * @brief For Berkeley Socket API - */ -#define SOCK_DGRAM Sn_MR_UDP - - -/* Sn_CR values */ -/** - * @brief Initialize or open socket - * @details Socket n is initialized and opened according to the protocol selected in Sn_MR(P3:P0). - * The table below shows the value of @ref Sn_SR corresponding to @ref Sn_MR.\n - * - * - * - * - * - * - *
\b Sn_MR (P[3:0]) \b Sn_SR
Sn_MR_CLOSE (000
Sn_MR_TCP (001 SOCK_INIT (0x13)
Sn_MR_UDP (010 SOCK_UDP (0x22)
S0_MR_MACRAW (100 SOCK_MACRAW (0x02)
- */ -#define Sn_CR_OPEN 0x01 - -/** - * @brief Wait connection request in TCP mode(Server mode) - * @details This is valid only in TCP mode (Sn_MR(P3:P0) = Sn_MR_TCP). - * In this mode, Socket n operates as a �TCP serverand waits for connection-request (SYN packet) from any �TCP client - * The @ref Sn_SR changes the state from SOCK_INIT to SOCKET_LISTEN. - * When a �TCP clientconnection request is successfully established, - * the @ref Sn_SR changes from SOCK_LISTEN to SOCK_ESTABLISHED and the Sn_IR(0) becomes - * But when a �TCP clientconnection request is failed, Sn_IR(3) becomes and the status of @ref Sn_SR changes to SOCK_CLOSED. - */ -#define Sn_CR_LISTEN 0x02 - -/** - * @brief Send connection request in TCP mode(Client mode) - * @details To connect, a connect-request (SYN packet) is sent to b>TCP server
configured by @ref Sn_DIPR & Sn_DPORT(destination address & port). - * If the connect-request is successful, the @ref Sn_SR is changed to @ref SOCK_ESTABLISHED and the Sn_IR(0) becomes \n\n - * The connect-request fails in the following three cases.\n - * 1. When a @b ARPTO occurs (@ref Sn_IR[3] = ) because destination hardware address is not acquired through the ARP-process.\n - * 2. When a @b SYN/ACK packet is not received and @b TCPTO (Sn_IR(3) = )\n - * 3. When a @b RST packet is received instead of a @b SYN/ACK packet. In these cases, @ref Sn_SR is changed to @ref SOCK_CLOSED. - * @note This is valid only in TCP mode and operates when Socket n acts as b>TCP client
- */ -#define Sn_CR_CONNECT 0x04 - -/** - * @brief Send closing request in TCP mode - * @details Regardless of b>TCP serveror b>TCP client the DISCON command processes the disconnect-process (b>Active closeor b>Passive close.\n - * @par Active close - * it transmits disconnect-request(FIN packet) to the connected peer\n - * @par Passive close - * When FIN packet is received from peer, a FIN packet is replied back to the peer.\n - * @details When the disconnect-process is successful (that is, FIN/ACK packet is received successfully), @ref Sn_SR is changed to @ref SOCK_CLOSED.\n - * Otherwise, TCPTO occurs (Sn_IR(3)=)= and then @ref Sn_SR is changed to @ref SOCK_CLOSED. - * @note Valid only in TCP mode. - */ -#define Sn_CR_DISCON 0x08 - -/** - * @brief Close socket - * @details Sn_SR is changed to @ref SOCK_CLOSED. - */ -#define Sn_CR_CLOSE 0x10 - -/** - * @brief Update TX buffer pointer and send data - * @details SEND transmits all the data in the Socket n TX buffer.\n - * For more details, please refer to Socket n TX Free Size Register (@ref Sn_TX_FSR), Socket n, - * TX Write Pointer Register(@ref Sn_TX_WR), and Socket n TX Read Pointer Register(@ref Sn_TX_RD). - */ -#define Sn_CR_SEND 0x20 - -/** - * @brief Send data with MAC address, so without ARP process - * @details The basic operation is same as SEND.\n - * Normally SEND transmits data after destination hardware address is acquired by the automatic ARP-process(Address Resolution Protocol).\n - * But SEND_MAC transmits data without the automatic ARP-process.\n - * In this case, the destination hardware address is acquired from @ref Sn_DHAR configured by host, instead of APR-process. - * @note Valid only in UDP mode. - */ -#define Sn_CR_SEND_MAC 0x21 - -/** - * @brief Send keep alive message - * @details It checks the connection status by sending 1byte keep-alive packet.\n - * If the peer can not respond to the keep-alive packet during timeout time, the connection is terminated and the timeout interrupt will occur. - * @note Valid only in TCP mode. - */ -#define Sn_CR_SEND_KEEP 0x22 - -/** - * @brief Update RX buffer pointer and receive data - * @details RECV completes the processing of the received data in Socket n RX Buffer by using a RX read pointer register (@ref Sn_RX_RD).\n - * For more details, refer to Socket n RX Received Size Register (@ref Sn_RX_RSR), Socket n RX Write Pointer Register (@ref Sn_RX_WR), - * and Socket n RX Read Pointer Register (@ref Sn_RX_RD). - */ -#define Sn_CR_RECV 0x40 - -/* Sn_IR values */ -/** - * @brief SEND_OK Interrupt - * @details This is issued when SEND command is completed. - */ -#define Sn_IR_SENDOK 0x10 - -/** - * @brief TIMEOUT Interrupt - * @details This is issued when ARPTO or TCPTO occurs. - */ -#define Sn_IR_TIMEOUT 0x08 - -/** - * @brief RECV Interrupt - * @details This is issued whenever data is received from a peer. - */ -#define Sn_IR_RECV 0x04 - -/** - * @brief DISCON Interrupt - * @details This is issued when FIN or FIN/ACK packet is received from a peer. - */ -#define Sn_IR_DISCON 0x02 - -/** - * @brief CON Interrupt - * @details This is issued one time when the connection with peer is successful and then @ref Sn_SR is changed to @ref SOCK_ESTABLISHED. - */ -#define Sn_IR_CON 0x01 - -/* Sn_SR values */ -/** - * @brief Closed - * @details This indicates that Socket n is released.\N - * When DICON, CLOSE command is ordered, or when a timeout occurs, it is changed to @ref SOCK_CLOSED regardless of previous status. - */ -#define SOCK_CLOSED 0x00 - -/** - * @brief Initiate state - * @details This indicates Socket n is opened with TCP mode.\N - * It is changed to @ref SOCK_INIT when Sn_MR(P[3:0]) = 001and OPEN command is ordered.\N - * After @ref SOCK_INIT, user can use LISTEN /CONNECT command. - */ -#define SOCK_INIT 0x13 - -/** - * @brief Listen state - * @details This indicates Socket n is operating as b>TCP servermode and waiting for connection-request (SYN packet) from a peer (b>TCP client.\n - * It will change to @ref SOCK_ESTALBLISHED when the connection-request is successfully accepted.\n - * Otherwise it will change to @ref SOCK_CLOSED after TCPTO occurred (Sn_IR(TIMEOUT) = . - */ -#define SOCK_LISTEN 0x14 - -/** - * @brief Connection state - * @details This indicates Socket n sent the connect-request packet (SYN packet) to a peer.\n - * It is temporarily shown when @ref Sn_SR is changed from @ref SOCK_INIT to @ref SOCK_ESTABLISHED by CONNECT command.\n - * If connect-accept(SYN/ACK packet) is received from the peer at SOCK_SYNSENT, it changes to @ref SOCK_ESTABLISHED.\n - * Otherwise, it changes to @ref SOCK_CLOSED after TCPTO (@ref Sn_IR[TIMEOUT] = is occurred. - */ -#define SOCK_SYNSENT 0x15 - -/** - * @brief Connection state - * @details It indicates Socket n successfully received the connect-request packet (SYN packet) from a peer.\n - * If socket n sends the response (SYN/ACK packet) to the peer successfully, it changes to @ref SOCK_ESTABLISHED. \n - * If not, it changes to @ref SOCK_CLOSED after timeout occurs (@ref Sn_IR[TIMEOUT] = . - */ -#define SOCK_SYNRECV 0x16 - -/** - * @brief Success to connect - * @details This indicates the status of the connection of Socket n.\n - * It changes to @ref SOCK_ESTABLISHED when the b>TCP SERVERprocessed the SYN packet from the b>TCP CLIENTduring @ref SOCK_LISTEN, or - * when the CONNECT command is successful.\n - * During @ref SOCK_ESTABLISHED, DATA packet can be transferred using SEND or RECV command. - */ -#define SOCK_ESTABLISHED 0x17 - -/** - * @brief Closing state - * @details These indicate Socket n is closing.\n - * These are shown in disconnect-process such as active-close and passive-close.\n - * When Disconnect-process is successfully completed, or when timeout occurs, these change to @ref SOCK_CLOSED. - */ -#define SOCK_FIN_WAIT 0x18 - -/** - * @brief Closing state - * @details These indicate Socket n is closing.\n - * These are shown in disconnect-process such as active-close and passive-close.\n - * When Disconnect-process is successfully completed, or when timeout occurs, these change to @ref SOCK_CLOSED. - */ -#define SOCK_CLOSING 0x1A - -/** - * @brief Closing state - * @details These indicate Socket n is closing.\n - * These are shown in disconnect-process such as active-close and passive-close.\n - * When Disconnect-process is successfully completed, or when timeout occurs, these change to @ref SOCK_CLOSED. - */ -#define SOCK_TIME_WAIT 0x1B - -/** - * @brief Closing state - * @details This indicates Socket n received the disconnect-request (FIN packet) from the connected peer.\n - * This is half-closing status, and data can be transferred.\n - * For full-closing, DISCON command is used. But For just-closing, CLOSE command is used. - */ -#define SOCK_CLOSE_WAIT 0x1C - -/** - * @brief Closing state - * @details This indicates Socket n is waiting for the response (FIN/ACK packet) to the disconnect-request (FIN packet) by passive-close.\n - * It changes to @ref SOCK_CLOSED when Socket n received the response successfully, or when timeout occurs (@ref Sn_IR[TIMEOUT] = . - */ -#define SOCK_LAST_ACK 0x1D - -/** - * @brief UDP socket - * @details This indicates Socket n is opened in UDP mode(Sn_MR(P[3:0]) = 010.\n - * It changes to SOCK_UPD when Sn_MR(P[3:0]) = 010 and OPEN command is ordered.\n - * Unlike TCP mode, data can be transfered without the connection-process. - */ -#define SOCK_UDP 0x22 - -//#define SOCK_IPRAW 0x32 /**< IP raw mode socket */ - -/** - * @brief MAC raw mode socket - * @details This indicates Socket 0 is opened in MACRAW mode (S0_MR(P[3:0]) = 100and is valid only in Socket 0.\n - * It changes to SOCK_MACRAW when S0_MR(P[3:0] = 100and OPEN command is ordered.\n - * Like UDP mode socket, MACRAW mode Socket 0 can transfer a MAC packet (Ethernet frame) without the connection-process. - */ -#define SOCK_MACRAW 0x42 - -//#define SOCK_PPPOE 0x5F - -/* IP PROTOCOL */ -#define IPPROTO_IP 0 //< Dummy for IP -#define IPPROTO_ICMP 1 //< Control message protocol -#define IPPROTO_IGMP 2 //< Internet group management protocol -#define IPPROTO_GGP 3 //< Gateway^2 (deprecated) -#define IPPROTO_TCP 6 //< TCP -#define IPPROTO_PUP 12 //< PUP -#define IPPROTO_UDP 17 //< UDP -#define IPPROTO_IDP 22 //< XNS idp -#define IPPROTO_ND 77 //< UNOFFICIAL net disk protocol -#define IPPROTO_RAW 255 //< Raw IP packet - - -/** - * @brief Enter a critical section - * - * @details It is provided to protect your shared code which are executed without distribution. \n \n - * - * In non-OS environment, It can be just implemented by disabling whole interrupt.\n - * In OS environment, You can replace it to critical section api supported by OS. - * - * \sa WIZCHIP_READ(), WIZCHIP_WRITE(), WIZCHIP_READ_BUF(), WIZCHIP_WRITE_BUF() - * \sa WIZCHIP_CRITICAL_EXIT() - */ -#define WIZCHIP_CRITICAL_ENTER() WIZCHIP.CRIS._enter() - -/** - * @brief Exit a critical section - * - * @details It is provided to protect your shared code which are executed without distribution. \n\n - * - * In non-OS environment, It can be just implemented by disabling whole interrupt. \n - * In OS environment, You can replace it to critical section api supported by OS. - * - * @sa WIZCHIP_READ(), WIZCHIP_WRITE(), WIZCHIP_READ_BUF(), WIZCHIP_WRITE_BUF() - * @sa WIZCHIP_CRITICAL_ENTER() - */ -#ifdef _exit -#undef _exit -#endif -#define WIZCHIP_CRITICAL_EXIT() WIZCHIP.CRIS._exit() - - - -//////////////////////// -// Basic I/O Function // -//////////////////////// - -/** - * @ingroup Basic_IO_function - * @brief It reads 1 byte value from a register. - * @param AddrSel Register address - * @return The value of register - */ -uint8_t WIZCHIP_READ (uint32_t AddrSel); - -/** - * @ingroup Basic_IO_function - * @brief It writes 1 byte value to a register. - * @param AddrSel Register address - * @param wb Write data - * @return void - */ -void WIZCHIP_WRITE(uint32_t AddrSel, uint8_t wb ); - -/** - * @ingroup Basic_IO_function - * @brief It reads sequence data from registers. - * @param AddrSel Register address - * @param pBuf Pointer buffer to read data - * @param len Data length - */ -void WIZCHIP_READ_BUF (uint32_t AddrSel, uint8_t* pBuf, uint16_t len); - -/** - * @ingroup Basic_IO_function - * @brief It writes sequence data to registers. - * @param AddrSel Register address - * @param pBuf Pointer buffer to write data - * @param len Data length - */ -void WIZCHIP_WRITE_BUF(uint32_t AddrSel, uint8_t* pBuf, uint16_t len); - -///////////////////////////////// -// Common Register I/O function // -///////////////////////////////// -/** - * @ingroup Common_register_access_function - * @brief Set Mode Register - * @param (uint8_t)mr The value to be set. - * @sa getMR() - */ -#define setMR(mr) \ - WIZCHIP_WRITE(MR,mr) - - -/** - * @ingroup Common_register_access_function - * @brief Get Mode Register - * @return uint8_t. The value of Mode register. - * @sa setMR() - */ -#define getMR() \ - WIZCHIP_READ(MR) - -/** - * @ingroup Common_register_access_function - * @brief Set gateway IP address - * @param (uint8_t*)gar Pointer variable to set gateway IP address. It should be allocated 4 bytes. - * @sa getGAR() - */ -#define setGAR(gar) \ - WIZCHIP_WRITE_BUF(GAR,gar,4) - -/** - * @ingroup Common_register_access_function - * @brief Get gateway IP address - * @param (uint8_t*)gar Pointer variable to get gateway IP address. It should be allocated 4 bytes. - * @sa setGAR() - */ -#define getGAR(gar) \ - WIZCHIP_READ_BUF(GAR,gar,4) - -/** - * @ingroup Common_register_access_function - * @brief Set subnet mask address - * @param (uint8_t*)subr Pointer variable to set subnet mask address. It should be allocated 4 bytes. - * @sa getSUBR() - */ -#define setSUBR(subr) \ - WIZCHIP_WRITE_BUF(SUBR, subr,4) - - -/** - * @ingroup Common_register_access_function - * @brief Get subnet mask address - * @param (uint8_t*)subr Pointer variable to get subnet mask address. It should be allocated 4 bytes. - * @sa setSUBR() - */ -#define getSUBR(subr) \ - WIZCHIP_READ_BUF(SUBR, subr, 4) - -/** - * @ingroup Common_register_access_function - * @brief Set local MAC address - * @param (uint8_t*)shar Pointer variable to set local MAC address. It should be allocated 6 bytes. - * @sa getSHAR() - */ -#define setSHAR(shar) \ - WIZCHIP_WRITE_BUF(SHAR, shar, 6) - -/** - * @ingroup Common_register_access_function - * @brief Get local MAC address - * @param (uint8_t*)shar Pointer variable to get local MAC address. It should be allocated 6 bytes. - * @sa setSHAR() - */ -#define getSHAR(shar) \ - WIZCHIP_READ_BUF(SHAR, shar, 6) - -/** - * @ingroup Common_register_access_function - * @brief Set local IP address - * @param (uint8_t*)sipr Pointer variable to set local IP address. It should be allocated 4 bytes. - * @sa getSIPR() - */ -#define setSIPR(sipr) \ - WIZCHIP_WRITE_BUF(SIPR, sipr, 4) - -/** - * @ingroup Common_register_access_function - * @brief Get local IP address - * @param (uint8_t*)sipr Pointer variable to get local IP address. It should be allocated 4 bytes. - * @sa setSIPR() - */ -#define getSIPR(sipr) \ - WIZCHIP_READ_BUF(SIPR, sipr, 4) - -/** - * @ingroup Common_register_access_function - * @brief Set INTLEVEL register - * @param (uint16_t)intlevel Value to set @ref INTLEVEL register. - * @sa getINTLEVEL() - */ -// dpgeorge: not yet implemented -#define setINTLEVEL(intlevel) (void)intlevel -#if 0 -#define setINTLEVEL(intlevel) {\ - WIZCHIP_WRITE(INTLEVEL, (uint8_t)(intlevel >> 8)); \ - WIZCHIP_WRITE(WIZCHIP_OFFSET_INC(INTLEVEL,1), (uint8_t) intlevel); \ - } -#endif - - -/** - * @ingroup Common_register_access_function - * @brief Get INTLEVEL register - * @return uint16_t. Value of @ref INTLEVEL register. - * @sa setINTLEVEL() - */ -// dpgeorge: not yet implemented -#define getINTLEVEL() (0) -#if 0 -#define getINTLEVEL() \ - ((WIZCHIP_READ(INTLEVEL) << 8) + WIZCHIP_READ(WIZCHIP_OFFSET_INC(INTLEVEL,1))) -#endif - -/** - * @ingroup Common_register_access_function - * @brief Set @ref IR register - * @param (uint8_t)ir Value to set @ref IR register. - * @sa getIR() - */ -#define setIR(ir) \ - WIZCHIP_WRITE(IR, (ir & 0xF0)) - -/** - * @ingroup Common_register_access_function - * @brief Get @ref IR register - * @return uint8_t. Value of @ref IR register. - * @sa setIR() - */ -#define getIR() \ - (WIZCHIP_READ(IR) & 0xF0) -/** - * @ingroup Common_register_access_function - * @brief Set @ref IMR register - * @param (uint8_t)imr Value to set @ref IMR register. - * @sa getIMR() - */ -#define setIMR(imr) \ - WIZCHIP_WRITE(IMR, imr) - -/** - * @ingroup Common_register_access_function - * @brief Get @ref IMR register - * @return uint8_t. Value of @ref IMR register. - * @sa setIMR() - */ -#define getIMR() \ - WIZCHIP_READ(IMR) - - -/** - * @ingroup Common_register_access_function - * @brief Set @ref SIR register - * @param (uint8_t)sir Value to set @ref SIR register. - * @sa getSIR() - */ -// dpgeorge: not yet implemented -#define setSIR(sir) ((void)sir) -#if 0 -#define setSIR(sir) \ - WIZCHIP_WRITE(SIR, sir) -#endif - -/** - * @ingroup Common_register_access_function - * @brief Get @ref SIR register - * @return uint8_t. Value of @ref SIR register. - * @sa setSIR() - */ -// dpgeorge: not yet implemented -#define getSIR() (0) -#if 0 -#define getSIR() \ - WIZCHIP_READ(SIR) -#endif - -/** - * @ingroup Common_register_access_function - * @brief Set @ref SIMR register - * @param (uint8_t)simr Value to set @ref SIMR register. - * @sa getSIMR() - */ -// dpgeorge: not yet implemented -#define setSIMR(simr) ((void)simr) -#if 0 -#define setSIMR(simr) \ - WIZCHIP_WRITE(SIMR, simr) -#endif - -/** - * @ingroup Common_register_access_function - * @brief Get @ref SIMR register - * @return uint8_t. Value of @ref SIMR register. - * @sa setSIMR() - */ -// dpgeorge: not yet implemented -#define getSIMR() (0) -#if 0 -#define getSIMR() \ - WIZCHIP_READ(SIMR) -#endif - -/** - * @ingroup Common_register_access_function - * @brief Set @ref RTR register - * @param (uint16_t)rtr Value to set @ref RTR register. - * @sa getRTR() - */ -#define setRTR(rtr) {\ - WIZCHIP_WRITE(RTR, (uint8_t)(rtr >> 8)); \ - WIZCHIP_WRITE(RTR + 1, (uint8_t) rtr); \ - } - -/** - * @ingroup Common_register_access_function - * @brief Get @ref RTR register - * @return uint16_t. Value of @ref RTR register. - * @sa setRTR() - */ -#define getRTR() \ - ((WIZCHIP_READ(RTR) << 8) + WIZCHIP_READ(RTR + 1)) - -/** - * @ingroup Common_register_access_function - * @brief Set @ref RCR register - * @param (uint8_t)rcr Value to set @ref RCR register. - * @sa getRCR() - */ -#define setRCR(rcr) \ - WIZCHIP_WRITE(RCR, rcr) - -/** - * @ingroup Common_register_access_function - * @brief Get @ref RCR register - * @return uint8_t. Value of @ref RCR register. - * @sa setRCR() - */ -#define getRCR() \ - WIZCHIP_READ(RCR) - -//================================================== test done =========================================================== - -/** - * @ingroup Common_register_access_function - * @brief Set @ref PTIMER register - * @param (uint8_t)ptimer Value to set @ref PTIMER register. - * @sa getPTIMER() - */ -#define setPTIMER(ptimer) \ - WIZCHIP_WRITE(PTIMER, ptimer) - -/** - * @ingroup Common_register_access_function - * @brief Get @ref PTIMER register - * @return uint8_t. Value of @ref PTIMER register. - * @sa setPTIMER() - */ -#define getPTIMER() \ - WIZCHIP_READ(PTIMER) - -/** - * @ingroup Common_register_access_function - * @brief Set @ref PMAGIC register - * @param (uint8_t)pmagic Value to set @ref PMAGIC register. - * @sa getPMAGIC() - */ -#define setPMAGIC(pmagic) \ - WIZCHIP_WRITE(PMAGIC, pmagic) - -/** - * @ingroup Common_register_access_function - * @brief Get @ref PMAGIC register - * @return uint8_t. Value of @ref PMAGIC register. - * @sa setPMAGIC() - */ -#define getPMAGIC() \ - WIZCHIP_READ(PMAGIC) - -/** - * @ingroup Common_register_access_function - * @brief Set PHAR address - * @param (uint8_t*)phar Pointer variable to set PPP destination MAC register address. It should be allocated 6 bytes. - * @sa getPHAR() - */ -#if 0 -#define setPHAR(phar) \ - WIZCHIP_WRITE_BUF(PHAR, phar, 6) - -/** - * @ingroup Common_register_access_function - * @brief Get local IP address - * @param (uint8_t*)phar Pointer variable to PPP destination MAC register address. It should be allocated 6 bytes. - * @sa setPHAR() - */ -#define getPHAR(phar) \ - WIZCHIP_READ_BUF(PHAR, phar, 6) - -/** - * @ingroup Common_register_access_function - * @brief Set @ref PSID register - * @param (uint16_t)psid Value to set @ref PSID register. - * @sa getPSID() - */ -#define setPSID(psid) {\ - WIZCHIP_WRITE(PSID, (uint8_t)(psid >> 8)); \ - WIZCHIP_WRITE(WIZCHIP_OFFSET_INC(PSID,1), (uint8_t) psid); \ - } - -/** - * @ingroup Common_register_access_function - * @brief Get @ref PSID register - * @return uint16_t. Value of @ref PSID register. - * @sa setPSID() - */ -//uint16_t getPSID(void); -#define getPSID() \ - ((WIZCHIP_READ(PSID) << 8) + WIZCHIP_READ(WIZCHIP_OFFSET_INC(PSID,1))) - -/** - * @ingroup Common_register_access_function - * @brief Set @ref PMRU register - * @param (uint16_t)pmru Value to set @ref PMRU register. - * @sa getPMRU() - */ -#define setPMRU(pmru) { \ - WIZCHIP_WRITE(PMRU, (uint8_t)(pmru>>8)); \ - WIZCHIP_WRITE(WIZCHIP_OFFSET_INC(PMRU,1), (uint8_t) pmru); \ - } - -/** - * @ingroup Common_register_access_function - * @brief Get @ref PMRU register - * @return uint16_t. Value of @ref PMRU register. - * @sa setPMRU() - */ -#define getPMRU() \ - ((WIZCHIP_READ(PMRU) << 8) + WIZCHIP_READ(WIZCHIP_OFFSET_INC(PMRU,1))) - -/** - * @ingroup Common_register_access_function - * @brief Get unreachable IP address - * @param (uint8_t*)uipr Pointer variable to get unreachable IP address. It should be allocated 4 bytes. - */ -#define getUIPR(uipr) \ - WIZCHIP_READ_BUF(UIPR,uipr,6) - -/** - * @ingroup Common_register_access_function - * @brief Get @ref UPORTR register - * @return uint16_t. Value of @ref UPORTR register. - */ -#define getUPORTR() \ - ((WIZCHIP_READ(UPORTR) << 8) + WIZCHIP_READ(WIZCHIP_OFFSET_INC(UPORTR,1))) - -/** - * @ingroup Common_register_access_function - * @brief Set @ref PHYCFGR register - * @param (uint8_t)phycfgr Value to set @ref PHYCFGR register. - * @sa getPHYCFGR() - */ -#define setPHYCFGR(phycfgr) \ - WIZCHIP_WRITE(PHYCFGR, phycfgr) -#endif - -/** - * @ingroup Common_register_access_function - * @brief Get @ref PHYCFGR register - * @return uint8_t. Value of @ref PHYCFGR register. - * @sa setPHYCFGR() - */ -#define getPHYSTATUS() \ - WIZCHIP_READ(PHYSTATUS) - -/** - * @ingroup Common_register_access_function - * @brief Get @ref VERSIONR register - * @return uint8_t. Value of @ref VERSIONR register. - */ -/* -#define getVERSIONR() \ - WIZCHIP_READ(VERSIONR) - */ -///////////////////////////////////// - -/////////////////////////////////// -// Socket N register I/O function // -/////////////////////////////////// -/** - * @ingroup Socket_register_access_function - * @brief Set @ref Sn_MR register - * @param (uint8_t)sn Socket number. It should be 0 ~ 7. - * @param (uint8_t)mr Value to set @ref Sn_MR - * @sa getSn_MR() - */ -#define setSn_MR(sn, mr) \ - WIZCHIP_WRITE(Sn_MR(sn),mr) - -/** - * @ingroup Socket_register_access_function - * @brief Get @ref Sn_MR register - * @param (uint8_t)sn Socket number. It should be 0 ~ 7. - * @return uint8_t. Value of @ref Sn_MR. - * @sa setSn_MR() - */ -#define getSn_MR(sn) \ - WIZCHIP_READ(Sn_MR(sn)) - -/** - * @ingroup Socket_register_access_function - * @brief Set @ref Sn_CR register - * @param (uint8_t)sn Socket number. It should be 0 ~ 7. - * @param (uint8_t)cr Value to set @ref Sn_CR - * @sa getSn_CR() - */ -#define setSn_CR(sn, cr) \ - WIZCHIP_WRITE(Sn_CR(sn), cr) - -/** - * @ingroup Socket_register_access_function - * @brief Get @ref Sn_CR register - * @param (uint8_t)sn Socket number. It should be 0 ~ 7. - * @return uint8_t. Value of @ref Sn_CR. - * @sa setSn_CR() - */ -#define getSn_CR(sn) \ - WIZCHIP_READ(Sn_CR(sn)) - -/** - * @ingroup Socket_register_access_function - * @brief Set @ref Sn_IR register - * @param (uint8_t)sn Socket number. It should be 0 ~ 7. - * @param (uint8_t)ir Value to set @ref Sn_IR - * @sa getSn_IR() - */ -#define setSn_IR(sn, ir) \ - WIZCHIP_WRITE(Sn_IR(sn), (ir & 0x1F)) - -/** - * @ingroup Socket_register_access_function - * @brief Get @ref Sn_IR register - * @param (uint8_t)sn Socket number. It should be 0 ~ 7. - * @return uint8_t. Value of @ref Sn_IR. - * @sa setSn_IR() - */ -#define getSn_IR(sn) \ - (WIZCHIP_READ(Sn_IR(sn)) & 0x1F) - -/** - * @ingroup Socket_register_access_function - * @brief Set @ref Sn_IMR register - * @param (uint8_t)sn Socket number. It should be 0 ~ 7. - * @param (uint8_t)imr Value to set @ref Sn_IMR - * @sa getSn_IMR() - */ -// dpgeorge: not yet implemented -#define setSn_IMR(sn, imr) (void)sn; (void)imr -#if 0 -#define setSn_IMR(sn, imr) \ - WIZCHIP_WRITE(Sn_IMR(sn), (imr & 0x1F)) -#endif - -/** - * @ingroup Socket_register_access_function - * @brief Get @ref Sn_IMR register - * @param (uint8_t)sn Socket number. It should be 0 ~ 7. - * @return uint8_t. Value of @ref Sn_IMR. - * @sa setSn_IMR() - */ -// dpgeorge: not yet implemented -#define getSn_IMR(sn) (0) -#if 0 -#define getSn_IMR(sn) \ - (WIZCHIP_READ(Sn_IMR(sn)) & 0x1F) -#endif - -/** - * @ingroup Socket_register_access_function - * @brief Get @ref Sn_SR register - * @param (uint8_t)sn Socket number. It should be 0 ~ 7. - * @return uint8_t. Value of @ref Sn_SR. - */ -#define getSn_SR(sn) \ - WIZCHIP_READ(Sn_SR(sn)) - -/** - * @ingroup Socket_register_access_function - * @brief Set @ref Sn_PORT register - * @param (uint8_t)sn Socket number. It should be 0 ~ 7. - * @param (uint16_t)port Value to set @ref Sn_PORT. - * @sa getSn_PORT() - */ -#define setSn_PORT(sn, port) { \ - WIZCHIP_WRITE(Sn_PORT(sn), (uint8_t)(port >> 8)); \ - WIZCHIP_WRITE(Sn_PORT(sn) + 1, (uint8_t) port); \ - } - -/** - * @ingroup Socket_register_access_function - * @brief Get @ref Sn_PORT register - * @param (uint8_t)sn Socket number. It should be 0 ~ 7. - * @return uint16_t. Value of @ref Sn_PORT. - * @sa setSn_PORT() - */ -#define getSn_PORT(sn) \ - ((WIZCHIP_READ(Sn_PORT(sn)) << 8) | WIZCHIP_READ(Sn_PORT(sn) + 1)) - -/** - * @ingroup Socket_register_access_function - * @brief Set @ref Sn_DHAR register - * @param (uint8_t)sn Socket number. It should be 0 ~ 7. - * @param (uint8_t*)dhar Pointer variable to set socket n destination hardware address. It should be allocated 6 bytes. - * @sa getSn_DHAR() - */ -#define setSn_DHAR(sn, dhar) \ - WIZCHIP_WRITE_BUF(Sn_DHAR(sn), dhar, 6) - -/** - * @ingroup Socket_register_access_function - * @brief Get @ref Sn_MR register - * @param (uint8_t)sn Socket number. It should be 0 ~ 7. - * @param (uint8_t*)dhar Pointer variable to get socket n destination hardware address. It should be allocated 6 bytes. - * @sa setSn_DHAR() - */ -#define getSn_DHAR(sn, dhar) \ - WIZCHIP_READ_BUF(Sn_DHAR(sn), dhar, 6) - -/** - * @ingroup Socket_register_access_function - * @brief Set @ref Sn_DIPR register - * @param (uint8_t)sn Socket number. It should be 0 ~ 7. - * @param (uint8_t*)dipr Pointer variable to set socket n destination IP address. It should be allocated 4 bytes. - * @sa getSn_DIPR() - */ -#define setSn_DIPR(sn, dipr) \ - WIZCHIP_WRITE_BUF(Sn_DIPR(sn), dipr, 4) - -/** - * @ingroup Socket_register_access_function - * @brief Get @ref Sn_DIPR register - * @param (uint8_t)sn Socket number. It should be 0 ~ 7. - * @param (uint8_t*)dipr Pointer variable to get socket n destination IP address. It should be allocated 4 bytes. - * @sa SetSn_DIPR() - */ -#define getSn_DIPR(sn, dipr) \ - WIZCHIP_READ_BUF(Sn_DIPR(sn), dipr, 4) - -/** - * @ingroup Socket_register_access_function - * @brief Set @ref Sn_DPORT register - * @param (uint8_t)sn Socket number. It should be 0 ~ 7. - * @param (uint16_t)dport Value to set @ref Sn_DPORT - * @sa getSn_DPORT() - */ -#define setSn_DPORT(sn, dport) { \ - WIZCHIP_WRITE(Sn_DPORT(sn), (uint8_t) (dport>>8)); \ - WIZCHIP_WRITE(Sn_DPORT(sn) + 1, (uint8_t) dport); \ - } - -/** - * @ingroup Socket_register_access_function - * @brief Get @ref Sn_DPORT register - * @param (uint8_t)sn Socket number. It should be 0 ~ 7. - * @return uint16_t. Value of @ref Sn_DPORT. - * @sa setSn_DPORT() - */ -#define getSn_DPORT(sn) \ - ((WIZCHIP_READ(Sn_DPORT(sn)) << 8) + WIZCHIP_READ((Sn_DPORT(sn)+1))) - -/** - * @ingroup Socket_register_access_function - * @brief Set @ref Sn_MSSR register - * @param (uint8_t)sn Socket number. It should be 0 ~ 7. - * @param (uint16_t)mss Value to set @ref Sn_MSSR - * @sa setSn_MSSR() - */ -#define setSn_MSSR(sn, mss) { \ - WIZCHIP_WRITE(Sn_MSSR(sn), (uint8_t)(mss>>8)); \ - WIZCHIP_WRITE((Sn_MSSR(sn)+1), (uint8_t) mss); \ - } - -/** - * @ingroup Socket_register_access_function - * @brief Get @ref Sn_MSSR register - * @param (uint8_t)sn Socket number. It should be 0 ~ 7. - * @return uint16_t. Value of @ref Sn_MSSR. - * @sa setSn_MSSR() - */ -#define getSn_MSSR(sn) \ - ((WIZCHIP_READ(Sn_MSSR(sn)) << 8) + WIZCHIP_READ((Sn_MSSR(sn)+1))) - -/** - * @ingroup Socket_register_access_function - * @brief Set @ref Sn_TOS register - * @param (uint8_t)sn Socket number. It should be 0 ~ 7. - * @param (uint8_t)tos Value to set @ref Sn_TOS - * @sa getSn_TOS() - */ -#define setSn_TOS(sn, tos) \ - WIZCHIP_WRITE(Sn_TOS(sn), tos) - -/** - * @ingroup Socket_register_access_function - * @brief Get @ref Sn_TOS register - * @param (uint8_t)sn Socket number. It should be 0 ~ 7. - * @return uint8_t. Value of Sn_TOS. - * @sa setSn_TOS() - */ -#define getSn_TOS(sn) \ - WIZCHIP_READ(Sn_TOS(sn)) - -/** - * @ingroup Socket_register_access_function - * @brief Set @ref Sn_TTL register - * @param (uint8_t)sn Socket number. It should be 0 ~ 7. - * @param (uint8_t)ttl Value to set @ref Sn_TTL - * @sa getSn_TTL() - */ -#define setSn_TTL(sn, ttl) \ - WIZCHIP_WRITE(Sn_TTL(sn), ttl) - - -/** - * @ingroup Socket_register_access_function - * @brief Get @ref Sn_TTL register - * @param (uint8_t)sn Socket number. It should be 0 ~ 7. - * @return uint8_t. Value of @ref Sn_TTL. - * @sa setSn_TTL() - */ -#define getSn_TTL(sn) \ - WIZCHIP_READ(Sn_TTL(sn)) - - -/** - * @ingroup Socket_register_access_function - * @brief Set @ref Sn_RXBUF_SIZE register - * @param (uint8_t)sn Socket number. It should be 0 ~ 7. - * @param (uint8_t)rxbufsize Value to set @ref Sn_RXBUF_SIZE - * @sa getSn_RXBUF_SIZE() - */ -#define setSn_RXBUF_SIZE(sn, rxbufsize) \ - WIZCHIP_WRITE(Sn_RXBUF_SIZE(sn),rxbufsize) - - -/** - * @ingroup Socket_register_access_function - * @brief Get @ref Sn_RXBUF_SIZE register - * @param (uint8_t)sn Socket number. It should be 0 ~ 7. - * @return uint8_t. Value of @ref Sn_RXBUF_SIZE. - * @sa setSn_RXBUF_SIZE() - */ -#define getSn_RXBUF_SIZE(sn) \ - WIZCHIP_READ(Sn_RXBUF_SIZE(sn)) - -/** - * @ingroup Socket_register_access_function - * @brief Set @ref Sn_TXBUF_SIZE register - * @param (uint8_t)sn Socket number. It should be 0 ~ 7. - * @param (uint8_t)txbufsize Value to set @ref Sn_TXBUF_SIZE - * @sa getSn_TXBUF_SIZE() - */ -#define setSn_TXBUF_SIZE(sn, txbufsize) \ - WIZCHIP_WRITE(Sn_TXBUF_SIZE(sn), txbufsize) - -/** - * @ingroup Socket_register_access_function - * @brief Get @ref Sn_TXBUF_SIZE register - * @param (uint8_t)sn Socket number. It should be 0 ~ 7. - * @return uint8_t. Value of @ref Sn_TXBUF_SIZE. - * @sa setSn_TXBUF_SIZE() - */ -#define getSn_TXBUF_SIZE(sn) \ - WIZCHIP_READ(Sn_TXBUF_SIZE(sn)) - -/** - * @ingroup Socket_register_access_function - * @brief Get @ref Sn_TX_FSR register - * @param (uint8_t)sn Socket number. It should be 0 ~ 7. - * @return uint16_t. Value of @ref Sn_TX_FSR. - */ -uint16_t getSn_TX_FSR(uint8_t sn); - -/** - * @ingroup Socket_register_access_function - * @brief Get @ref Sn_TX_RD register - * @param (uint8_t)sn Socket number. It should be 0 ~ 7. - * @return uint16_t. Value of @ref Sn_TX_RD. - */ -#define getSn_TX_RD(sn) \ - ((WIZCHIP_READ(Sn_TX_RD(sn)) << 8) + WIZCHIP_READ((Sn_TX_RD(sn)+1))) - -/** - * @ingroup Socket_register_access_function - * @brief Set @ref Sn_TX_WR register - * @param (uint8_t)sn Socket number. It should be 0 ~ 7. - * @param (uint16_t)txwr Value to set @ref Sn_TX_WR - * @sa GetSn_TX_WR() - */ -#define setSn_TX_WR(sn, txwr) { \ - WIZCHIP_WRITE(Sn_TX_WR(sn), (uint8_t)(txwr>>8)); \ - WIZCHIP_WRITE((Sn_TX_WR(sn)+1), (uint8_t) txwr); \ - } - -/** - * @ingroup Socket_register_access_function - * @brief Get @ref Sn_TX_WR register - * @param (uint8_t)sn Socket number. It should be 0 ~ 7. - * @return uint16_t. Value of @ref Sn_TX_WR. - * @sa setSn_TX_WR() - */ -#define getSn_TX_WR(sn) \ - ((WIZCHIP_READ(Sn_TX_WR(sn)) << 8) + WIZCHIP_READ((Sn_TX_WR(sn)+1))) - - -/** - * @ingroup Socket_register_access_function - * @brief Get @ref Sn_RX_RSR register - * @param (uint8_t)sn Socket number. It should be 0 ~ 7. - * @return uint16_t. Value of @ref Sn_RX_RSR. - */ -uint16_t getSn_RX_RSR(uint8_t sn); - - -/** - * @ingroup Socket_register_access_function - * @brief Set @ref Sn_RX_RD register - * @param (uint8_t)sn Socket number. It should be 0 ~ 7. - * @param (uint16_t)rxrd Value to set @ref Sn_RX_RD - * @sa getSn_RX_RD() - */ -#define setSn_RX_RD(sn, rxrd) { \ - WIZCHIP_WRITE(Sn_RX_RD(sn), (uint8_t)(rxrd>>8)); \ - WIZCHIP_WRITE((Sn_RX_RD(sn)+1), (uint8_t) rxrd); \ - } - -/** - * @ingroup Socket_register_access_function - * @brief Get @ref Sn_RX_RD register - * @param (uint8_t)sn Socket number. It should be 0 ~ 7. - * @regurn uint16_t. Value of @ref Sn_RX_RD. - * @sa setSn_RX_RD() - */ -#define getSn_RX_RD(sn) \ - ((WIZCHIP_READ(Sn_RX_RD(sn)) << 8) + WIZCHIP_READ((Sn_RX_RD(sn)+1))) - -/** - * @ingroup Socket_register_access_function - * @brief Get @ref Sn_RX_WR register - * @param (uint8_t)sn Socket number. It should be 0 ~ 7. - * @return uint16_t. Value of @ref Sn_RX_WR. - */ -#define getSn_RX_WR(sn) \ - ((WIZCHIP_READ(Sn_RX_WR(sn)) << 8) + WIZCHIP_READ((Sn_RX_WR(sn)+1))) - - -/** - * @ingroup Socket_register_access_function - * @brief Set @ref Sn_FRAG register - * @param (uint8_t)sn Socket number. It should be 0 ~ 7. - * @param (uint16_t)frag Value to set @ref Sn_FRAG - * @sa getSn_FRAD() - */ -#if 0 // dpgeorge -#define setSn_FRAG(sn, frag) { \ - WIZCHIP_WRITE(Sn_FRAG(sn), (uint8_t)(frag >>8)); \ - WIZCHIP_WRITE(WIZCHIP_OFFSET_INC(Sn_FRAG(sn),1), (uint8_t) frag); \ - } - -/** - * @ingroup Socket_register_access_function - * @brief Get @ref Sn_FRAG register - * @param (uint8_t)sn Socket number. It should be 0 ~ 7. - * @return uint16_t. Value of @ref Sn_FRAG. - * @sa setSn_FRAG() - */ -#define getSn_FRAG(sn) \ - ((WIZCHIP_READ(Sn_FRAG(sn)) << 8) + WIZCHIP_READ(WIZCHIP_OFFSET_INC(Sn_FRAG(sn),1))) - -/** - * @ingroup Socket_register_access_function - * @brief Set @ref Sn_KPALVTR register - * @param (uint8_t)sn Socket number. It should be 0 ~ 7. - * @param (uint8_t)kpalvt Value to set @ref Sn_KPALVTR - * @sa getSn_KPALVTR() - */ -#define setSn_KPALVTR(sn, kpalvt) \ - WIZCHIP_WRITE(Sn_KPALVTR(sn), kpalvt) - -/** - * @ingroup Socket_register_access_function - * @brief Get @ref Sn_KPALVTR register - * @param (uint8_t)sn Socket number. It should be 0 ~ 7. - * @return uint8_t. Value of @ref Sn_KPALVTR. - * @sa setSn_KPALVTR() - */ -#define getSn_KPALVTR(sn) \ - WIZCHIP_READ(Sn_KPALVTR(sn)) - -////////////////////////////////////// -#endif - -///////////////////////////////////// -// Sn_TXBUF & Sn_RXBUF IO function // -///////////////////////////////////// -/** - * @brief Gets the max buffer size of socket sn passed as parameter. - * @param (uint8_t)sn Socket number. It should be 0 ~ 7. - * @return uint16_t. Value of Socket n RX max buffer size. - */ -#define getSn_RxMAX(sn) \ - (getSn_RXBUF_SIZE(sn) << 10) - -/** - * @brief Gets the max buffer size of socket sn passed as parameters. - * @param (uint8_t)sn Socket number. It should be 0 ~ 7. - * @return uint16_t. Value of Socket n TX max buffer size. - */ -//uint16_t getSn_TxMAX(uint8_t sn); -#define getSn_TxMAX(sn) \ - (getSn_TXBUF_SIZE(sn) << 10) - -void wiz_init(void); - -/** - * @ingroup Basic_IO_function - * @brief It copies data to internal TX memory - * - * @details This function reads the Tx write pointer register and after that, - * it copies the wizdata(pointer buffer) of the length of len(variable) bytes to internal TX memory - * and updates the Tx write pointer register. - * This function is being called by send() and sendto() function also. - * - * @note User should read upper byte first and lower byte later to get proper value. - * @param (uint8_t)sn Socket number. It should be 0 ~ 7. - * @param wizdata Pointer buffer to write data - * @param len Data length - * @sa wiz_recv_data() - */ -void wiz_send_data(uint8_t sn, uint8_t *wizdata, uint16_t len); - -/** - * @ingroup Basic_IO_function - * @brief It copies data to your buffer from internal RX memory - * - * @details This function read the Rx read pointer register and after that, - * it copies the received data from internal RX memory - * to wizdata(pointer variable) of the length of len(variable) bytes. - * This function is being called by recv() also. - * - * @note User should read upper byte first and lower byte later to get proper value. - * @param (uint8_t)sn Socket number. It should be 0 ~ 7. - * @param wizdata Pointer buffer to read data - * @param len Data length - * @sa wiz_send_data() - */ -void wiz_recv_data(uint8_t sn, uint8_t *wizdata, uint16_t len); - -/** - * @ingroup Basic_IO_function - * @brief It discard the received data in RX memory. - * @details It discards the data of the length of len(variable) bytes in internal RX memory. - * @param (uint8_t)sn Socket number. It should be 0 ~ 7. - * @param len Data length - */ -void wiz_recv_ignore(uint8_t sn, uint16_t len); - -#endif // _W5500_H_ diff --git a/drivers/wiznet5k/ethernet/w5500/w5500.c b/drivers/wiznet5k/ethernet/w5500/w5500.c deleted file mode 100644 index 6b3111f996..0000000000 --- a/drivers/wiznet5k/ethernet/w5500/w5500.c +++ /dev/null @@ -1,237 +0,0 @@ -//***************************************************************************** -// -//! \file w5500.c -//! \brief W5500 HAL Interface. -//! \version 1.0.1 -//! \date 2013/10/21 -//! \par Revision history -//! <2014/05/01> V1.0.2 -//! 1. Implicit type casting -> Explicit type casting. Refer to M20140501 -//! Fixed the problem on porting into under 32bit MCU -//! Issued by Mathias ClauBen, wizwiki forum ID Think01 and bobh -//! Thank for your interesting and serious advices. -//! <2013/10/21> 1st Release -//! <2013/12/20> V1.0.1 -//! 1. Remove warning -//! 2. WIZCHIP_READ_BUF WIZCHIP_WRITE_BUF in case _WIZCHIP_IO_MODE_SPI_FDM_ -//! for loop optimized(removed). refer to M20131220 -//! \author MidnightCow -//! \copyright -//! -//! Copyright (c) 2013, WIZnet Co., LTD. -//! All rights reserved. -//! -//! Redistribution and use in source and binary forms, with or without -//! modification, are permitted provided that the following conditions -//! are met: -//! -//! * Redistributions of source code must retain the above copyright -//! notice, this list of conditions and the following disclaimer. -//! * Redistributions in binary form must reproduce the above copyright -//! notice, this list of conditions and the following disclaimer in the -//! documentation and/or other materials provided with the distribution. -//! * Neither the name of the nor the names of its -//! contributors may be used to endorse or promote products derived -//! from this software without specific prior written permission. -//! -//! THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" -//! AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -//! IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE -//! ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE -//! LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR -//! CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF -//! SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS -//! INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN -//! CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) -//! ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF -//! THE POSSIBILITY OF SUCH DAMAGE. -// -//***************************************************************************** -//#include -#include "w5500.h" - -#define _W5500_SPI_VDM_OP_ 0x00 -#define _W5500_SPI_FDM_OP_LEN1_ 0x01 -#define _W5500_SPI_FDM_OP_LEN2_ 0x02 -#define _W5500_SPI_FDM_OP_LEN4_ 0x03 - -//////////////////////////////////////////////////// - -uint8_t WIZCHIP_READ(uint32_t AddrSel) -{ - uint8_t ret; - uint8_t spi_data[3]; - - WIZCHIP_CRITICAL_ENTER(); - WIZCHIP.CS._select(); - - AddrSel |= (_W5500_SPI_READ_ | _W5500_SPI_VDM_OP_); - - //WIZCHIP.IF.SPI._write_byte((AddrSel & 0x00FF0000) >> 16); - //WIZCHIP.IF.SPI._write_byte((AddrSel & 0x0000FF00) >> 8); - //WIZCHIP.IF.SPI._write_byte((AddrSel & 0x000000FF) >> 0); - //ret = WIZCHIP.IF.SPI._read_byte(); - spi_data[0] = (AddrSel & 0x00FF0000) >> 16; - spi_data[1] = (AddrSel & 0x0000FF00) >> 8; - spi_data[2] = (AddrSel & 0x000000FF) >> 0; - Chip_SSP_WriteFrames_Blocking(LPC_SSP0, spi_data, 3); - Chip_SSP_ReadFrames_Blocking(LPC_SSP0, &ret, 1); - - WIZCHIP.CS._deselect(); - WIZCHIP_CRITICAL_EXIT(); - return ret; -} - -void WIZCHIP_WRITE(uint32_t AddrSel, uint8_t wb ) -{ - uint8_t spi_data[4]; - - WIZCHIP_CRITICAL_ENTER(); - WIZCHIP.CS._select(); - - AddrSel |= (_W5500_SPI_WRITE_ | _W5500_SPI_VDM_OP_); - - //WIZCHIP.IF.SPI._write_byte((AddrSel & 0x00FF0000) >> 16); - //WIZCHIP.IF.SPI._write_byte((AddrSel & 0x0000FF00) >> 8); - //WIZCHIP.IF.SPI._write_byte((AddrSel & 0x000000FF) >> 0); - //WIZCHIP.IF.SPI._write_byte(wb); - spi_data[0] = (AddrSel & 0x00FF0000) >> 16; - spi_data[1] = (AddrSel & 0x0000FF00) >> 8; - spi_data[2] = (AddrSel & 0x000000FF) >> 0; - spi_data[3] = wb; - Chip_SSP_WriteFrames_Blocking(LPC_SSP0, spi_data, 4); - - WIZCHIP.CS._deselect(); - WIZCHIP_CRITICAL_EXIT(); -} - -void WIZCHIP_READ_BUF (uint32_t AddrSel, uint8_t* pBuf, uint16_t len) -{ - uint8_t spi_data[3]; - //uint16_t i; - - WIZCHIP_CRITICAL_ENTER(); - WIZCHIP.CS._select(); - - AddrSel |= (_W5500_SPI_READ_ | _W5500_SPI_VDM_OP_); - - //WIZCHIP.IF.SPI._write_byte((AddrSel & 0x00FF0000) >> 16); - //WIZCHIP.IF.SPI._write_byte((AddrSel & 0x0000FF00) >> 8); - //WIZCHIP.IF.SPI._write_byte((AddrSel & 0x000000FF) >> 0); - //for(i = 0; i < len; i++) - // pBuf[i] = WIZCHIP.IF.SPI._read_byte(); - spi_data[0] = (AddrSel & 0x00FF0000) >> 16; - spi_data[1] = (AddrSel & 0x0000FF00) >> 8; - spi_data[2] = (AddrSel & 0x000000FF) >> 0; - Chip_SSP_WriteFrames_Blocking(LPC_SSP0, spi_data, 3); - Chip_SSP_ReadFrames_Blocking(LPC_SSP0, pBuf, len); - - WIZCHIP.CS._deselect(); - WIZCHIP_CRITICAL_EXIT(); -} - -void WIZCHIP_WRITE_BUF(uint32_t AddrSel, uint8_t* pBuf, uint16_t len) -{ - uint8_t spi_data[3]; - //uint16_t i; - - WIZCHIP_CRITICAL_ENTER(); - WIZCHIP.CS._select(); - - AddrSel |= (_W5500_SPI_WRITE_ | _W5500_SPI_VDM_OP_); - - //WIZCHIP.IF.SPI._write_byte((AddrSel & 0x00FF0000) >> 16); - //WIZCHIP.IF.SPI._write_byte((AddrSel & 0x0000FF00) >> 8); - //WIZCHIP.IF.SPI._write_byte((AddrSel & 0x000000FF) >> 0); - //for(i = 0; i < len; i++) - // WIZCHIP.IF.SPI._write_byte(pBuf[i]); - spi_data[0] = (AddrSel & 0x00FF0000) >> 16; - spi_data[1] = (AddrSel & 0x0000FF00) >> 8; - spi_data[2] = (AddrSel & 0x000000FF) >> 0; - Chip_SSP_WriteFrames_Blocking(LPC_SSP0, spi_data, 3); - Chip_SSP_WriteFrames_Blocking(LPC_SSP0, pBuf, len); - - WIZCHIP.CS._deselect(); - WIZCHIP_CRITICAL_EXIT(); -} - - -uint16_t getSn_TX_FSR(uint8_t sn) -{ - uint16_t val=0,val1=0; - - do - { - val1 = WIZCHIP_READ(Sn_TX_FSR(sn)); - val1 = (val1 << 8) + WIZCHIP_READ(WIZCHIP_OFFSET_INC(Sn_TX_FSR(sn),1)); - if (val1 != 0) - { - val = WIZCHIP_READ(Sn_TX_FSR(sn)); - val = (val << 8) + WIZCHIP_READ(WIZCHIP_OFFSET_INC(Sn_TX_FSR(sn),1)); - } - }while (val != val1); - return val; -} - - -uint16_t getSn_RX_RSR(uint8_t sn) -{ - uint16_t val=0,val1=0; - - do - { - val1 = WIZCHIP_READ(Sn_RX_RSR(sn)); - val1 = (val1 << 8) + WIZCHIP_READ(WIZCHIP_OFFSET_INC(Sn_RX_RSR(sn),1)); - if (val1 != 0) - { - val = WIZCHIP_READ(Sn_RX_RSR(sn)); - val = (val << 8) + WIZCHIP_READ(WIZCHIP_OFFSET_INC(Sn_RX_RSR(sn),1)); - } - }while (val != val1); - return val; -} - -void wiz_send_data(uint8_t sn, uint8_t *wizdata, uint16_t len) -{ - uint16_t ptr = 0; - uint32_t addrsel = 0; - - if(len == 0) return; - ptr = getSn_TX_WR(sn); - //M20140501 : implict type casting -> explict type casting - //addrsel = (ptr << 8) + (WIZCHIP_TXBUF_BLOCK(sn) << 3); - addrsel = ((uint32_t)ptr << 8) + (WIZCHIP_TXBUF_BLOCK(sn) << 3); - // - WIZCHIP_WRITE_BUF(addrsel,wizdata, len); - - ptr += len; - setSn_TX_WR(sn,ptr); -} - -void wiz_recv_data(uint8_t sn, uint8_t *wizdata, uint16_t len) -{ - uint16_t ptr = 0; - uint32_t addrsel = 0; - - if(len == 0) return; - ptr = getSn_RX_RD(sn); - //M20140501 : implict type casting -> explict type casting - //addrsel = ((ptr << 8) + (WIZCHIP_RXBUF_BLOCK(sn) << 3); - addrsel = ((uint32_t)ptr << 8) + (WIZCHIP_RXBUF_BLOCK(sn) << 3); - // - WIZCHIP_READ_BUF(addrsel, wizdata, len); - ptr += len; - - setSn_RX_RD(sn,ptr); -} - - -void wiz_recv_ignore(uint8_t sn, uint16_t len) -{ - uint16_t ptr = 0; - - ptr = getSn_RX_RD(sn); - ptr += len; - setSn_RX_RD(sn,ptr); -} - diff --git a/drivers/wiznet5k/ethernet/w5500/w5500.h b/drivers/wiznet5k/ethernet/w5500/w5500.h deleted file mode 100644 index f0ffcb0c8e..0000000000 --- a/drivers/wiznet5k/ethernet/w5500/w5500.h +++ /dev/null @@ -1,2058 +0,0 @@ -//***************************************************************************** -// -//! \file w5500.h -//! \brief W5500 HAL Header File. -//! \version 1.0.0 -//! \date 2013/10/21 -//! \par Revision history -//! <2013/10/21> 1st Release -//! \author MidnightCow -//! \copyright -//! -//! Copyright (c) 2013, WIZnet Co., LTD. -//! All rights reserved. -//! -//! Redistribution and use in source and binary forms, with or without -//! modification, are permitted provided that the following conditions -//! are met: -//! -//! * Redistributions of source code must retain the above copyright -//! notice, this list of conditions and the following disclaimer. -//! * Redistributions in binary form must reproduce the above copyright -//! notice, this list of conditions and the following disclaimer in the -//! documentation and/or other materials provided with the distribution. -//! * Neither the name of the nor the names of its -//! contributors may be used to endorse or promote products derived -//! from this software without specific prior written permission. -//! -//! THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" -//! AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -//! IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE -//! ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE -//! LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR -//! CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF -//! SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS -//! INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN -//! CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) -//! ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF -//! THE POSSIBILITY OF SUCH DAMAGE. -// -//***************************************************************************** - -#ifndef _W5500_H_ -#define _W5500_H_ - -#include -#include "../wizchip_conf.h" -#include "board.h" - -#define _W5500_IO_BASE_ 0x00000000 - -#define _W5500_SPI_READ_ (0x00 << 2) //< SPI interface Read operation in Control Phase -#define _W5500_SPI_WRITE_ (0x01 << 2) //< SPI interface Write operation in Control Phase - -#define WIZCHIP_CREG_BLOCK 0x00 //< Common register block -#define WIZCHIP_SREG_BLOCK(N) (1+4*N) //< Socket N register block -#define WIZCHIP_TXBUF_BLOCK(N) (2+4*N) //< Socket N Tx buffer address block -#define WIZCHIP_RXBUF_BLOCK(N) (3+4*N) //< Socket N Rx buffer address block - -#define WIZCHIP_OFFSET_INC(ADDR, N) (ADDR + (N<<8)) //< Increase offset address - - -/////////////////////////////////////// -// Definition For Legacy Chip Driver // -/////////////////////////////////////// -#define IINCHIP_READ(ADDR) WIZCHIP_READ(ADDR) ///< The defined for legacy chip driver -#define IINCHIP_WRITE(ADDR,VAL) WIZCHIP_WRITE(ADDR,VAL) ///< The defined for legacy chip driver -#define IINCHIP_READ_BUF(ADDR,BUF,LEN) WIZCHIP_READ_BUF(ADDR,BUF,LEN) ///< The defined for legacy chip driver -#define IINCHIP_WRITE_BUF(ADDR,BUF,LEN) WIZCHIP_WRITE(ADDR,BUF,LEN) ///< The defined for legacy chip driver - -////////////////////////////// -//-------------------------- defgroup --------------------------------- -/** - * @defgroup W5500 W5500 - * - * @brief WHIZCHIP register defines and I/O functions of @b W5500. - * - * - @ref WIZCHIP_register : @ref Common_register_group and @ref Socket_register_group - * - @ref WIZCHIP_IO_Functions : @ref Basic_IO_function, @ref Common_register_access_function and @ref Socket_register_access_function - */ - - -/** - * @defgroup WIZCHIP_register WIZCHIP register - * @ingroup W5500 - * - * @brief WHIZCHIP register defines register group of @b W5500. - * - * - @ref Common_register_group : Common register group - * - @ref Socket_register_group : \c SOCKET n register group - */ - - -/** - * @defgroup WIZCHIP_IO_Functions WIZCHIP I/O functions - * @ingroup W5500 - * - * @brief This supports the basic I/O functions for @ref WIZCHIP_register. - * - * - Basic I/O function \n - * WIZCHIP_READ(), WIZCHIP_WRITE(), WIZCHIP_READ_BUF(), WIZCHIP_WRITE_BUF() \n\n - * - * - @ref Common_register_group access functions \n - * -# @b Mode \n - * getMR(), setMR() - * -# @b Interrupt \n - * getIR(), setIR(), getIMR(), setIMR(), getSIR(), setSIR(), getSIMR(), setSIMR(), getINTLEVEL(), setINTLEVEL() - * -# Network Information \n - * getSHAR(), setSHAR(), getGAR(), setGAR(), getSUBR(), setSUBR(), getSIPR(), setSIPR() - * -# @b Retransmission \n - * getRCR(), setRCR(), getRTR(), setRTR() - * -# @b PPPoE \n - * getPTIMER(), setPTIMER(), getPMAGIC(), getPMAGIC(), getPSID(), setPSID(), getPHAR(), setPHAR(), getPMRU(), setPMRU() - * -# ICMP packet \n - * getUIPR(), getUPORTR() - * -# @b etc. \n - * getPHYCFGR(), setPHYCFGR(), getVERSIONR() \n\n - * - * - \ref Socket_register_group access functions \n - * -# SOCKET control \n - * getSn_MR(), setSn_MR(), getSn_CR(), setSn_CR(), getSn_IMR(), setSn_IMR(), getSn_IR(), setSn_IR() - * -# SOCKET information \n - * getSn_SR(), getSn_DHAR(), setSn_DHAR(), getSn_PORT(), setSn_PORT(), getSn_DIPR(), setSn_DIPR(), getSn_DPORT(), setSn_DPORT() - * getSn_MSSR(), setSn_MSSR() - * -# SOCKET communication \n - * getSn_RXBUF_SIZE(), setSn_RXBUF_SIZE(), getSn_TXBUF_SIZE(), setSn_TXBUF_SIZE() \n - * getSn_TX_RD(), getSn_TX_WR(), setSn_TX_WR() \n - * getSn_RX_RD(), setSn_RX_RD(), getSn_RX_WR() \n - * getSn_TX_FSR(), getSn_RX_RSR(), getSn_KPALVTR(), setSn_KPALVTR() - * -# IP header field \n - * getSn_FRAG(), setSn_FRAG(), getSn_TOS(), setSn_TOS() \n - * getSn_TTL(), setSn_TTL() - */ - - - -/** - * @defgroup Common_register_group Common register - * @ingroup WIZCHIP_register - * - * @brief Common register group\n - * It set the basic for the networking\n - * It set the configuration such as interrupt, network information, ICMP, etc. - * @details - * @sa MR : Mode register. - * @sa GAR, SUBR, SHAR, SIPR - * @sa INTLEVEL, IR, IMR, SIR, SIMR : Interrupt. - * @sa RTR, RCR : Data retransmission. - * @sa PTIMER, PMAGIC, PHAR, PSID, PMRU : PPPoE. - * @sa UIPR, UPORTR : ICMP message. - * @sa PHYCFGR, VERSIONR : etc. - */ - - - -/** - * @defgroup Socket_register_group Socket register - * @ingroup WIZCHIP_register - * - * @brief Socket register group.\n - * Socket register configures and control SOCKETn which is necessary to data communication. - * @details - * @sa Sn_MR, Sn_CR, Sn_IR, Sn_IMR : SOCKETn Control - * @sa Sn_SR, Sn_PORT, Sn_DHAR, Sn_DIPR, Sn_DPORT : SOCKETn Information - * @sa Sn_MSSR, Sn_TOS, Sn_TTL, Sn_KPALVTR, Sn_FRAG : Internet protocol. - * @sa Sn_RXBUF_SIZE, Sn_TXBUF_SIZE, Sn_TX_FSR, Sn_TX_RD, Sn_TX_WR, Sn_RX_RSR, Sn_RX_RD, Sn_RX_WR : Data communication - */ - - - - /** - * @defgroup Basic_IO_function Basic I/O function - * @ingroup WIZCHIP_IO_Functions - * @brief These are basic input/output functions to read values from register or write values to register. - */ - -/** - * @defgroup Common_register_access_function Common register access functions - * @ingroup WIZCHIP_IO_Functions - * @brief These are functions to access common registers. - */ - -/** - * @defgroup Socket_register_access_function Socket register access functions - * @ingroup WIZCHIP_IO_Functions - * @brief These are functions to access socket registers. - */ - -//------------------------------- defgroup end -------------------------------------------- -//----------------------------- W5500 Common Registers IOMAP ----------------------------- -/** - * @ingroup Common_register_group - * @brief Mode Register address(R/W)\n - * @ref MR is used for S/W reset, ping block mode, PPPoE mode and etc. - * @details Each bit of @ref MR defined as follows. - * - * - * - *
7 6 5 4 3 2 1 0
RST Reserved WOL PB PPPoE Reserved FARP Reserved
- * - \ref MR_RST : Reset - * - \ref MR_WOL : Wake on LAN - * - \ref MR_PB : Ping block - * - \ref MR_PPPOE : PPPoE mode - * - \ref MR_FARP : Force ARP mode - */ -#define MR (_W5500_IO_BASE_ + (0x0000 << 8) + (WIZCHIP_CREG_BLOCK << 3)) - -/** - * @ingroup Common_register_group - * @brief Gateway IP Register address(R/W) - * @details @ref GAR configures the default gateway address. - */ -#define GAR (_W5500_IO_BASE_ + (0x0001 << 8) + (WIZCHIP_CREG_BLOCK << 3)) - -/** - * @ingroup Common_register_group - * @brief Subnet mask Register address(R/W) - * @details @ref SUBR configures the subnet mask address. - */ -#define SUBR (_W5500_IO_BASE_ + (0x0005 << 8) + (WIZCHIP_CREG_BLOCK << 3)) - -/** - * @ingroup Common_register_group - * @brief Source MAC Register address(R/W) - * @details @ref SHAR configures the source hardware address. - */ -#define SHAR (_W5500_IO_BASE_ + (0x0009 << 8) + (WIZCHIP_CREG_BLOCK << 3)) - -/** - * @ingroup Common_register_group - * @brief Source IP Register address(R/W) - * @details @ref SIPR configures the source IP address. - */ -#define SIPR (_W5500_IO_BASE_ + (0x000F << 8) + (WIZCHIP_CREG_BLOCK << 3)) - -/** - * @ingroup Common_register_group - * @brief Set Interrupt low level timer register address(R/W) - * @details @ref INTLEVEL configures the Interrupt Assert Time. - */ -#define INTLEVEL (_W5500_IO_BASE_ + (0x0013 << 8) + (WIZCHIP_CREG_BLOCK << 3)) - -/** - * @ingroup Common_register_group - * @brief Interrupt Register(R/W) - * @details @ref IR indicates the interrupt status. Each bit of @ref IR will be still until the bit will be written to by the host. - * If @ref IR is not equal to x00 INTn PIN is asserted to low until it is x00\n\n - * Each bit of @ref IR defined as follows. - * - * - * - *
7 6 5 4 3 2 1 0
CONFLICT UNREACH PPPoE MP Reserved Reserved Reserved Reserved
- * - \ref IR_CONFLICT : IP conflict - * - \ref IR_UNREACH : Destination unreachable - * - \ref IR_PPPoE : PPPoE connection close - * - \ref IR_MP : Magic packet - */ -#define IR (_W5500_IO_BASE_ + (0x0015 << 8) + (WIZCHIP_CREG_BLOCK << 3)) - -/** - * @ingroup Common_register_group - * @brief Interrupt mask register(R/W) - * @details @ref IMR is used to mask interrupts. Each bit of @ref IMR corresponds to each bit of @ref IR. - * When a bit of @ref IMR is and the corresponding bit of @ref IR is an interrupt will be issued. In other words, - * if a bit of @ref IMR is an interrupt will not be issued even if the corresponding bit of @ref IR is \n\n - * Each bit of @ref IMR defined as the following. - * - * - * - *
7 6 5 4 3 2 1 0
IM_IR7 IM_IR6 IM_IR5 IM_IR4 Reserved Reserved Reserved Reserved
- * - \ref IM_IR7 : IP Conflict Interrupt Mask - * - \ref IM_IR6 : Destination unreachable Interrupt Mask - * - \ref IM_IR5 : PPPoE Close Interrupt Mask - * - \ref IM_IR4 : Magic Packet Interrupt Mask - */ -#define IMR (_W5500_IO_BASE_ + (0x0016 << 8) + (WIZCHIP_CREG_BLOCK << 3)) - -/** - * @ingroup Common_register_group - * @brief Socket Interrupt Register(R/W) - * @details @ref SIR indicates the interrupt status of Socket.\n - * Each bit of @ref SIR be still until @ref Sn_IR is cleared by the host.\n - * If @ref Sn_IR is not equal to x00 the n-th bit of @ref SIR is and INTn PIN is asserted until @ref SIR is x00 */ -#define SIR (_W5500_IO_BASE_ + (0x0017 << 8) + (WIZCHIP_CREG_BLOCK << 3)) - -/** - * @ingroup Common_register_group - * @brief Socket Interrupt Mask Register(R/W) - * @details Each bit of @ref SIMR corresponds to each bit of @ref SIR. - * When a bit of @ref SIMR is and the corresponding bit of @ref SIR is Interrupt will be issued. - * In other words, if a bit of @ref SIMR is an interrupt will be not issued even if the corresponding bit of @ref SIR is - */ -#define SIMR (_W5500_IO_BASE_ + (0x0018 << 8) + (WIZCHIP_CREG_BLOCK << 3)) - -/** - * @ingroup Common_register_group - * @brief Timeout register address( 1 is 100us )(R/W) - * @details @ref RTR configures the retransmission timeout period. The unit of timeout period is 100us and the default of @ref RTR is x07D0or 000 - * And so the default timeout period is 200ms(100us X 2000). During the time configured by @ref RTR, W5500 waits for the peer response - * to the packet that is transmitted by \ref Sn_CR (CONNECT, DISCON, CLOSE, SEND, SEND_MAC, SEND_KEEP command). - * If the peer does not respond within the @ref RTR time, W5500 retransmits the packet or issues timeout. - */ -#define RTR (_W5500_IO_BASE_ + (0x0019 << 8) + (WIZCHIP_CREG_BLOCK << 3)) - -/** - * @ingroup Common_register_group - * @brief Retry count register(R/W) - * @details @ref RCR configures the number of time of retransmission. - * When retransmission occurs as many as ref RCR+1 Timeout interrupt is issued (@ref Sn_IR[TIMEOUT] = . - */ -#define RCR (_W5500_IO_BASE_ + (0x001B << 8) + (WIZCHIP_CREG_BLOCK << 3)) - -/** - * @ingroup Common_register_group - * @brief PPP LCP Request Timer register in PPPoE mode(R/W) - * @details @ref PTIMER configures the time for sending LCP echo request. The unit of time is 25ms. - */ -#define PTIMER (_W5500_IO_BASE_ + (0x001C << 8) + (WIZCHIP_CREG_BLOCK << 3)) - -/** - * @ingroup Common_register_group - * @brief PPP LCP Magic number register in PPPoE mode(R/W) - * @details @ref PMAGIC configures the 4bytes magic number to be used in LCP negotiation. - */ -#define PMAGIC (_W5500_IO_BASE_ + (0x001D << 8) + (WIZCHIP_CREG_BLOCK << 3)) - -/** - * @ingroup Common_register_group - * @brief PPP Destination MAC Register address(R/W) - * @details @ref PHAR configures the PPPoE server hardware address that is acquired during PPPoE connection process. - */ -#define PHAR (_W5500_IO_BASE_ + (0x001E << 8) + (WIZCHIP_CREG_BLOCK << 3)) - -/** - * @ingroup Common_register_group - * @brief PPP Session Identification Register(R/W) - * @details @ref PSID configures the PPPoE sever session ID acquired during PPPoE connection process. - */ -#define PSID (_W5500_IO_BASE_ + (0x0024 << 8) + (WIZCHIP_CREG_BLOCK << 3)) - -/** - * @ingroup Common_register_group - * @brief PPP Maximum Segment Size(MSS) register(R/W) - * @details @ref PMRU configures the maximum receive unit of PPPoE. - */ -#define PMRU (_W5500_IO_BASE_ + (0x0026 << 8) + (WIZCHIP_CREG_BLOCK << 3)) - -/** - * @ingroup Common_register_group - * @brief Unreachable IP register address in UDP mode(R) - * @details W5500 receives an ICMP packet(Destination port unreachable) when data is sent to a port number - * which socket is not open and @ref UNREACH bit of @ref IR becomes and @ref UIPR & @ref UPORTR indicates - * the destination IP address & port number respectively. - */ -#define UIPR (_W5500_IO_BASE_ + (0x0028 << 8) + (WIZCHIP_CREG_BLOCK << 3)) - -/** - * @ingroup Common_register_group - * @brief Unreachable Port register address in UDP mode(R) - * @details W5500 receives an ICMP packet(Destination port unreachable) when data is sent to a port number - * which socket is not open and @ref UNREACH bit of @ref IR becomes and @ref UIPR & @ref UPORTR - * indicates the destination IP address & port number respectively. - */ -#define UPORTR (_W5500_IO_BASE_ + (0x002C << 8) + (WIZCHIP_CREG_BLOCK << 3)) - -/** - * @ingroup Common_register_group - * @brief PHY Status Register(R/W) - * @details @ref PHYCFGR configures PHY operation mode and resets PHY. In addition, @ref PHYCFGR indicates the status of PHY such as duplex, Speed, Link. - */ -#define PHYCFGR (_W5500_IO_BASE_ + (0x002E << 8) + (WIZCHIP_CREG_BLOCK << 3)) - -// Reserved (_W5500_IO_BASE_ + (0x002F << 8) + (WIZCHIP_CREG_BLOCK << 3)) -// Reserved (_W5500_IO_BASE_ + (0x0030 << 8) + (WIZCHIP_CREG_BLOCK << 3)) -// Reserved (_W5500_IO_BASE_ + (0x0031 << 8) + (WIZCHIP_CREG_BLOCK << 3)) -// Reserved (_W5500_IO_BASE_ + (0x0032 << 8) + (WIZCHIP_CREG_BLOCK << 3)) -// Reserved (_W5500_IO_BASE_ + (0x0033 << 8) + (WIZCHIP_CREG_BLOCK << 3)) -// Reserved (_W5500_IO_BASE_ + (0x0034 << 8) + (WIZCHIP_CREG_BLOCK << 3)) -// Reserved (_W5500_IO_BASE_ + (0x0035 << 8) + (WIZCHIP_CREG_BLOCK << 3)) -// Reserved (_W5500_IO_BASE_ + (0x0036 << 8) + (WIZCHIP_CREG_BLOCK << 3)) -// Reserved (_W5500_IO_BASE_ + (0x0037 << 8) + (WIZCHIP_CREG_BLOCK << 3)) -// Reserved (_W5500_IO_BASE_ + (0x0038 << 8) + (WIZCHIP_CREG_BLOCK << 3)) - -/** - * @ingroup Common_register_group - * @brief chip version register address(R) - * @details @ref VERSIONR always indicates the W5500 version as @b 0x04. - */ -#define VERSIONR (_W5500_IO_BASE_ + (0x0039 << 8) + (WIZCHIP_CREG_BLOCK << 3)) - - -//----------------------------- W5500 Socket Registers IOMAP ----------------------------- -/** - * @ingroup Socket_register_group - * @brief socket Mode register(R/W) - * @details @ref Sn_MR configures the option or protocol type of Socket n.\n\n - * Each bit of @ref Sn_MR defined as the following. - * - * - * - *
7 6 5 4 3 2 1 0
MULTI/MFEN BCASTB ND/MC/MMB UCASTB/MIP6B Protocol[3] Protocol[2] Protocol[1] Protocol[0]
- * - @ref Sn_MR_MULTI : Support UDP Multicasting - * - @ref Sn_MR_BCASTB : Broadcast block in UDP Multicasting - * - @ref Sn_MR_ND : No Delayed Ack(TCP) flag - * - @ref Sn_MR_MC : IGMP version used in UDP mulitcasting - * - @ref Sn_MR_MMB : Multicast Blocking in @ref Sn_MR_MACRAW mode - * - @ref Sn_MR_UCASTB : Unicast Block in UDP Multicating - * - @ref Sn_MR_MIP6B : IPv6 packet Blocking in @ref Sn_MR_MACRAW mode - * - Protocol - * - * - * - * - * - * - *
Protocol[3] Protocol[2] Protocol[1] Protocol[0] @b Meaning
0 0 0 0 Closed
0 0 0 1 TCP
0 0 1 0 UDP
0 1 0 0 MACRAW
- * - @ref Sn_MR_MACRAW : MAC LAYER RAW SOCK \n - * - @ref Sn_MR_UDP : UDP - * - @ref Sn_MR_TCP : TCP - * - @ref Sn_MR_CLOSE : Unused socket - * @note MACRAW mode should be only used in Socket 0. - */ -#define Sn_MR(N) (_W5500_IO_BASE_ + (0x0000 << 8) + (WIZCHIP_SREG_BLOCK(N) << 3)) - -/** - * @ingroup Socket_register_group - * @brief Socket command register(R/W) - * @details This is used to set the command for Socket n such as OPEN, CLOSE, CONNECT, LISTEN, SEND, and RECEIVE.\n - * After W5500 accepts the command, the @ref Sn_CR register is automatically cleared to 0x00. - * Even though @ref Sn_CR is cleared to 0x00, the command is still being processed.\n - * To check whether the command is completed or not, please check the @ref Sn_IR or @ref Sn_SR. - * - @ref Sn_CR_OPEN : Initialize or open socket. - * - @ref Sn_CR_LISTEN : Wait connection request in TCP mode(Server mode) - * - @ref Sn_CR_CONNECT : Send connection request in TCP mode(Client mode) - * - @ref Sn_CR_DISCON : Send closing request in TCP mode. - * - @ref Sn_CR_CLOSE : Close socket. - * - @ref Sn_CR_SEND : Update TX buffer pointer and send data. - * - @ref Sn_CR_SEND_MAC : Send data with MAC address, so without ARP process. - * - @ref Sn_CR_SEND_KEEP : Send keep alive message. - * - @ref Sn_CR_RECV : Update RX buffer pointer and receive data. - */ -#define Sn_CR(N) (_W5500_IO_BASE_ + (0x0001 << 8) + (WIZCHIP_SREG_BLOCK(N) << 3)) - -/** - * @ingroup Socket_register_group - * @brief Socket interrupt register(R) - * @details @ref Sn_IR indicates the status of Socket Interrupt such as establishment, termination, receiving data, timeout).\n - * When an interrupt occurs and the corresponding bit of @ref Sn_IMR is the corresponding bit of @ref Sn_IR becomes \n - * In order to clear the @ref Sn_IR bit, the host should write the bit to \n - * - * - * - *
7 6 5 4 3 2 1 0
Reserved Reserved Reserved SEND_OK TIMEOUT RECV DISCON CON
- * - \ref Sn_IR_SENDOK : SEND_OK Interrupt - * - \ref Sn_IR_TIMEOUT : TIMEOUT Interrupt - * - \ref Sn_IR_RECV : RECV Interrupt - * - \ref Sn_IR_DISCON : DISCON Interrupt - * - \ref Sn_IR_CON : CON Interrupt - */ -#define Sn_IR(N) (_W5500_IO_BASE_ + (0x0002 << 8) + (WIZCHIP_SREG_BLOCK(N) << 3)) - -/** - * @ingroup Socket_register_group - * @brief Socket status register(R) - * @details @ref Sn_SR indicates the status of Socket n.\n - * The status of Socket n is changed by @ref Sn_CR or some special control packet as SYN, FIN packet in TCP. - * @par Normal status - * - @ref SOCK_CLOSED : Closed - * - @ref SOCK_INIT : Initiate state - * - @ref SOCK_LISTEN : Listen state - * - @ref SOCK_ESTABLISHED : Success to connect - * - @ref SOCK_CLOSE_WAIT : Closing state - * - @ref SOCK_UDP : UDP socket - * - @ref SOCK_MACRAW : MAC raw mode socket - *@par Temporary status during changing the status of Socket n. - * - @ref SOCK_SYNSENT : This indicates Socket n sent the connect-request packet (SYN packet) to a peer. - * - @ref SOCK_SYNRECV : It indicates Socket n successfully received the connect-request packet (SYN packet) from a peer. - * - @ref SOCK_FIN_WAIT : Connection state - * - @ref SOCK_CLOSING : Closing state - * - @ref SOCK_TIME_WAIT : Closing state - * - @ref SOCK_LAST_ACK : Closing state - */ -#define Sn_SR(N) (_W5500_IO_BASE_ + (0x0003 << 8) + (WIZCHIP_SREG_BLOCK(N) << 3)) - -/** - * @ingroup Socket_register_group - * @brief source port register(R/W) - * @details @ref Sn_PORT configures the source port number of Socket n. - * It is valid when Socket n is used in TCP/UPD mode. It should be set before OPEN command is ordered. - */ -#define Sn_PORT(N) (_W5500_IO_BASE_ + (0x0004 << 8) + (WIZCHIP_SREG_BLOCK(N) << 3)) - -/** - * @ingroup Socket_register_group - * @brief Peer MAC register address(R/W) - * @details @ref Sn_DHAR configures the destination hardware address of Socket n when using SEND_MAC command in UDP mode or - * it indicates that it is acquired in ARP-process by CONNECT/SEND command. - */ -#define Sn_DHAR(N) (_W5500_IO_BASE_ + (0x0006 << 8) + (WIZCHIP_SREG_BLOCK(N) << 3)) - -/** - * @ingroup Socket_register_group - * @brief Peer IP register address(R/W) - * @details @ref Sn_DIPR configures or indicates the destination IP address of Socket n. It is valid when Socket n is used in TCP/UDP mode. - * In TCP client mode, it configures an IP address of �TCP serverbefore CONNECT command. - * In TCP server mode, it indicates an IP address of �TCP clientafter successfully establishing connection. - * In UDP mode, it configures an IP address of peer to be received the UDP packet by SEND or SEND_MAC command. - */ -#define Sn_DIPR(N) (_W5500_IO_BASE_ + (0x000C << 8) + (WIZCHIP_SREG_BLOCK(N) << 3)) - -/** - * @ingroup Socket_register_group - * @brief Peer port register address(R/W) - * @details @ref Sn_DPORT configures or indicates the destination port number of Socket n. It is valid when Socket n is used in TCP/UDP mode. - * In �TCP clientmode, it configures the listen port number of �TCP serverbefore CONNECT command. - * In �TCP Servermode, it indicates the port number of TCP client after successfully establishing connection. - * In UDP mode, it configures the port number of peer to be transmitted the UDP packet by SEND/SEND_MAC command. - */ -#define Sn_DPORT(N) (_W5500_IO_BASE_ + (0x0010 << 8) + (WIZCHIP_SREG_BLOCK(N) << 3)) - -/** - * @ingroup Socket_register_group - * @brief Maximum Segment Size(Sn_MSSR0) register address(R/W) - * @details @ref Sn_MSSR configures or indicates the MTU(Maximum Transfer Unit) of Socket n. - */ -#define Sn_MSSR(N) (_W5500_IO_BASE_ + (0x0012 << 8) + (WIZCHIP_SREG_BLOCK(N) << 3)) - -// Reserved (_W5500_IO_BASE_ + (0x0014 << 8) + (WIZCHIP_SREG_BLOCK(N) << 3)) - -/** - * @ingroup Socket_register_group - * @brief IP Type of Service(TOS) Register(R/W) - * @details @ref Sn_TOS configures the TOS(Type Of Service field in IP Header) of Socket n. - * It is set before OPEN command. - */ -#define Sn_TOS(N) (_W5500_IO_BASE_ + (0x0015 << 8) + (WIZCHIP_SREG_BLOCK(N) << 3)) -/** - * @ingroup Socket_register_group - * @brief IP Time to live(TTL) Register(R/W) - * @details @ref Sn_TTL configures the TTL(Time To Live field in IP header) of Socket n. - * It is set before OPEN command. - */ -#define Sn_TTL(N) (_W5500_IO_BASE_ + (0x0016 << 8) + (WIZCHIP_SREG_BLOCK(N) << 3)) -// Reserved (_W5500_IO_BASE_ + (0x0017 << 8) + (WIZCHIP_SREG_BLOCK(N) << 3)) -// Reserved (_W5500_IO_BASE_ + (0x0018 << 8) + (WIZCHIP_SREG_BLOCK(N) << 3)) -// Reserved (_W5500_IO_BASE_ + (0x0019 << 8) + (WIZCHIP_SREG_BLOCK(N) << 3)) -// Reserved (_W5500_IO_BASE_ + (0x001A << 8) + (WIZCHIP_SREG_BLOCK(N) << 3)) -// Reserved (_W5500_IO_BASE_ + (0x001B << 8) + (WIZCHIP_SREG_BLOCK(N) << 3)) -// Reserved (_W5500_IO_BASE_ + (0x001C << 8) + (WIZCHIP_SREG_BLOCK(N) << 3)) -// Reserved (_W5500_IO_BASE_ + (0x001D << 8) + (WIZCHIP_SREG_BLOCK(N) << 3)) - -/** - * @ingroup Socket_register_group - * @brief Receive memory size register(R/W) - * @details @ref Sn_RXBUF_SIZE configures the RX buffer block size of Socket n. - * Socket n RX Buffer Block size can be configured with 1,2,4,8, and 16 Kbytes. - * If a different size is configured, the data cannot be normally received from a peer. - * Although Socket n RX Buffer Block size is initially configured to 2Kbytes, - * user can re-configure its size using @ref Sn_RXBUF_SIZE. The total sum of @ref Sn_RXBUF_SIZE can not be exceed 16Kbytes. - * When exceeded, the data reception error is occurred. - */ -#define Sn_RXBUF_SIZE(N) (_W5500_IO_BASE_ + (0x001E << 8) + (WIZCHIP_SREG_BLOCK(N) << 3)) - -/** - * @ingroup Socket_register_group - * @brief Transmit memory size register(R/W) - * @details @ref Sn_TXBUF_SIZE configures the TX buffer block size of Socket n. Socket n TX Buffer Block size can be configured with 1,2,4,8, and 16 Kbytes. - * If a different size is configured, the data can�t be normally transmitted to a peer. - * Although Socket n TX Buffer Block size is initially configured to 2Kbytes, - * user can be re-configure its size using @ref Sn_TXBUF_SIZE. The total sum of @ref Sn_TXBUF_SIZE can not be exceed 16Kbytes. - * When exceeded, the data transmission error is occurred. - */ -#define Sn_TXBUF_SIZE(N) (_W5500_IO_BASE_ + (0x001F << 8) + (WIZCHIP_SREG_BLOCK(N) << 3)) - -/** - * @ingroup Socket_register_group - * @brief Transmit free memory size register(R) - * @details @ref Sn_TX_FSR indicates the free size of Socket n TX Buffer Block. It is initialized to the configured size by @ref Sn_TXBUF_SIZE. - * Data bigger than @ref Sn_TX_FSR should not be saved in the Socket n TX Buffer because the bigger data overwrites the previous saved data not yet sent. - * Therefore, check before saving the data to the Socket n TX Buffer, and if data is equal or smaller than its checked size, - * transmit the data with SEND/SEND_MAC command after saving the data in Socket n TX buffer. But, if data is bigger than its checked size, - * transmit the data after dividing into the checked size and saving in the Socket n TX buffer. - */ -#define Sn_TX_FSR(N) (_W5500_IO_BASE_ + (0x0020 << 8) + (WIZCHIP_SREG_BLOCK(N) << 3)) - -/** - * @ingroup Socket_register_group - * @brief Transmit memory read pointer register address(R) - * @details @ref Sn_TX_RD is initialized by OPEN command. However, if Sn_MR(P[3:0]) is TCP mode(001, it is re-initialized while connecting with TCP. - * After its initialization, it is auto-increased by SEND command. - * SEND command transmits the saved data from the current @ref Sn_TX_RD to the @ref Sn_TX_WR in the Socket n TX Buffer. - * After transmitting the saved data, the SEND command increases the @ref Sn_TX_RD as same as the @ref Sn_TX_WR. - * If its increment value exceeds the maximum value 0xFFFF, (greater than 0x10000 and the carry bit occurs), - * then the carry bit is ignored and will automatically update with the lower 16bits value. - */ -#define Sn_TX_RD(N) (_W5500_IO_BASE_ + (0x0022 << 8) + (WIZCHIP_SREG_BLOCK(N) << 3)) - -/** - * @ingroup Socket_register_group - * @brief Transmit memory write pointer register address(R/W) - * @details @ref Sn_TX_WR is initialized by OPEN command. However, if Sn_MR(P[3:0]) is TCP mode(001, it is re-initialized while connecting with TCP.\n - * It should be read or be updated like as follows.\n - * 1. Read the starting address for saving the transmitting data.\n - * 2. Save the transmitting data from the starting address of Socket n TX buffer.\n - * 3. After saving the transmitting data, update @ref Sn_TX_WR to the increased value as many as transmitting data size. - * If the increment value exceeds the maximum value 0xFFFF(greater than 0x10000 and the carry bit occurs), - * then the carry bit is ignored and will automatically update with the lower 16bits value.\n - * 4. Transmit the saved data in Socket n TX Buffer by using SEND/SEND command - */ -#define Sn_TX_WR(N) (_W5500_IO_BASE_ + (0x0024 << 8) + (WIZCHIP_SREG_BLOCK(N) << 3)) - -/** - * @ingroup Socket_register_group - * @brief Received data size register(R) - * @details @ref Sn_RX_RSR indicates the data size received and saved in Socket n RX Buffer. - * @ref Sn_RX_RSR does not exceed the @ref Sn_RXBUF_SIZE and is calculated as the difference between - * �Socket n RX Write Pointer (@ref Sn_RX_WR)and �Socket n RX Read Pointer (@ref Sn_RX_RD) - */ -#define Sn_RX_RSR(N) (_W5500_IO_BASE_ + (0x0026 << 8) + (WIZCHIP_SREG_BLOCK(N) << 3)) - -/** - * @ingroup Socket_register_group - * @brief Read point of Receive memory(R/W) - * @details @ref Sn_RX_RD is initialized by OPEN command. Make sure to be read or updated as follows.\n - * 1. Read the starting save address of the received data.\n - * 2. Read data from the starting address of Socket n RX Buffer.\n - * 3. After reading the received data, Update @ref Sn_RX_RD to the increased value as many as the reading size. - * If the increment value exceeds the maximum value 0xFFFF, that is, is greater than 0x10000 and the carry bit occurs, - * update with the lower 16bits value ignored the carry bit.\n - * 4. Order RECV command is for notifying the updated @ref Sn_RX_RD to W5500. - */ -#define Sn_RX_RD(N) (_W5500_IO_BASE_ + (0x0028 << 8) + (WIZCHIP_SREG_BLOCK(N) << 3)) - -/** - * @ingroup Socket_register_group - * @brief Write point of Receive memory(R) - * @details @ref Sn_RX_WR is initialized by OPEN command and it is auto-increased by the data reception. - * If the increased value exceeds the maximum value 0xFFFF, (greater than 0x10000 and the carry bit occurs), - * then the carry bit is ignored and will automatically update with the lower 16bits value. - */ -#define Sn_RX_WR(N) (_W5500_IO_BASE_ + (0x002A << 8) + (WIZCHIP_SREG_BLOCK(N) << 3)) - -/** - * @ingroup Socket_register_group - * @brief socket interrupt mask register(R) - * @details @ref Sn_IMR masks the interrupt of Socket n. - * Each bit corresponds to each bit of @ref Sn_IR. When a Socket n Interrupt is occurred and the corresponding bit of @ref Sn_IMR is - * the corresponding bit of @ref Sn_IR becomes When both the corresponding bit of @ref Sn_IMR and @ref Sn_IR are and the n-th bit of @ref IR is - * Host is interrupted by asserted INTn PIN to low. - */ -#define Sn_IMR(N) (_W5500_IO_BASE_ + (0x002C << 8) + (WIZCHIP_SREG_BLOCK(N) << 3)) - -/** - * @ingroup Socket_register_group - * @brief Fragment field value in IP header register(R/W) - * @details @ref Sn_FRAG configures the FRAG(Fragment field in IP header). - */ -#define Sn_FRAG(N) (_W5500_IO_BASE_ + (0x002D << 8) + (WIZCHIP_SREG_BLOCK(N) << 3)) - -/** - * @ingroup Socket_register_group - * @brief Keep Alive Timer register(R/W) - * @details @ref Sn_KPALVTR configures the transmitting timer of �KEEP ALIVE(KA)packet of SOCKETn. It is valid only in TCP mode, - * and ignored in other modes. The time unit is 5s. - * KA packet is transmittable after @ref Sn_SR is changed to SOCK_ESTABLISHED and after the data is transmitted or received to/from a peer at least once. - * In case of '@ref Sn_KPALVTR > 0', W5500 automatically transmits KA packet after time-period for checking the TCP connection (Auto-keepalive-process). - * In case of '@ref Sn_KPALVTR = 0', Auto-keep-alive-process will not operate, - * and KA packet can be transmitted by SEND_KEEP command by the host (Manual-keep-alive-process). - * Manual-keep-alive-process is ignored in case of '@ref Sn_KPALVTR > 0'. - */ -#define Sn_KPALVTR(N) (_W5500_IO_BASE_ + (0x002F << 8) + (WIZCHIP_SREG_BLOCK(N) << 3)) - -//#define Sn_TSR(N) (_W5500_IO_BASE_ + (0x0030 << 8) + (WIZCHIP_SREG_BLOCK(N) << 3)) - - -//----------------------------- W5500 Register values ----------------------------- - -/* MODE register values */ -/** - * @brief Reset - * @details If this bit is All internal registers will be initialized. It will be automatically cleared as after S/W reset. - */ -#define MR_RST 0x80 - -/** - * @brief Wake on LAN - * @details 0 : Disable WOL mode\n - * 1 : Enable WOL mode\n - * If WOL mode is enabled and the received magic packet over UDP has been normally processed, the Interrupt PIN (INTn) asserts to low. - * When using WOL mode, the UDP Socket should be opened with any source port number. (Refer to Socket n Mode Register (@ref Sn_MR) for opening Socket.) - * @note The magic packet over UDP supported by W5500 consists of 6 bytes synchronization stream (xFFFFFFFFFFFF and - * 16 times Target MAC address stream in UDP payload. The options such like password are ignored. You can use any UDP source port number for WOL mode. - */ -#define MR_WOL 0x20 - -/** - * @brief Ping block - * @details 0 : Disable Ping block\n - * 1 : Enable Ping block\n - * If the bit is it blocks the response to a ping request. - */ -#define MR_PB 0x10 - -/** - * @brief Enable PPPoE - * @details 0 : DisablePPPoE mode\n - * 1 : EnablePPPoE mode\n - * If you use ADSL, this bit should be - */ -#define MR_PPPOE 0x08 - -/** - * @brief Enable UDP_FORCE_ARP CHECHK - * @details 0 : Disable Force ARP mode\n - * 1 : Enable Force ARP mode\n - * In Force ARP mode, It forces on sending ARP Request whenever data is sent. - */ -#define MR_FARP 0x02 - -/* IR register values */ -/** - * @brief Check IP conflict. - * @details Bit is set as when own source IP address is same with the sender IP address in the received ARP request. - */ -#define IR_CONFLICT 0x80 - -/** - * @brief Get the destination unreachable message in UDP sending. - * @details When receiving the ICMP (Destination port unreachable) packet, this bit is set as - * When this bit is Destination Information such as IP address and Port number may be checked with the corresponding @ref UIPR & @ref UPORTR. - */ -#define IR_UNREACH 0x40 - -/** - * @brief Get the PPPoE close message. - * @details When PPPoE is disconnected during PPPoE mode, this bit is set. - */ -#define IR_PPPoE 0x20 - -/** - * @brief Get the magic packet interrupt. - * @details When WOL mode is enabled and receives the magic packet over UDP, this bit is set. - */ -#define IR_MP 0x10 - - -/* PHYCFGR register value */ -#define PHYCFGR_RST ~(1<<7) //< For PHY reset, must operate AND mask. -#define PHYCFGR_OPMD (1<<6) // Configre PHY with OPMDC value -#define PHYCFGR_OPMDC_ALLA (7<<3) -#define PHYCFGR_OPMDC_PDOWN (6<<3) -#define PHYCFGR_OPMDC_NA (5<<3) -#define PHYCFGR_OPMDC_100FA (4<<3) -#define PHYCFGR_OPMDC_100F (3<<3) -#define PHYCFGR_OPMDC_100H (2<<3) -#define PHYCFGR_OPMDC_10F (1<<3) -#define PHYCFGR_OPMDC_10H (0<<3) -#define PHYCFGR_DPX_FULL (1<<2) -#define PHYCFGR_DPX_HALF (0<<2) -#define PHYCFGR_SPD_100 (1<<1) -#define PHYCFGR_SPD_10 (0<<1) -#define PHYCFGR_LNK_ON (1<<0) -#define PHYCFGR_LNK_OFF (0<<0) - -/* IMR register values */ -/** - * @brief IP Conflict Interrupt Mask. - * @details 0: Disable IP Conflict Interrupt\n - * 1: Enable IP Conflict Interrupt - */ -#define IM_IR7 0x80 - -/** - * @brief Destination unreachable Interrupt Mask. - * @details 0: Disable Destination unreachable Interrupt\n - * 1: Enable Destination unreachable Interrupt - */ -#define IM_IR6 0x40 - -/** - * @brief PPPoE Close Interrupt Mask. - * @details 0: Disable PPPoE Close Interrupt\n - * 1: Enable PPPoE Close Interrupt - */ -#define IM_IR5 0x20 - -/** - * @brief Magic Packet Interrupt Mask. - * @details 0: Disable Magic Packet Interrupt\n - * 1: Enable Magic Packet Interrupt - */ -#define IM_IR4 0x10 - -/* Sn_MR Default values */ -/** - * @brief Support UDP Multicasting - * @details 0 : disable Multicasting\n - * 1 : enable Multicasting\n - * This bit is applied only during UDP mode(P[3:0] = 010.\n - * To use multicasting, @ref Sn_DIPR & @ref Sn_DPORT should be respectively configured with the multicast group IP address & port number - * before Socket n is opened by OPEN command of @ref Sn_CR. - */ -#define Sn_MR_MULTI 0x80 - -/** - * @brief Broadcast block in UDP Multicasting. - * @details 0 : disable Broadcast Blocking\n - * 1 : enable Broadcast Blocking\n - * This bit blocks to receive broadcasting packet during UDP mode(P[3:0] = 010.\m - * In addition, This bit does when MACRAW mode(P[3:0] = 100 - */ -#define Sn_MR_BCASTB 0x40 - -/** - * @brief No Delayed Ack(TCP), Multicast flag - * @details 0 : Disable No Delayed ACK option\n - * 1 : Enable No Delayed ACK option\n - * This bit is applied only during TCP mode (P[3:0] = 001.\n - * When this bit is It sends the ACK packet without delay as soon as a Data packet is received from a peer.\n - * When this bit is It sends the ACK packet after waiting for the timeout time configured by @ref RTR. - */ -#define Sn_MR_ND 0x20 - -/** - * @brief Unicast Block in UDP Multicasting - * @details 0 : disable Unicast Blocking\n - * 1 : enable Unicast Blocking\n - * This bit blocks receiving the unicast packet during UDP mode(P[3:0] = 010 and MULTI = - */ -#define Sn_MR_UCASTB 0x10 - -/** - * @brief MAC LAYER RAW SOCK - * @details This configures the protocol mode of Socket n. - * @note MACRAW mode should be only used in Socket 0. - */ -#define Sn_MR_MACRAW 0x04 - -//#define Sn_MR_IPRAW 0x03 /**< IP LAYER RAW SOCK */ - -/** - * @brief UDP - * @details This configures the protocol mode of Socket n. - */ -#define Sn_MR_UDP 0x02 - -/** - * @brief TCP - * @details This configures the protocol mode of Socket n. - */ -#define Sn_MR_TCP 0x01 - -/** - * @brief Unused socket - * @details This configures the protocol mode of Socket n. - */ -#define Sn_MR_CLOSE 0x00 - -/* Sn_MR values used with Sn_MR_MACRAW */ -/** - * @brief MAC filter enable in @ref Sn_MR_MACRAW mode - * @details 0 : disable MAC Filtering\n - * 1 : enable MAC Filtering\n - * This bit is applied only during MACRAW mode(P[3:0] = 100.\n - * When set as W5500 can only receive broadcasting packet or packet sent to itself. - * When this bit is W5500 can receive all packets on Ethernet. - * If user wants to implement Hybrid TCP/IP stack, - * it is recommended that this bit is set as for reducing host overhead to process the all received packets. - */ -#define Sn_MR_MFEN Sn_MR_MULTI - -/** - * @brief Multicast Blocking in @ref Sn_MR_MACRAW mode - * @details 0 : using IGMP version 2\n - * 1 : using IGMP version 1\n - * This bit is applied only during UDP mode(P[3:0] = 010 and MULTI = - * It configures the version for IGMP messages (Join/Leave/Report). - */ -#define Sn_MR_MMB Sn_MR_ND - -/** - * @brief IPv6 packet Blocking in @ref Sn_MR_MACRAW mode - * @details 0 : disable IPv6 Blocking\n - * 1 : enable IPv6 Blocking\n - * This bit is applied only during MACRAW mode (P[3:0] = 100. It blocks to receiving the IPv6 packet. - */ -#define Sn_MR_MIP6B Sn_MR_UCASTB - -/* Sn_MR value used with Sn_MR_UDP & Sn_MR_MULTI */ -/** - * @brief IGMP version used in UDP mulitcasting - * @details 0 : disable Multicast Blocking\n - * 1 : enable Multicast Blocking\n - * This bit is applied only when MACRAW mode(P[3:0] = 100. It blocks to receive the packet with multicast MAC address. - */ -#define Sn_MR_MC Sn_MR_ND - -/* Sn_MR alternate values */ -/** - * @brief For Berkeley Socket API - */ -#define SOCK_STREAM Sn_MR_TCP - -/** - * @brief For Berkeley Socket API - */ -#define SOCK_DGRAM Sn_MR_UDP - - -/* Sn_CR values */ -/** - * @brief Initialize or open socket - * @details Socket n is initialized and opened according to the protocol selected in Sn_MR(P3:P0). - * The table below shows the value of @ref Sn_SR corresponding to @ref Sn_MR.\n - * - * - * - * - * - * - *
\b Sn_MR (P[3:0]) \b Sn_SR
Sn_MR_CLOSE (000
Sn_MR_TCP (001 SOCK_INIT (0x13)
Sn_MR_UDP (010 SOCK_UDP (0x22)
S0_MR_MACRAW (100 SOCK_MACRAW (0x02)
- */ -#define Sn_CR_OPEN 0x01 - -/** - * @brief Wait connection request in TCP mode(Server mode) - * @details This is valid only in TCP mode (Sn_MR(P3:P0) = Sn_MR_TCP). - * In this mode, Socket n operates as a �TCP serverand waits for connection-request (SYN packet) from any �TCP client - * The @ref Sn_SR changes the state from SOCK_INIT to SOCKET_LISTEN. - * When a �TCP clientconnection request is successfully established, - * the @ref Sn_SR changes from SOCK_LISTEN to SOCK_ESTABLISHED and the Sn_IR(0) becomes - * But when a �TCP clientconnection request is failed, Sn_IR(3) becomes and the status of @ref Sn_SR changes to SOCK_CLOSED. - */ -#define Sn_CR_LISTEN 0x02 - -/** - * @brief Send connection request in TCP mode(Client mode) - * @details To connect, a connect-request (SYN packet) is sent to b>TCP serverconfigured by @ref Sn_DIPR & Sn_DPORT(destination address & port). - * If the connect-request is successful, the @ref Sn_SR is changed to @ref SOCK_ESTABLISHED and the Sn_IR(0) becomes \n\n - * The connect-request fails in the following three cases.\n - * 1. When a @b ARPTO occurs (@ref Sn_IR[3] = ) because destination hardware address is not acquired through the ARP-process.\n - * 2. When a @b SYN/ACK packet is not received and @b TCPTO (Sn_IR(3) = )\n - * 3. When a @b RST packet is received instead of a @b SYN/ACK packet. In these cases, @ref Sn_SR is changed to @ref SOCK_CLOSED. - * @note This is valid only in TCP mode and operates when Socket n acts as b>TCP client - */ -#define Sn_CR_CONNECT 0x04 - -/** - * @brief Send closing request in TCP mode - * @details Regardless of b>TCP serveror b>TCP client the DISCON command processes the disconnect-process (b>Active closeor b>Passive close.\n - * @par Active close - * it transmits disconnect-request(FIN packet) to the connected peer\n - * @par Passive close - * When FIN packet is received from peer, a FIN packet is replied back to the peer.\n - * @details When the disconnect-process is successful (that is, FIN/ACK packet is received successfully), @ref Sn_SR is changed to @ref SOCK_CLOSED.\n - * Otherwise, TCPTO occurs (Sn_IR(3)=)= and then @ref Sn_SR is changed to @ref SOCK_CLOSED. - * @note Valid only in TCP mode. - */ -#define Sn_CR_DISCON 0x08 - -/** - * @brief Close socket - * @details Sn_SR is changed to @ref SOCK_CLOSED. - */ -#define Sn_CR_CLOSE 0x10 - -/** - * @brief Update TX buffer pointer and send data - * @details SEND transmits all the data in the Socket n TX buffer.\n - * For more details, please refer to Socket n TX Free Size Register (@ref Sn_TX_FSR), Socket n, - * TX Write Pointer Register(@ref Sn_TX_WR), and Socket n TX Read Pointer Register(@ref Sn_TX_RD). - */ -#define Sn_CR_SEND 0x20 - -/** - * @brief Send data with MAC address, so without ARP process - * @details The basic operation is same as SEND.\n - * Normally SEND transmits data after destination hardware address is acquired by the automatic ARP-process(Address Resolution Protocol).\n - * But SEND_MAC transmits data without the automatic ARP-process.\n - * In this case, the destination hardware address is acquired from @ref Sn_DHAR configured by host, instead of APR-process. - * @note Valid only in UDP mode. - */ -#define Sn_CR_SEND_MAC 0x21 - -/** - * @brief Send keep alive message - * @details It checks the connection status by sending 1byte keep-alive packet.\n - * If the peer can not respond to the keep-alive packet during timeout time, the connection is terminated and the timeout interrupt will occur. - * @note Valid only in TCP mode. - */ -#define Sn_CR_SEND_KEEP 0x22 - -/** - * @brief Update RX buffer pointer and receive data - * @details RECV completes the processing of the received data in Socket n RX Buffer by using a RX read pointer register (@ref Sn_RX_RD).\n - * For more details, refer to Socket n RX Received Size Register (@ref Sn_RX_RSR), Socket n RX Write Pointer Register (@ref Sn_RX_WR), - * and Socket n RX Read Pointer Register (@ref Sn_RX_RD). - */ -#define Sn_CR_RECV 0x40 - -/* Sn_IR values */ -/** - * @brief SEND_OK Interrupt - * @details This is issued when SEND command is completed. - */ -#define Sn_IR_SENDOK 0x10 - -/** - * @brief TIMEOUT Interrupt - * @details This is issued when ARPTO or TCPTO occurs. - */ -#define Sn_IR_TIMEOUT 0x08 - -/** - * @brief RECV Interrupt - * @details This is issued whenever data is received from a peer. - */ -#define Sn_IR_RECV 0x04 - -/** - * @brief DISCON Interrupt - * @details This is issued when FIN or FIN/ACK packet is received from a peer. - */ -#define Sn_IR_DISCON 0x02 - -/** - * @brief CON Interrupt - * @details This is issued one time when the connection with peer is successful and then @ref Sn_SR is changed to @ref SOCK_ESTABLISHED. - */ -#define Sn_IR_CON 0x01 - -/* Sn_SR values */ -/** - * @brief Closed - * @details This indicates that Socket n is released.\N - * When DICON, CLOSE command is ordered, or when a timeout occurs, it is changed to @ref SOCK_CLOSED regardless of previous status. - */ -#define SOCK_CLOSED 0x00 - -/** - * @brief Initiate state - * @details This indicates Socket n is opened with TCP mode.\N - * It is changed to @ref SOCK_INIT when Sn_MR(P[3:0]) = 001and OPEN command is ordered.\N - * After @ref SOCK_INIT, user can use LISTEN /CONNECT command. - */ -#define SOCK_INIT 0x13 - -/** - * @brief Listen state - * @details This indicates Socket n is operating as b>TCP servermode and waiting for connection-request (SYN packet) from a peer (b>TCP client.\n - * It will change to @ref SOCK_ESTALBLISHED when the connection-request is successfully accepted.\n - * Otherwise it will change to @ref SOCK_CLOSED after TCPTO occurred (Sn_IR(TIMEOUT) = . - */ -#define SOCK_LISTEN 0x14 - -/** - * @brief Connection state - * @details This indicates Socket n sent the connect-request packet (SYN packet) to a peer.\n - * It is temporarily shown when @ref Sn_SR is changed from @ref SOCK_INIT to @ref SOCK_ESTABLISHED by CONNECT command.\n - * If connect-accept(SYN/ACK packet) is received from the peer at SOCK_SYNSENT, it changes to @ref SOCK_ESTABLISHED.\n - * Otherwise, it changes to @ref SOCK_CLOSED after TCPTO (@ref Sn_IR[TIMEOUT] = is occurred. - */ -#define SOCK_SYNSENT 0x15 - -/** - * @brief Connection state - * @details It indicates Socket n successfully received the connect-request packet (SYN packet) from a peer.\n - * If socket n sends the response (SYN/ACK packet) to the peer successfully, it changes to @ref SOCK_ESTABLISHED. \n - * If not, it changes to @ref SOCK_CLOSED after timeout occurs (@ref Sn_IR[TIMEOUT] = . - */ -#define SOCK_SYNRECV 0x16 - -/** - * @brief Success to connect - * @details This indicates the status of the connection of Socket n.\n - * It changes to @ref SOCK_ESTABLISHED when the b>TCP SERVERprocessed the SYN packet from the b>TCP CLIENTduring @ref SOCK_LISTEN, or - * when the CONNECT command is successful.\n - * During @ref SOCK_ESTABLISHED, DATA packet can be transferred using SEND or RECV command. - */ -#define SOCK_ESTABLISHED 0x17 - -/** - * @brief Closing state - * @details These indicate Socket n is closing.\n - * These are shown in disconnect-process such as active-close and passive-close.\n - * When Disconnect-process is successfully completed, or when timeout occurs, these change to @ref SOCK_CLOSED. - */ -#define SOCK_FIN_WAIT 0x18 - -/** - * @brief Closing state - * @details These indicate Socket n is closing.\n - * These are shown in disconnect-process such as active-close and passive-close.\n - * When Disconnect-process is successfully completed, or when timeout occurs, these change to @ref SOCK_CLOSED. - */ -#define SOCK_CLOSING 0x1A - -/** - * @brief Closing state - * @details These indicate Socket n is closing.\n - * These are shown in disconnect-process such as active-close and passive-close.\n - * When Disconnect-process is successfully completed, or when timeout occurs, these change to @ref SOCK_CLOSED. - */ -#define SOCK_TIME_WAIT 0x1B - -/** - * @brief Closing state - * @details This indicates Socket n received the disconnect-request (FIN packet) from the connected peer.\n - * This is half-closing status, and data can be transferred.\n - * For full-closing, DISCON command is used. But For just-closing, CLOSE command is used. - */ -#define SOCK_CLOSE_WAIT 0x1C - -/** - * @brief Closing state - * @details This indicates Socket n is waiting for the response (FIN/ACK packet) to the disconnect-request (FIN packet) by passive-close.\n - * It changes to @ref SOCK_CLOSED when Socket n received the response successfully, or when timeout occurs (@ref Sn_IR[TIMEOUT] = . - */ -#define SOCK_LAST_ACK 0x1D - -/** - * @brief UDP socket - * @details This indicates Socket n is opened in UDP mode(Sn_MR(P[3:0]) = 010.\n - * It changes to SOCK_UPD when Sn_MR(P[3:0]) = 010 and OPEN command is ordered.\n - * Unlike TCP mode, data can be transfered without the connection-process. - */ -#define SOCK_UDP 0x22 - -//#define SOCK_IPRAW 0x32 /**< IP raw mode socket */ - -/** - * @brief MAC raw mode socket - * @details This indicates Socket 0 is opened in MACRAW mode (S0_MR(P[3:0]) = 100and is valid only in Socket 0.\n - * It changes to SOCK_MACRAW when S0_MR(P[3:0] = 100and OPEN command is ordered.\n - * Like UDP mode socket, MACRAW mode Socket 0 can transfer a MAC packet (Ethernet frame) without the connection-process. - */ -#define SOCK_MACRAW 0x42 - -//#define SOCK_PPPOE 0x5F - -/* IP PROTOCOL */ -#define IPPROTO_IP 0 //< Dummy for IP -#define IPPROTO_ICMP 1 //< Control message protocol -#define IPPROTO_IGMP 2 //< Internet group management protocol -#define IPPROTO_GGP 3 //< Gateway^2 (deprecated) -#define IPPROTO_TCP 6 //< TCP -#define IPPROTO_PUP 12 //< PUP -#define IPPROTO_UDP 17 //< UDP -#define IPPROTO_IDP 22 //< XNS idp -#define IPPROTO_ND 77 //< UNOFFICIAL net disk protocol -#define IPPROTO_RAW 255 //< Raw IP packet - - -/** - * @brief Enter a critical section - * - * @details It is provided to protect your shared code which are executed without distribution. \n \n - * - * In non-OS environment, It can be just implemented by disabling whole interrupt.\n - * In OS environment, You can replace it to critical section api supported by OS. - * - * \sa WIZCHIP_READ(), WIZCHIP_WRITE(), WIZCHIP_READ_BUF(), WIZCHIP_WRITE_BUF() - * \sa WIZCHIP_CRITICAL_EXIT() - */ -#define WIZCHIP_CRITICAL_ENTER() WIZCHIP.CRIS._enter() - -/** - * @brief Exit a critical section - * - * @details It is provided to protect your shared code which are executed without distribution. \n\n - * - * In non-OS environment, It can be just implemented by disabling whole interrupt. \n - * In OS environment, You can replace it to critical section api supported by OS. - * - * @sa WIZCHIP_READ(), WIZCHIP_WRITE(), WIZCHIP_READ_BUF(), WIZCHIP_WRITE_BUF() - * @sa WIZCHIP_CRITICAL_ENTER() - */ -#ifdef _exit -#undef _exit -#endif -#define WIZCHIP_CRITICAL_EXIT() WIZCHIP.CRIS._exit() - - - -//////////////////////// -// Basic I/O Function // -//////////////////////// - -/** - * @ingroup Basic_IO_function - * @brief It reads 1 byte value from a register. - * @param AddrSel Register address - * @return The value of register - */ -uint8_t WIZCHIP_READ (uint32_t AddrSel); - -/** - * @ingroup Basic_IO_function - * @brief It writes 1 byte value to a register. - * @param AddrSel Register address - * @param wb Write data - * @return void - */ -void WIZCHIP_WRITE(uint32_t AddrSel, uint8_t wb ); - -/** - * @ingroup Basic_IO_function - * @brief It reads sequence data from registers. - * @param AddrSel Register address - * @param pBuf Pointer buffer to read data - * @param len Data length - */ -void WIZCHIP_READ_BUF (uint32_t AddrSel, uint8_t* pBuf, uint16_t len); - -/** - * @ingroup Basic_IO_function - * @brief It writes sequence data to registers. - * @param AddrSel Register address - * @param pBuf Pointer buffer to write data - * @param len Data length - */ -void WIZCHIP_WRITE_BUF(uint32_t AddrSel, uint8_t* pBuf, uint16_t len); - -///////////////////////////////// -// Common Register I/O function // -///////////////////////////////// -/** - * @ingroup Common_register_access_function - * @brief Set Mode Register - * @param (uint8_t)mr The value to be set. - * @sa getMR() - */ -#define setMR(mr) \ - WIZCHIP_WRITE(MR,mr) - - -/** - * @ingroup Common_register_access_function - * @brief Get Mode Register - * @return uint8_t. The value of Mode register. - * @sa setMR() - */ -#define getMR() \ - WIZCHIP_READ(MR) - -/** - * @ingroup Common_register_access_function - * @brief Set gateway IP address - * @param (uint8_t*)gar Pointer variable to set gateway IP address. It should be allocated 4 bytes. - * @sa getGAR() - */ -#define setGAR(gar) \ - WIZCHIP_WRITE_BUF(GAR,gar,4) - -/** - * @ingroup Common_register_access_function - * @brief Get gateway IP address - * @param (uint8_t*)gar Pointer variable to get gateway IP address. It should be allocated 4 bytes. - * @sa setGAR() - */ -#define getGAR(gar) \ - WIZCHIP_READ_BUF(GAR,gar,4) - -/** - * @ingroup Common_register_access_function - * @brief Set subnet mask address - * @param (uint8_t*)subr Pointer variable to set subnet mask address. It should be allocated 4 bytes. - * @sa getSUBR() - */ -#define setSUBR(subr) \ - WIZCHIP_WRITE_BUF(SUBR, subr,4) - - -/** - * @ingroup Common_register_access_function - * @brief Get subnet mask address - * @param (uint8_t*)subr Pointer variable to get subnet mask address. It should be allocated 4 bytes. - * @sa setSUBR() - */ -#define getSUBR(subr) \ - WIZCHIP_READ_BUF(SUBR, subr, 4) - -/** - * @ingroup Common_register_access_function - * @brief Set local MAC address - * @param (uint8_t*)shar Pointer variable to set local MAC address. It should be allocated 6 bytes. - * @sa getSHAR() - */ -#define setSHAR(shar) \ - WIZCHIP_WRITE_BUF(SHAR, shar, 6) - -/** - * @ingroup Common_register_access_function - * @brief Get local MAC address - * @param (uint8_t*)shar Pointer variable to get local MAC address. It should be allocated 6 bytes. - * @sa setSHAR() - */ -#define getSHAR(shar) \ - WIZCHIP_READ_BUF(SHAR, shar, 6) - -/** - * @ingroup Common_register_access_function - * @brief Set local IP address - * @param (uint8_t*)sipr Pointer variable to set local IP address. It should be allocated 4 bytes. - * @sa getSIPR() - */ -#define setSIPR(sipr) \ - WIZCHIP_WRITE_BUF(SIPR, sipr, 4) - -/** - * @ingroup Common_register_access_function - * @brief Get local IP address - * @param (uint8_t*)sipr Pointer variable to get local IP address. It should be allocated 4 bytes. - * @sa setSIPR() - */ -#define getSIPR(sipr) \ - WIZCHIP_READ_BUF(SIPR, sipr, 4) - -/** - * @ingroup Common_register_access_function - * @brief Set INTLEVEL register - * @param (uint16_t)intlevel Value to set @ref INTLEVEL register. - * @sa getINTLEVEL() - */ -#define setINTLEVEL(intlevel) {\ - WIZCHIP_WRITE(INTLEVEL, (uint8_t)(intlevel >> 8)); \ - WIZCHIP_WRITE(WIZCHIP_OFFSET_INC(INTLEVEL,1), (uint8_t) intlevel); \ - } - - -/** - * @ingroup Common_register_access_function - * @brief Get INTLEVEL register - * @return uint16_t. Value of @ref INTLEVEL register. - * @sa setINTLEVEL() - */ -#define getINTLEVEL() \ - ((WIZCHIP_READ(INTLEVEL) << 8) + WIZCHIP_READ(WIZCHIP_OFFSET_INC(INTLEVEL,1))) - -/** - * @ingroup Common_register_access_function - * @brief Set @ref IR register - * @param (uint8_t)ir Value to set @ref IR register. - * @sa getIR() - */ -#define setIR(ir) \ - WIZCHIP_WRITE(IR, (ir & 0xF0)) - -/** - * @ingroup Common_register_access_function - * @brief Get @ref IR register - * @return uint8_t. Value of @ref IR register. - * @sa setIR() - */ -#define getIR() \ - (WIZCHIP_READ(IR) & 0xF0) -/** - * @ingroup Common_register_access_function - * @brief Set @ref IMR register - * @param (uint8_t)imr Value to set @ref IMR register. - * @sa getIMR() - */ -#define setIMR(imr) \ - WIZCHIP_WRITE(IMR, imr) - -/** - * @ingroup Common_register_access_function - * @brief Get @ref IMR register - * @return uint8_t. Value of @ref IMR register. - * @sa setIMR() - */ -#define getIMR() \ - WIZCHIP_READ(IMR) - - -/** - * @ingroup Common_register_access_function - * @brief Set @ref SIR register - * @param (uint8_t)sir Value to set @ref SIR register. - * @sa getSIR() - */ -#define setSIR(sir) \ - WIZCHIP_WRITE(SIR, sir) - -/** - * @ingroup Common_register_access_function - * @brief Get @ref SIR register - * @return uint8_t. Value of @ref SIR register. - * @sa setSIR() - */ -#define getSIR() \ - WIZCHIP_READ(SIR) -/** - * @ingroup Common_register_access_function - * @brief Set @ref SIMR register - * @param (uint8_t)simr Value to set @ref SIMR register. - * @sa getSIMR() - */ -#define setSIMR(simr) \ - WIZCHIP_WRITE(SIMR, simr) - -/** - * @ingroup Common_register_access_function - * @brief Get @ref SIMR register - * @return uint8_t. Value of @ref SIMR register. - * @sa setSIMR() - */ -#define getSIMR() \ - WIZCHIP_READ(SIMR) - -/** - * @ingroup Common_register_access_function - * @brief Set @ref RTR register - * @param (uint16_t)rtr Value to set @ref RTR register. - * @sa getRTR() - */ -#define setRTR(rtr) {\ - WIZCHIP_WRITE(RTR, (uint8_t)(rtr >> 8)); \ - WIZCHIP_WRITE(WIZCHIP_OFFSET_INC(RTR,1), (uint8_t) rtr); \ - } - -/** - * @ingroup Common_register_access_function - * @brief Get @ref RTR register - * @return uint16_t. Value of @ref RTR register. - * @sa setRTR() - */ -#define getRTR() \ - ((WIZCHIP_READ(RTR) << 8) + WIZCHIP_READ(WIZCHIP_OFFSET_INC(RTR,1))) - -/** - * @ingroup Common_register_access_function - * @brief Set @ref RCR register - * @param (uint8_t)rcr Value to set @ref RCR register. - * @sa getRCR() - */ -#define setRCR(rcr) \ - WIZCHIP_WRITE(RCR, rcr) - -/** - * @ingroup Common_register_access_function - * @brief Get @ref RCR register - * @return uint8_t. Value of @ref RCR register. - * @sa setRCR() - */ -#define getRCR() \ - WIZCHIP_READ(RCR) - -//================================================== test done =========================================================== - -/** - * @ingroup Common_register_access_function - * @brief Set @ref PTIMER register - * @param (uint8_t)ptimer Value to set @ref PTIMER register. - * @sa getPTIMER() - */ -#define setPTIMER(ptimer) \ - WIZCHIP_WRITE(PTIMER, ptimer) - -/** - * @ingroup Common_register_access_function - * @brief Get @ref PTIMER register - * @return uint8_t. Value of @ref PTIMER register. - * @sa setPTIMER() - */ -#define getPTIMER() \ - WIZCHIP_READ(PTIMER) - -/** - * @ingroup Common_register_access_function - * @brief Set @ref PMAGIC register - * @param (uint8_t)pmagic Value to set @ref PMAGIC register. - * @sa getPMAGIC() - */ -#define setPMAGIC(pmagic) \ - WIZCHIP_WRITE(PMAGIC, pmagic) - -/** - * @ingroup Common_register_access_function - * @brief Get @ref PMAGIC register - * @return uint8_t. Value of @ref PMAGIC register. - * @sa setPMAGIC() - */ -#define getPMAGIC() \ - WIZCHIP_READ(PMAGIC) - -/** - * @ingroup Common_register_access_function - * @brief Set PHAR address - * @param (uint8_t*)phar Pointer variable to set PPP destination MAC register address. It should be allocated 6 bytes. - * @sa getPHAR() - */ -#define setPHAR(phar) \ - WIZCHIP_WRITE_BUF(PHAR, phar, 6) - -/** - * @ingroup Common_register_access_function - * @brief Get local IP address - * @param (uint8_t*)phar Pointer variable to PPP destination MAC register address. It should be allocated 6 bytes. - * @sa setPHAR() - */ -#define getPHAR(phar) \ - WIZCHIP_READ_BUF(PHAR, phar, 6) - -/** - * @ingroup Common_register_access_function - * @brief Set @ref PSID register - * @param (uint16_t)psid Value to set @ref PSID register. - * @sa getPSID() - */ -#define setPSID(psid) {\ - WIZCHIP_WRITE(PSID, (uint8_t)(psid >> 8)); \ - WIZCHIP_WRITE(WIZCHIP_OFFSET_INC(PSID,1), (uint8_t) psid); \ - } - -/** - * @ingroup Common_register_access_function - * @brief Get @ref PSID register - * @return uint16_t. Value of @ref PSID register. - * @sa setPSID() - */ -//uint16_t getPSID(void); -#define getPSID() \ - ((WIZCHIP_READ(PSID) << 8) + WIZCHIP_READ(WIZCHIP_OFFSET_INC(PSID,1))) - -/** - * @ingroup Common_register_access_function - * @brief Set @ref PMRU register - * @param (uint16_t)pmru Value to set @ref PMRU register. - * @sa getPMRU() - */ -#define setPMRU(pmru) { \ - WIZCHIP_WRITE(PMRU, (uint8_t)(pmru>>8)); \ - WIZCHIP_WRITE(WIZCHIP_OFFSET_INC(PMRU,1), (uint8_t) pmru); \ - } - -/** - * @ingroup Common_register_access_function - * @brief Get @ref PMRU register - * @return uint16_t. Value of @ref PMRU register. - * @sa setPMRU() - */ -#define getPMRU() \ - ((WIZCHIP_READ(PMRU) << 8) + WIZCHIP_READ(WIZCHIP_OFFSET_INC(PMRU,1))) - -/** - * @ingroup Common_register_access_function - * @brief Get unreachable IP address - * @param (uint8_t*)uipr Pointer variable to get unreachable IP address. It should be allocated 4 bytes. - */ -#define getUIPR(uipr) \ - WIZCHIP_READ_BUF(UIPR,uipr,6) - -/** - * @ingroup Common_register_access_function - * @brief Get @ref UPORTR register - * @return uint16_t. Value of @ref UPORTR register. - */ -#define getUPORTR() \ - ((WIZCHIP_READ(UPORTR) << 8) + WIZCHIP_READ(WIZCHIP_OFFSET_INC(UPORTR,1))) - -/** - * @ingroup Common_register_access_function - * @brief Set @ref PHYCFGR register - * @param (uint8_t)phycfgr Value to set @ref PHYCFGR register. - * @sa getPHYCFGR() - */ -#define setPHYCFGR(phycfgr) \ - WIZCHIP_WRITE(PHYCFGR, phycfgr) - -/** - * @ingroup Common_register_access_function - * @brief Get @ref PHYCFGR register - * @return uint8_t. Value of @ref PHYCFGR register. - * @sa setPHYCFGR() - */ -#define getPHYCFGR() \ - WIZCHIP_READ(PHYCFGR) - -/** - * @ingroup Common_register_access_function - * @brief Get @ref VERSIONR register - * @return uint8_t. Value of @ref VERSIONR register. - */ -#define getVERSIONR() \ - WIZCHIP_READ(VERSIONR) - -///////////////////////////////////// - -/////////////////////////////////// -// Socket N register I/O function // -/////////////////////////////////// -/** - * @ingroup Socket_register_access_function - * @brief Set @ref Sn_MR register - * @param (uint8_t)sn Socket number. It should be 0 ~ 7. - * @param (uint8_t)mr Value to set @ref Sn_MR - * @sa getSn_MR() - */ -#define setSn_MR(sn, mr) \ - WIZCHIP_WRITE(Sn_MR(sn),mr) - -/** - * @ingroup Socket_register_access_function - * @brief Get @ref Sn_MR register - * @param (uint8_t)sn Socket number. It should be 0 ~ 7. - * @return uint8_t. Value of @ref Sn_MR. - * @sa setSn_MR() - */ -#define getSn_MR(sn) \ - WIZCHIP_READ(Sn_MR(sn)) - -/** - * @ingroup Socket_register_access_function - * @brief Set @ref Sn_CR register - * @param (uint8_t)sn Socket number. It should be 0 ~ 7. - * @param (uint8_t)cr Value to set @ref Sn_CR - * @sa getSn_CR() - */ -#define setSn_CR(sn, cr) \ - WIZCHIP_WRITE(Sn_CR(sn), cr) - -/** - * @ingroup Socket_register_access_function - * @brief Get @ref Sn_CR register - * @param (uint8_t)sn Socket number. It should be 0 ~ 7. - * @return uint8_t. Value of @ref Sn_CR. - * @sa setSn_CR() - */ -#define getSn_CR(sn) \ - WIZCHIP_READ(Sn_CR(sn)) - -/** - * @ingroup Socket_register_access_function - * @brief Set @ref Sn_IR register - * @param (uint8_t)sn Socket number. It should be 0 ~ 7. - * @param (uint8_t)ir Value to set @ref Sn_IR - * @sa getSn_IR() - */ -#define setSn_IR(sn, ir) \ - WIZCHIP_WRITE(Sn_IR(sn), (ir & 0x1F)) - -/** - * @ingroup Socket_register_access_function - * @brief Get @ref Sn_IR register - * @param (uint8_t)sn Socket number. It should be 0 ~ 7. - * @return uint8_t. Value of @ref Sn_IR. - * @sa setSn_IR() - */ -#define getSn_IR(sn) \ - (WIZCHIP_READ(Sn_IR(sn)) & 0x1F) - -/** - * @ingroup Socket_register_access_function - * @brief Set @ref Sn_IMR register - * @param (uint8_t)sn Socket number. It should be 0 ~ 7. - * @param (uint8_t)imr Value to set @ref Sn_IMR - * @sa getSn_IMR() - */ -#define setSn_IMR(sn, imr) \ - WIZCHIP_WRITE(Sn_IMR(sn), (imr & 0x1F)) - -/** - * @ingroup Socket_register_access_function - * @brief Get @ref Sn_IMR register - * @param (uint8_t)sn Socket number. It should be 0 ~ 7. - * @return uint8_t. Value of @ref Sn_IMR. - * @sa setSn_IMR() - */ -#define getSn_IMR(sn) \ - (WIZCHIP_READ(Sn_IMR(sn)) & 0x1F) - -/** - * @ingroup Socket_register_access_function - * @brief Get @ref Sn_SR register - * @param (uint8_t)sn Socket number. It should be 0 ~ 7. - * @return uint8_t. Value of @ref Sn_SR. - */ -#define getSn_SR(sn) \ - WIZCHIP_READ(Sn_SR(sn)) - -/** - * @ingroup Socket_register_access_function - * @brief Set @ref Sn_PORT register - * @param (uint8_t)sn Socket number. It should be 0 ~ 7. - * @param (uint16_t)port Value to set @ref Sn_PORT. - * @sa getSn_PORT() - */ -#define setSn_PORT(sn, port) { \ - WIZCHIP_WRITE(Sn_PORT(sn), (uint8_t)(port >> 8)); \ - WIZCHIP_WRITE(WIZCHIP_OFFSET_INC(Sn_PORT(sn),1), (uint8_t) port); \ - } - -/** - * @ingroup Socket_register_access_function - * @brief Get @ref Sn_PORT register - * @param (uint8_t)sn Socket number. It should be 0 ~ 7. - * @return uint16_t. Value of @ref Sn_PORT. - * @sa setSn_PORT() - */ -#define getSn_PORT(sn) \ - ((WIZCHIP_READ(Sn_PORT(sn)) << 8) + WIZCHIP_READ(WIZCHIP_OFFSET_INC(Sn_PORT(sn),1))) - -/** - * @ingroup Socket_register_access_function - * @brief Set @ref Sn_DHAR register - * @param (uint8_t)sn Socket number. It should be 0 ~ 7. - * @param (uint8_t*)dhar Pointer variable to set socket n destination hardware address. It should be allocated 6 bytes. - * @sa getSn_DHAR() - */ -#define setSn_DHAR(sn, dhar) \ - WIZCHIP_WRITE_BUF(Sn_DHAR(sn), dhar, 6) - -/** - * @ingroup Socket_register_access_function - * @brief Get @ref Sn_MR register - * @param (uint8_t)sn Socket number. It should be 0 ~ 7. - * @param (uint8_t*)dhar Pointer variable to get socket n destination hardware address. It should be allocated 6 bytes. - * @sa setSn_DHAR() - */ -#define getSn_DHAR(sn, dhar) \ - WIZCHIP_READ_BUF(Sn_DHAR(sn), dhar, 6) - -/** - * @ingroup Socket_register_access_function - * @brief Set @ref Sn_DIPR register - * @param (uint8_t)sn Socket number. It should be 0 ~ 7. - * @param (uint8_t*)dipr Pointer variable to set socket n destination IP address. It should be allocated 4 bytes. - * @sa getSn_DIPR() - */ -#define setSn_DIPR(sn, dipr) \ - WIZCHIP_WRITE_BUF(Sn_DIPR(sn), dipr, 4) - -/** - * @ingroup Socket_register_access_function - * @brief Get @ref Sn_DIPR register - * @param (uint8_t)sn Socket number. It should be 0 ~ 7. - * @param (uint8_t*)dipr Pointer variable to get socket n destination IP address. It should be allocated 4 bytes. - * @sa SetSn_DIPR() - */ -#define getSn_DIPR(sn, dipr) \ - WIZCHIP_READ_BUF(Sn_DIPR(sn), dipr, 4) - -/** - * @ingroup Socket_register_access_function - * @brief Set @ref Sn_DPORT register - * @param (uint8_t)sn Socket number. It should be 0 ~ 7. - * @param (uint16_t)dport Value to set @ref Sn_DPORT - * @sa getSn_DPORT() - */ -#define setSn_DPORT(sn, dport) { \ - WIZCHIP_WRITE(Sn_DPORT(sn), (uint8_t) (dport>>8)); \ - WIZCHIP_WRITE(WIZCHIP_OFFSET_INC(Sn_DPORT(sn),1), (uint8_t) dport); \ - } - -/** - * @ingroup Socket_register_access_function - * @brief Get @ref Sn_DPORT register - * @param (uint8_t)sn Socket number. It should be 0 ~ 7. - * @return uint16_t. Value of @ref Sn_DPORT. - * @sa setSn_DPORT() - */ -#define getSn_DPORT(sn) \ - ((WIZCHIP_READ(Sn_DPORT(sn)) << 8) + WIZCHIP_READ(WIZCHIP_OFFSET_INC(Sn_DPORT(sn),1))) - -/** - * @ingroup Socket_register_access_function - * @brief Set @ref Sn_MSSR register - * @param (uint8_t)sn Socket number. It should be 0 ~ 7. - * @param (uint16_t)mss Value to set @ref Sn_MSSR - * @sa setSn_MSSR() - */ -#define setSn_MSSR(sn, mss) { \ - WIZCHIP_WRITE(Sn_MSSR(sn), (uint8_t)(mss>>8)); \ - WIZCHIP_WRITE(WIZCHIP_OFFSET_INC(Sn_MSSR(sn),1), (uint8_t) mss); \ - } - -/** - * @ingroup Socket_register_access_function - * @brief Get @ref Sn_MSSR register - * @param (uint8_t)sn Socket number. It should be 0 ~ 7. - * @return uint16_t. Value of @ref Sn_MSSR. - * @sa setSn_MSSR() - */ -#define getSn_MSSR(sn) \ - ((WIZCHIP_READ(Sn_MSSR(sn)) << 8) + WIZCHIP_READ(WIZCHIP_OFFSET_INC(Sn_MSSR(sn),1))) - -/** - * @ingroup Socket_register_access_function - * @brief Set @ref Sn_TOS register - * @param (uint8_t)sn Socket number. It should be 0 ~ 7. - * @param (uint8_t)tos Value to set @ref Sn_TOS - * @sa getSn_TOS() - */ -#define setSn_TOS(sn, tos) \ - WIZCHIP_WRITE(Sn_TOS(sn), tos) - -/** - * @ingroup Socket_register_access_function - * @brief Get @ref Sn_TOS register - * @param (uint8_t)sn Socket number. It should be 0 ~ 7. - * @return uint8_t. Value of Sn_TOS. - * @sa setSn_TOS() - */ -#define getSn_TOS(sn) \ - WIZCHIP_READ(Sn_TOS(sn)) - -/** - * @ingroup Socket_register_access_function - * @brief Set @ref Sn_TTL register - * @param (uint8_t)sn Socket number. It should be 0 ~ 7. - * @param (uint8_t)ttl Value to set @ref Sn_TTL - * @sa getSn_TTL() - */ -#define setSn_TTL(sn, ttl) \ - WIZCHIP_WRITE(Sn_TTL(sn), ttl) - - -/** - * @ingroup Socket_register_access_function - * @brief Get @ref Sn_TTL register - * @param (uint8_t)sn Socket number. It should be 0 ~ 7. - * @return uint8_t. Value of @ref Sn_TTL. - * @sa setSn_TTL() - */ -#define getSn_TTL(sn) \ - WIZCHIP_READ(Sn_TTL(sn)) - - -/** - * @ingroup Socket_register_access_function - * @brief Set @ref Sn_RXBUF_SIZE register - * @param (uint8_t)sn Socket number. It should be 0 ~ 7. - * @param (uint8_t)rxbufsize Value to set @ref Sn_RXBUF_SIZE - * @sa getSn_RXBUF_SIZE() - */ -#define setSn_RXBUF_SIZE(sn, rxbufsize) \ - WIZCHIP_WRITE(Sn_RXBUF_SIZE(sn),rxbufsize) - - -/** - * @ingroup Socket_register_access_function - * @brief Get @ref Sn_RXBUF_SIZE register - * @param (uint8_t)sn Socket number. It should be 0 ~ 7. - * @return uint8_t. Value of @ref Sn_RXBUF_SIZE. - * @sa setSn_RXBUF_SIZE() - */ -#define getSn_RXBUF_SIZE(sn) \ - WIZCHIP_READ(Sn_RXBUF_SIZE(sn)) - -/** - * @ingroup Socket_register_access_function - * @brief Set @ref Sn_TXBUF_SIZE register - * @param (uint8_t)sn Socket number. It should be 0 ~ 7. - * @param (uint8_t)txbufsize Value to set @ref Sn_TXBUF_SIZE - * @sa getSn_TXBUF_SIZE() - */ -#define setSn_TXBUF_SIZE(sn, txbufsize) \ - WIZCHIP_WRITE(Sn_TXBUF_SIZE(sn), txbufsize) - -/** - * @ingroup Socket_register_access_function - * @brief Get @ref Sn_TXBUF_SIZE register - * @param (uint8_t)sn Socket number. It should be 0 ~ 7. - * @return uint8_t. Value of @ref Sn_TXBUF_SIZE. - * @sa setSn_TXBUF_SIZE() - */ -#define getSn_TXBUF_SIZE(sn) \ - WIZCHIP_READ(Sn_TXBUF_SIZE(sn)) - -/** - * @ingroup Socket_register_access_function - * @brief Get @ref Sn_TX_FSR register - * @param (uint8_t)sn Socket number. It should be 0 ~ 7. - * @return uint16_t. Value of @ref Sn_TX_FSR. - */ -uint16_t getSn_TX_FSR(uint8_t sn); - -/** - * @ingroup Socket_register_access_function - * @brief Get @ref Sn_TX_RD register - * @param (uint8_t)sn Socket number. It should be 0 ~ 7. - * @return uint16_t. Value of @ref Sn_TX_RD. - */ -#define getSn_TX_RD(sn) \ - ((WIZCHIP_READ(Sn_TX_RD(sn)) << 8) + WIZCHIP_READ(WIZCHIP_OFFSET_INC(Sn_TX_RD(sn),1))) - -/** - * @ingroup Socket_register_access_function - * @brief Set @ref Sn_TX_WR register - * @param (uint8_t)sn Socket number. It should be 0 ~ 7. - * @param (uint16_t)txwr Value to set @ref Sn_TX_WR - * @sa GetSn_TX_WR() - */ -#define setSn_TX_WR(sn, txwr) { \ - WIZCHIP_WRITE(Sn_TX_WR(sn), (uint8_t)(txwr>>8)); \ - WIZCHIP_WRITE(WIZCHIP_OFFSET_INC(Sn_TX_WR(sn),1), (uint8_t) txwr); \ - } - -/** - * @ingroup Socket_register_access_function - * @brief Get @ref Sn_TX_WR register - * @param (uint8_t)sn Socket number. It should be 0 ~ 7. - * @return uint16_t. Value of @ref Sn_TX_WR. - * @sa setSn_TX_WR() - */ -#define getSn_TX_WR(sn) \ - ((WIZCHIP_READ(Sn_TX_WR(sn)) << 8) + WIZCHIP_READ(WIZCHIP_OFFSET_INC(Sn_TX_WR(sn),1))) - - -/** - * @ingroup Socket_register_access_function - * @brief Get @ref Sn_RX_RSR register - * @param (uint8_t)sn Socket number. It should be 0 ~ 7. - * @return uint16_t. Value of @ref Sn_RX_RSR. - */ -uint16_t getSn_RX_RSR(uint8_t sn); - - -/** - * @ingroup Socket_register_access_function - * @brief Set @ref Sn_RX_RD register - * @param (uint8_t)sn Socket number. It should be 0 ~ 7. - * @param (uint16_t)rxrd Value to set @ref Sn_RX_RD - * @sa getSn_RX_RD() - */ -#define setSn_RX_RD(sn, rxrd) { \ - WIZCHIP_WRITE(Sn_RX_RD(sn), (uint8_t)(rxrd>>8)); \ - WIZCHIP_WRITE(WIZCHIP_OFFSET_INC(Sn_RX_RD(sn),1), (uint8_t) rxrd); \ - } - -/** - * @ingroup Socket_register_access_function - * @brief Get @ref Sn_RX_RD register - * @param (uint8_t)sn Socket number. It should be 0 ~ 7. - * @regurn uint16_t. Value of @ref Sn_RX_RD. - * @sa setSn_RX_RD() - */ -#define getSn_RX_RD(sn) \ - ((WIZCHIP_READ(Sn_RX_RD(sn)) << 8) + WIZCHIP_READ(WIZCHIP_OFFSET_INC(Sn_RX_RD(sn),1))) - -/** - * @ingroup Socket_register_access_function - * @brief Get @ref Sn_RX_WR register - * @param (uint8_t)sn Socket number. It should be 0 ~ 7. - * @return uint16_t. Value of @ref Sn_RX_WR. - */ -#define getSn_RX_WR(sn) \ - ((WIZCHIP_READ(Sn_RX_WR(sn)) << 8) + WIZCHIP_READ(WIZCHIP_OFFSET_INC(Sn_RX_WR(sn),1))) - - -/** - * @ingroup Socket_register_access_function - * @brief Set @ref Sn_FRAG register - * @param (uint8_t)sn Socket number. It should be 0 ~ 7. - * @param (uint16_t)frag Value to set @ref Sn_FRAG - * @sa getSn_FRAD() - */ -#define setSn_FRAG(sn, frag) { \ - WIZCHIP_WRITE(Sn_FRAG(sn), (uint8_t)(frag >>8)); \ - WIZCHIP_WRITE(WIZCHIP_OFFSET_INC(Sn_FRAG(sn),1), (uint8_t) frag); \ - } - -/** - * @ingroup Socket_register_access_function - * @brief Get @ref Sn_FRAG register - * @param (uint8_t)sn Socket number. It should be 0 ~ 7. - * @return uint16_t. Value of @ref Sn_FRAG. - * @sa setSn_FRAG() - */ -#define getSn_FRAG(sn) \ - ((WIZCHIP_READ(Sn_FRAG(sn)) << 8) + WIZCHIP_READ(WIZCHIP_OFFSET_INC(Sn_FRAG(sn),1))) - -/** - * @ingroup Socket_register_access_function - * @brief Set @ref Sn_KPALVTR register - * @param (uint8_t)sn Socket number. It should be 0 ~ 7. - * @param (uint8_t)kpalvt Value to set @ref Sn_KPALVTR - * @sa getSn_KPALVTR() - */ -#define setSn_KPALVTR(sn, kpalvt) \ - WIZCHIP_WRITE(Sn_KPALVTR(sn), kpalvt) - -/** - * @ingroup Socket_register_access_function - * @brief Get @ref Sn_KPALVTR register - * @param (uint8_t)sn Socket number. It should be 0 ~ 7. - * @return uint8_t. Value of @ref Sn_KPALVTR. - * @sa setSn_KPALVTR() - */ -#define getSn_KPALVTR(sn) \ - WIZCHIP_READ(Sn_KPALVTR(sn)) - -////////////////////////////////////// - -///////////////////////////////////// -// Sn_TXBUF & Sn_RXBUF IO function // -///////////////////////////////////// -/** - * @brief Gets the max buffer size of socket sn passed as parameter. - * @param (uint8_t)sn Socket number. It should be 0 ~ 7. - * @return uint16_t. Value of Socket n RX max buffer size. - */ -#define getSn_RxMAX(sn) \ - (getSn_RXBUF_SIZE(sn) << 10) - -/** - * @brief Gets the max buffer size of socket sn passed as parameters. - * @param (uint8_t)sn Socket number. It should be 0 ~ 7. - * @return uint16_t. Value of Socket n TX max buffer size. - */ -//uint16_t getSn_TxMAX(uint8_t sn); -#define getSn_TxMAX(sn) \ - (getSn_TXBUF_SIZE(sn) << 10) - -/** - * @ingroup Basic_IO_function - * @brief It copies data to internal TX memory - * - * @details This function reads the Tx write pointer register and after that, - * it copies the wizdata(pointer buffer) of the length of len(variable) bytes to internal TX memory - * and updates the Tx write pointer register. - * This function is being called by send() and sendto() function also. - * - * @note User should read upper byte first and lower byte later to get proper value. - * @param (uint8_t)sn Socket number. It should be 0 ~ 7. - * @param wizdata Pointer buffer to write data - * @param len Data length - * @sa wiz_recv_data() - */ -void wiz_send_data(uint8_t sn, uint8_t *wizdata, uint16_t len); - -/** - * @ingroup Basic_IO_function - * @brief It copies data to your buffer from internal RX memory - * - * @details This function read the Rx read pointer register and after that, - * it copies the received data from internal RX memory - * to wizdata(pointer variable) of the length of len(variable) bytes. - * This function is being called by recv() also. - * - * @note User should read upper byte first and lower byte later to get proper value. - * @param (uint8_t)sn Socket number. It should be 0 ~ 7. - * @param wizdata Pointer buffer to read data - * @param len Data length - * @sa wiz_send_data() - */ -void wiz_recv_data(uint8_t sn, uint8_t *wizdata, uint16_t len); - -/** - * @ingroup Basic_IO_function - * @brief It discard the received data in RX memory. - * @details It discards the data of the length of len(variable) bytes in internal RX memory. - * @param (uint8_t)sn Socket number. It should be 0 ~ 7. - * @param len Data length - */ -void wiz_recv_ignore(uint8_t sn, uint16_t len); - -#endif // _W5500_H_ diff --git a/drivers/wiznet5k/ethernet/wizchip_conf.c b/drivers/wiznet5k/ethernet/wizchip_conf.c deleted file mode 100644 index 3e54d2c90b..0000000000 --- a/drivers/wiznet5k/ethernet/wizchip_conf.c +++ /dev/null @@ -1,662 +0,0 @@ -//****************************************************************************/ -//! -//! \file wizchip_conf.c -//! \brief WIZCHIP Config Header File. -//! \version 1.0.1 -//! \date 2013/10/21 -//! \par Revision history -//! <2014/05/01> V1.0.1 Refer to M20140501 -//! 1. Explicit type casting in wizchip_bus_readbyte() & wizchip_bus_writebyte() -// Issued by Mathias ClauBen. -//! uint32_t type converts into ptrdiff_t first. And then recoverting it into uint8_t* -//! For remove the warning when pointer type size is not 32bit. -//! If ptrdiff_t doesn't support in your complier, You should must replace ptrdiff_t into your suitable pointer type. -//! <2013/10/21> 1st Release -//! \author MidnightCow -//! \copyright -//! -//! Copyright (c) 2013, WIZnet Co., LTD. -//! All rights reserved. -//! -//! Redistribution and use in source and binary forms, with or without -//! modification, are permitted provided that the following conditions -//! are met: -//! -//! * Redistributions of source code must retain the above copyright -//! notice, this list of conditions and the following disclaimer. -//! * Redistributions in binary form must reproduce the above copyright -//! notice, this list of conditions and the following disclaimer in the -//! documentation and/or other materials provided with the distribution. -//! * Neither the name of the nor the names of its -//! contributors may be used to endorse or promote products derived -//! from this software without specific prior written permission. -//! -//! THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" -//! AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -//! IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE -//! ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE -//! LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR -//! CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF -//! SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS -//! INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN -//! CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) -//! ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF -//! THE POSSIBILITY OF SUCH DAMAGE. -// -//*****************************************************************************/ -//A20140501 : for use the type - ptrdiff_t -#include -// - -#include "wizchip_conf.h" -#include "socket.h" - -/** - * @brief Default function to enable interrupt. - * @note This function help not to access wrong address. If you do not describe this function or register any functions, - * null function is called. - */ -void wizchip_cris_enter(void) {}; -/** - * @brief Default function to disable interrupt. - * @note This function help not to access wrong address. If you do not describe this function or register any functions, - * null function is called. - */ -void wizchip_cris_exit(void) {}; -/** - * @brief Default function to select chip. - * @note This function help not to access wrong address. If you do not describe this function or register any functions, - * null function is called. - */ -void wizchip_cs_select(void) {}; -/** - * @brief Default function to deselect chip. - * @note This function help not to access wrong address. If you do not describe this function or register any functions, - * null function is called. - */ -void wizchip_cs_deselect(void) {}; -/** - * @brief Default function to read in direct or indirect interface. - * @note This function help not to access wrong address. If you do not describe this function or register any functions, - * null function is called. - */ - //M20140501 : Explict pointer type casting -//uint8_t wizchip_bus_readbyte(uint32_t AddrSel) { return * ((volatile uint8_t *) AddrSel); }; -uint8_t wizchip_bus_readbyte(uint32_t AddrSel) { return * ((volatile uint8_t *)((ptrdiff_t) AddrSel)); }; -/** - * @brief Default function to write in direct or indirect interface. - * @note This function help not to access wrong address. If you do not describe this function or register any functions, - * null function is called. - */ - -//M20140501 : Explict pointer type casting -//void wizchip_bus_writebyte(uint32_t AddrSel, uint8_t wb) { *((volatile uint8_t*) AddrSel) = wb; }; -void wizchip_bus_writebyte(uint32_t AddrSel, uint8_t wb) { *((volatile uint8_t*)((ptrdiff_t)AddrSel)) = wb; }; - -/** - * @brief Default function to read in SPI interface. - * @note This function help not to access wrong address. If you do not describe this function or register any functions, - * null function is called. - */ -void wizchip_spi_readbytes(uint8_t *buf, uint32_t len) {} -/** - * @brief Default function to write in SPI interface. - * @note This function help not to access wrong address. If you do not describe this function or register any functions, - * null function is called. - */ -void wizchip_spi_writebytes(const uint8_t *buf, uint32_t len) {} - -/** - * @\ref _WIZCHIP instance - */ -_WIZCHIP WIZCHIP = - { - .id = _WIZCHIP_ID_, - .if_mode = _WIZCHIP_IO_MODE_, - .CRIS._enter = wizchip_cris_enter, - .CRIS._exit = wizchip_cris_exit, - .CS._select = wizchip_cs_select, - .CS._deselect = wizchip_cs_deselect, - .IF.BUS._read_byte = wizchip_bus_readbyte, - .IF.BUS._write_byte = wizchip_bus_writebyte -// .IF.SPI._read_byte = wizchip_spi_readbyte, -// .IF.SPI._write_byte = wizchip_spi_writebyte - }; - -#if _WIZCHIP_ == 5200 // for W5200 ARP errata -static uint8_t _SUBN_[4]; // subnet -#endif -static uint8_t _DNS_[4]; // DNS server ip address -static dhcp_mode _DHCP_; // DHCP mode - -void reg_wizchip_cris_cbfunc(void(*cris_en)(void), void(*cris_ex)(void)) -{ - if(!cris_en || !cris_ex) - { - WIZCHIP.CRIS._enter = wizchip_cris_enter; - WIZCHIP.CRIS._exit = wizchip_cris_exit; - } - else - { - WIZCHIP.CRIS._enter = cris_en; - WIZCHIP.CRIS._exit = cris_ex; - } -} - -void reg_wizchip_cs_cbfunc(void(*cs_sel)(void), void(*cs_desel)(void)) -{ - if(!cs_sel || !cs_desel) - { - WIZCHIP.CS._select = wizchip_cs_select; - WIZCHIP.CS._deselect = wizchip_cs_deselect; - } - else - { - WIZCHIP.CS._select = cs_sel; - WIZCHIP.CS._deselect = cs_desel; - } -} - -void reg_wizchip_bus_cbfunc(uint8_t(*bus_rb)(uint32_t addr), void (*bus_wb)(uint32_t addr, uint8_t wb)) -{ - while(!(WIZCHIP.if_mode & _WIZCHIP_IO_MODE_BUS_)); - - if(!bus_rb || !bus_wb) - { - WIZCHIP.IF.BUS._read_byte = wizchip_bus_readbyte; - WIZCHIP.IF.BUS._write_byte = wizchip_bus_writebyte; - } - else - { - WIZCHIP.IF.BUS._read_byte = bus_rb; - WIZCHIP.IF.BUS._write_byte = bus_wb; - } -} - -void reg_wizchip_spi_cbfunc(void (*spi_rb)(uint8_t *, uint32_t), void (*spi_wb)(const uint8_t *, uint32_t)) -{ - while(!(WIZCHIP.if_mode & _WIZCHIP_IO_MODE_SPI_)); - - if(!spi_rb || !spi_wb) - { - WIZCHIP.IF.SPI._read_bytes = wizchip_spi_readbytes; - WIZCHIP.IF.SPI._write_bytes = wizchip_spi_writebytes; - } - else - { - WIZCHIP.IF.SPI._read_bytes = spi_rb; - WIZCHIP.IF.SPI._write_bytes = spi_wb; - } -} - -int8_t ctlwizchip(ctlwizchip_type cwtype, void* arg) -{ - uint8_t tmp = 0; - uint8_t* ptmp[2] = {0,0}; - switch(cwtype) - { - case CW_RESET_WIZCHIP: - wizchip_sw_reset(); - break; - case CW_INIT_WIZCHIP: - if(arg != 0) - { - ptmp[0] = (uint8_t*)arg; - ptmp[1] = ptmp[0] + _WIZCHIP_SOCK_NUM_; - } - return wizchip_init(ptmp[0], ptmp[1]); - case CW_CLR_INTERRUPT: - wizchip_clrinterrupt(*((intr_kind*)arg)); - break; - case CW_GET_INTERRUPT: - *((intr_kind*)arg) = wizchip_getinterrupt(); - break; - case CW_SET_INTRMASK: - wizchip_setinterruptmask(*((intr_kind*)arg)); - break; - case CW_GET_INTRMASK: - *((intr_kind*)arg) = wizchip_getinterruptmask(); - break; - #if _WIZCHIP_ > 5100 - case CW_SET_INTRTIME: - setINTLEVEL(*(uint16_t*)arg); - break; - case CW_GET_INTRTIME: - *(uint16_t*)arg = getINTLEVEL(); - break; - #endif - case CW_GET_ID: - ((uint8_t*)arg)[0] = WIZCHIP.id[0]; - ((uint8_t*)arg)[1] = WIZCHIP.id[1]; - ((uint8_t*)arg)[2] = WIZCHIP.id[2]; - ((uint8_t*)arg)[3] = WIZCHIP.id[3]; - ((uint8_t*)arg)[4] = WIZCHIP.id[4]; - ((uint8_t*)arg)[5] = 0; - break; - #if _WIZCHIP_ == 5500 - case CW_RESET_PHY: - wizphy_reset(); - break; - case CW_SET_PHYCONF: - wizphy_setphyconf((wiz_PhyConf*)arg); - break; - case CW_GET_PHYCONF: - wizphy_getphyconf((wiz_PhyConf*)arg); - break; - case CW_GET_PHYSTATUS: - break; - case CW_SET_PHYPOWMODE: - return wizphy_setphypmode(*(uint8_t*)arg); - #endif - case CW_GET_PHYPOWMODE: - tmp = wizphy_getphypmode(); - if((int8_t)tmp == -1) return -1; - *(uint8_t*)arg = tmp; - break; - case CW_GET_PHYLINK: - tmp = wizphy_getphylink(); - if((int8_t)tmp == -1) return -1; - *(uint8_t*)arg = tmp; - break; - default: - return -1; - } - return 0; -} - - -int8_t ctlnetwork(ctlnetwork_type cntype, void* arg) -{ - - switch(cntype) - { - case CN_SET_NETINFO: - wizchip_setnetinfo((wiz_NetInfo*)arg); - break; - case CN_GET_NETINFO: - wizchip_getnetinfo((wiz_NetInfo*)arg); - break; - case CN_SET_NETMODE: - return wizchip_setnetmode(*(netmode_type*)arg); - case CN_GET_NETMODE: - *(netmode_type*)arg = wizchip_getnetmode(); - break; - case CN_SET_TIMEOUT: - wizchip_settimeout((wiz_NetTimeout*)arg); - break; - case CN_GET_TIMEOUT: - wizchip_gettimeout((wiz_NetTimeout*)arg); - break; - default: - return -1; - } - return 0; -} - -void wizchip_sw_reset(void) -{ - uint8_t gw[4], sn[4], sip[4]; - uint8_t mac[6]; - getSHAR(mac); - getGAR(gw); getSUBR(sn); getSIPR(sip); - setMR(MR_RST); - getMR(); // for delay - setSHAR(mac); - setGAR(gw); - setSUBR(sn); - setSIPR(sip); -} - -int8_t wizchip_init(uint8_t* txsize, uint8_t* rxsize) -{ - int8_t i; - int8_t tmp = 0; - wizchip_sw_reset(); - if(txsize) - { - tmp = 0; - for(i = 0 ; i < _WIZCHIP_SOCK_NUM_; i++) - tmp += txsize[i]; - if(tmp > 16) return -1; - for(i = 0 ; i < _WIZCHIP_SOCK_NUM_; i++) - setSn_TXBUF_SIZE(i, txsize[i]); - } - if(rxsize) - { - tmp = 0; - for(i = 0 ; i < _WIZCHIP_SOCK_NUM_; i++) - tmp += rxsize[i]; - if(tmp > 16) return -1; - for(i = 0 ; i < _WIZCHIP_SOCK_NUM_; i++) - setSn_RXBUF_SIZE(i, rxsize[i]); - } - - WIZCHIP_EXPORT(socket_reset)(); - - return 0; -} - -void wizchip_clrinterrupt(intr_kind intr) -{ - uint8_t ir = (uint8_t)intr; - uint8_t sir = (uint8_t)((uint16_t)intr >> 8); -#if _WIZCHIP_ < 5500 - ir |= (1<<4); // IK_WOL -#endif -#if _WIZCHIP_ == 5200 - ir |= (1 << 6); -#endif - -#if _WIZCHIP_ < 5200 - sir &= 0x0F; -#endif - -#if _WIZCHIP_ == 5100 - ir |= sir; - setIR(ir); -#else - setIR(ir); - setSIR(sir); -#endif -} - -intr_kind wizchip_getinterrupt(void) -{ - uint8_t ir = 0; - uint8_t sir = 0; - uint16_t ret = 0; -#if _WIZCHIP_ == 5100 - ir = getIR(); - sir = ir 0x0F; -#else - ir = getIR(); - sir = getSIR(); -#endif - -#if _WIZCHIP_ < 5500 - ir &= ~(1<<4); // IK_WOL -#endif -#if _WIZCHIP_ == 5200 - ir &= ~(1 << 6); -#endif - ret = sir; - ret = (ret << 8) + ir; - return (intr_kind)ret; -} - -void wizchip_setinterruptmask(intr_kind intr) -{ - uint8_t imr = (uint8_t)intr; - uint8_t simr = (uint8_t)((uint16_t)intr >> 8); -#if _WIZCHIP_ < 5500 - imr &= ~(1<<4); // IK_WOL -#endif -#if _WIZCHIP_ == 5200 - imr &= ~(1 << 6); -#endif - -#if _WIZCHIP_ < 5200 - simr &= 0x0F; -#endif - -#if _WIZCHIP_ == 5100 - imr |= simr; - setIMR(imr); -#else - setIMR(imr); - setSIMR(simr); -#endif -} - -intr_kind wizchip_getinterruptmask(void) -{ - uint8_t imr = 0; - uint8_t simr = 0; - uint16_t ret = 0; -#if _WIZCHIP_ == 5100 - imr = getIMR(); - simr = imr 0x0F; -#else - imr = getIMR(); - simr = getSIMR(); -#endif - -#if _WIZCHIP_ < 5500 - imr &= ~(1<<4); // IK_WOL -#endif -#if _WIZCHIP_ == 5200 - imr &= ~(1 << 6); // IK_DEST_UNREACH -#endif - ret = simr; - ret = (ret << 8) + imr; - return (intr_kind)ret; -} - -int8_t wizphy_getphylink(void) -{ - int8_t tmp; -#if _WIZCHIP_ == 5200 - if(getPHYSTATUS() & PHYSTATUS_LINK) - tmp = PHY_LINK_ON; - else - tmp = PHY_LINK_OFF; -#elif _WIZCHIP_ == 5500 - if(getPHYCFGR() & PHYCFGR_LNK_ON) - tmp = PHY_LINK_ON; - else - tmp = PHY_LINK_OFF; -#else - tmp = -1; -#endif - return tmp; -} - -#if _WIZCHIP_ > 5100 - -int8_t wizphy_getphypmode(void) -{ - int8_t tmp = 0; - #if _WIZCHIP_ == 5200 - if(getPHYSTATUS() & PHYSTATUS_POWERDOWN) - tmp = PHY_POWER_DOWN; - else - tmp = PHY_POWER_NORM; - #elif _WIZCHIP_ == 5500 - if(getPHYCFGR() & PHYCFGR_OPMDC_PDOWN) - tmp = PHY_POWER_DOWN; - else - tmp = PHY_POWER_NORM; - #else - tmp = -1; - #endif - return tmp; -} -#endif - -#if _WIZCHIP_ == 5500 -void wizphy_reset(void) -{ - uint8_t tmp = getPHYCFGR(); - tmp &= PHYCFGR_RST; - setPHYCFGR(tmp); - tmp = getPHYCFGR(); - tmp |= ~PHYCFGR_RST; - setPHYCFGR(tmp); -} - -void wizphy_setphyconf(wiz_PhyConf* phyconf) -{ - uint8_t tmp = 0; - if(phyconf->by == PHY_CONFBY_SW) - tmp |= PHYCFGR_OPMD; - else - tmp &= ~PHYCFGR_OPMD; - if(phyconf->mode == PHY_MODE_AUTONEGO) - tmp |= PHYCFGR_OPMDC_ALLA; - else - { - if(phyconf->duplex == PHY_DUPLEX_FULL) - { - if(phyconf->speed == PHY_SPEED_100) - tmp |= PHYCFGR_OPMDC_100F; - else - tmp |= PHYCFGR_OPMDC_10F; - } - else - { - if(phyconf->speed == PHY_SPEED_100) - tmp |= PHYCFGR_OPMDC_100H; - else - tmp |= PHYCFGR_OPMDC_10H; - } - } - setPHYCFGR(tmp); - wizphy_reset(); -} - -void wizphy_getphyconf(wiz_PhyConf* phyconf) -{ - uint8_t tmp = 0; - tmp = getPHYCFGR(); - phyconf->by = (tmp & PHYCFGR_OPMD) ? PHY_CONFBY_SW : PHY_CONFBY_HW; - switch(tmp & PHYCFGR_OPMDC_ALLA) - { - case PHYCFGR_OPMDC_ALLA: - case PHYCFGR_OPMDC_100FA: - phyconf->mode = PHY_MODE_AUTONEGO; - break; - default: - phyconf->mode = PHY_MODE_MANUAL; - break; - } - switch(tmp & PHYCFGR_OPMDC_ALLA) - { - case PHYCFGR_OPMDC_100FA: - case PHYCFGR_OPMDC_100F: - case PHYCFGR_OPMDC_100H: - phyconf->speed = PHY_SPEED_100; - break; - default: - phyconf->speed = PHY_SPEED_10; - break; - } - switch(tmp & PHYCFGR_OPMDC_ALLA) - { - case PHYCFGR_OPMDC_100FA: - case PHYCFGR_OPMDC_100F: - case PHYCFGR_OPMDC_10F: - phyconf->duplex = PHY_DUPLEX_FULL; - break; - default: - phyconf->duplex = PHY_DUPLEX_HALF; - break; - } -} - -void wizphy_getphystat(wiz_PhyConf* phyconf) -{ - uint8_t tmp = getPHYCFGR(); - phyconf->duplex = (tmp & PHYCFGR_DPX_FULL) ? PHY_DUPLEX_FULL : PHY_DUPLEX_HALF; - phyconf->speed = (tmp & PHYCFGR_SPD_100) ? PHY_SPEED_100 : PHY_SPEED_10; -} - -int8_t wizphy_setphypmode(uint8_t pmode) -{ - uint8_t tmp = 0; - tmp = getPHYCFGR(); - if((tmp & PHYCFGR_OPMD)== 0) return -1; - tmp &= ~PHYCFGR_OPMDC_ALLA; - if( pmode == PHY_POWER_DOWN) - tmp |= PHYCFGR_OPMDC_PDOWN; - else - tmp |= PHYCFGR_OPMDC_ALLA; - setPHYCFGR(tmp); - wizphy_reset(); - tmp = getPHYCFGR(); - if( pmode == PHY_POWER_DOWN) - { - if(tmp & PHYCFGR_OPMDC_PDOWN) return 0; - } - else - { - if(tmp & PHYCFGR_OPMDC_ALLA) return 0; - } - return -1; -} -#endif - - -void wizchip_setnetinfo(wiz_NetInfo* pnetinfo) -{ - setSHAR(pnetinfo->mac); - setGAR(pnetinfo->gw); - setSUBR(pnetinfo->sn); - setSIPR(pnetinfo->ip); -#if _WIZCHIP_ == 5200 // for W5200 ARP errata - _SUBN_[0] = pnetinfo->sn[0]; - _SUBN_[1] = pnetinfo->sn[1]; - _SUBN_[2] = pnetinfo->sn[2]; - _SUBN_[3] = pnetinfo->sn[3]; -#endif - _DNS_[0] = pnetinfo->dns[0]; - _DNS_[1] = pnetinfo->dns[1]; - _DNS_[2] = pnetinfo->dns[2]; - _DNS_[3] = pnetinfo->dns[3]; - _DHCP_ = pnetinfo->dhcp; -} - -void wizchip_getnetinfo(wiz_NetInfo* pnetinfo) -{ - getSHAR(pnetinfo->mac); - getGAR(pnetinfo->gw); - getSUBR(pnetinfo->sn); - getSIPR(pnetinfo->ip); -#if _WIZCHIP_ == 5200 // for W5200 ARP errata - pnetinfo->sn[0] = _SUBN_[0]; - pnetinfo->sn[1] = _SUBN_[1]; - pnetinfo->sn[2] = _SUBN_[2]; - pnetinfo->sn[3] = _SUBN_[3]; -#endif - pnetinfo->dns[0]= _DNS_[0]; - pnetinfo->dns[1]= _DNS_[1]; - pnetinfo->dns[2]= _DNS_[2]; - pnetinfo->dns[3]= _DNS_[3]; - pnetinfo->dhcp = _DHCP_; -} - -#if _WIZCHIP_ == 5200 // for W5200 ARP errata -uint8_t *wizchip_getsubn(void) { - return _SUBN_; -} -#endif - -int8_t wizchip_setnetmode(netmode_type netmode) -{ - uint8_t tmp = 0; -#if _WIZCHIP_ != 5500 - if(netmode & ~(NM_WAKEONLAN | NM_PPPOE | NM_PINGBLOCK)) return -1; -#else - if(netmode & ~(NM_WAKEONLAN | NM_PPPOE | NM_PINGBLOCK | NM_FORCEARP)) return -1; -#endif - tmp = getMR(); - tmp |= (uint8_t)netmode; - setMR(tmp); - return 0; -} - -netmode_type wizchip_getnetmode(void) -{ - return (netmode_type) getMR(); -} - -void wizchip_settimeout(wiz_NetTimeout* nettime) -{ - setRCR(nettime->retry_cnt); - setRTR(nettime->time_100us); -} - -void wizchip_gettimeout(wiz_NetTimeout* nettime) -{ - nettime->retry_cnt = getRCR(); - nettime->time_100us = getRTR(); -} diff --git a/drivers/wiznet5k/ethernet/wizchip_conf.h b/drivers/wiznet5k/ethernet/wizchip_conf.h deleted file mode 100644 index 55c79ae0a1..0000000000 --- a/drivers/wiznet5k/ethernet/wizchip_conf.h +++ /dev/null @@ -1,552 +0,0 @@ -//***************************************************************************** -// -//! \file wizchip_conf.h -//! \brief WIZCHIP Config Header File. -//! \version 1.0.0 -//! \date 2013/10/21 -//! \par Revision history -//! <2013/10/21> 1st Release -//! \author MidnightCow -//! \copyright -//! -//! Copyright (c) 2013, WIZnet Co., LTD. -//! All rights reserved. -//! -//! Redistribution and use in source and binary forms, with or without -//! modification, are permitted provided that the following conditions -//! are met: -//! -//! * Redistributions of source code must retain the above copyright -//! notice, this list of conditions and the following disclaimer. -//! * Redistributions in binary form must reproduce the above copyright -//! notice, this list of conditions and the following disclaimer in the -//! documentation and/or other materials provided with the distribution. -//! * Neither the name of the nor the names of its -//! contributors may be used to endorse or promote products derived -//! from this software without specific prior written permission. -//! -//! THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" -//! AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -//! IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE -//! ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE -//! LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR -//! CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF -//! SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS -//! INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN -//! CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) -//! ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF -//! THE POSSIBILITY OF SUCH DAMAGE. -// -//***************************************************************************** - -/** - * @defgroup extra_functions 2. WIZnet Extra Functions - * - * @brief These functions is optional function. It could be replaced at WIZCHIP I/O function because they were made by WIZCHIP I/O functions. - * @details There are functions of configuring WIZCHIP, network, interrupt, phy, network information and timer. \n - * - */ - -#ifndef _WIZCHIP_CONF_H_ -#define _WIZCHIP_CONF_H_ - -#include -/** - * @brief Select WIZCHIP. - * @todo You should select one, \b 5100, \b 5200 ,\b 5500 or etc. \n\n - * ex> #define \_WIZCHIP_ 5500 - */ -#define _WIZCHIP_ 5200 // 5100, 5200, 5500 - -#define _WIZCHIP_IO_MODE_NONE_ 0x0000 -#define _WIZCHIP_IO_MODE_BUS_ 0x0100 /**< Bus interface mode */ -#define _WIZCHIP_IO_MODE_SPI_ 0x0200 /**< SPI interface mode */ -//#define _WIZCHIP_IO_MODE_IIC_ 0x0400 -//#define _WIZCHIP_IO_MODE_SDIO_ 0x0800 -// Add to -// - -#define _WIZCHIP_IO_MODE_BUS_DIR_ (_WIZCHIP_IO_MODE_BUS_ + 1) /**< BUS interface mode for direct */ -#define _WIZCHIP_IO_MODE_BUS_INDIR_ (_WIZCHIP_IO_MODE_BUS_ + 2) /**< BUS interface mode for indirect */ - -#define _WIZCHIP_IO_MODE_SPI_VDM_ (_WIZCHIP_IO_MODE_SPI_ + 1) /**< SPI interface mode for variable length data*/ -#define _WIZCHIP_IO_MODE_SPI_FDM_ (_WIZCHIP_IO_MODE_SPI_ + 2) /**< SPI interface mode for fixed length data mode*/ - - -#if (_WIZCHIP_ == 5100) - #define _WIZCHIP_ID_ "W5100\0" -/** - * @brief Define interface mode. - * @todo you should select interface mode as chip. Select one of @ref \_WIZCHIP_IO_MODE_SPI_ , @ref \_WIZCHIP_IO_MODE_BUS_DIR_ or @ref \_WIZCHIP_IO_MODE_BUS_INDIR_ - */ - -// #define _WIZCHIP_IO_MODE_ _WIZCHIP_IO_MODE_BUS_DIR_ -// #define _WIZCHIP_IO_MODE_ _WIZCHIP_IO_MODE_BUS_INDIR_ - #define _WIZCHIP_IO_MODE_ _WIZCHIP_IO_MODE_SPI_ - -#elif (_WIZCHIP_ == 5200) - #define _WIZCHIP_ID_ "W5200\0" -/** - * @brief Define interface mode. - * @todo you should select interface mode as chip. Select one of @ref \_WIZCHIP_IO_MODE_SPI_ or @ref \_WIZCHIP_IO_MODE_BUS_INDIR_ - */ -// #define _WIZCHIP_IO_MODE_ _WIZCHIP_IO_MODE_BUS_INDIR_ - #define _WIZCHIP_IO_MODE_ _WIZCHIP_IO_MODE_SPI_ - #include "w5200/w5200.h" -#elif (_WIZCHIP_ == 5500) - #define _WIZCHIP_ID_ "W5500\0" - -/** - * @brief Define interface mode. \n - * @todo Should select interface mode as chip. - * - @ref \_WIZCHIP_IO_MODE_SPI_ \n - * -@ref \_WIZCHIP_IO_MODE_SPI_VDM_ : Valid only in @ref \_WIZCHIP_ == 5500 \n - * -@ref \_WIZCHIP_IO_MODE_SPI_FDM_ : Valid only in @ref \_WIZCHIP_ == 5500 \n - * - @ref \_WIZCHIP_IO_MODE_BUS_ \n - * - @ref \_WIZCHIP_IO_MODE_BUS_DIR_ \n - * - @ref \_WIZCHIP_IO_MODE_BUS_INDIR_ \n - * - Others will be defined in future. \n\n - * ex> #define \_WIZCHIP_IO_MODE_ \_WIZCHIP_IO_MODE_SPI_VDM_ - * - */ - //#define _WIZCHIP_IO_MODE_ _WIZCHIP_IO_MODE_SPI_FDM_ - #define _WIZCHIP_IO_MODE_ _WIZCHIP_IO_MODE_SPI_VDM_ - #include "w5500/w5500.h" -#else - #error "Unknown defined _WIZCHIP_. You should define one of 5100, 5200, and 5500 !!!" -#endif - -#ifndef _WIZCHIP_IO_MODE_ - #error "Undefined _WIZCHIP_IO_MODE_. You should define it !!!" -#endif - -/** - * @brief Define I/O base address when BUS IF mode. - * @todo Should re-define it to fit your system when BUS IF Mode (@ref \_WIZCHIP_IO_MODE_BUS_, - * @ref \_WIZCHIP_IO_MODE_BUS_DIR_, @ref \_WIZCHIP_IO_MODE_BUS_INDIR_). \n\n - * ex> #define \_WIZCHIP_IO_BASE_ 0x00008000 - */ -#define _WIZCHIP_IO_BASE_ 0x00000000 // - -#if _WIZCHIP_IO_MODE_ & _WIZCHIP_IO_MODE_BUS - #ifndef _WIZCHIP_IO_BASE_ - #error "You should be define _WIZCHIP_IO_BASE to fit your system memory map." - #endif -#endif - -#if _WIZCHIP_ > 5100 - #define _WIZCHIP_SOCK_NUM_ 8 ///< The count of independant socket of @b WIZCHIP -#else - #define _WIZCHIP_SOCK_NUM_ 4 ///< The count of independant socket of @b WIZCHIP -#endif - - -/******************************************************** -* WIZCHIP BASIC IF functions for SPI, SDIO, I2C , ETC. -*********************************************************/ -/** - * @ingroup DATA_TYPE - * @brief The set of callback functions for W5500:@ref WIZCHIP_IO_Functions W5200:@ref WIZCHIP_IO_Functions_W5200 - */ -typedef struct __WIZCHIP -{ - uint16_t if_mode; ///< host interface mode - uint8_t id[6]; ///< @b WIZCHIP ID such as @b 5100, @b 5200, @b 5500, and so on. - /** - * The set of critical section callback func. - */ - struct _CRIS - { - void (*_enter) (void); ///< crtical section enter - void (*_exit) (void); ///< critial section exit - }CRIS; - /** - * The set of @ref\_WIZCHIP_ select control callback func. - */ - struct _CS - { - void (*_select) (void); ///< @ref \_WIZCHIP_ selected - void (*_deselect)(void); ///< @ref \_WIZCHIP_ deselected - }CS; - /** - * The set of interface IO callback func. - */ - union _IF - { - /** - * For BUS interface IO - */ - struct - { - uint8_t (*_read_byte) (uint32_t AddrSel); - void (*_write_byte) (uint32_t AddrSel, uint8_t wb); - }BUS; - /** - * For SPI interface IO - */ - struct - { - void (*_read_bytes) (uint8_t *buf, uint32_t len); - void (*_write_bytes) (const uint8_t *buf, uint32_t len); - }SPI; - // To be added - // - }IF; -}_WIZCHIP; - -extern _WIZCHIP WIZCHIP; - -/** - * @ingroup DATA_TYPE - * WIZCHIP control type enumration used in @ref ctlwizchip(). - */ -typedef enum -{ - CW_RESET_WIZCHIP, ///< Resets WIZCHIP by softly - CW_INIT_WIZCHIP, ///< Inializes to WIZCHIP with SOCKET buffer size 2 or 1 dimension array typed uint8_t. - CW_GET_INTERRUPT, ///< Get Interrupt status of WIZCHIP - CW_CLR_INTERRUPT, ///< Clears interrupt - CW_SET_INTRMASK, ///< Masks interrupt - CW_GET_INTRMASK, ///< Get interrupt mask - CW_SET_INTRTIME, ///< Set interval time between the current and next interrupt. - CW_GET_INTRTIME, ///< Set interval time between the current and next interrupt. - CW_GET_ID, ///< Gets WIZCHIP name. - -#if _WIZCHIP_ == 5500 - CW_RESET_PHY, ///< Resets internal PHY. Valid Only W5000 - CW_SET_PHYCONF, ///< When PHY configured by interal register, PHY operation mode (Manual/Auto, 10/100, Half/Full). Valid Only W5000 - CW_GET_PHYCONF, ///< Get PHY operation mode in interal register. Valid Only W5000 - CW_GET_PHYSTATUS, ///< Get real PHY status on operating. Valid Only W5000 - CW_SET_PHYPOWMODE, ///< Set PHY power mode as noraml and down when PHYSTATUS.OPMD == 1. Valid Only W5000 -#endif - CW_GET_PHYPOWMODE, ///< Get PHY Power mode as down or normal - CW_GET_PHYLINK ///< Get PHY Link status -}ctlwizchip_type; - -/** - * @ingroup DATA_TYPE - * Network control type enumration used in @ref ctlnetwork(). - */ -typedef enum -{ - CN_SET_NETINFO, ///< Set Network with @ref wiz_NetInfo - CN_GET_NETINFO, ///< Get Network with @ref wiz_NetInfo - CN_SET_NETMODE, ///< Set network mode as WOL, PPPoE, Ping Block, and Force ARP mode - CN_GET_NETMODE, ///< Get network mode as WOL, PPPoE, Ping Block, and Force ARP mode - CN_SET_TIMEOUT, ///< Set network timeout as retry count and time. - CN_GET_TIMEOUT, ///< Get network timeout as retry count and time. -}ctlnetwork_type; - -/** - * @ingroup DATA_TYPE - * Interrupt kind when CW_SET_INTRRUPT, CW_GET_INTERRUPT, CW_SET_INTRMASK - * and CW_GET_INTRMASK is used in @ref ctlnetwork(). - * It can be used with OR operation. - */ -typedef enum -{ -#if _WIZCHIP_ > 5200 - IK_WOL = (1 << 4), ///< Wake On Lan by receiving the magic packet. Valid in W500. -#endif - - IK_PPPOE_TERMINATED = (1 << 5), ///< PPPoE Disconnected - -#if _WIZCHIP_ != 5200 - IK_DEST_UNREACH = (1 << 6), ///< Destination IP & Port Unreable, No use in W5200 -#endif - - IK_IP_CONFLICT = (1 << 7), ///< IP conflict occurred - - IK_SOCK_0 = (1 << 8), ///< Socket 0 interrupt - IK_SOCK_1 = (1 << 9), ///< Socket 1 interrupt - IK_SOCK_2 = (1 << 10), ///< Socket 2 interrupt - IK_SOCK_3 = (1 << 11), ///< Socket 3 interrupt -#if _WIZCHIP_ > 5100 - IK_SOCK_4 = (1 << 12), ///< Socket 4 interrupt, No use in 5100 - IK_SOCK_5 = (1 << 13), ///< Socket 5 interrupt, No use in 5100 - IK_SOCK_6 = (1 << 14), ///< Socket 6 interrupt, No use in 5100 - IK_SOCK_7 = (1 << 15), ///< Socket 7 interrupt, No use in 5100 -#endif - -#if _WIZCHIP_ > 5100 - IK_SOCK_ALL = (0xFF << 8) ///< All Socket interrpt -#else - IK_SOCK_ALL = (0x0F << 8) ///< All Socket interrpt -#endif -}intr_kind; - -#define PHY_CONFBY_HW 0 ///< Configured PHY operation mode by HW pin -#define PHY_CONFBY_SW 1 ///< Configured PHY operation mode by SW register -#define PHY_MODE_MANUAL 0 ///< Configured PHY operation mode with user setting. -#define PHY_MODE_AUTONEGO 1 ///< Configured PHY operation mode with auto-negotiation -#define PHY_SPEED_10 0 ///< Link Speed 10 -#define PHY_SPEED_100 1 ///< Link Speed 100 -#define PHY_DUPLEX_HALF 0 ///< Link Half-Duplex -#define PHY_DUPLEX_FULL 1 ///< Link Full-Duplex -#define PHY_LINK_OFF 0 ///< Link Off -#define PHY_LINK_ON 1 ///< Link On -#define PHY_POWER_NORM 0 ///< PHY power normal mode -#define PHY_POWER_DOWN 1 ///< PHY power down mode - - -#if _WIZCHIP_ == 5500 -/** - * @ingroup DATA_TYPE - * It configures PHY configuration when CW_SET PHYCONF or CW_GET_PHYCONF in W5500, - * and it indicates the real PHY status configured by HW or SW in all WIZCHIP. \n - * Valid only in W5500. - */ -typedef struct wiz_PhyConf_t -{ - uint8_t by; ///< set by @ref PHY_CONFBY_HW or @ref PHY_CONFBY_SW - uint8_t mode; ///< set by @ref PHY_MODE_MANUAL or @ref PHY_MODE_AUTONEGO - uint8_t speed; ///< set by @ref PHY_SPEED_10 or @ref PHY_SPEED_100 - uint8_t duplex; ///< set by @ref PHY_DUPLEX_HALF @ref PHY_DUPLEX_FULL - //uint8_t power; ///< set by @ref PHY_POWER_NORM or @ref PHY_POWER_DOWN - //uint8_t link; ///< Valid only in CW_GET_PHYSTATUS. set by @ref PHY_LINK_ON or PHY_DUPLEX_OFF - }wiz_PhyConf; -#endif - -/** - * @ingroup DATA_TYPE - * It used in setting dhcp_mode of @ref wiz_NetInfo. - */ -typedef enum -{ - NETINFO_STATIC = 1, ///< Static IP configuration by manually. - NETINFO_DHCP ///< Dynamic IP configruation from a DHCP sever -}dhcp_mode; - -/** - * @ingroup DATA_TYPE - * Network Information for WIZCHIP - */ -typedef struct wiz_NetInfo_t -{ - uint8_t mac[6]; ///< Source Mac Address - uint8_t ip[4]; ///< Source IP Address - uint8_t sn[4]; ///< Subnet Mask - uint8_t gw[4]; ///< Gateway IP Address - uint8_t dns[4]; ///< DNS server IP Address - dhcp_mode dhcp; ///< 1 - Static, 2 - DHCP -}wiz_NetInfo; - -/** - * @ingroup DATA_TYPE - * Network mode - */ -typedef enum -{ -#if _WIZCHIP_ == 5500 - NM_FORCEARP = (1<<1), ///< Force to APP send whenever udp data is sent. Valid only in W5500 -#endif - NM_WAKEONLAN = (1<<5), ///< Wake On Lan - NM_PINGBLOCK = (1<<4), ///< Block ping-request - NM_PPPOE = (1<<3), ///< PPPoE mode -}netmode_type; - -/** - * @ingroup DATA_TYPE - * Used in CN_SET_TIMEOUT or CN_GET_TIMEOUT of @ref ctlwizchip() for timeout configruation. - */ -typedef struct wiz_NetTimeout_t -{ - uint8_t retry_cnt; ///< retry count - uint16_t time_100us; ///< time unit 100us -}wiz_NetTimeout; - -/** - *@brief Registers call back function for critical section of I/O functions such as - *\ref WIZCHIP_READ, @ref WIZCHIP_WRITE, @ref WIZCHIP_READ_BUF and @ref WIZCHIP_WRITE_BUF. - *@param cris_en : callback function for critical section enter. - *@param cris_ex : callback function for critical section exit. - *@todo Describe @ref WIZCHIP_CRITICAL_ENTER and @ref WIZCHIP_CRITICAL_EXIT marco or register your functions. - *@note If you do not describe or register, default functions(@ref wizchip_cris_enter & @ref wizchip_cris_exit) is called. - */ -void reg_wizchip_cris_cbfunc(void(*cris_en)(void), void(*cris_ex)(void)); - - -/** - *@brief Registers call back function for WIZCHIP select & deselect. - *@param cs_sel : callback function for WIZCHIP select - *@param cs_desel : callback fucntion for WIZCHIP deselect - *@todo Describe @ref wizchip_cs_select and @ref wizchip_cs_deselect function or register your functions. - *@note If you do not describe or register, null function is called. - */ -void reg_wizchip_cs_cbfunc(void(*cs_sel)(void), void(*cs_desel)(void)); - -/** - *@brief Registers call back function for bus interface. - *@param bus_rb : callback function to read byte data using system bus - *@param bus_wb : callback function to write byte data using system bus - *@todo Describe @ref wizchip_bus_readbyte and @ref wizchip_bus_writebyte function - *or register your functions. - *@note If you do not describe or register, null function is called. - */ -void reg_wizchip_bus_cbfunc(uint8_t (*bus_rb)(uint32_t addr), void (*bus_wb)(uint32_t addr, uint8_t wb)); - -/** - *@brief Registers call back function for SPI interface. - *@param spi_rb : callback function to read byte usig SPI - *@param spi_wb : callback function to write byte usig SPI - *@todo Describe \ref wizchip_spi_readbyte and \ref wizchip_spi_writebyte function - *or register your functions. - *@note If you do not describe or register, null function is called. - */ -void reg_wizchip_spi_cbfunc(void (*spi_rb)(uint8_t *, uint32_t), void (*spi_wb)(const uint8_t *, uint32_t)); - -/** - * @ingroup extra_functions - * @brief Controls to the WIZCHIP. - * @details Resets WIZCHIP & internal PHY, Configures PHY mode, Monitor PHY(Link,Speed,Half/Full/Auto), - * controls interrupt & mask and so on. - * @param cwtype : Decides to the control type - * @param arg : arg type is dependent on cwtype. - * @return 0 : Success \n - * -1 : Fail because of invalid \ref ctlwizchip_type or unsupported \ref ctlwizchip_type in WIZCHIP - */ -int8_t ctlwizchip(ctlwizchip_type cwtype, void* arg); - -/** - * @ingroup extra_functions - * @brief Controls to network. - * @details Controls to network environment, mode, timeout and so on. - * @param cntype : Input. Decides to the control type - * @param arg : Inout. arg type is dependent on cntype. - * @return -1 : Fail because of invalid \ref ctlnetwork_type or unsupported \ref ctlnetwork_type in WIZCHIP \n - * 0 : Success - */ -int8_t ctlnetwork(ctlnetwork_type cntype, void* arg); - - -/* - * The following functions are implemented for internal use. - * but You can call these functions for code size reduction instead of ctlwizchip() and ctlnetwork(). - */ - -/** - * @ingroup extra_functions - * @brief Reset WIZCHIP by softly. - */ -void wizchip_sw_reset(void); - -/** - * @ingroup extra_functions - * @brief Initializes WIZCHIP with socket buffer size - * @param txsize Socket tx buffer sizes. If null, initialized the default size 2KB. - * @param rxsize Socket rx buffer sizes. If null, initialized the default size 2KB. - * @return 0 : succcess \n - * -1 : fail. Invalid buffer size - */ -int8_t wizchip_init(uint8_t* txsize, uint8_t* rxsize); - -/** - * @ingroup extra_functions - * @brief Clear Interrupt of WIZCHIP. - * @param intr : @ref intr_kind value operated OR. It can type-cast to uint16_t. - */ -void wizchip_clrinterrupt(intr_kind intr); - -/** - * @ingroup extra_functions - * @brief Get Interrupt of WIZCHIP. - * @return @ref intr_kind value operated OR. It can type-cast to uint16_t. - */ -intr_kind wizchip_getinterrupt(void); - -/** - * @ingroup extra_functions - * @brief Mask or Unmask Interrupt of WIZCHIP. - * @param intr : @ref intr_kind value operated OR. It can type-cast to uint16_t. - */ -void wizchip_setinterruptmask(intr_kind intr); - -/** - * @ingroup extra_functions - * @brief Get Interrupt mask of WIZCHIP. - * @return : The operated OR vaule of @ref intr_kind. It can type-cast to uint16_t. - */ -intr_kind wizchip_getinterruptmask(void); - -#if _WIZCHIP_ > 5100 - int8_t wizphy_getphylink(void); ///< get the link status of phy in WIZCHIP. No use in W5100 - int8_t wizphy_getphypmode(void); ///< get the power mode of PHY in WIZCHIP. No use in W5100 -#endif - -#if _WIZCHIP_ == 5500 - void wizphy_reset(void); ///< Reset phy. Vailid only in W5500 -/** - * @ingroup extra_functions - * @brief Set the phy information for WIZCHIP without power mode - * @param phyconf : @ref wiz_PhyConf - */ - void wizphy_setphyconf(wiz_PhyConf* phyconf); - /** - * @ingroup extra_functions - * @brief Get phy configuration information. - * @param phyconf : @ref wiz_PhyConf - */ - void wizphy_getphyconf(wiz_PhyConf* phyconf); - /** - * @ingroup extra_functions - * @brief Get phy status. - * @param phyconf : @ref wiz_PhyConf - */ - void wizphy_getphystat(wiz_PhyConf* phyconf); - /** - * @ingroup extra_functions - * @brief set the power mode of phy inside WIZCHIP. Refer to @ref PHYCFGR in W5500, @ref PHYSTATUS in W5200 - * @param pmode Settig value of power down mode. - */ - int8_t wizphy_setphypmode(uint8_t pmode); -#endif - -/** -* @ingroup extra_functions - * @brief Set the network information for WIZCHIP - * @param pnetinfo : @ref wizNetInfo - */ -void wizchip_setnetinfo(wiz_NetInfo* pnetinfo); - -/** - * @ingroup extra_functions - * @brief Get the network information for WIZCHIP - * @param pnetinfo : @ref wizNetInfo - */ -void wizchip_getnetinfo(wiz_NetInfo* pnetinfo); - -#if _WIZCHIP_ == 5200 // for W5200 ARP errata -uint8_t *wizchip_getsubn(void); -#endif - -/** - * @ingroup extra_functions - * @brief Set the network mode such WOL, PPPoE, Ping Block, and etc. - * @param pnetinfo Value of network mode. Refer to @ref netmode_type. - */ -int8_t wizchip_setnetmode(netmode_type netmode); - -/** - * @ingroup extra_functions - * @brief Get the network mode such WOL, PPPoE, Ping Block, and etc. - * @return Value of network mode. Refer to @ref netmode_type. - */ -netmode_type wizchip_getnetmode(void); - -/** - * @ingroup extra_functions - * @brief Set retry time value(@ref RTR) and retry count(@ref RCR). - * @details @ref RTR configures the retransmission timeout period and @ref RCR configures the number of time of retransmission. - * @param nettime @ref RTR value and @ref RCR value. Refer to @ref wiz_NetTimeout. - */ -void wizchip_settimeout(wiz_NetTimeout* nettime); - -/** - * @ingroup extra_functions - * @brief Get retry time value(@ref RTR) and retry count(@ref RCR). - * @details @ref RTR configures the retransmission timeout period and @ref RCR configures the number of time of retransmission. - * @param nettime @ref RTR value and @ref RCR value. Refer to @ref wiz_NetTimeout. - */ -void wizchip_gettimeout(wiz_NetTimeout* nettime); - -#endif // _WIZCHIP_CONF_H_ diff --git a/drivers/wiznet5k/internet/dhcp/dhcp.c b/drivers/wiznet5k/internet/dhcp/dhcp.c deleted file mode 100644 index 5747582599..0000000000 --- a/drivers/wiznet5k/internet/dhcp/dhcp.c +++ /dev/null @@ -1,978 +0,0 @@ -//***************************************************************************** -// -//! \file dhcp.c -//! \brief DHCP APIs implement file. -//! \details Processig DHCP protocol as DISCOVER, OFFER, REQUEST, ACK, NACK and DECLINE. -//! \version 1.1.0 -//! \date 2013/11/18 -//! \par Revision history -//! <2013/11/18> 1st Release -//! <2012/12/20> V1.1.0 -//! 1. Optimize code -//! 2. Add reg_dhcp_cbfunc() -//! 3. Add DHCP_stop() -//! 4. Integrate check_DHCP_state() & DHCP_run() to DHCP_run() -//! 5. Don't care system endian -//! 6. Add comments -//! <2012/12/26> V1.1.1 -//! 1. Modify variable declaration: dhcp_tick_1s is declared volatile for code optimization -//! \author Eric Jung & MidnightCow -//! \copyright -//! -//! Copyright (c) 2013, WIZnet Co., LTD. -//! All rights reserved. -//! -//! Redistribution and use in source and binary forms, with or without -//! modification, are permitted provided that the following conditions -//! are met: -//! -//! * Redistributions of source code must retain the above copyright -//! notice, this list of conditions and the following disclaimer. -//! * Redistributions in binary form must reproduce the above copyright -//! notice, this list of conditions and the following disclaimer in the -//! documentation and/or other materials provided with the distribution. -//! * Neither the name of the nor the names of its -//! contributors may be used to endorse or promote products derived -//! from this software without specific prior written permission. -//! -//! THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" -//! AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -//! IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE -//! ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE -//! LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR -//! CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF -//! SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS -//! INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN -//! CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) -//! ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF -//! THE POSSIBILITY OF SUCH DAMAGE. -// -//***************************************************************************** - -//#include "Ethernet/socket.h" -//#include "Internet/DHCP/dhcp.h" -#include "../../Ethernet/socket.h" -#include "dhcp.h" - -/* If you want to display debug & processing message, Define _DHCP_DEBUG_ in dhcp.h */ - -#ifdef _DHCP_DEBUG_ - #include -#endif - -/* DHCP state machine. */ -#define STATE_DHCP_INIT 0 ///< Initialize -#define STATE_DHCP_DISCOVER 1 ///< send DISCOVER and wait OFFER -#define STATE_DHCP_REQUEST 2 ///< send REQEUST and wait ACK or NACK -#define STATE_DHCP_LEASED 3 ///< ReceiveD ACK and IP leased -#define STATE_DHCP_REREQUEST 4 ///< send REQUEST for maintaining leased IP -#define STATE_DHCP_RELEASE 5 ///< No use -#define STATE_DHCP_STOP 6 ///< Stop processing DHCP - -#define DHCP_FLAGSBROADCAST 0x8000 ///< The broadcast value of flags in @ref RIP_MSG -#define DHCP_FLAGSUNICAST 0x0000 ///< The unicast value of flags in @ref RIP_MSG - -/* DHCP message OP code */ -#define DHCP_BOOTREQUEST 1 ///< Request Message used in op of @ref RIP_MSG -#define DHCP_BOOTREPLY 2 ///< Reply Message used i op of @ref RIP_MSG - -/* DHCP message type */ -#define DHCP_DISCOVER 1 ///< DISCOVER message in OPT of @ref RIP_MSG -#define DHCP_OFFER 2 ///< OFFER message in OPT of @ref RIP_MSG -#define DHCP_REQUEST 3 ///< REQUEST message in OPT of @ref RIP_MSG -#define DHCP_DECLINE 4 ///< DECLINE message in OPT of @ref RIP_MSG -#define DHCP_ACK 5 ///< ACK message in OPT of @ref RIP_MSG -#define DHCP_NAK 6 ///< NACK message in OPT of @ref RIP_MSG -#define DHCP_RELEASE 7 ///< RELEASE message in OPT of @ref RIP_MSG. No use -#define DHCP_INFORM 8 ///< INFORM message in OPT of @ref RIP_MSG. No use - -#define DHCP_HTYPE10MB 1 ///< Used in type of @ref RIP_MSG -#define DHCP_HTYPE100MB 2 ///< Used in type of @ref RIP_MSG - -#define DHCP_HLENETHERNET 6 ///< Used in hlen of @ref RIP_MSG -#define DHCP_HOPS 0 ///< Used in hops of @ref RIP_MSG -#define DHCP_SECS 0 ///< Used in secs of @ref RIP_MSG - -#define INFINITE_LEASETIME 0xffffffff ///< Infinite lease time - -#define OPT_SIZE 312 /// Max OPT size of @ref RIP_MSG -#define RIP_MSG_SIZE (236+OPT_SIZE) /// Max size of @ref RIP_MSG - -/* - * @brief DHCP option and value (cf. RFC1533) - */ -enum -{ - padOption = 0, - subnetMask = 1, - timerOffset = 2, - routersOnSubnet = 3, - timeServer = 4, - nameServer = 5, - dns = 6, - logServer = 7, - cookieServer = 8, - lprServer = 9, - impressServer = 10, - resourceLocationServer = 11, - hostName = 12, - bootFileSize = 13, - meritDumpFile = 14, - domainName = 15, - swapServer = 16, - rootPath = 17, - extentionsPath = 18, - IPforwarding = 19, - nonLocalSourceRouting = 20, - policyFilter = 21, - maxDgramReasmSize = 22, - defaultIPTTL = 23, - pathMTUagingTimeout = 24, - pathMTUplateauTable = 25, - ifMTU = 26, - allSubnetsLocal = 27, - broadcastAddr = 28, - performMaskDiscovery = 29, - maskSupplier = 30, - performRouterDiscovery = 31, - routerSolicitationAddr = 32, - staticRoute = 33, - trailerEncapsulation = 34, - arpCacheTimeout = 35, - ethernetEncapsulation = 36, - tcpDefaultTTL = 37, - tcpKeepaliveInterval = 38, - tcpKeepaliveGarbage = 39, - nisDomainName = 40, - nisServers = 41, - ntpServers = 42, - vendorSpecificInfo = 43, - netBIOSnameServer = 44, - netBIOSdgramDistServer = 45, - netBIOSnodeType = 46, - netBIOSscope = 47, - xFontServer = 48, - xDisplayManager = 49, - dhcpRequestedIPaddr = 50, - dhcpIPaddrLeaseTime = 51, - dhcpOptionOverload = 52, - dhcpMessageType = 53, - dhcpServerIdentifier = 54, - dhcpParamRequest = 55, - dhcpMsg = 56, - dhcpMaxMsgSize = 57, - dhcpT1value = 58, - dhcpT2value = 59, - dhcpClassIdentifier = 60, - dhcpClientIdentifier = 61, - endOption = 255 -}; - -/* - * @brief DHCP message format - */ -typedef struct { - uint8_t op; ///< @ref DHCP_BOOTREQUEST or @ref DHCP_BOOTREPLY - uint8_t htype; ///< @ref DHCP_HTYPE10MB or @ref DHCP_HTYPE100MB - uint8_t hlen; ///< @ref DHCP_HLENETHERNET - uint8_t hops; ///< @ref DHCP_HOPS - uint32_t xid; ///< @ref DHCP_XID This increase one every DHCP transaction. - uint16_t secs; ///< @ref DHCP_SECS - uint16_t flags; ///< @ref DHCP_FLAGSBROADCAST or @ref DHCP_FLAGSUNICAST - uint8_t ciaddr[4]; ///< @ref Request IP to DHCP sever - uint8_t yiaddr[4]; ///< @ref Offered IP from DHCP server - uint8_t siaddr[4]; ///< No use - uint8_t giaddr[4]; ///< No use - uint8_t chaddr[16]; ///< DHCP client 6bytes MAC address. Others is filled to zero - uint8_t sname[64]; ///< No use - uint8_t file[128]; ///< No use - uint8_t OPT[OPT_SIZE]; ///< Option -} RIP_MSG; - - - -uint8_t DHCP_SOCKET; // Socket number for DHCP - -uint8_t DHCP_SIP[4]; // DHCP Server IP address - -// Network information from DHCP Server -uint8_t OLD_allocated_ip[4] = {0, }; // Previous IP address -uint8_t DHCP_allocated_ip[4] = {0, }; // IP address from DHCP -uint8_t DHCP_allocated_gw[4] = {0, }; // Gateway address from DHCP -uint8_t DHCP_allocated_sn[4] = {0, }; // Subnet mask from DHCP -uint8_t DHCP_allocated_dns[4] = {0, }; // DNS address from DHCP - - -int8_t dhcp_state = STATE_DHCP_INIT; // DHCP state -int8_t dhcp_retry_count = 0; - -uint32_t dhcp_lease_time = INFINITE_LEASETIME; -volatile uint32_t dhcp_tick_1s = 0; // unit 1 second -uint32_t dhcp_tick_next = DHCP_WAIT_TIME ; - -uint32_t DHCP_XID; // Any number - -RIP_MSG* pDHCPMSG; // Buffer pointer for DHCP processing - -uint8_t HOST_NAME[] = DCHP_HOST_NAME; - -uint8_t DHCP_CHADDR[6]; // DHCP Client MAC address. - -/* The default callback function */ -void default_ip_assign(void); -void default_ip_update(void); -void default_ip_conflict(void); - -/* Callback handler */ -void (*dhcp_ip_assign)(void) = default_ip_assign; /* handler to be called when the IP address from DHCP server is first assigned */ -void (*dhcp_ip_update)(void) = default_ip_update; /* handler to be called when the IP address from DHCP server is updated */ -void (*dhcp_ip_conflict)(void) = default_ip_conflict; /* handler to be called when the IP address from DHCP server is conflict */ - -void reg_dhcp_cbfunc(void(*ip_assign)(void), void(*ip_update)(void), void(*ip_conflict)(void)); - - -/* send DISCOVER message to DHCP server */ -void send_DHCP_DISCOVER(void); - -/* send REQEUST message to DHCP server */ -void send_DHCP_REQUEST(void); - -/* send DECLINE message to DHCP server */ -void send_DHCP_DECLINE(void); - -/* IP conflict check by sending ARP-request to leased IP and wait ARP-response. */ -int8_t check_DHCP_leasedIP(void); - -/* check the timeout in DHCP process */ -uint8_t check_DHCP_timeout(void); - -/* Intialize to timeout process. */ -void reset_DHCP_timeout(void); - -/* Parse message as OFFER and ACK and NACK from DHCP server.*/ -int8_t parseDHCPCMSG(void); - -/* The default handler of ip assign first */ -void default_ip_assign(void) -{ - setSIPR(DHCP_allocated_ip); - setSUBR(DHCP_allocated_sn); - setGAR (DHCP_allocated_gw); -} - -/* The default handler of ip changed */ -void default_ip_update(void) -{ - /* WIZchip Software Reset */ - setMR(MR_RST); - getMR(); // for delay - default_ip_assign(); - setSHAR(DHCP_CHADDR); -} - -/* The default handler of ip changed */ -void default_ip_conflict(void) -{ - // WIZchip Software Reset - setMR(MR_RST); - getMR(); // for delay - setSHAR(DHCP_CHADDR); -} - -/* register the call back func. */ -void reg_dhcp_cbfunc(void(*ip_assign)(void), void(*ip_update)(void), void(*ip_conflict)(void)) -{ - dhcp_ip_assign = default_ip_assign; - dhcp_ip_update = default_ip_update; - dhcp_ip_conflict = default_ip_conflict; - if(ip_assign) dhcp_ip_assign = ip_assign; - if(ip_update) dhcp_ip_update = ip_update; - if(ip_conflict) dhcp_ip_conflict = ip_conflict; -} - -/* make the common DHCP message */ -void makeDHCPMSG(void) -{ - uint8_t bk_mac[6]; - uint8_t* ptmp; - uint8_t i; - getSHAR(bk_mac); - pDHCPMSG->op = DHCP_BOOTREQUEST; - pDHCPMSG->htype = DHCP_HTYPE10MB; - pDHCPMSG->hlen = DHCP_HLENETHERNET; - pDHCPMSG->hops = DHCP_HOPS; - ptmp = (uint8_t*)(&pDHCPMSG->xid); - *(ptmp+0) = (uint8_t)((DHCP_XID & 0xFF000000) >> 24); - *(ptmp+1) = (uint8_t)((DHCP_XID & 0x00FF0000) >> 16); - *(ptmp+2) = (uint8_t)((DHCP_XID & 0x0000FF00) >> 8); - *(ptmp+3) = (uint8_t)((DHCP_XID & 0x000000FF) >> 0); - pDHCPMSG->secs = DHCP_SECS; - ptmp = (uint8_t*)(&pDHCPMSG->flags); - *(ptmp+0) = (uint8_t)((DHCP_FLAGSBROADCAST & 0xFF00) >> 8); - *(ptmp+1) = (uint8_t)((DHCP_FLAGSBROADCAST & 0x00FF) >> 0); - - pDHCPMSG->ciaddr[0] = 0; - pDHCPMSG->ciaddr[1] = 0; - pDHCPMSG->ciaddr[2] = 0; - pDHCPMSG->ciaddr[3] = 0; - - pDHCPMSG->yiaddr[0] = 0; - pDHCPMSG->yiaddr[1] = 0; - pDHCPMSG->yiaddr[2] = 0; - pDHCPMSG->yiaddr[3] = 0; - - pDHCPMSG->siaddr[0] = 0; - pDHCPMSG->siaddr[1] = 0; - pDHCPMSG->siaddr[2] = 0; - pDHCPMSG->siaddr[3] = 0; - - pDHCPMSG->giaddr[0] = 0; - pDHCPMSG->giaddr[1] = 0; - pDHCPMSG->giaddr[2] = 0; - pDHCPMSG->giaddr[3] = 0; - - pDHCPMSG->chaddr[0] = DHCP_CHADDR[0]; - pDHCPMSG->chaddr[1] = DHCP_CHADDR[1]; - pDHCPMSG->chaddr[2] = DHCP_CHADDR[2]; - pDHCPMSG->chaddr[3] = DHCP_CHADDR[3]; - pDHCPMSG->chaddr[4] = DHCP_CHADDR[4]; - pDHCPMSG->chaddr[5] = DHCP_CHADDR[5]; - - for (i = 6; i < 16; i++) pDHCPMSG->chaddr[i] = 0; - for (i = 0; i < 64; i++) pDHCPMSG->sname[i] = 0; - for (i = 0; i < 128; i++) pDHCPMSG->file[i] = 0; - - // MAGIC_COOKIE - pDHCPMSG->OPT[0] = (uint8_t)((MAGIC_COOKIE & 0xFF000000) >> 24); - pDHCPMSG->OPT[1] = (uint8_t)((MAGIC_COOKIE & 0x00FF0000) >> 16); - pDHCPMSG->OPT[2] = (uint8_t)((MAGIC_COOKIE & 0x0000FF00) >> 8); - pDHCPMSG->OPT[3] = (uint8_t) (MAGIC_COOKIE & 0x000000FF) >> 0; -} - -/* SEND DHCP DISCOVER */ -void send_DHCP_DISCOVER(void) -{ - uint16_t i; - uint8_t ip[4]; - uint16_t k = 0; - - makeDHCPMSG(); - - k = 4; // because MAGIC_COOKIE already made by makeDHCPMSG() - - // Option Request Param - pDHCPMSG->OPT[k++] = dhcpMessageType; - pDHCPMSG->OPT[k++] = 0x01; - pDHCPMSG->OPT[k++] = DHCP_DISCOVER; - - // Client identifier - pDHCPMSG->OPT[k++] = dhcpClientIdentifier; - pDHCPMSG->OPT[k++] = 0x07; - pDHCPMSG->OPT[k++] = 0x01; - pDHCPMSG->OPT[k++] = DHCP_CHADDR[0]; - pDHCPMSG->OPT[k++] = DHCP_CHADDR[1]; - pDHCPMSG->OPT[k++] = DHCP_CHADDR[2]; - pDHCPMSG->OPT[k++] = DHCP_CHADDR[3]; - pDHCPMSG->OPT[k++] = DHCP_CHADDR[4]; - pDHCPMSG->OPT[k++] = DHCP_CHADDR[5]; - - // host name - pDHCPMSG->OPT[k++] = hostName; - pDHCPMSG->OPT[k++] = 0; // fill zero length of hostname - for(i = 0 ; HOST_NAME[i] != 0; i++) - pDHCPMSG->OPT[k++] = HOST_NAME[i]; - pDHCPMSG->OPT[k++] = DHCP_CHADDR[3]; - pDHCPMSG->OPT[k++] = DHCP_CHADDR[4]; - pDHCPMSG->OPT[k++] = DHCP_CHADDR[5]; - pDHCPMSG->OPT[k - (i+3+1)] = i+3; // length of hostname - - pDHCPMSG->OPT[k++] = dhcpParamRequest; - pDHCPMSG->OPT[k++] = 0x06; // length of request - pDHCPMSG->OPT[k++] = subnetMask; - pDHCPMSG->OPT[k++] = routersOnSubnet; - pDHCPMSG->OPT[k++] = dns; - pDHCPMSG->OPT[k++] = domainName; - pDHCPMSG->OPT[k++] = dhcpT1value; - pDHCPMSG->OPT[k++] = dhcpT2value; - pDHCPMSG->OPT[k++] = endOption; - - for (i = k; i < OPT_SIZE; i++) pDHCPMSG->OPT[i] = 0; - - // send broadcasting packet - ip[0] = 255; - ip[1] = 255; - ip[2] = 255; - ip[3] = 255; - -#ifdef _DHCP_DEBUG_ - printf("> Send DHCP_DISCOVER\r\n"); -#endif - - sendto(DHCP_SOCKET, (uint8_t *)pDHCPMSG, RIP_MSG_SIZE, ip, DHCP_SERVER_PORT); -} - -/* SEND DHCP REQUEST */ -void send_DHCP_REQUEST(void) -{ - int i; - uint8_t ip[4]; - uint16_t k = 0; - - makeDHCPMSG(); - - if(dhcp_state == STATE_DHCP_LEASED || dhcp_state == STATE_DHCP_REREQUEST) - { - *((uint8_t*)(&pDHCPMSG->flags)) = ((DHCP_FLAGSUNICAST & 0xFF00)>> 8); - *((uint8_t*)(&pDHCPMSG->flags)+1) = (DHCP_FLAGSUNICAST & 0x00FF); - pDHCPMSG->ciaddr[0] = DHCP_allocated_ip[0]; - pDHCPMSG->ciaddr[1] = DHCP_allocated_ip[1]; - pDHCPMSG->ciaddr[2] = DHCP_allocated_ip[2]; - pDHCPMSG->ciaddr[3] = DHCP_allocated_ip[3]; - ip[0] = DHCP_SIP[0]; - ip[1] = DHCP_SIP[1]; - ip[2] = DHCP_SIP[2]; - ip[3] = DHCP_SIP[3]; - } - else - { - ip[0] = 255; - ip[1] = 255; - ip[2] = 255; - ip[3] = 255; - } - - k = 4; // because MAGIC_COOKIE already made by makeDHCPMSG() - - // Option Request Param. - pDHCPMSG->OPT[k++] = dhcpMessageType; - pDHCPMSG->OPT[k++] = 0x01; - pDHCPMSG->OPT[k++] = DHCP_REQUEST; - - pDHCPMSG->OPT[k++] = dhcpClientIdentifier; - pDHCPMSG->OPT[k++] = 0x07; - pDHCPMSG->OPT[k++] = 0x01; - pDHCPMSG->OPT[k++] = DHCP_CHADDR[0]; - pDHCPMSG->OPT[k++] = DHCP_CHADDR[1]; - pDHCPMSG->OPT[k++] = DHCP_CHADDR[2]; - pDHCPMSG->OPT[k++] = DHCP_CHADDR[3]; - pDHCPMSG->OPT[k++] = DHCP_CHADDR[4]; - pDHCPMSG->OPT[k++] = DHCP_CHADDR[5]; - - if(ip[3] == 255) // if(dchp_state == STATE_DHCP_LEASED || dchp_state == DHCP_REREQUEST_STATE) - { - pDHCPMSG->OPT[k++] = dhcpRequestedIPaddr; - pDHCPMSG->OPT[k++] = 0x04; - pDHCPMSG->OPT[k++] = DHCP_allocated_ip[0]; - pDHCPMSG->OPT[k++] = DHCP_allocated_ip[1]; - pDHCPMSG->OPT[k++] = DHCP_allocated_ip[2]; - pDHCPMSG->OPT[k++] = DHCP_allocated_ip[3]; - - pDHCPMSG->OPT[k++] = dhcpServerIdentifier; - pDHCPMSG->OPT[k++] = 0x04; - pDHCPMSG->OPT[k++] = DHCP_SIP[0]; - pDHCPMSG->OPT[k++] = DHCP_SIP[1]; - pDHCPMSG->OPT[k++] = DHCP_SIP[2]; - pDHCPMSG->OPT[k++] = DHCP_SIP[3]; - } - - // host name - pDHCPMSG->OPT[k++] = hostName; - pDHCPMSG->OPT[k++] = 0; // length of hostname - for(i = 0 ; HOST_NAME[i] != 0; i++) - pDHCPMSG->OPT[k++] = HOST_NAME[i]; - pDHCPMSG->OPT[k++] = DHCP_CHADDR[3]; - pDHCPMSG->OPT[k++] = DHCP_CHADDR[4]; - pDHCPMSG->OPT[k++] = DHCP_CHADDR[5]; - pDHCPMSG->OPT[k - (i+3+1)] = i+3; // length of hostname - - pDHCPMSG->OPT[k++] = dhcpParamRequest; - pDHCPMSG->OPT[k++] = 0x08; - pDHCPMSG->OPT[k++] = subnetMask; - pDHCPMSG->OPT[k++] = routersOnSubnet; - pDHCPMSG->OPT[k++] = dns; - pDHCPMSG->OPT[k++] = domainName; - pDHCPMSG->OPT[k++] = dhcpT1value; - pDHCPMSG->OPT[k++] = dhcpT2value; - pDHCPMSG->OPT[k++] = performRouterDiscovery; - pDHCPMSG->OPT[k++] = staticRoute; - pDHCPMSG->OPT[k++] = endOption; - - for (i = k; i < OPT_SIZE; i++) pDHCPMSG->OPT[i] = 0; - -#ifdef _DHCP_DEBUG_ - printf("> Send DHCP_REQUEST\r\n"); -#endif - - sendto(DHCP_SOCKET, (uint8_t *)pDHCPMSG, RIP_MSG_SIZE, ip, DHCP_SERVER_PORT); - -} - -/* SEND DHCP DHCPDECLINE */ -void send_DHCP_DECLINE(void) -{ - int i; - uint8_t ip[4]; - uint16_t k = 0; - - makeDHCPMSG(); - - k = 4; // because MAGIC_COOKIE already made by makeDHCPMSG() - - *((uint8_t*)(&pDHCPMSG->flags)) = ((DHCP_FLAGSUNICAST & 0xFF00)>> 8); - *((uint8_t*)(&pDHCPMSG->flags)+1) = (DHCP_FLAGSUNICAST & 0x00FF); - - // Option Request Param. - pDHCPMSG->OPT[k++] = dhcpMessageType; - pDHCPMSG->OPT[k++] = 0x01; - pDHCPMSG->OPT[k++] = DHCP_DECLINE; - - pDHCPMSG->OPT[k++] = dhcpClientIdentifier; - pDHCPMSG->OPT[k++] = 0x07; - pDHCPMSG->OPT[k++] = 0x01; - pDHCPMSG->OPT[k++] = DHCP_CHADDR[0]; - pDHCPMSG->OPT[k++] = DHCP_CHADDR[1]; - pDHCPMSG->OPT[k++] = DHCP_CHADDR[2]; - pDHCPMSG->OPT[k++] = DHCP_CHADDR[3]; - pDHCPMSG->OPT[k++] = DHCP_CHADDR[4]; - pDHCPMSG->OPT[k++] = DHCP_CHADDR[5]; - - pDHCPMSG->OPT[k++] = dhcpRequestedIPaddr; - pDHCPMSG->OPT[k++] = 0x04; - pDHCPMSG->OPT[k++] = DHCP_allocated_ip[0]; - pDHCPMSG->OPT[k++] = DHCP_allocated_ip[1]; - pDHCPMSG->OPT[k++] = DHCP_allocated_ip[2]; - pDHCPMSG->OPT[k++] = DHCP_allocated_ip[3]; - - pDHCPMSG->OPT[k++] = dhcpServerIdentifier; - pDHCPMSG->OPT[k++] = 0x04; - pDHCPMSG->OPT[k++] = DHCP_SIP[0]; - pDHCPMSG->OPT[k++] = DHCP_SIP[1]; - pDHCPMSG->OPT[k++] = DHCP_SIP[2]; - pDHCPMSG->OPT[k++] = DHCP_SIP[3]; - - pDHCPMSG->OPT[k++] = endOption; - - for (i = k; i < OPT_SIZE; i++) pDHCPMSG->OPT[i] = 0; - - //send broadcasting packet - ip[0] = 0xFF; - ip[1] = 0xFF; - ip[2] = 0xFF; - ip[3] = 0xFF; - -#ifdef _DHCP_DEBUG_ - printf("\r\n> Send DHCP_DECLINE\r\n"); -#endif - - sendto(DHCP_SOCKET, (uint8_t *)pDHCPMSG, RIP_MSG_SIZE, ip, DHCP_SERVER_PORT); -} - -/* PARSE REPLY pDHCPMSG */ -int8_t parseDHCPMSG(void) -{ - uint8_t svr_addr[6]; - uint16_t svr_port; - uint16_t len; - - uint8_t * p; - uint8_t * e; - uint8_t type; - uint8_t opt_len; - - if((len = getSn_RX_RSR(DHCP_SOCKET)) > 0) - { - len = recvfrom(DHCP_SOCKET, (uint8_t *)pDHCPMSG, len, svr_addr, &svr_port); - #ifdef _DHCP_DEBUG_ - printf("DHCP message : %d.%d.%d.%d(%d) %d received. \r\n",svr_addr[0],svr_addr[1],svr_addr[2], svr_addr[3],svr_port, len); - #endif - } - else return 0; - if (svr_port == DHCP_SERVER_PORT) { - // compare mac address - if ( (pDHCPMSG->chaddr[0] != DHCP_CHADDR[0]) || (pDHCPMSG->chaddr[1] != DHCP_CHADDR[1]) || - (pDHCPMSG->chaddr[2] != DHCP_CHADDR[2]) || (pDHCPMSG->chaddr[3] != DHCP_CHADDR[3]) || - (pDHCPMSG->chaddr[4] != DHCP_CHADDR[4]) || (pDHCPMSG->chaddr[5] != DHCP_CHADDR[5]) ) - return 0; - type = 0; - p = (uint8_t *)(&pDHCPMSG->op); - p = p + 240; // 240 = sizeof(RIP_MSG) + MAGIC_COOKIE size in RIP_MSG.opt - sizeof(RIP_MSG.opt) - e = p + (len - 240); - - while ( p < e ) { - - switch ( *p ) { - - case endOption : - p = e; // for break while(p < e) - break; - case padOption : - p++; - break; - case dhcpMessageType : - p++; - p++; - type = *p++; - break; - case subnetMask : - p++; - p++; - DHCP_allocated_sn[0] = *p++; - DHCP_allocated_sn[1] = *p++; - DHCP_allocated_sn[2] = *p++; - DHCP_allocated_sn[3] = *p++; - break; - case routersOnSubnet : - p++; - opt_len = *p++; - DHCP_allocated_gw[0] = *p++; - DHCP_allocated_gw[1] = *p++; - DHCP_allocated_gw[2] = *p++; - DHCP_allocated_gw[3] = *p++; - p = p + (opt_len - 4); - break; - case dns : - p++; - opt_len = *p++; - DHCP_allocated_dns[0] = *p++; - DHCP_allocated_dns[1] = *p++; - DHCP_allocated_dns[2] = *p++; - DHCP_allocated_dns[3] = *p++; - p = p + (opt_len - 4); - break; - case dhcpIPaddrLeaseTime : - p++; - opt_len = *p++; - dhcp_lease_time = *p++; - dhcp_lease_time = (dhcp_lease_time << 8) + *p++; - dhcp_lease_time = (dhcp_lease_time << 8) + *p++; - dhcp_lease_time = (dhcp_lease_time << 8) + *p++; - #ifdef _DHCP_DEBUG_ - dhcp_lease_time = 10; - #endif - break; - case dhcpServerIdentifier : - p++; - opt_len = *p++; - DHCP_SIP[0] = *p++; - DHCP_SIP[1] = *p++; - DHCP_SIP[2] = *p++; - DHCP_SIP[3] = *p++; - break; - default : - p++; - opt_len = *p++; - p += opt_len; - break; - } // switch - } // while - } // if - return type; -} - -uint8_t DHCP_run(void) -{ - uint8_t type; - uint8_t ret; - - if(dhcp_state == STATE_DHCP_STOP) return DHCP_STOPPED; - - if(getSn_SR(DHCP_SOCKET) != SOCK_UDP) - socket(DHCP_SOCKET, Sn_MR_UDP, DHCP_CLIENT_PORT, 0x00); - - ret = DHCP_RUNNING; - type = parseDHCPMSG(); - - switch ( dhcp_state ) { - case STATE_DHCP_INIT : - DHCP_allocated_ip[0] = 0; - DHCP_allocated_ip[1] = 0; - DHCP_allocated_ip[2] = 0; - DHCP_allocated_ip[3] = 0; - send_DHCP_DISCOVER(); - dhcp_state = STATE_DHCP_DISCOVER; - break; - case STATE_DHCP_DISCOVER : - if (type == DHCP_OFFER){ -#ifdef _DHCP_DEBUG_ - printf("> Receive DHCP_OFFER\r\n"); -#endif - DHCP_allocated_ip[0] = pDHCPMSG->yiaddr[0]; - DHCP_allocated_ip[1] = pDHCPMSG->yiaddr[1]; - DHCP_allocated_ip[2] = pDHCPMSG->yiaddr[2]; - DHCP_allocated_ip[3] = pDHCPMSG->yiaddr[3]; - - send_DHCP_REQUEST(); - dhcp_state = STATE_DHCP_REQUEST; - } else ret = check_DHCP_timeout(); - break; - - case STATE_DHCP_REQUEST : - if (type == DHCP_ACK) { - -#ifdef _DHCP_DEBUG_ - printf("> Receive DHCP_ACK\r\n"); -#endif - if (check_DHCP_leasedIP()) { - // Network info assignment from DHCP - dhcp_ip_assign(); - reset_DHCP_timeout(); - - dhcp_state = STATE_DHCP_LEASED; - } else { - // IP address conflict occurred - reset_DHCP_timeout(); - dhcp_ip_conflict(); - dhcp_state = STATE_DHCP_INIT; - } - } else if (type == DHCP_NAK) { - -#ifdef _DHCP_DEBUG_ - printf("> Receive DHCP_NACK\r\n"); -#endif - - reset_DHCP_timeout(); - - dhcp_state = STATE_DHCP_DISCOVER; - } else ret = check_DHCP_timeout(); - break; - - case STATE_DHCP_LEASED : - ret = DHCP_IP_LEASED; - if ((dhcp_lease_time != INFINITE_LEASETIME) && ((dhcp_lease_time/2) < dhcp_tick_1s)) { - -#ifdef _DHCP_DEBUG_ - printf("> Maintains the IP address \r\n"); -#endif - - type = 0; - OLD_allocated_ip[0] = DHCP_allocated_ip[0]; - OLD_allocated_ip[1] = DHCP_allocated_ip[1]; - OLD_allocated_ip[2] = DHCP_allocated_ip[2]; - OLD_allocated_ip[3] = DHCP_allocated_ip[3]; - - DHCP_XID++; - - send_DHCP_REQUEST(); - - reset_DHCP_timeout(); - - dhcp_state = STATE_DHCP_REREQUEST; - } - break; - - case STATE_DHCP_REREQUEST : - ret = DHCP_IP_LEASED; - if (type == DHCP_ACK) { - dhcp_retry_count = 0; - if (OLD_allocated_ip[0] != DHCP_allocated_ip[0] || - OLD_allocated_ip[1] != DHCP_allocated_ip[1] || - OLD_allocated_ip[2] != DHCP_allocated_ip[2] || - OLD_allocated_ip[3] != DHCP_allocated_ip[3]) - { - ret = DHCP_IP_CHANGED; - dhcp_ip_update(); - #ifdef _DHCP_DEBUG_ - printf(">IP changed.\r\n"); - #endif - - } - #ifdef _DHCP_DEBUG_ - else printf(">IP is continued.\r\n"); - #endif - reset_DHCP_timeout(); - dhcp_state = STATE_DHCP_LEASED; - } else if (type == DHCP_NAK) { - -#ifdef _DHCP_DEBUG_ - printf("> Receive DHCP_NACK, Failed to maintain ip\r\n"); -#endif - - reset_DHCP_timeout(); - - dhcp_state = STATE_DHCP_DISCOVER; - } else ret = check_DHCP_timeout(); - break; - default : - break; - } - - return ret; -} - -void DHCP_stop(void) -{ - close(DHCP_SOCKET); - dhcp_state = STATE_DHCP_STOP; -} - -uint8_t check_DHCP_timeout(void) -{ - uint8_t ret = DHCP_RUNNING; - - if (dhcp_retry_count < MAX_DHCP_RETRY) { - if (dhcp_tick_next < dhcp_tick_1s) { - - switch ( dhcp_state ) { - case STATE_DHCP_DISCOVER : -// printf("<> state : STATE_DHCP_DISCOVER\r\n"); - send_DHCP_DISCOVER(); - break; - - case STATE_DHCP_REQUEST : -// printf("<> state : STATE_DHCP_REQUEST\r\n"); - - send_DHCP_REQUEST(); - break; - - case STATE_DHCP_REREQUEST : -// printf("<> state : STATE_DHCP_REREQUEST\r\n"); - - send_DHCP_REQUEST(); - break; - - default : - break; - } - - dhcp_tick_1s = 0; - dhcp_tick_next = dhcp_tick_1s + DHCP_WAIT_TIME; - dhcp_retry_count++; - } - } else { // timeout occurred - - switch(dhcp_state) { - case STATE_DHCP_DISCOVER: - dhcp_state = STATE_DHCP_INIT; - ret = DHCP_FAILED; - break; - case STATE_DHCP_REQUEST: - case STATE_DHCP_REREQUEST: - send_DHCP_DISCOVER(); - dhcp_state = STATE_DHCP_DISCOVER; - break; - default : - break; - } - reset_DHCP_timeout(); - } - return ret; -} - -int8_t check_DHCP_leasedIP(void) -{ - uint8_t tmp; - int32_t ret; - - //WIZchip RCR value changed for ARP Timeout count control - tmp = getRCR(); - setRCR(0x03); - - // IP conflict detection : ARP request - ARP reply - // Broadcasting ARP Request for check the IP conflict using UDP sendto() function - ret = sendto(DHCP_SOCKET, (uint8_t *)"CHECK_IP_CONFLICT", 17, DHCP_allocated_ip, 5000); - - // RCR value restore - setRCR(tmp); - - if(ret == SOCKERR_TIMEOUT) { - // UDP send Timeout occurred : allocated IP address is unique, DHCP Success - -#ifdef _DHCP_DEBUG_ - printf("\r\n> Check leased IP - OK\r\n"); -#endif - - return 1; - } else { - // Received ARP reply or etc : IP address conflict occur, DHCP Failed - send_DHCP_DECLINE(); - - ret = dhcp_tick_1s; - while((dhcp_tick_1s - ret) < 2) ; // wait for 1s over; wait to complete to send DECLINE message; - - return 0; - } -} - -void DHCP_init(uint8_t s, uint8_t * buf) -{ - uint8_t zeroip[4] = {0,0,0,0}; - getSHAR(DHCP_CHADDR); - if((DHCP_CHADDR[0] | DHCP_CHADDR[1] | DHCP_CHADDR[2] | DHCP_CHADDR[3] | DHCP_CHADDR[4] | DHCP_CHADDR[5]) == 0x00) - { - // assign temporary mac address, you should be set SHAR before call this function. - DHCP_CHADDR[0] = 0x00; - DHCP_CHADDR[1] = 0x08; - DHCP_CHADDR[2] = 0xdc; - DHCP_CHADDR[3] = 0x00; - DHCP_CHADDR[4] = 0x00; - DHCP_CHADDR[5] = 0x00; - setSHAR(DHCP_CHADDR); - } - - DHCP_SOCKET = s; // SOCK_DHCP - pDHCPMSG = (RIP_MSG*)buf; - DHCP_XID = 0x12345678; - - // WIZchip Netinfo Clear - setSIPR(zeroip); - setSIPR(zeroip); - setGAR(zeroip); - - reset_DHCP_timeout(); - dhcp_state = STATE_DHCP_INIT; -} - - -/* Rset the DHCP timeout count and retry count. */ -void reset_DHCP_timeout(void) -{ - dhcp_tick_1s = 0; - dhcp_tick_next = DHCP_WAIT_TIME; - dhcp_retry_count = 0; -} - -void DHCP_time_handler(void) -{ - dhcp_tick_1s++; -} - -void getIPfromDHCP(uint8_t* ip) -{ - ip[0] = DHCP_allocated_ip[0]; - ip[1] = DHCP_allocated_ip[1]; - ip[2] = DHCP_allocated_ip[2]; - ip[3] = DHCP_allocated_ip[3]; -} - -void getGWfromDHCP(uint8_t* ip) -{ - ip[0] =DHCP_allocated_gw[0]; - ip[1] =DHCP_allocated_gw[1]; - ip[2] =DHCP_allocated_gw[2]; - ip[3] =DHCP_allocated_gw[3]; -} - -void getSNfromDHCP(uint8_t* ip) -{ - ip[0] = DHCP_allocated_sn[0]; - ip[1] = DHCP_allocated_sn[1]; - ip[2] = DHCP_allocated_sn[2]; - ip[3] = DHCP_allocated_sn[3]; -} - -void getDNSfromDHCP(uint8_t* ip) -{ - ip[0] = DHCP_allocated_dns[0]; - ip[1] = DHCP_allocated_dns[1]; - ip[2] = DHCP_allocated_dns[2]; - ip[3] = DHCP_allocated_dns[3]; -} - -uint32_t getDHCPLeasetime(void) -{ - return dhcp_lease_time; -} - - - - diff --git a/drivers/wiznet5k/internet/dhcp/dhcp.h b/drivers/wiznet5k/internet/dhcp/dhcp.h deleted file mode 100644 index ee154d506a..0000000000 --- a/drivers/wiznet5k/internet/dhcp/dhcp.h +++ /dev/null @@ -1,150 +0,0 @@ -//***************************************************************************** -// -//! \file dhcp.h -//! \brief DHCP APIs Header file. -//! \details Processig DHCP protocol as DISCOVER, OFFER, REQUEST, ACK, NACK and DECLINE. -//! \version 1.1.0 -//! \date 2013/11/18 -//! \par Revision history -//! <2013/11/18> 1st Release -//! <2012/12/20> V1.1.0 -//! 1. Move unreferenced DEFINE to dhcp.c -//! <2012/12/26> V1.1.1 -//! \author Eric Jung & MidnightCow -//! \copyright -//! -//! Copyright (c) 2013, WIZnet Co., LTD. -//! All rights reserved. -//! -//! Redistribution and use in source and binary forms, with or without -//! modification, are permitted provided that the following conditions -//! are met: -//! -//! * Redistributions of source code must retain the above copyright -//! notice, this list of conditions and the following disclaimer. -//! * Redistributions in binary form must reproduce the above copyright -//! notice, this list of conditions and the following disclaimer in the -//! documentation and/or other materials provided with the distribution. -//! * Neither the name of the nor the names of its -//! contributors may be used to endorse or promote products derived -//! from this software without specific prior written permission. -//! -//! THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" -//! AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -//! IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE -//! ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE -//! LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR -//! CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF -//! SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS -//! INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN -//! CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) -//! ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF -//! THE POSSIBILITY OF SUCH DAMAGE. -// -//***************************************************************************** -#ifndef _DHCP_H_ -#define _DHCP_H_ - -/* - * @brief - * @details If you want to display debug & processing message, Define _DHCP_DEBUG_ - * @note If defined, it depends on - */ - -//#define _DHCP_DEBUG_ - -/* Retry to processing DHCP */ -#define MAX_DHCP_RETRY 2 ///< Maximum retry count -#define DHCP_WAIT_TIME 10 ///< Wait Time 10s - -/* UDP port numbers for DHCP */ -#define DHCP_SERVER_PORT 67 ///< DHCP server port number -#define DHCP_CLIENT_PORT 68 ///< DHCP client port number - -#define MAGIC_COOKIE 0x63825363 ///< Any number. You can be modified it any number - -#define DCHP_HOST_NAME "WIZnet\0" - -/* - * @brief return value of @ref DHCP_run() - */ -enum -{ - DHCP_FAILED = 0, ///< Processing Fail - DHCP_RUNNING, ///< Processing DHCP protocol - DHCP_IP_ASSIGN, ///< First Occupy IP from DHPC server (if cbfunc == null, act as default default_ip_assign) - DHCP_IP_CHANGED, ///< Change IP address by new IP address from DHCP (if cbfunc == null, act as default default_ip_update) - DHCP_IP_LEASED, ///< Stand by - DHCP_STOPPED ///< Stop processing DHCP protocol -}; - -/* - * @brief DHCP client initialization (outside of the main loop) - * @param s - socket number - * @param buf - buffer for processing DHCP message - */ -void DHCP_init(uint8_t s, uint8_t * buf); - -/* - * @brief DHCP 1s Tick Timer handler - * @note SHOULD BE register to your system 1s Tick timer handler - */ -void DHCP_time_handler(void); - -/* - * @brief Register call back function - * @param ip_assign - callback func when IP is assigned from DHCP server first - * @param ip_update - callback func when IP is changed - * @prarm ip_conflict - callback func when the assigned IP is conflict with others. - */ -void reg_dhcp_cbfunc(void(*ip_assign)(void), void(*ip_update)(void), void(*ip_conflict)(void)); - -/* - * @brief DHCP client in the main loop - * @return The value is as the follow \n - * @ref DHCP_FAILED \n - * @ref DHCP_RUNNING \n - * @ref DHCP_IP_ASSIGN \n - * @ref DHCP_IP_CHANGED \n - * @ref DHCP_IP_LEASED \n - * @ref DHCP_STOPPED \n - * - * @note This function is always called by you main task. - */ -uint8_t DHCP_run(void); - -/* - * @brief Stop DHCP processing - * @note If you want to restart. call DHCP_init() and DHCP_run() - */ -void DHCP_stop(void); - -/* Get Network information assigned from DHCP server */ -/* - * @brief Get IP address - * @param ip - IP address to be returned - */ -void getIPfromDHCP(uint8_t* ip); -/* - * @brief Get Gateway address - * @param ip - Gateway address to be returned - */ -void getGWfromDHCP(uint8_t* ip); -/* - * @brief Get Subnet mask value - * @param ip - Subnet mask to be returned - */ -void getSNfromDHCP(uint8_t* ip); -/* - * @brief Get DNS address - * @param ip - DNS address to be returned - */ -void getDNSfromDHCP(uint8_t* ip); - -/* - * @brief Get the leased time by DHCP sever - * @return unit 1s - */ -uint32_t getDHCPLeasetime(void); - -#endif /* _DHCP_H_ */ diff --git a/drivers/wiznet5k/internet/dns/dns.c b/drivers/wiznet5k/internet/dns/dns.c deleted file mode 100644 index c0ad570c00..0000000000 --- a/drivers/wiznet5k/internet/dns/dns.c +++ /dev/null @@ -1,566 +0,0 @@ -//***************************************************************************** -// -//! \file dns.c -//! \brief DNS APIs Implement file. -//! \details Send DNS query & Receive DNS reponse. \n -//! It depends on stdlib.h & string.h in ansi-c library -//! \version 1.1.0 -//! \date 2013/11/18 -//! \par Revision history -//! <2013/10/21> 1st Release -//! <2013/12/20> V1.1.0 -//! 1. Remove secondary DNS server in DNS_run -//! If 1st DNS_run failed, call DNS_run with 2nd DNS again -//! 2. DNS_timerHandler -> DNS_time_handler -//! 3. Remove the unused define -//! 4. Integrated dns.h dns.c & dns_parse.h dns_parse.c into dns.h & dns.c -//! <2013/12/20> V1.1.0 -//! -//! \author Eric Jung & MidnightCow -//! \copyright -//! -//! Copyright (c) 2013, WIZnet Co., LTD. -//! All rights reserved. -//! -//! Redistribution and use in source and binary forms, with or without -//! modification, are permitted provided that the following conditions -//! are met: -//! -//! * Redistributions of source code must retain the above copyright -//! notice, this list of conditions and the following disclaimer. -//! * Redistributions in binary form must reproduce the above copyright -//! notice, this list of conditions and the following disclaimer in the -//! documentation and/or other materials provided with the distribution. -//! * Neither the name of the nor the names of its -//! contributors may be used to endorse or promote products derived -//! from this software without specific prior written permission. -//! -//! THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" -//! AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -//! IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE -//! ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE -//! LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR -//! CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF -//! SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS -//! INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN -//! CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) -//! ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF -//! THE POSSIBILITY OF SUCH DAMAGE. -// -//***************************************************************************** - -#include -#include - -//#include "Ethernet/socket.h" -//#include "Internet/DNS/dns.h" -#include "../../ethernet/socket.h" -#include "dns.h" - -#ifdef _DNS_DEBUG_ - #include -#endif - -#define INITRTT 2000L /* Initial smoothed response time */ -#define MAXCNAME (MAX_DOMAIN_NAME + (MAX_DOMAIN_NAME>>1)) /* Maximum amount of cname recursion */ - -#define TYPE_A 1 /* Host address */ -#define TYPE_NS 2 /* Name server */ -#define TYPE_MD 3 /* Mail destination (obsolete) */ -#define TYPE_MF 4 /* Mail forwarder (obsolete) */ -#define TYPE_CNAME 5 /* Canonical name */ -#define TYPE_SOA 6 /* Start of Authority */ -#define TYPE_MB 7 /* Mailbox name (experimental) */ -#define TYPE_MG 8 /* Mail group member (experimental) */ -#define TYPE_MR 9 /* Mail rename name (experimental) */ -#define TYPE_NULL 10 /* Null (experimental) */ -#define TYPE_WKS 11 /* Well-known sockets */ -#define TYPE_PTR 12 /* Pointer record */ -#define TYPE_HINFO 13 /* Host information */ -#define TYPE_MINFO 14 /* Mailbox information (experimental)*/ -#define TYPE_MX 15 /* Mail exchanger */ -#define TYPE_TXT 16 /* Text strings */ -#define TYPE_ANY 255 /* Matches any type */ - -#define CLASS_IN 1 /* The ARPA Internet */ - -/* Round trip timing parameters */ -#define AGAIN 8 /* Average RTT gain = 1/8 */ -#define LAGAIN 3 /* Log2(AGAIN) */ -#define DGAIN 4 /* Mean deviation gain = 1/4 */ -#define LDGAIN 2 /* log2(DGAIN) */ - -/* Header for all domain messages */ -struct dhdr -{ - uint16_t id; /* Identification */ - uint8_t qr; /* Query/Response */ -#define QUERY 0 -#define RESPONSE 1 - uint8_t opcode; -#define IQUERY 1 - uint8_t aa; /* Authoratative answer */ - uint8_t tc; /* Truncation */ - uint8_t rd; /* Recursion desired */ - uint8_t ra; /* Recursion available */ - uint8_t rcode; /* Response code */ -#define NO_ERROR 0 -#define FORMAT_ERROR 1 -#define SERVER_FAIL 2 -#define NAME_ERROR 3 -#define NOT_IMPL 4 -#define REFUSED 5 - uint16_t qdcount; /* Question count */ - uint16_t ancount; /* Answer count */ - uint16_t nscount; /* Authority (name server) count */ - uint16_t arcount; /* Additional record count */ -}; - - -uint8_t* pDNSMSG; // DNS message buffer -uint8_t DNS_SOCKET; // SOCKET number for DNS -uint16_t DNS_MSGID; // DNS message ID - -extern uint32_t HAL_GetTick(void); -uint32_t hal_sys_tick; - -/* converts uint16_t from network buffer to a host byte order integer. */ -uint16_t get16(uint8_t * s) -{ - uint16_t i; - i = *s++ << 8; - i = i + *s; - return i; -} - -/* copies uint16_t to the network buffer with network byte order. */ -uint8_t * put16(uint8_t * s, uint16_t i) -{ - *s++ = i >> 8; - *s++ = i; - return s; -} - - -/* - * CONVERT A DOMAIN NAME TO THE HUMAN-READABLE FORM - * - * Description : This function converts a compressed domain name to the human-readable form - * Arguments : msg - is a pointer to the reply message - * compressed - is a pointer to the domain name in reply message. - * buf - is a pointer to the buffer for the human-readable form name. - * len - is the MAX. size of buffer. - * Returns : the length of compressed message - */ -int parse_name(uint8_t * msg, uint8_t * compressed, char * buf, int16_t len) -{ - uint16_t slen; /* Length of current segment */ - uint8_t * cp; - int clen = 0; /* Total length of compressed name */ - int indirect = 0; /* Set if indirection encountered */ - int nseg = 0; /* Total number of segments in name */ - - cp = compressed; - - for (;;) - { - slen = *cp++; /* Length of this segment */ - - if (!indirect) clen++; - - if ((slen & 0xc0) == 0xc0) - { - if (!indirect) - clen++; - indirect = 1; - /* Follow indirection */ - cp = &msg[((slen & 0x3f)<<8) + *cp]; - slen = *cp++; - } - - if (slen == 0) /* zero length == all done */ - break; - - len -= slen + 1; - - if (len < 0) return -1; - - if (!indirect) clen += slen; - - while (slen-- != 0) *buf++ = (char)*cp++; - *buf++ = '.'; - nseg++; - } - - if (nseg == 0) - { - /* Root name; represent as single dot */ - *buf++ = '.'; - len--; - } - - *buf++ = '\0'; - len--; - - return clen; /* Length of compressed message */ -} - -/* - * PARSE QUESTION SECTION - * - * Description : This function parses the question record of the reply message. - * Arguments : msg - is a pointer to the reply message - * cp - is a pointer to the question record. - * Returns : a pointer the to next record. - */ -uint8_t * dns_question(uint8_t * msg, uint8_t * cp) -{ - int len; - char name[MAXCNAME]; - - len = parse_name(msg, cp, name, MAXCNAME); - - - if (len == -1) return 0; - - cp += len; - cp += 2; /* type */ - cp += 2; /* class */ - - return cp; -} - - -/* - * PARSE ANSER SECTION - * - * Description : This function parses the answer record of the reply message. - * Arguments : msg - is a pointer to the reply message - * cp - is a pointer to the answer record. - * Returns : a pointer the to next record. - */ -uint8_t * dns_answer(uint8_t * msg, uint8_t * cp, uint8_t * ip_from_dns) -{ - int len, type; - char name[MAXCNAME]; - - len = parse_name(msg, cp, name, MAXCNAME); - - if (len == -1) return 0; - - cp += len; - type = get16(cp); - cp += 2; /* type */ - cp += 2; /* class */ - cp += 4; /* ttl */ - cp += 2; /* len */ - - - switch (type) - { - case TYPE_A: - /* Just read the address directly into the structure */ - ip_from_dns[0] = *cp++; - ip_from_dns[1] = *cp++; - ip_from_dns[2] = *cp++; - ip_from_dns[3] = *cp++; - break; - case TYPE_CNAME: - case TYPE_MB: - case TYPE_MG: - case TYPE_MR: - case TYPE_NS: - case TYPE_PTR: - /* These types all consist of a single domain name */ - /* convert it to ASCII format */ - len = parse_name(msg, cp, name, MAXCNAME); - if (len == -1) return 0; - - cp += len; - break; - case TYPE_HINFO: - len = *cp++; - cp += len; - - len = *cp++; - cp += len; - break; - case TYPE_MX: - cp += 2; - /* Get domain name of exchanger */ - len = parse_name(msg, cp, name, MAXCNAME); - if (len == -1) return 0; - - cp += len; - break; - case TYPE_SOA: - /* Get domain name of name server */ - len = parse_name(msg, cp, name, MAXCNAME); - if (len == -1) return 0; - - cp += len; - - /* Get domain name of responsible person */ - len = parse_name(msg, cp, name, MAXCNAME); - if (len == -1) return 0; - - cp += len; - - cp += 4; - cp += 4; - cp += 4; - cp += 4; - cp += 4; - break; - case TYPE_TXT: - /* Just stash */ - break; - default: - /* Ignore */ - break; - } - - return cp; -} - -/* - * PARSE THE DNS REPLY - * - * Description : This function parses the reply message from DNS server. - * Arguments : dhdr - is a pointer to the header for DNS message - * buf - is a pointer to the reply message. - * len - is the size of reply message. - * Returns : -1 - Domain name length is too big - * 0 - Fail (Timeout or parse error) - * 1 - Success, - */ -int8_t parseDNSMSG(struct dhdr * pdhdr, uint8_t * pbuf, uint8_t * ip_from_dns) -{ - uint16_t tmp; - uint16_t i; - uint8_t * msg; - uint8_t * cp; - - msg = pbuf; - memset(pdhdr, 0, sizeof(*pdhdr)); - - pdhdr->id = get16(&msg[0]); - tmp = get16(&msg[2]); - if (tmp & 0x8000) pdhdr->qr = 1; - - pdhdr->opcode = (tmp >> 11) & 0xf; - - if (tmp & 0x0400) pdhdr->aa = 1; - if (tmp & 0x0200) pdhdr->tc = 1; - if (tmp & 0x0100) pdhdr->rd = 1; - if (tmp & 0x0080) pdhdr->ra = 1; - - pdhdr->rcode = tmp & 0xf; - pdhdr->qdcount = get16(&msg[4]); - pdhdr->ancount = get16(&msg[6]); - pdhdr->nscount = get16(&msg[8]); - pdhdr->arcount = get16(&msg[10]); - - - /* Now parse the variable length sections */ - cp = &msg[12]; - - /* Question section */ - for (i = 0; i < pdhdr->qdcount; i++) - { - cp = dns_question(msg, cp); - if(!cp) - { -#ifdef _DNS_DEBUG_ - printf("MAX_DOMAIN_NAME is too small, it should be redefined in dns.h\r\n"); -#endif - return -1; - } - } - - /* Answer section */ - for (i = 0; i < pdhdr->ancount; i++) - { - cp = dns_answer(msg, cp, ip_from_dns); - if(!cp) - { -#ifdef _DNS_DEBUG_ - printf("MAX_DOMAIN_NAME is too small, it should be redefined in dns.h\r\n"); -#endif - return -1; - } - - } - - /* Name server (authority) section */ - for (i = 0; i < pdhdr->nscount; i++) - { - ; - } - - /* Additional section */ - for (i = 0; i < pdhdr->arcount; i++) - { - ; - } - - if(pdhdr->rcode == 0) return 1; // No error - else return 0; -} - - -/* - * MAKE DNS QUERY MESSAGE - * - * Description : This function makes DNS query message. - * Arguments : op - Recursion desired - * name - is a pointer to the domain name. - * buf - is a pointer to the buffer for DNS message. - * len - is the MAX. size of buffer. - * Returns : the pointer to the DNS message. - */ -int16_t dns_makequery(uint16_t op, char * name, uint8_t * buf, uint16_t len) -{ - uint8_t *cp; - char *cp1; - char sname[MAXCNAME]; - char *dname; - uint16_t p; - uint16_t dlen; - - cp = buf; - - DNS_MSGID++; - cp = put16(cp, DNS_MSGID); - p = (op << 11) | 0x0100; /* Recursion desired */ - cp = put16(cp, p); - cp = put16(cp, 1); - cp = put16(cp, 0); - cp = put16(cp, 0); - cp = put16(cp, 0); - - strcpy(sname, name); - dname = sname; - dlen = strlen(dname); - for (;;) - { - /* Look for next dot */ - cp1 = strchr(dname, '.'); - - if (cp1 != NULL) len = cp1 - dname; /* More to come */ - else len = dlen; /* Last component */ - - *cp++ = len; /* Write length of component */ - if (len == 0) break; - - /* Copy component up to (but not including) dot */ - memcpy(cp, dname, len); - cp += len; - if (cp1 == NULL) - { - *cp++ = 0; /* Last one; write null and finish */ - break; - } - dname += len+1; - dlen -= len+1; - } - - cp = put16(cp, 0x0001); /* type */ - cp = put16(cp, 0x0001); /* class */ - - return ((int16_t)((uint32_t)(cp) - (uint32_t)(buf))); -} - -/* - * CHECK DNS TIMEOUT - * - * Description : This function check the DNS timeout - * Arguments : None. - * Returns : -1 - timeout occurred, 0 - timer over, but no timeout, 1 - no timer over, no timeout occur - * Note : timeout : retry count and timer both over. - */ - -int8_t check_DNS_timeout(void) -{ - static uint8_t retry_count; - - uint32_t tick = HAL_GetTick(); - if(tick - hal_sys_tick >= DNS_WAIT_TIME * 1000) - { - hal_sys_tick = tick; - if(retry_count >= MAX_DNS_RETRY) { - retry_count = 0; - return -1; // timeout occurred - } - retry_count++; - return 0; // timer over, but no timeout - } - - return 1; // no timer over, no timeout occur -} - - - -/* DNS CLIENT INIT */ -void DNS_init(uint8_t s, uint8_t * buf) -{ - DNS_SOCKET = s; // SOCK_DNS - pDNSMSG = buf; // User's shared buffer - DNS_MSGID = DNS_MSG_ID; -} - -/* DNS CLIENT RUN */ -int8_t DNS_run(uint8_t * dns_ip, uint8_t * name, uint8_t * ip_from_dns) -{ - int8_t ret; - struct dhdr dhp; - uint8_t ip[4]; - uint16_t len, port; - int8_t ret_check_timeout; - - hal_sys_tick = HAL_GetTick(); - - // Socket open - WIZCHIP_EXPORT(socket)(DNS_SOCKET, Sn_MR_UDP, 0, 0); - -#ifdef _DNS_DEBUG_ - printf("> DNS Query to DNS Server : %d.%d.%d.%d\r\n", dns_ip[0], dns_ip[1], dns_ip[2], dns_ip[3]); -#endif - - len = dns_makequery(0, (char *)name, pDNSMSG, MAX_DNS_BUF_SIZE); - WIZCHIP_EXPORT(sendto)(DNS_SOCKET, pDNSMSG, len, dns_ip, IPPORT_DOMAIN); - - while (1) - { - if ((len = getSn_RX_RSR(DNS_SOCKET)) > 0) - { - if (len > MAX_DNS_BUF_SIZE) len = MAX_DNS_BUF_SIZE; - len = WIZCHIP_EXPORT(recvfrom)(DNS_SOCKET, pDNSMSG, len, ip, &port); - #ifdef _DNS_DEBUG_ - printf("> Receive DNS message from %d.%d.%d.%d(%d). len = %d\r\n", ip[0], ip[1], ip[2], ip[3],port,len); - #endif - ret = parseDNSMSG(&dhp, pDNSMSG, ip_from_dns); - break; - } - // Check Timeout - ret_check_timeout = check_DNS_timeout(); - if (ret_check_timeout < 0) { - -#ifdef _DNS_DEBUG_ - printf("> DNS Server is not responding : %d.%d.%d.%d\r\n", dns_ip[0], dns_ip[1], dns_ip[2], dns_ip[3]); -#endif - return 0; // timeout occurred - } - else if (ret_check_timeout == 0) { - -#ifdef _DNS_DEBUG_ - printf("> DNS Timeout\r\n"); -#endif - WIZCHIP_EXPORT(sendto)(DNS_SOCKET, pDNSMSG, len, dns_ip, IPPORT_DOMAIN); - } - } - WIZCHIP_EXPORT(close)(DNS_SOCKET); - // Return value - // 0 > : failed / 1 - success - return ret; -} diff --git a/drivers/wiznet5k/internet/dns/dns.h b/drivers/wiznet5k/internet/dns/dns.h deleted file mode 100644 index de0039515e..0000000000 --- a/drivers/wiznet5k/internet/dns/dns.h +++ /dev/null @@ -1,96 +0,0 @@ -//***************************************************************************** -// -//! \file dns.h -//! \brief DNS APIs Header file. -//! \details Send DNS query & Receive DNS reponse. -//! \version 1.1.0 -//! \date 2013/11/18 -//! \par Revision history -//! <2013/10/21> 1st Release -//! <2013/12/20> V1.1.0 -//! 1. Remove secondary DNS server in DNS_run -//! If 1st DNS_run failed, call DNS_run with 2nd DNS again -//! 2. DNS_timerHandler -> DNS_time_handler -//! 3. Move the no reference define to dns.c -//! 4. Integrated dns.h dns.c & dns_parse.h dns_parse.c into dns.h & dns.c -//! <2013/12/20> V1.1.0 -//! -//! \author Eric Jung & MidnightCow -//! \copyright -//! -//! Copyright (c) 2013, WIZnet Co., LTD. -//! All rights reserved. -//! -//! Redistribution and use in source and binary forms, with or without -//! modification, are permitted provided that the following conditions -//! are met: -//! -//! * Redistributions of source code must retain the above copyright -//! notice, this list of conditions and the following disclaimer. -//! * Redistributions in binary form must reproduce the above copyright -//! notice, this list of conditions and the following disclaimer in the -//! documentation and/or other materials provided with the distribution. -//! * Neither the name of the nor the names of its -//! contributors may be used to endorse or promote products derived -//! from this software without specific prior written permission. -//! -//! THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" -//! AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -//! IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE -//! ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE -//! LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR -//! CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF -//! SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS -//! INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN -//! CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) -//! ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF -//! THE POSSIBILITY OF SUCH DAMAGE. -// -//***************************************************************************** - -#ifndef _DNS_H_ -#define _DNS_H_ - -#include -/* - * @brief Define it for Debug & Monitor DNS processing. - * @note If defined, it depends on - */ - -//#define _DNS_DEBUG_ - -#define MAX_DNS_BUF_SIZE 256 ///< maximum size of DNS buffer. */ -/* - * @brief Maximum length of your queried Domain name - * @todo SHOULD BE defined it equal as or greater than your Domain name length + null character(1) - * @note SHOULD BE careful to stack overflow because it is allocated 1.5 times as MAX_DOMAIN_NAME in stack. - */ -#define MAX_DOMAIN_NAME 32 // for example "www.google.com" - -#define MAX_DNS_RETRY 2 ///< Requery Count -#define DNS_WAIT_TIME 4 ///< Wait response time. unit 1s. - -#define IPPORT_DOMAIN 53 ///< DNS server port number - -#define DNS_MSG_ID 0x1122 ///< ID for DNS message. You can be modified it any number -/* - * @brief DNS process initialize - * @param s : Socket number for DNS - * @param buf : Buffer for DNS message - */ -void DNS_init(uint8_t s, uint8_t * buf); - -/* - * @brief DNS process - * @details Send DNS query and receive DNS response - * @param dns_ip : DNS server ip address - * @param name : Domain name to be queried - * @param ip_from_dns : IP address from DNS server - * @return -1 : failed. @ref MAX_DOMIN_NAME is too small \n - * 0 : failed (Timeout or Parse error)\n - * 1 : success - * @note This function blocks until success or fail. max time = @ref MAX_DNS_RETRY * @ref DNS_WAIT_TIME - */ -int8_t DNS_run(uint8_t * dns_ip, uint8_t * name, uint8_t * ip_from_dns); - -#endif /* _DNS_H_ */ diff --git a/examples/SDdatalogger/README.md b/examples/SDdatalogger/README.md deleted file mode 100644 index 24e69c87e0..0000000000 --- a/examples/SDdatalogger/README.md +++ /dev/null @@ -1,4 +0,0 @@ -This is a SDdatalogger, to log data from the accelerometer to the SD-card. It also functions as card reader, so you can easily get the data on your PC. - -To run, put the boot.py, cardreader.py and datalogger.py files on either the flash or the SD-card of your pyboard. -Upon reset, the datalogger script is run and logs the data. If you press the user button after reset and hold it until the orange LED goes out, you enter the cardreader mode and the filesystem is mounted to your PC. diff --git a/examples/SDdatalogger/boot.py b/examples/SDdatalogger/boot.py deleted file mode 100644 index 4ac94bbaa4..0000000000 --- a/examples/SDdatalogger/boot.py +++ /dev/null @@ -1,25 +0,0 @@ -# boot.py -- runs on boot-up -# Let's you choose which script to run. -# > To run 'datalogger.py': -# * press reset and do nothing else -# > To run 'cardreader.py': -# * press reset -# * press user switch and hold until orange LED goes out - -import pyb - -pyb.LED(3).on() # indicate we are waiting for switch press -pyb.delay(2000) # wait for user to maybe press the switch -switch_value = pyb.Switch()() # sample the switch at end of delay -pyb.LED(3).off() # indicate that we finished waiting for the switch - -pyb.LED(4).on() # indicate that we are selecting the mode - -if switch_value: - pyb.usb_mode('VCP+MSC') - pyb.main('cardreader.py') # if switch was pressed, run this -else: - pyb.usb_mode('VCP+HID') - pyb.main('datalogger.py') # if switch wasn't pressed, run this - -pyb.LED(4).off() # indicate that we finished selecting the mode diff --git a/examples/SDdatalogger/cardreader.py b/examples/SDdatalogger/cardreader.py deleted file mode 100644 index 98d7a37925..0000000000 --- a/examples/SDdatalogger/cardreader.py +++ /dev/null @@ -1,2 +0,0 @@ -# cardread.py -# This is called when the user enters cardreader mode. It does nothing. diff --git a/examples/SDdatalogger/datalogger.py b/examples/SDdatalogger/datalogger.py deleted file mode 100644 index 0690c20bb9..0000000000 --- a/examples/SDdatalogger/datalogger.py +++ /dev/null @@ -1,33 +0,0 @@ -# datalogger.py -# Logs the data from the acceleromter to a file on the SD-card - -import pyb - -# creating objects -accel = pyb.Accel() -blue = pyb.LED(4) -switch = pyb.Switch() - -# loop -while True: - - # wait for interrupt - # this reduces power consumption while waiting for switch press - pyb.wfi() - - # start if switch is pressed - if switch(): - pyb.delay(200) # delay avoids detection of multiple presses - blue.on() # blue LED indicates file open - log = open('/sd/log.csv', 'w') # open file on SD (SD: '/sd/', flash: '/flash/) - - # until switch is pressed again - while not switch(): - t = pyb.millis() # get time - x, y, z = accel.filtered_xyz() # get acceleration data - log.write('{},{},{},{}\n'.format(t,x,y,z)) # write data to file - - # end after switch is pressed again - log.close() # close file - blue.off() # blue LED indicates file closed - pyb.delay(200) # delay avoids detection of multiple presses diff --git a/examples/accel_i2c.py b/examples/accel_i2c.py deleted file mode 100644 index d635e3ccc1..0000000000 --- a/examples/accel_i2c.py +++ /dev/null @@ -1,34 +0,0 @@ -# This is an example on how to access accelerometer on -# PyBoard directly using I2C bus. As such, it's more -# intended to be an I2C example, rather than accelerometer -# example. For the latter, using pyb.Accel class is -# much easier. - -from machine import Pin -from machine import I2C -import time - -# Accelerometer needs to be powered on first. Even -# though signal is called "AVDD", and there's separate -# "DVDD", without AVDD, it won't event talk on I2C bus. -accel_pwr = Pin("MMA_AVDD") -accel_pwr.value(1) - -i2c = I2C(1, baudrate=100000) -addrs = i2c.scan() -print("Scanning devices:", [hex(x) for x in addrs]) -if 0x4c not in addrs: - print("Accelerometer is not detected") - -ACCEL_ADDR = 0x4c -ACCEL_AXIS_X_REG = 0 -ACCEL_MODE_REG = 7 - -# Now activate measurements -i2c.mem_write(b"\x01", ACCEL_ADDR, ACCEL_MODE_REG) - -print("Try to move accelerometer and watch the values") -while True: - val = i2c.mem_read(1, ACCEL_ADDR, ACCEL_AXIS_X_REG) - print(val[0]) - time.sleep(1) diff --git a/examples/accellog.py b/examples/accellog.py deleted file mode 100644 index b1f289f8ad..0000000000 --- a/examples/accellog.py +++ /dev/null @@ -1,17 +0,0 @@ -# log the accelerometer values to a .csv-file on the SD-card - -import pyb - -accel = pyb.Accel() # create object of accelerometer -blue = pyb.LED(4) # create object of blue LED - -log = open('/sd/log.csv', 'w') # open file to write data - /sd/ is the SD-card, /flash/ the internal memory -blue.on() # turn on blue LED - -for i in range(100): # do 100 times (if the board is connected via USB, you can't write longer because the PC tries to open the filesystem which messes up your file.) - t = pyb.millis() # get time since reset - x, y, z = accel.filtered_xyz() # get acceleration data - log.write('{},{},{},{}\n'.format(t,x,y,z)) # write data to file - -log.close() # close file -blue.off() # turn off LED diff --git a/examples/asmled.py b/examples/asmled.py deleted file mode 100644 index 917d9ba03c..0000000000 --- a/examples/asmled.py +++ /dev/null @@ -1,85 +0,0 @@ -# flash LED #1 using inline assembler -# this version is overly verbose and uses word stores -@micropython.asm_thumb -def flash_led(r0): - movw(r1, (stm.GPIOA + stm.GPIO_BSRRL) & 0xffff) - movt(r1, ((stm.GPIOA + stm.GPIO_BSRRL) >> 16) & 0x7fff) - movw(r2, 1 << 13) - movt(r2, 0) - movw(r3, 0) - movt(r3, 1 << 13) - - b(loop_entry) - - label(loop1) - - # turn LED on - str(r2, [r1, 0]) - - # delay for a bit - movw(r4, 5599900 & 0xffff) - movt(r4, (5599900 >> 16) & 0xffff) - label(delay_on) - sub(r4, r4, 1) - cmp(r4, 0) - bgt(delay_on) - - # turn LED off - str(r3, [r1, 0]) - - # delay for a bit - movw(r4, 5599900 & 0xffff) - movt(r4, (5599900 >> 16) & 0xffff) - label(delay_off) - sub(r4, r4, 1) - cmp(r4, 0) - bgt(delay_off) - - # loop r0 times - sub(r0, r0, 1) - label(loop_entry) - cmp(r0, 0) - bgt(loop1) - -# flash LED #2 using inline assembler -# this version uses half-word sortes, and the convenience assembler operation 'movwt' -@micropython.asm_thumb -def flash_led_v2(r0): - # get the GPIOA address in r1 - movwt(r1, stm.GPIOA) - - # get the bit mask for PA14 (the pin LED #2 is on) - movw(r2, 1 << 14) - - b(loop_entry) - - label(loop1) - - # turn LED on - strh(r2, [r1, stm.GPIO_BSRRL]) - - # delay for a bit - movwt(r4, 5599900) - label(delay_on) - sub(r4, r4, 1) - cmp(r4, 0) - bgt(delay_on) - - # turn LED off - strh(r2, [r1, stm.GPIO_BSRRH]) - - # delay for a bit - movwt(r4, 5599900) - label(delay_off) - sub(r4, r4, 1) - cmp(r4, 0) - bgt(delay_off) - - # loop r0 times - sub(r0, r0, 1) - label(loop_entry) - cmp(r0, 0) - bgt(loop1) - -flash_led(5) -flash_led_v2(5) diff --git a/examples/asmsum.py b/examples/asmsum.py deleted file mode 100644 index 07e71c7384..0000000000 --- a/examples/asmsum.py +++ /dev/null @@ -1,57 +0,0 @@ -@micropython.asm_thumb -def asm_sum_words(r0, r1): - - # r0 = len - # r1 = ptr - # r2 = sum - # r3 = dummy - mov(r2, 0) - - b(loop_entry) - - label(loop1) - ldr(r3, [r1, 0]) - add(r2, r2, r3) - - add(r1, r1, 4) - sub(r0, r0, 1) - - label(loop_entry) - cmp(r0, 0) - bgt(loop1) - - mov(r0, r2) - -@micropython.asm_thumb -def asm_sum_bytes(r0, r1): - - # r0 = len - # r1 = ptr - # r2 = sum - # r3 = dummy - mov(r2, 0) - - b(loop_entry) - - label(loop1) - ldrb(r3, [r1, 0]) - add(r2, r2, r3) - - add(r1, r1, 1) - sub(r0, r0, 1) - - label(loop_entry) - cmp(r0, 0) - bgt(loop1) - - mov(r0, r2) - -import array - -b = array.array('l', (100, 200, 300, 400)) -n = asm_sum_words(len(b), b) -print(b, n) - -b = array.array('b', (10, 20, 30, 40, 50, 60, 70, 80)) -n = asm_sum_bytes(len(b), b) -print(b, n) diff --git a/examples/conwaylife.py b/examples/conwaylife.py deleted file mode 100644 index 323f42e850..0000000000 --- a/examples/conwaylife.py +++ /dev/null @@ -1,46 +0,0 @@ -#import essential libraries -import pyb - -lcd = pyb.LCD('x') -lcd.light(1) - -# do 1 iteration of Conway's Game of Life -def conway_step(): - for x in range(128): # loop over x coordinates - for y in range(32): # loop over y coordinates - # count number of neighbours - num_neighbours = (lcd.get(x - 1, y - 1) + - lcd.get(x, y - 1) + - lcd.get(x + 1, y - 1) + - lcd.get(x - 1, y) + - lcd.get(x + 1, y) + - lcd.get(x + 1, y + 1) + - lcd.get(x, y + 1) + - lcd.get(x - 1, y + 1)) - - # check if the centre cell is alive or not - self = lcd.get(x, y) - - # apply the rules of life - if self and not (2 <= num_neighbours <= 3): - lcd.pixel(x, y, 0) # not enough, or too many neighbours: cell dies - elif not self and num_neighbours == 3: - lcd.pixel(x, y, 1) # exactly 3 neighbours around an empty cell: cell is born - -# randomise the start -def conway_rand(): - lcd.fill(0) # clear the LCD - for x in range(128): # loop over x coordinates - for y in range(32): # loop over y coordinates - lcd.pixel(x, y, pyb.rng() & 1) # set the pixel randomly - -# loop for a certain number of frames, doing iterations of Conway's Game of Life -def conway_go(num_frames): - for i in range(num_frames): - conway_step() # do 1 iteration - lcd.show() # update the LCD - pyb.delay(50) - -# testing -conway_rand() -conway_go(100) diff --git a/examples/embedding/Makefile b/examples/embedding/Makefile deleted file mode 100644 index 99f239a7c5..0000000000 --- a/examples/embedding/Makefile +++ /dev/null @@ -1,8 +0,0 @@ -MPTOP = ../.. -CFLAGS = -std=c99 -I. -I$(MPTOP) -DNO_QSTR -LDFLAGS = -L. - -hello-embed: hello-embed.o -lmicropython - --lmicropython: - $(MAKE) -f $(MPTOP)/examples/embedding/Makefile.upylib MPTOP=$(MPTOP) diff --git a/examples/embedding/Makefile.upylib b/examples/embedding/Makefile.upylib deleted file mode 100644 index a9b6535170..0000000000 --- a/examples/embedding/Makefile.upylib +++ /dev/null @@ -1,199 +0,0 @@ -MPTOP = ../.. --include mpconfigport.mk -include $(MPTOP)/py/mkenv.mk - -all: lib - -# OS name, for simple autoconfig -UNAME_S := $(shell uname -s) - -# include py core make definitions -include $(MPTOP)/py/py.mk - -INC += -I. -INC += -I.. -INC += -I$(MPTOP) -INC += -I$(MPTOP)/unix -INC += -I$(BUILD) - -# compiler settings -CWARN = -Wall -Werror -CWARN += -Wpointer-arith -Wuninitialized -CFLAGS = $(INC) $(CWARN) -std=gnu99 -DUNIX $(CFLAGS_MOD) $(COPT) $(CFLAGS_EXTRA) - -# Debugging/Optimization -ifdef DEBUG -CFLAGS += -g -COPT = -O0 -else -COPT = -Os #-DNDEBUG -# _FORTIFY_SOURCE is a feature in gcc/glibc which is intended to provide extra -# security for detecting buffer overflows. Some distros (Ubuntu at the very least) -# have it enabled by default. -# -# gcc already optimizes some printf calls to call puts and/or putchar. When -# _FORTIFY_SOURCE is enabled and compiling with -O1 or greater, then some -# printf calls will also be optimized to call __printf_chk (in glibc). Any -# printfs which get redirected to __printf_chk are then no longer synchronized -# with printfs that go through mp_printf. -# -# In MicroPython, we don't want to use the runtime library's printf but rather -# go through mp_printf, so that stdout is properly tied into streams, etc. -# This means that we either need to turn off _FORTIFY_SOURCE or provide our -# own implementation of __printf_chk. We've chosen to turn off _FORTIFY_SOURCE. -# It should also be noted that the use of printf in MicroPython is typically -# quite limited anyways (primarily for debug and some error reporting, etc -# in the unix version). -# -# Information about _FORTIFY_SOURCE seems to be rather scarce. The best I could -# find was this: https://securityblog.redhat.com/2014/03/26/fortify-and-you/ -# Original patchset was introduced by -# https://gcc.gnu.org/ml/gcc-patches/2004-09/msg02055.html . -# -# Turning off _FORTIFY_SOURCE is only required when compiling with -O1 or greater -CFLAGS += -U _FORTIFY_SOURCE -endif - -# On OSX, 'gcc' is a symlink to clang unless a real gcc is installed. -# The unix port of MicroPython on OSX must be compiled with clang, -# while cross-compile ports require gcc, so we test here for OSX and -# if necessary override the value of 'CC' set in py/mkenv.mk -ifeq ($(UNAME_S),Darwin) -CC = clang -# Use clang syntax for map file -LDFLAGS_ARCH = -Wl,-map,$@.map -else -# Use gcc syntax for map file -LDFLAGS_ARCH = -Wl,-Map=$@.map,--cref -endif -LDFLAGS = $(LDFLAGS_MOD) $(LDFLAGS_ARCH) -lm $(LDFLAGS_EXTRA) - -ifeq ($(MICROPY_FORCE_32BIT),1) -# Note: you may need to install i386 versions of dependency packages, -# starting with linux-libc-dev:i386 -ifeq ($(MICROPY_PY_FFI),1) -ifeq ($(UNAME_S),Linux) -CFLAGS_MOD += -I/usr/include/i686-linux-gnu -endif -endif -endif - -ifeq ($(MICROPY_USE_READLINE),1) -INC += -I../lib/mp-readline -CFLAGS_MOD += -DMICROPY_USE_READLINE=1 -LIB_SRC_C_EXTRA += mp-readline/readline.c -endif -ifeq ($(MICROPY_USE_READLINE),2) -CFLAGS_MOD += -DMICROPY_USE_READLINE=2 -LDFLAGS_MOD += -lreadline -# the following is needed for BSD -#LDFLAGS_MOD += -ltermcap -endif -ifeq ($(MICROPY_PY_TIME),1) -CFLAGS_MOD += -DMICROPY_PY_TIME=1 -SRC_MOD += modtime.c -endif -ifeq ($(MICROPY_PY_TERMIOS),1) -CFLAGS_MOD += -DMICROPY_PY_TERMIOS=1 -SRC_MOD += modtermios.c -endif -ifeq ($(MICROPY_PY_SOCKET),1) -CFLAGS_MOD += -DMICROPY_PY_SOCKET=1 -SRC_MOD += modsocket.c -endif - -ifeq ($(MICROPY_PY_FFI),1) - -ifeq ($(MICROPY_STANDALONE),1) -LIBFFI_CFLAGS_MOD := -I$(shell ls -1d ../lib/libffi/build_dir/out/lib/libffi-*/include) - ifeq ($(MICROPY_FORCE_32BIT),1) - LIBFFI_LDFLAGS_MOD = ../lib/libffi/build_dir/out/lib32/libffi.a - else - LIBFFI_LDFLAGS_MOD = ../lib/libffi/build_dir/out/lib/libffi.a - endif -else -LIBFFI_CFLAGS_MOD := $(shell pkg-config --cflags libffi) -LIBFFI_LDFLAGS_MOD := $(shell pkg-config --libs libffi) -endif - -ifeq ($(UNAME_S),Linux) -LIBFFI_LDFLAGS_MOD += -ldl -endif - -CFLAGS_MOD += $(LIBFFI_CFLAGS_MOD) -DMICROPY_PY_FFI=1 -LDFLAGS_MOD += $(LIBFFI_LDFLAGS_MOD) -SRC_MOD += modffi.c -endif - -MAIN_C = main.c - -# source files -SRC_C = $(addprefix $(MPTOP)/unix/,\ - $(MAIN_C) \ - gccollect.c \ - unix_mphal.c \ - input.c \ - file.c \ - modmachine.c \ - modos.c \ - moduselect.c \ - alloc.c \ - coverage.c \ - fatfs_port.c \ - $(SRC_MOD) \ - ) - -LIB_SRC_C = $(addprefix lib/,\ - $(LIB_SRC_C_EXTRA) \ - utils/printf.c \ - timeutils/timeutils.c \ - ) - -ifeq ($(MICROPY_FATFS),1) -LIB_SRC_C += $(addprefix lib/,\ - fatfs/ff.c \ - fatfs/option/ccsbcs.c \ - ) -endif - -OBJ = $(PY_O) -OBJ += $(addprefix $(BUILD)/, $(SRC_C:.c=.o)) -OBJ += $(addprefix $(BUILD)/, $(LIB_SRC_C:.c=.o)) -OBJ += $(addprefix $(BUILD)/, $(STMHAL_SRC_C:.c=.o)) - -# List of sources for qstr extraction -SRC_QSTR += $(SRC_C) $(LIB_SRC_C) -# Append any auto-generated sources that are needed by sources listed in -# SRC_QSTR -SRC_QSTR_AUTO_DEPS += - -include $(MPTOP)/py/mkrules.mk - -# Value of configure's --host= option (required for cross-compilation). -# Deduce it from CROSS_COMPILE by default, but can be overridden. -ifneq ($(CROSS_COMPILE),) -CROSS_COMPILE_HOST = --host=$(patsubst %-,%,$(CROSS_COMPILE)) -else -CROSS_COMPILE_HOST = -endif - -deplibs: libffi axtls - -# install-exec-recursive & install-data-am targets are used to avoid building -# docs and depending on makeinfo -libffi: - cd ../lib/libffi; git clean -d -x -f - cd ../lib/libffi; ./autogen.sh - mkdir -p ../lib/libffi/build_dir; cd ../lib/libffi/build_dir; \ - ../configure $(CROSS_COMPILE_HOST) --prefix=$$PWD/out CC="$(CC)" CXX="$(CXX)" LD="$(LD)"; \ - make install-exec-recursive; make -C include install-data-am - -axtls: ../lib/axtls/README - cd ../lib/axtls; cp config/upyconfig config/.config - cd ../lib/axtls; make oldconfig -B - cd ../lib/axtls; make clean - cd ../lib/axtls; make all CC="$(CC)" LD="$(LD)" - -../lib/axtls/README: - @echo "You cloned without --recursive, fetching submodules for you." - (cd ..; git submodule update --init --recursive) diff --git a/examples/embedding/README.md b/examples/embedding/README.md deleted file mode 100644 index 804dfede6f..0000000000 --- a/examples/embedding/README.md +++ /dev/null @@ -1,67 +0,0 @@ -Example of embedding MicroPython in a standlone C application -============================================================= - -This directory contains a (very simple!) example of how to embed a MicroPython -in an existing C application. - -A C application is represented by the file hello-embed.c. It executes a simple -Python statement which prints to the standard output. - - -Building the example --------------------- - -Building the example is as simple as running: - - make - -It's worth to trace what's happening behind the scenes though: - -1. As a first step, a MicroPython library is built. This is handled by a -separate makefile, Makefile.upylib. It is more or less complex, but the -good news is that you won't need to change anything in it, just use it -as is, the main Makefile shows how. What may require editing though is -a MicroPython configuration file. MicroPython is highly configurable, so -you would need to build a library suiting your application well, while -not bloating its size. Check the options in the file "mpconfigport.h". -Included is a copy of the "minimal" Unix port, which should be a good start -for minimal embedding. For the list of all available options, see -py/mpconfig.h. - -2. Once the MicroPython library is built, your application is compiled -and linked it. The main Makefile is very simple and shows that the changes -you would need to do to your application's Makefile (or other build -configuration) are also simple: - -a) You would need to use C99 standard (you're using this 15+ years old -standard already, not a 25+ years old one, right?). - -b) You need to provide a path to MicroPython's top-level dir, for includes. - -c) You need to include -DNO_QSTR compile-time flag. - -d) Otherwise, just link with the MicroPython library produced in step 1. - - -Out of tree build ------------------ - -This example is set up to work out of the box, being part of the MicroPython -tree. Your application of course will be outside of its tree, but the -only thing you need to do is to pass MPTOP variable pointing to -MicroPython directory to both Makefiles (in this example, the main Makefile -automatically passes it to Makefile.upylib; in your own Makefile, don't forget -to use a suitable value). - -A practical way to embed MicroPython in your application is to include it -as a git submodule. Suppose you included it as libs/micropython. Then in -your main Makefile you would have something like: - -~~~ -MPTOP = libs/micropython - -my_app: $(MY_OBJS) -lmicropython - --lmicropython: - $(MAKE) -f $(MPTOP)/examples/embedding/Makefile.upylib MPTOP=$(MPTOP) -~~~ diff --git a/examples/embedding/hello-embed.c b/examples/embedding/hello-embed.c deleted file mode 100644 index 3473e5bcd8..0000000000 --- a/examples/embedding/hello-embed.c +++ /dev/null @@ -1,74 +0,0 @@ -/* - * This file is part of the MicroPython project, http://micropython.org/ - * - * The MIT License (MIT) - * - * Copyright (c) 2016 Paul Sokolovsky - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ - -#include -#include -#include - -#include "py/compile.h" -#include "py/runtime.h" -#include "py/gc.h" -#include "py/stackctrl.h" - -static char heap[16384]; - -mp_obj_t execute_from_str(const char *str) { - nlr_buf_t nlr; - if (nlr_push(&nlr) == 0) { - mp_lexer_t *lex = mp_lexer_new_from_str_len(0/*MP_QSTR_*/, str, strlen(str), false); - mp_parse_tree_t pt = mp_parse(lex, MP_PARSE_FILE_INPUT); - mp_obj_t module_fun = mp_compile(&pt, lex->source_name, MP_EMIT_OPT_NONE, false); - mp_call_function_0(module_fun); - nlr_pop(); - return 0; - } else { - // uncaught exception - return (mp_obj_t)nlr.ret_val; - } -} - -int main() { - // Initialized stack limit - mp_stack_set_limit(40000 * (BYTES_PER_WORD / 4)); - // Initialize heap - gc_init(heap, heap + sizeof(heap)); - // Initialize interpreter - mp_init(); - - const char str[] = "print('Hello world of easy embedding!')"; - if (execute_from_str(str)) { - printf("Error\n"); - } -} - -uint mp_import_stat(const char *path) { - return MP_IMPORT_STAT_NO_EXIST; -} - -void nlr_jump_fail(void *val) { - printf("FATAL: uncaught NLR %p\n", val); - exit(1); -} diff --git a/examples/embedding/mpconfigport.h b/examples/embedding/mpconfigport.h deleted file mode 120000 index 142e5d6f43..0000000000 --- a/examples/embedding/mpconfigport.h +++ /dev/null @@ -1 +0,0 @@ -mpconfigport_minimal.h \ No newline at end of file diff --git a/examples/embedding/mpconfigport_minimal.h b/examples/embedding/mpconfigport_minimal.h deleted file mode 100644 index fa52be4ad7..0000000000 --- a/examples/embedding/mpconfigport_minimal.h +++ /dev/null @@ -1,134 +0,0 @@ -/* - * This file is part of the MicroPython project, http://micropython.org/ - * - * The MIT License (MIT) - * - * Copyright (c) 2015 Damien P. George - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ - -// options to control how MicroPython is built - -#define MICROPY_ALLOC_PATH_MAX (PATH_MAX) -#define MICROPY_ENABLE_GC (1) -#define MICROPY_ENABLE_FINALISER (0) -#define MICROPY_STACK_CHECK (0) -#define MICROPY_COMP_CONST (0) -#define MICROPY_MEM_STATS (0) -#define MICROPY_DEBUG_PRINTERS (0) -#define MICROPY_READER_POSIX (1) -#define MICROPY_KBD_EXCEPTION (1) -#define MICROPY_HELPER_REPL (1) -#define MICROPY_HELPER_LEXER_UNIX (1) -#define MICROPY_ENABLE_SOURCE_LINE (0) -#define MICROPY_ERROR_REPORTING (MICROPY_ERROR_REPORTING_TERSE) -#define MICROPY_WARNINGS (0) -#define MICROPY_ENABLE_EMERGENCY_EXCEPTION_BUF (0) -#define MICROPY_FLOAT_IMPL (MICROPY_FLOAT_IMPL_NONE) -#define MICROPY_LONGINT_IMPL (MICROPY_LONGINT_IMPL_NONE) -#define MICROPY_STREAMS_NON_BLOCK (0) -#define MICROPY_OPT_COMPUTED_GOTO (0) -#define MICROPY_OPT_CACHE_MAP_LOOKUP_IN_BYTECODE (0) -#define MICROPY_CAN_OVERRIDE_BUILTINS (0) -#define MICROPY_BUILTIN_METHOD_CHECK_SELF_ARG (0) -#define MICROPY_CPYTHON_COMPAT (0) -#define MICROPY_PY_BUILTINS_BYTEARRAY (0) -#define MICROPY_PY_BUILTINS_MEMORYVIEW (0) -#define MICROPY_PY_BUILTINS_COMPILE (0) -#define MICROPY_PY_BUILTINS_ENUMERATE (0) -#define MICROPY_PY_BUILTINS_FILTER (0) -#define MICROPY_PY_BUILTINS_FROZENSET (0) -#define MICROPY_PY_BUILTINS_REVERSED (0) -#define MICROPY_PY_BUILTINS_SET (0) -#define MICROPY_PY_BUILTINS_SLICE (0) -#define MICROPY_PY_BUILTINS_STR_UNICODE (0) -#define MICROPY_PY_BUILTINS_PROPERTY (0) -#define MICROPY_PY_BUILTINS_MIN_MAX (0) -#define MICROPY_PY___FILE__ (0) -#define MICROPY_PY_MICROPYTHON_MEM_INFO (0) -#define MICROPY_PY_GC (0) -#define MICROPY_PY_GC_COLLECT_RETVAL (0) -#define MICROPY_PY_ARRAY (0) -#define MICROPY_PY_COLLECTIONS (0) -#define MICROPY_PY_MATH (0) -#define MICROPY_PY_CMATH (0) -#define MICROPY_PY_IO (0) -#define MICROPY_PY_IO_FILEIO (0) -#define MICROPY_PY_STRUCT (0) -#define MICROPY_PY_SYS (1) -#define MICROPY_PY_SYS_EXIT (0) -#define MICROPY_PY_SYS_PLATFORM "linux" -#define MICROPY_PY_SYS_MAXSIZE (0) -#define MICROPY_PY_SYS_STDFILES (0) -#define MICROPY_PY_CMATH (0) -#define MICROPY_PY_UCTYPES (0) -#define MICROPY_PY_UZLIB (0) -#define MICROPY_PY_UJSON (0) -#define MICROPY_PY_URE (0) -#define MICROPY_PY_UHEAPQ (0) -#define MICROPY_PY_UHASHLIB (0) -#define MICROPY_PY_UBINASCII (0) - -extern const struct _mp_obj_module_t mp_module_os; - -#define MICROPY_PORT_BUILTIN_MODULES \ - { MP_ROM_QSTR(MP_QSTR_uos), MP_ROM_PTR(&mp_module_os) }, \ - -#define MICROPY_PORT_ROOT_POINTERS \ - -////////////////////////////////////////// -// Do not change anything beyond this line -////////////////////////////////////////// - -// Define to 1 to use undertested inefficient GC helper implementation -// (if more efficient arch-specific one is not available). -#ifndef MICROPY_GCREGS_SETJMP - #ifdef __mips__ - #define MICROPY_GCREGS_SETJMP (1) - #else - #define MICROPY_GCREGS_SETJMP (0) - #endif -#endif - -// type definitions for the specific machine - -#ifdef __LP64__ -typedef long mp_int_t; // must be pointer size -typedef unsigned long mp_uint_t; // must be pointer size -#else -// These are definitions for machines where sizeof(int) == sizeof(void*), -// regardless for actual size. -typedef int mp_int_t; // must be pointer size -typedef unsigned int mp_uint_t; // must be pointer size -#endif - -// Cannot include , as it may lead to symbol name clashes -#if _FILE_OFFSET_BITS == 64 && !defined(__LP64__) -typedef long long mp_off_t; -#else -typedef long mp_off_t; -#endif - -// We need to provide a declaration/definition of alloca() -#ifdef __FreeBSD__ -#include -#else -#include -#endif diff --git a/examples/hwapi/README.md b/examples/hwapi/README.md deleted file mode 100644 index 1992eb6609..0000000000 --- a/examples/hwapi/README.md +++ /dev/null @@ -1,126 +0,0 @@ -This directory shows the best practices for using MicroPython hardware API -(`machine` module). `machine` module strives to provide consistent API -across various boards, with the aim to enable writing portable applications, -which would work from a board to board, from a system to another systems. -This is inherently a hard problem, because hardware is different from one -board type to another, and even from examplar of board to another. For -example, if your app requires an external LED, one user may connect it -to one GPIO pin, while another user may find it much more convinient to -use another pin. This of course applies to relays, buzzers, sensors, etc. - -With complications above in mind, it's still possible to write portable -applications by using "low[est] denominator" subset of hardware API and -following simple rules outlined below. The applications won't be able -to rely on advanced hardware capabilities of a particular board and -will be limited to generic capabilities, but it's still possible to -write many useful applications in such a way, with the obvious benefit of -"write once - run everywhere" approach (only configuration for a particular -board is required). - -The key to this approach is splitting your application into (at least) -2 parts: - -* main application logic -* hardware configuration - -The key point is that hardware configuration should be a separate file -(module in Python terms). A good name would be `hwconfig.py`, and that's -how we'll call it from now on. Another key point is that main application -should never instantiate (construct) hardware objects directly. Instead, -they should be defined in `hwconfig.py`, and main application should -import and reference hardware objects via this module. The simplest -application of this idea would look like: - -`hwconfig.py`: - - from machine import Pin - - LED = Pin("A3", Pin.OUT) - -`app.py`: - - from hwconfig import * - import utime - - while True: - LED.value(1) - utime.sleep_ms(500) - LED.value(0) - utime.sleep_ms(500) - - -To deploy this application to a particular board, a user will need: - -1. Edit `hwconfig.py` to adjust Pin and other hardware peripheral - parameters and locations. -2. Actually deploy `hwconfig.py` and `app.py` to a board (e.g. copy to - board's filesystem, or build new firmware with these modules frozen - into it). - -Note that there's no need to edit the main application code! (Which may -be complex, while `hwconfig.py` should usually remain short enough, and -focused solely on hardware configuration). - -An obvious improvement to this approach is the following. There're few -well-known boards which run MicroPython, and most of them include an -onboard LED. So, to help users of these boards to do configuration -quickly (that's especially important for novice users, for who may -be stumped by the need to reach out to a board reference to find LED -pin assignments), `hwconfig.py` your application ships may include -commented out sections with working configurations for different -boards. The step 1 above then will be: - -1. Look thru `hwconfig.py` to find a section which either exactly - matches your board, or the closest to it. Uncomment, and if any - adjustments required, apply them. - -It's important to keep in mind that adjustments may be always required, -and that there may be users whose configuration doesn't match any of -the available. So, always include a section or instructions for them. -Consider for example that even on a supported board, user may want to -blink not an on-board LED, but the one they connected externally. -MicroPython's Hardware API offers portability not just among "supported" -boards, but to any board at all, so make sure users can enjoy it. - -There's next step of improvement to make. While having one `hwconfig.py` -with many sections would work for smaller projects with few hardware -objects, it may become more cumbersome to maintain both on programmer's -and user's sides for larger projects. Then instead of single -`hwconfig.py` file, you can provide few "template" ones for well-known -boards: - -* `hwconfig_pyboard.py` -* `hwconfig_wipy.py` -* `hwconfig_esp8266.py` -* etc. - -Then step 1 above will be: - -1. Look thru available `hwconfig_*.py` files and find one which matches - your board the best, then rename to `hwconfig.py` and make adjustments, - if any. - -Again, please keep in mind that there may be users whose hardware will be -completely unlike you heard of. Give them some helpful hints too, perhaps -provide `hwconfig_custom.py` with some instructions. - -That's where we stop with improvements to the "separate file for hardware -configuration" idea, as it is already pretty flexible and viable. An -application in this directory shows it in practice, using slightly less -trivial example than just a blinking LED: `soft_pwm.py` implements a -software PWM (pulse width modulation) to produce an LED fade-in/fade-out -effect - without any dependence on hardware PWM availability. - -Note that improvements to board configuration handling may continue further. -For example, one may invent a "configuration manager" helper module which will -try to detect current board (among well-known ones), and load appropriate -`hwconfig_*.py` - this assumes that a user would lazily deploy them all -(or that application will be automatically installed, e.g. using MicroPython's -`upip` package manager). The key point in this case remains the same as -elaborated above - always assume there can, and will be a custom configuration, -and it should be well supported. So, any automatic detection should be -overridable by a user, and instructions how to do so are among the most -important you may provide for your application. - -By following these best practices, you will use MicroPython at its full -potential, and let users enjoy it too. Good luck! diff --git a/examples/hwapi/button_led.py b/examples/hwapi/button_led.py deleted file mode 100644 index bd6fe01729..0000000000 --- a/examples/hwapi/button_led.py +++ /dev/null @@ -1,9 +0,0 @@ -import utime -from hwconfig import LED, BUTTON - -# Light LED when (and while) a BUTTON is pressed - -while 1: - LED.value(BUTTON.value()) - # Don't burn CPU - utime.sleep_ms(10) diff --git a/examples/hwapi/button_reaction.py b/examples/hwapi/button_reaction.py deleted file mode 100644 index b72e813e4c..0000000000 --- a/examples/hwapi/button_reaction.py +++ /dev/null @@ -1,19 +0,0 @@ -import utime -import machine -from hwconfig import LED, BUTTON - -# machine.time_pulse_us() function demo - -print("""\ -Let's play an interesting game: -You click button as fast as you can, and I tell you how slow you are. -Ready? Cliiiiick! -""") - -while 1: - delay = machine.time_pulse_us(BUTTON, 1, 10*1000*1000) - if delay < 0: - print("Well, you're *really* slow") - else: - print("You are as slow as %d microseconds!" % delay) - utime.sleep_ms(10) diff --git a/examples/hwapi/hwconfig_console.py b/examples/hwapi/hwconfig_console.py deleted file mode 100644 index 4b0b0d79bd..0000000000 --- a/examples/hwapi/hwconfig_console.py +++ /dev/null @@ -1,13 +0,0 @@ -# This is hwconfig for "emulation" for cases when there's no real hardware. -# It just prints information to console. -class LEDClass: - - def __init__(self, id): - self.id = "LED(%d):" % id - - def value(self, v): - print(self.id, v) - - -LED = LEDClass(1) -LED2 = LEDClass(12) diff --git a/examples/hwapi/hwconfig_dragonboard410c.py b/examples/hwapi/hwconfig_dragonboard410c.py deleted file mode 100644 index eec3582039..0000000000 --- a/examples/hwapi/hwconfig_dragonboard410c.py +++ /dev/null @@ -1,22 +0,0 @@ -from machine import Pin, Signal - -# 96Boards/Qualcomm DragonBoard 410c -# -# By default, on-board LEDs are controlled by kernel LED driver. -# To make corresponding pins be available as normal GPIO, -# corresponding driver needs to be unbound first (as root): -# echo -n "soc:leds" >/sys/class/leds/apq8016-sbc:green:user1/device/driver/unbind -# Note that application also either should be run as root, or -# /sys/class/gpio ownership needs to be changed. -# Likewise, onboard buttons are controlled by gpio_keys driver. -# To release corresponding GPIOs: -# echo -n "gpio_keys" >/sys/class/input/input1/device/driver/unbind - -# User LED 1 on gpio21 -LED = Signal(Pin(21, Pin.OUT)) - -# User LED 2 on gpio120 -LED2 = Signal(Pin(120, Pin.OUT)) - -# Button S3 on gpio107 -BUTTON = Pin(107, Pin.IN) diff --git a/examples/hwapi/hwconfig_esp8266_esp12.py b/examples/hwapi/hwconfig_esp8266_esp12.py deleted file mode 100644 index 2e855ee3d3..0000000000 --- a/examples/hwapi/hwconfig_esp8266_esp12.py +++ /dev/null @@ -1,5 +0,0 @@ -from machine import Pin, Signal - -# ESP12 module as used by many boards -# Blue LED on pin 2, active low (inverted) -LED = Signal(2, Pin.OUT, invert=True) diff --git a/examples/hwapi/hwconfig_pyboard.py b/examples/hwapi/hwconfig_pyboard.py deleted file mode 100644 index fb260033e5..0000000000 --- a/examples/hwapi/hwconfig_pyboard.py +++ /dev/null @@ -1,13 +0,0 @@ -from machine import Pin, Signal - -# Red LED on pin LED_RED also kown as A13 -LED = Signal('LED_RED', Pin.OUT) - -# Green LED on pin LED_GREEN also known as A14 -LED2 = Signal('LED_GREEN', Pin.OUT) - -# Yellow LED on pin LED_YELLOW also known as A15 -LED3 = Signal('LED_YELLOW', Pin.OUT) - -# Blue LED on pin LED_BLUE also known as B4 -LED4 = Signal('LED_BLUE', Pin.OUT) diff --git a/examples/hwapi/hwconfig_z_96b_carbon.py b/examples/hwapi/hwconfig_z_96b_carbon.py deleted file mode 100644 index 97fd57a07f..0000000000 --- a/examples/hwapi/hwconfig_z_96b_carbon.py +++ /dev/null @@ -1,9 +0,0 @@ -from machine import Signal - -# 96Boards Carbon board -# USR1 - User controlled led, connected to PD2 -# USR2 - User controlled led, connected to PA15 -# BT - Bluetooth indicator, connected to PB5. -# Note - 96b_carbon uses (at the time of writing) non-standard -# for Zephyr port device naming convention. -LED = Signal(("GPIOA", 15), Pin.OUT) diff --git a/examples/hwapi/hwconfig_z_frdm_k64f.py b/examples/hwapi/hwconfig_z_frdm_k64f.py deleted file mode 100644 index 377c638787..0000000000 --- a/examples/hwapi/hwconfig_z_frdm_k64f.py +++ /dev/null @@ -1,5 +0,0 @@ -from machine import Pin, Signal - -# Freescale/NXP FRDM-K64F board -# Blue LED on port B, pin 21 -LED = Signal(("GPIO_1", 21), Pin.OUT) diff --git a/examples/hwapi/soft_pwm.py b/examples/hwapi/soft_pwm.py deleted file mode 100644 index 72291b0ecd..0000000000 --- a/examples/hwapi/soft_pwm.py +++ /dev/null @@ -1,38 +0,0 @@ -import utime -from hwconfig import LED - - -# Using sleep_ms() gives pretty poor PWM resolution and -# brightness control, but we use it in the attempt to -# make this demo portable to even more boards (e.g. to -# those which don't provide sleep_us(), or provide, but -# it's not precise, like would be on non realtime OSes). -# We otherwise use 20ms period, to make frequency not less -# than 50Hz to avoid visible flickering (you may still see -# if you're unlucky). -def pwm_cycle(led, duty, cycles): - duty_off = 20 - duty - for i in range(cycles): - if duty: - led.on() - utime.sleep_ms(duty) - if duty_off: - led.off() - utime.sleep_ms(duty_off) - - -# At the duty setting of 1, an LED is still pretty bright, then -# at duty 0, it's off. This makes rather unsmooth transition, and -# breaks fade effect. So, we avoid value of 0 and oscillate between -# 1 and 20. Actually, highest values like 19 and 20 are also -# barely distinguishible (like, both of them too bright and burn -# your eye). So, improvement to the visible effect would be to use -# more steps (at least 10x), and then higher frequency, and use -# range which includes 1 but excludes values at the top. -while True: - # Fade in - for i in range(1, 21): - pwm_cycle(LED, i, 2) - # Fade out - for i in range(20, 0, -1): - pwm_cycle(LED, i, 2) diff --git a/examples/hwapi/soft_pwm2_uasyncio.py b/examples/hwapi/soft_pwm2_uasyncio.py deleted file mode 100644 index 908ef2d8ac..0000000000 --- a/examples/hwapi/soft_pwm2_uasyncio.py +++ /dev/null @@ -1,31 +0,0 @@ -# Like soft_pwm_uasyncio.py, but fading 2 LEDs with different phase. -# Also see original soft_pwm.py. -import uasyncio -from hwconfig import LED, LED2 - - -async def pwm_cycle(led, duty, cycles): - duty_off = 20 - duty - for i in range(cycles): - if duty: - led.value(1) - await uasyncio.sleep_ms(duty) - if duty_off: - led.value(0) - await uasyncio.sleep_ms(duty_off) - - -async def fade_in_out(LED): - while True: - # Fade in - for i in range(1, 21): - await pwm_cycle(LED, i, 2) - # Fade out - for i in range(20, 0, -1): - await pwm_cycle(LED, i, 2) - - -loop = uasyncio.get_event_loop() -loop.create_task(fade_in_out(LED)) -loop.call_later_ms(800, fade_in_out(LED2)) -loop.run_forever() diff --git a/examples/hwapi/soft_pwm_uasyncio.py b/examples/hwapi/soft_pwm_uasyncio.py deleted file mode 100644 index 8d7ad8c9e0..0000000000 --- a/examples/hwapi/soft_pwm_uasyncio.py +++ /dev/null @@ -1,28 +0,0 @@ -# See original soft_pwm.py for detailed comments. -import uasyncio -from hwconfig import LED - - -async def pwm_cycle(led, duty, cycles): - duty_off = 20 - duty - for i in range(cycles): - if duty: - led.value(1) - await uasyncio.sleep_ms(duty) - if duty_off: - led.value(0) - await uasyncio.sleep_ms(duty_off) - - -async def fade_in_out(LED): - while True: - # Fade in - for i in range(1, 21): - await pwm_cycle(LED, i, 2) - # Fade out - for i in range(20, 0, -1): - await pwm_cycle(LED, i, 2) - - -loop = uasyncio.get_event_loop() -loop.run_until_complete(fade_in_out(LED)) diff --git a/examples/ledangle.py b/examples/ledangle.py deleted file mode 100644 index 8c8d9e99d9..0000000000 --- a/examples/ledangle.py +++ /dev/null @@ -1,25 +0,0 @@ -import pyb - -def led_angle(seconds_to_run_for): - # make LED objects - l1 = pyb.LED(1) - l2 = pyb.LED(2) - accel = pyb.Accel() - - for i in range(20 * seconds_to_run_for): - # get x-axis - x = accel.x() - - # turn on LEDs depending on angle - if x < -10: - l1.on() - l2.off() - elif x > 10: - l1.off() - l2.on() - else: - l1.off() - l2.off() - - # delay so that loop runs at at 1/50ms = 20Hz - pyb.delay(50) diff --git a/examples/mandel.py b/examples/mandel.py deleted file mode 100644 index bbb8086470..0000000000 --- a/examples/mandel.py +++ /dev/null @@ -1,27 +0,0 @@ -try: - import micropython -except: - pass - -def mandelbrot(): - # returns True if c, complex, is in the Mandelbrot set - #@micropython.native - def in_set(c): - z = 0 - for i in range(40): - z = z*z + c - if abs(z) > 60: - return False - return True - - lcd.clear() - for u in range(91): - for v in range(31): - if in_set((u / 30 - 2) + (v / 15 - 1) * 1j): - lcd.set(u, v) - lcd.show() - -# PC testing -import lcd -lcd = lcd.LCD(128, 32) -mandelbrot() diff --git a/examples/micropython.py b/examples/micropython.py deleted file mode 100644 index f91da94f41..0000000000 --- a/examples/micropython.py +++ /dev/null @@ -1,8 +0,0 @@ -# micropython module placeholder for CPython - -# Dummy function decorators - -def nodecor(x): - return x - -bytecode = native = viper = nodecor diff --git a/examples/network/http_client.py b/examples/network/http_client.py deleted file mode 100644 index 0791c8066b..0000000000 --- a/examples/network/http_client.py +++ /dev/null @@ -1,30 +0,0 @@ -try: - import usocket as socket -except: - import socket - - -def main(use_stream=False): - s = socket.socket() - - ai = socket.getaddrinfo("google.com", 80) - print("Address infos:", ai) - addr = ai[0][-1] - - print("Connect address:", addr) - s.connect(addr) - - if use_stream: - # MicroPython socket objects support stream (aka file) interface - # directly, but the line below is needed for CPython. - s = s.makefile("rwb", 0) - s.write(b"GET / HTTP/1.0\r\n\r\n") - print(s.read()) - else: - s.send(b"GET / HTTP/1.0\r\n\r\n") - print(s.recv(4096)) - - s.close() - - -main() diff --git a/examples/network/http_client_ssl.py b/examples/network/http_client_ssl.py deleted file mode 100644 index 83f685fdf3..0000000000 --- a/examples/network/http_client_ssl.py +++ /dev/null @@ -1,38 +0,0 @@ -try: - import usocket as _socket -except: - import _socket -try: - import ussl as ssl -except: - import ssl - - -def main(use_stream=True): - s = _socket.socket() - - ai = _socket.getaddrinfo("google.com", 443) - print("Address infos:", ai) - addr = ai[0][-1] - - print("Connect address:", addr) - s.connect(addr) - - s = ssl.wrap_socket(s) - print(s) - - if use_stream: - # Both CPython and MicroPython SSLSocket objects support read() and - # write() methods. - s.write(b"GET / HTTP/1.0\r\n\r\n") - print(s.read(4096)) - else: - # MicroPython SSLSocket objects implement only stream interface, not - # socket interface - s.send(b"GET / HTTP/1.0\r\n\r\n") - print(s.recv(4096)) - - s.close() - - -main() diff --git a/examples/network/http_server.py b/examples/network/http_server.py deleted file mode 100644 index e3a66e8283..0000000000 --- a/examples/network/http_server.py +++ /dev/null @@ -1,64 +0,0 @@ -try: - import usocket as socket -except: - import socket - - -CONTENT = b"""\ -HTTP/1.0 200 OK - -Hello #%d from MicroPython! -""" - -def main(micropython_optimize=False): - s = socket.socket() - - # Binding to all interfaces - server will be accessible to other hosts! - ai = socket.getaddrinfo("0.0.0.0", 8080) - print("Bind address info:", ai) - addr = ai[0][-1] - - s.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1) - s.bind(addr) - s.listen(5) - print("Listening, connect your browser to http://:8080/") - - counter = 0 - while True: - res = s.accept() - client_sock = res[0] - client_addr = res[1] - print("Client address:", client_addr) - print("Client socket:", client_sock) - - if not micropython_optimize: - # To read line-oriented protocol (like HTTP) from a socket (and - # avoid short read problem), it must be wrapped in a stream (aka - # file-like) object. That's how you do it in CPython: - client_stream = client_sock.makefile("rwb") - else: - # .. but MicroPython socket objects support stream interface - # directly, so calling .makefile() method is not required. If - # you develop application which will run only on MicroPython, - # especially on a resource-constrained embedded device, you - # may take this shortcut to save resources. - client_stream = client_sock - - print("Request:") - req = client_stream.readline() - print(req) - while True: - h = client_stream.readline() - if h == b"" or h == b"\r\n": - break - print(h) - client_stream.write(CONTENT % counter) - - client_stream.close() - if not micropython_optimize: - client_sock.close() - counter += 1 - print() - - -main() diff --git a/examples/network/http_server_simplistic.py b/examples/network/http_server_simplistic.py deleted file mode 100644 index 67ecb1ad7a..0000000000 --- a/examples/network/http_server_simplistic.py +++ /dev/null @@ -1,40 +0,0 @@ -# Do not use this code in real projects! Read -# http_server_simplistic_commented.py for details. -try: - import usocket as socket -except: - import socket - - -CONTENT = b"""\ -HTTP/1.0 200 OK - -Hello #%d from MicroPython! -""" - -def main(): - s = socket.socket() - ai = socket.getaddrinfo("0.0.0.0", 8080) - addr = ai[0][-1] - - s.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1) - - s.bind(addr) - s.listen(5) - print("Listening, connect your browser to http://:8080/") - - counter = 0 - while True: - res = s.accept() - client_s = res[0] - client_addr = res[1] - req = client_s.recv(4096) - print("Request:") - print(req) - client_s.send(CONTENT % counter) - client_s.close() - counter += 1 - print() - - -main() diff --git a/examples/network/http_server_simplistic_commented.py b/examples/network/http_server_simplistic_commented.py deleted file mode 100644 index b58e9eeb60..0000000000 --- a/examples/network/http_server_simplistic_commented.py +++ /dev/null @@ -1,76 +0,0 @@ -# -# MicroPython http_server_simplistic.py example -# -# This example shows how to write the smallest possible HTTP -# server in MicroPython. With comments and convenience code -# removed, this example can be compressed literally to ten -# lines. There's a catch though - read comments below for -# details, and use this code only for quick hacks, preferring -# http_server.py for "real thing". -# -try: - import usocket as socket -except: - import socket - - -CONTENT = b"""\ -HTTP/1.0 200 OK - -Hello #%d from MicroPython! -""" - -def main(): - s = socket.socket() - - # Bind to (allow to be connected on ) all interfaces. This means - # this server will be accessible to other hosts on your local - # network, and if your server has direct (non-firewalled) connection - # to the Internet, then to anyone on the Internet. We bind to all - # interfaces to let this example work easily on embedded MicroPython - # targets, which you will likely access from another machine on your - # local network. Take care when running this on an Internet-connected - # machine though! Replace "0.0.0.0" with "127.0.0.1" if in doubt, to - # make the server accessible only on the machine it runs on. - ai = socket.getaddrinfo("0.0.0.0", 8080) - print("Bind address info:", ai) - addr = ai[0][-1] - - # A port on which a socket listened remains inactive during some time. - # This means that if you run this sample, terminate it, and run again - # you will likely get an error. To avoid this timeout, set SO_REUSEADDR - # socket option. - s.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1) - - s.bind(addr) - s.listen(5) - print("Listening, connect your browser to http://:8080/") - - counter = 0 - while True: - res = s.accept() - client_s = res[0] - client_addr = res[1] - print("Client address:", client_addr) - print("Client socket:", client_s) - # We assume here that .recv() call will read entire HTTP request - # from client. This is usually true, at least on "big OS" systems - # like Linux/MacOS/Windows. But that doesn't have to be true in - # all cases, in particular on embedded systems, when there can - # easily be "short recv", where it returns much less than requested - # data size. That's why this example is called "simplistic" - it - # shows that writing a web server in Python that *usually works* is - # ten lines of code, and you can use this technique for quick hacks - # and experimentation. But don't do it like that in production - # applications - instead, parse HTTP request properly, as shown - # by http_server.py example. - req = client_s.recv(4096) - print("Request:") - print(req) - client_s.send(CONTENT % counter) - client_s.close() - counter += 1 - print() - - -main() diff --git a/examples/network/http_server_ssl.py b/examples/network/http_server_ssl.py deleted file mode 100644 index 9a69ca9d41..0000000000 --- a/examples/network/http_server_ssl.py +++ /dev/null @@ -1,64 +0,0 @@ -try: - import usocket as socket -except: - import socket -import ussl as ssl - - -CONTENT = b"""\ -HTTP/1.0 200 OK - -Hello #%d from MicroPython! -""" - -def main(use_stream=True): - s = socket.socket() - - # Binding to all interfaces - server will be accessible to other hosts! - ai = socket.getaddrinfo("0.0.0.0", 8443) - print("Bind address info:", ai) - addr = ai[0][-1] - - s.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1) - s.bind(addr) - s.listen(5) - print("Listening, connect your browser to https://:8443/") - - counter = 0 - while True: - res = s.accept() - client_s = res[0] - client_addr = res[1] - print("Client address:", client_addr) - print("Client socket:", client_s) - client_s = ssl.wrap_socket(client_s, server_side=True) - print(client_s) - print("Request:") - if use_stream: - # Both CPython and MicroPython SSLSocket objects support read() and - # write() methods. - # Browsers are prone to terminate SSL connection abruptly if they - # see unknown certificate, etc. We must continue in such case - - # next request they issue will likely be more well-behaving and - # will succeed. - try: - req = client_s.readline() - print(req) - while True: - h = client_s.readline() - if h == b"" or h == b"\r\n": - break - print(h) - if req: - client_s.write(CONTENT % counter) - except Exception as e: - print("Exception serving request:", e) - else: - print(client_s.recv(4096)) - client_s.send(CONTENT % counter) - client_s.close() - counter += 1 - print() - - -main() diff --git a/examples/pins.py b/examples/pins.py deleted file mode 100644 index ab359f6921..0000000000 --- a/examples/pins.py +++ /dev/null @@ -1,58 +0,0 @@ -# Print a nice list of pins, their current settings, and available afs. -# Requires pins_af.py from stmhal/build-PYBV10/ directory. - -import pyb -import pins_af - -def af(): - max_name_width = 0 - max_af_width = 0 - for pin_entry in pins_af.PINS_AF: - max_name_width = max(max_name_width, len(pin_entry[0])) - for af_entry in pin_entry[1:]: - max_af_width = max(max_af_width, len(af_entry[1])) - for pin_entry in pins_af.PINS_AF: - pin_name = pin_entry[0] - print('%-*s ' % (max_name_width, pin_name), end='') - for af_entry in pin_entry[1:]: - print('%2d: %-*s ' % (af_entry[0], max_af_width, af_entry[1]), end='') - print('') - -def pins(): - mode_str = { pyb.Pin.IN : 'IN', - pyb.Pin.OUT_PP : 'OUT_PP', - pyb.Pin.OUT_OD : 'OUT_OD', - pyb.Pin.AF_PP : 'AF_PP', - pyb.Pin.AF_OD : 'AF_OD', - pyb.Pin.ANALOG : 'ANALOG' } - pull_str = { pyb.Pin.PULL_NONE : '', - pyb.Pin.PULL_UP : 'PULL_UP', - pyb.Pin.PULL_DOWN : 'PULL_DOWN' } - width = [0, 0, 0, 0] - rows = [] - for pin_entry in pins_af.PINS_AF: - row = [] - pin_name = pin_entry[0] - pin = pyb.Pin(pin_name) - pin_mode = pin.mode() - row.append(pin_name) - row.append(mode_str[pin_mode]) - row.append(pull_str[pin.pull()]) - if pin_mode == pyb.Pin.AF_PP or pin_mode == pyb.Pin.AF_OD: - pin_af = pin.af() - for af_entry in pin_entry[1:]: - if pin_af == af_entry[0]: - af_str = '%d: %s' % (pin_af, af_entry[1]) - break - else: - af_str = '%d' % pin_af - else: - af_str = '' - row.append(af_str) - for col in range(len(width)): - width[col] = max(width[col], len(row[col])) - rows.append(row) - for row in rows: - for col in range(len(width)): - print('%-*s ' % (width[col], row[col]), end='') - print('') diff --git a/examples/pyb.py b/examples/pyb.py deleted file mode 100644 index b303777e5a..0000000000 --- a/examples/pyb.py +++ /dev/null @@ -1,49 +0,0 @@ -# pyboard testing functions for CPython -import time - -def delay(n): - #time.sleep(float(n) / 1000) - pass - -rand_seed = 1 -def rng(): - global rand_seed - # for these choice of numbers, see P L'Ecuyer, "Tables of linear congruential generators of different sizes and good lattice structure" - rand_seed = (rand_seed * 653276) % 8388593 - return rand_seed - -# LCD testing object for PC -# uses double buffering -class LCD: - def __init__(self, port): - self.width = 128 - self.height = 32 - self.buf1 = [[0 for x in range(self.width)] for y in range(self.height)] - self.buf2 = [[0 for x in range(self.width)] for y in range(self.height)] - - def light(self, value): - pass - - def fill(self, value): - for y in range(self.height): - for x in range(self.width): - self.buf1[y][x] = self.buf2[y][x] = value - - def show(self): - print('') # blank line to separate frames - for y in range(self.height): - for x in range(self.width): - self.buf1[y][x] = self.buf2[y][x] - for y in range(self.height): - row = ''.join(['*' if self.buf1[y][x] else ' ' for x in range(self.width)]) - print(row) - - def get(self, x, y): - if 0 <= x < self.width and 0 <= y < self.height: - return self.buf1[y][x] - else: - return 0 - - def pixel(self, x, y, value): - if 0 <= x < self.width and 0 <= y < self.height: - self.buf2[y][x] = value diff --git a/examples/switch.py b/examples/switch.py deleted file mode 100644 index 0efaf22675..0000000000 --- a/examples/switch.py +++ /dev/null @@ -1,45 +0,0 @@ -""" -switch.py -========= - -Light up some leds when the USR switch on the pyboard is pressed. - -Example Usage:: - - Micro Python v1.0.1 on 2014-05-12; PYBv1.0 with STM32F405RG - Type "help()" for more information. - >>> import switch - >>> switch.run_loop() - Loop started. - Press Ctrl+C to break out of the loop. - -""" - -import pyb - -switch = pyb.Switch() -red_led = pyb.LED(1) -green_led = pyb.LED(2) -orange_led = pyb.LED(3) -blue_led = pyb.LED(4) -all_leds = (red_led, green_led, orange_led, blue_led) - -def run_loop(leds=all_leds): - """ - Start the loop. - - :param `leds`: Which LEDs to light up upon switch press. - :type `leds`: sequence of LED objects - """ - print('Loop started.\nPress Ctrl+C to break out of the loop.') - while 1: - try: - if switch(): - [led.on() for led in leds] - else: - [led.off() for led in leds] - except OSError: # VCPInterrupt # Ctrl+C in interpreter mode. - break - -if __name__ == '__main__': - run_loop() diff --git a/examples/unix/ffi_example.py b/examples/unix/ffi_example.py deleted file mode 100644 index f650e33708..0000000000 --- a/examples/unix/ffi_example.py +++ /dev/null @@ -1,38 +0,0 @@ -import ffi - -libc = ffi.open("libc.so.6") -print("libc:", libc) -print() - -# Declare few functions -perror = libc.func("v", "perror", "s") -time = libc.func("i", "time", "p") -open = libc.func("i", "open", "si") -qsort = libc.func("v", "qsort", "piip") -# And one variable -errno = libc.var("i", "errno") - -print("time:", time) -print("UNIX time is:", time(None)) -print() - -perror("ffi before error") -open("somethingnonexistent__", 0) -print("errno object:", errno) -print("errno value:", errno.get()) -perror("ffi after error") -print() - -def cmp(pa, pb): - a = ffi.as_bytearray(pa, 1) - b = ffi.as_bytearray(pb, 1) - print("cmp:", a, b) - return a[0] - b[0] - -cmp_c = ffi.callback("i", cmp, "pp") -print("callback:", cmp_c) - -s = bytearray(b"foobar") -print("org string:", s) -qsort(s, len(s), 1, cmp_c) -print("qsort'ed string:", s) diff --git a/examples/unix/machine_bios.py b/examples/unix/machine_bios.py deleted file mode 100644 index f62e4dbdb4..0000000000 --- a/examples/unix/machine_bios.py +++ /dev/null @@ -1,9 +0,0 @@ -# This example shows how to access Video BIOS memory area via machine.mem -# It requires root privilege and x86 legacy harfware (which has mentioned -# Video BIOS at all). -# It is expected to print 0xaa55, which is a signature at the start of -# Video BIOS. - -import umachine as machine - -print(hex(machine.mem16[0xc0000])) diff --git a/index.rst b/index.rst deleted file mode 100644 index 48b89583a7..0000000000 --- a/index.rst +++ /dev/null @@ -1,92 +0,0 @@ -Adafruit CircuitPython API Reference -==================================== - -.. image:: https://travis-ci.org/adafruit/circuitpython.svg?branch=master - :target: https://travis-ci.org/adafruit/circuitpython - :alt: Build Status - -.. image:: https://readthedocs.org/projects/circuitpython/badge/?version=latest - :target: http://circuitpython.readthedocs.io/ - :alt: Doc Status - -.. image:: https://badges.gitter.im/adafruit/circuitpython.svg - :target: https://gitter.im/adafruit/circuitpython?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge - :alt: Gitter - -.. image:: https://img.shields.io/discord/327254708534116352.svg - :target: https://adafru.it/discord - :alt: Discord - -Welcome to the API reference documentation for Adafruit CircuitPython. -This contains low-level API reference docs which may link out to separate -*"getting started"* guides. `Adafruit `_ has many -excellent tutorials available through the -`Adafruit Learning System `_. - -What is CircuitPython? ----------------------- - -**CircuitPython** is an *education friendly* open source derivative of -`MicroPython `_. CircuitPython supports use on -educational development boards designed and sold by -`Adafruit `_. Adafruit CircuitPython features unified -Python core APIs and a growing list of Adafruit libraries and drivers of -that work with it. - -What boards use CircuitPython? ------------------------------- - -The Adafruit Express line of boards is specifically -designed for use with CircuitPython. This line includes: -`CircuitPlayground Express `_; -`Feather M0 Express `_; and -`Metro M0 Express `_ - -Other supported boards include: -`Arduino Zero `_; -`Adafruit Feather M0 Basic `_; -`Adafruit Feather HUZZAH `_; and -`Adafruit Feather M0 Bluefruit LE `_. - -.. _contents: - -Full Table of Contents ----------------------- - -.. toctree:: - :maxdepth: 3 - :caption: API and Usage - - shared-bindings/index.rst - docs/supported_ports.rst - docs/troubleshooting.rst - docs/drivers.rst - -.. toctree:: - :maxdepth: 1 - :caption: Design and porting reference - - docs/design_guide - docs/common_hal - -.. toctree:: - :maxdepth: 2 - :caption: MicroPython specific - - docs/library/index.rst - -.. toctree:: - :maxdepth: 1 - :caption: About the project - - README - CONTRIBUTING - CODE_OF_CONDUCT - license.rst - -Indices and tables -================== - -* :ref:`genindex` -* :ref:`modindex` -* :ref:`search` diff --git a/shared-bindings/_stage/__init__.c b/shared-bindings/_stage/__init__.c index 16e0b58d94..832b287716 100644 --- a/shared-bindings/_stage/__init__.c +++ b/shared-bindings/_stage/__init__.c @@ -32,7 +32,22 @@ #include "Layer.h" #include "Text.h" -//| .. currentmodule:: _stage +//| :mod:`_stage` --- C-level helpers for animation of sprites on a stage +//| ===================================================================== +//| +//| .. module:: _stage +//| :synopsis: C-level helpers for animation of sprites on a stage +//| :platform: SAMD21 +//| +//| The `_stage` module contains native code to speed-up the ```stage`` Library +//| `_. +//| Libraries +//| +//| .. toctree:: +//| :maxdepth: 3 +//| +//| Layer +//| Text //| //| .. function:: render(x0, y0, x1, y1, layers, buffer, spi) //| @@ -42,9 +57,9 @@ //| :param int y0: Top edge of the fragment. //| :param int x1: Right edge of the fragment. //| :param int y1: Bottom edge of the fragment. -//| :param list layers: A list of the `Layer` objects. +//| :param list layers: A list of the :py:class:`~_stage.Layer` objects. //| :param bytearray buffer: A buffer to use for rendering. -//| :param SPI spi: The SPI device to use. +//| :param ~busio.SPI spi: The SPI bus to use. //| //| Note that this function only sends the raw pixel data. Setting up //| the display for receiving it and handling the chip-select and diff --git a/shared-bindings/audiobusio/PDMIn.c b/shared-bindings/audiobusio/PDMIn.c index c71f44679a..a48b48a2db 100644 --- a/shared-bindings/audiobusio/PDMIn.c +++ b/shared-bindings/audiobusio/PDMIn.c @@ -51,7 +51,7 @@ //| :param ~microcontroller.Pin clock_pin: The pin to output the clock to //| :param ~microcontroller.Pin data_pin: The pin to read the data from //| :param int frequency: Target frequency of the resulting samples. Check `frequency` for actual value. -//| Minimum frequency is about 16000 Hz. +//| Minimum frequency is about 16000 Hz. //| :param int bit_depth: Final number of bits per sample. Must be divisible by 8 //| :param bool mono: True when capturing a single channel of audio, captures two channels otherwise //| :param int oversample: Number of single bit samples to decimate into a final sample. Must be divisible by 8 @@ -180,8 +180,8 @@ STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(audiobusio_pdmin___exit___obj, 4, 4, //| audio at the given rate. For internal flash, writing all 1s to the file //| before recording is recommended to speed up writes. //| -//| :return: The number of samples recorded. If this is less than `destination_length`, -//| some samples were missed due to processing time. +//| :return: The number of samples recorded. If this is less than ``destination_length``, +//| some samples were missed due to processing time. //| STATIC mp_obj_t audiobusio_pdmin_obj_record(mp_obj_t self_obj, mp_obj_t destination, mp_obj_t destination_length) { audiobusio_pdmin_obj_t *self = MP_OBJ_TO_PTR(self_obj); diff --git a/shared-bindings/audiobusio/__init__.c b/shared-bindings/audiobusio/__init__.c index 70606e4964..bdd999b044 100644 --- a/shared-bindings/audiobusio/__init__.c +++ b/shared-bindings/audiobusio/__init__.c @@ -34,7 +34,7 @@ #include "shared-bindings/audiobusio/PDMIn.h" //| :mod:`audiobusio` --- Support for audio input and output over digital bus -//| ================================================= +//| ========================================================================= //| //| .. module:: audiobusio //| :synopsis: Support for audio input and output over digital bus diff --git a/shared-bindings/help.c b/shared-bindings/help.c index a3ae947975..cdd9a4a937 100644 --- a/shared-bindings/help.c +++ b/shared-bindings/help.c @@ -26,6 +26,15 @@ #include "genhdr/mpversion.h" +//| :func:`help` - Built-in method to provide helpful information +//| ============================================================== +//| +//| .. method:: help(object=None) +//| +//| Prints a help method about the given object. When ``object`` is none, +//| prints general port information. +//| + const char *circuitpython_help_text = "Welcome to Adafruit CircuitPython " MICROPY_GIT_TAG "!\r\n" "\r\n" diff --git a/shared-bindings/microcontroller/Processor.c b/shared-bindings/microcontroller/Processor.c index 0e843bd31d..528925ef77 100644 --- a/shared-bindings/microcontroller/Processor.c +++ b/shared-bindings/microcontroller/Processor.c @@ -38,7 +38,7 @@ //| .. currentmodule:: microcontroller //| //| :class:`Processor` --- Microcontroller CPU information and control -//| -------------------------------------------------------- +//| ------------------------------------------------------------------ //| //| Get information about the microcontroller CPU and control it. //| diff --git a/shared-bindings/microcontroller/__init__.c b/shared-bindings/microcontroller/__init__.c index cc091591f4..b5738f8661 100644 --- a/shared-bindings/microcontroller/__init__.c +++ b/shared-bindings/microcontroller/__init__.c @@ -59,11 +59,12 @@ //| //| Pin //| Processor +//| RunMode //| //| .. attribute:: cpu //| -//| CPU information and control, such as `cpu.temperature` and `cpu.frequency` +//| CPU information and control, such as ``cpu.temperature`` and ``cpu.frequency`` //| (clock frequency). //| This object is the sole instance of `microcontroller.Processor`. //| @@ -130,7 +131,7 @@ STATIC MP_DEFINE_CONST_FUN_OBJ_1(mcu_on_next_reset_obj, mcu_on_next_reset); //| .. method:: reset() //| //| Reset the microcontroller. After reset, the microcontroller will enter the -//| run mode last set by `one_next_reset`. +//| run mode last set by `on_next_reset`. //| //| .. warning:: This may result in file system corruption when connected to a //| host computer. Be very careful when calling this! Make sure the device diff --git a/shared-bindings/random/__init__.c b/shared-bindings/random/__init__.c index fe52c1fc05..cea437e98d 100644 --- a/shared-bindings/random/__init__.c +++ b/shared-bindings/random/__init__.c @@ -79,7 +79,7 @@ STATIC MP_DEFINE_CONST_FUN_OBJ_1(random_getrandbits_obj, random_getrandbits); //| .. function:: randrange(stop) //| randrange(start, stop, step=1) //| -//| Returns a randomly selected integer from `range(start, stop, step)`. +//| Returns a randomly selected integer from ``range(start, stop, step)``. //| STATIC mp_obj_t random_randrange(size_t n_args, const mp_obj_t *args) { mp_int_t start = 0; @@ -122,7 +122,7 @@ STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(random_randrange_obj, 1, 3, random_ra //| .. function:: randint(a, b) //| //| Returns a randomly selected integer between a and b inclusive. Equivalent -//| to `randrange(a, b + 1, 1)` +//| to ``randrange(a, b + 1, 1)`` //| STATIC mp_obj_t random_randint(mp_obj_t a_in, mp_obj_t b_in) { mp_int_t a = mp_obj_get_int(a_in); diff --git a/shared-bindings/storage/__init__.c b/shared-bindings/storage/__init__.c index 4831b0037a..ccf8ff511f 100644 --- a/shared-bindings/storage/__init__.c +++ b/shared-bindings/storage/__init__.c @@ -43,9 +43,7 @@ //| The `storage` provides storage management functionality such as mounting and //| unmounting which is typically handled by the operating system hosting Python. //| CircuitPython does not have an OS, so this module provides this functionality -//| directly. Its based on MicroPython's `uos` module but deliberately separates -//| CPython compatible functionality (in `os`) from incompatible functionality -//| (in `storage`). +//| directly. //| //| .. function:: mount(filesystem, mount_path, \*, readonly=False) From e667bdfe0583909c1a6fd7789ab5605f010d3005 Mon Sep 17 00:00:00 2001 From: Scott Shawcroft Date: Tue, 20 Feb 2018 18:06:42 -0800 Subject: [PATCH 064/135] Polish up the README since it was converted to RST from Markdown. --- README.rst | 32 +++++++++++--------------------- 1 file changed, 11 insertions(+), 21 deletions(-) diff --git a/README.rst b/README.rst index b2de4decab..7e234331ee 100644 --- a/README.rst +++ b/README.rst @@ -3,17 +3,17 @@ Adafruit CircuitPython |Build Status| |Doc Status| |Discord| -**`Status <#status>`__** \| **`Supported Boards <#supported-boards>`__** -\| **`Download <#download>`__** \| -**`Documentation <#documentation>`__** \| -**`Contributing <#contributing>`__** \| **`Differences from -Micropython <#differences-from-micropython>`__** \| **`Project -Structure <#project-structure>`__** +`Status <#status>`__ \| `Supported Boards <#supported-boards>`__ +\| `Download <#download>`__ \| +`Documentation <#documentation>`__ \| +`Contributing <#contributing>`__ \| `Differences from +Micropython <#differences-from-micropython>`__ \| `Project +Structure <#project-structure>`__ **CircuitPython** is an *education friendly* open source derivative of -``MicroPython ``\ *. CircuitPython supports use +`MicroPython `_. CircuitPython supports use on educational development boards designed and sold by -``Adafruit ``*. Adafruit CircuitPython features +`Adafruit `_. Adafruit CircuitPython features unified Python core APIs and a growing list of Adafruit libraries and drivers of that work with it. @@ -126,17 +126,7 @@ Behavior API ~~~ -- Unified hardware APIs: - ```audioio`` `__, - ```analogio`` `__, - ```busio`` `__, - ```digitalio`` `__, - ```pulseio`` `__, - ```touchio`` `__, - ```microcontroller`` `__, - ```board`` `__, - ```bitbangio`` `__ - (Only available on atmel-samd21 and ESP8266 currently.) +- Unified hardware APIs: `audioio `_, `analogio `_, `busio `_, `digitalio `_, `pulseio `_, `touchio `_, `microcontroller `_, `board `_, `bitbangio `_ - No ``machine`` API on Atmel SAMD21 port. Modules @@ -155,7 +145,7 @@ Modules Therefore, code from CircuitPython is runnable on CPython but not necessarily the reverse. - tick count is available as - ```time.monotonic()`` `__ + `time.monotonic() `__ atmel-samd21 features ~~~~~~~~~~~~~~~~~~~~~ @@ -243,7 +233,7 @@ The rest are here to maintain compatibility with the `MicroPython `__ parent project. -**`⬆ back to top <#adafruit-circuitpython>`__** +`⬆ back to top <#adafruit-circuitpython>`__ .. |Build Status| image:: https://travis-ci.org/adafruit/circuitpython.svg?branch=master :target: https://travis-ci.org/adafruit/circuitpython From 9c5a9e34118532bd54d92c9f968534ad9f9409ae Mon Sep 17 00:00:00 2001 From: James Devine Date: Wed, 21 Feb 2018 16:14:46 +0000 Subject: [PATCH 065/135] Update boards URL in README.rst Corrected a (probably) old URL in the read me. --- ports/atmel-samd/README.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ports/atmel-samd/README.rst b/ports/atmel-samd/README.rst index 5c314c53f6..8915189bdc 100644 --- a/ports/atmel-samd/README.rst +++ b/ports/atmel-samd/README.rst @@ -137,7 +137,7 @@ To build for other boards you must change it by setting ``BOARD``. For example: make BOARD=feather_m0_basic -Board names are the directory names in the `boards `_ folder. +Board names are the directory names in the `boards `_ folder. Deploying --------- From 9b4477e1dc088d18127838310b828514cb33edea Mon Sep 17 00:00:00 2001 From: Dan Halbert Date: Wed, 21 Feb 2018 16:30:26 -0500 Subject: [PATCH 066/135] Implement UART for 3.0 + related fixes. 1. UART: ported to ASF4. Allow rx-only and tx-only. Add .baudrate r/w property. 2. Make NeoPixel timing deterministic by turning off caches during NeoPixel writes. 3. Incorporate asf4 updates: a. async USART driver b. bringing Atmel START configuration closer to what we use c. Clock initialization order now specified by CIRCUITPY_GCLK_INIT_1ST and _LAST. 4. supervisor/port.c: Move commented-out clock-test pin setting to correct location. --- ports/atmel-samd/Makefile | 6 +- ports/atmel-samd/asf4 | 2 +- .../asf4_conf/samd21/hpl_gclk_config.h | 11 + .../asf4_conf/samd21/hpl_sercom_config.h | 188 ++++++- .../asf4_conf/samd21/peripheral_clk_config.h | 166 ++----- .../asf4_conf/samd51/hpl_gclk_config.h | 18 +- .../asf4_conf/samd51/hpl_sercom_config.h | 195 +++++++- .../asf4_conf/samd51/peripheral_clk_config.h | 140 ++++-- .../atmel-samd/boards/metro_m4_express/pins.c | 2 + ports/atmel-samd/common-hal/busio/SPI.c | 2 + ports/atmel-samd/common-hal/busio/UART.c | 463 ++++++++---------- ports/atmel-samd/common-hal/busio/UART.h | 29 +- .../common-hal/neopixel_write/__init__.c | 32 +- ports/atmel-samd/supervisor/port.c | 38 +- shared-bindings/busio/UART.c | 39 +- shared-bindings/busio/UART.h | 4 + shared-bindings/busio/__init__.c | 8 +- 17 files changed, 875 insertions(+), 468 deletions(-) diff --git a/ports/atmel-samd/Makefile b/ports/atmel-samd/Makefile index a5d1fd7c0e..4660d575ec 100644 --- a/ports/atmel-samd/Makefile +++ b/ports/atmel-samd/Makefile @@ -36,6 +36,7 @@ INC += -I. \ -Iasf4/$(CHIP_FAMILY)/hal/utils/include \ -Iasf4/$(CHIP_FAMILY)/hri \ -Iasf4/$(CHIP_FAMILY)/hpl/core \ + -Iasf4/$(CHIP_FAMILY)/hpl/gclk \ -Iasf4/$(CHIP_FAMILY)/hpl/pm \ -Iasf4/$(CHIP_FAMILY)/hpl/port \ -Iasf4/$(CHIP_FAMILY)/hpl/tc \ @@ -96,6 +97,7 @@ ifeq ($(DEBUG), 1) # Turn on Python modules useful for debugging (e.g. uheap, ustack). CFLAGS += -ggdb CFLAGS += -flto + ## CFLAGS += -fno-inline ifeq ($(CHIP_FAMILY), samd21) CFLAGS += -DENABLE_MICRO_TRACE_BUFFER endif @@ -178,6 +180,7 @@ SRC_ASF := \ hal/src/hal_sleep.c \ hal/src/hal_spi_m_sync.c \ hal/src/hal_timer.c \ + hal/src/hal_usart_async.c \ hal/src/hal_usb_device.c \ hpl/adc/hpl_adc.c \ hpl/core/hpl_init.c \ @@ -194,6 +197,7 @@ SRC_ASF := \ usb/device/usbdc.c \ usb/usb_protocol.c \ hal/utils/src/utils_list.c \ + hal/utils/src/utils_ringbuffer.c \ ifeq ($(CHIP_FAMILY), samd21) SRC_ASF += \ @@ -263,6 +267,7 @@ SRC_COMMON_HAL = \ busio/__init__.c \ busio/I2C.c \ busio/SPI.c \ + busio/UART.c \ digitalio/__init__.c \ digitalio/DigitalInOut.c \ microcontroller/__init__.c \ @@ -283,7 +288,6 @@ SRC_COMMON_HAL = \ audiobusio/PDMIn.c \ audioio/__init__.c \ audioio/AudioOut.c \ - busio/UART.c \ nvm/__init__.c \ nvm/ByteArray.c \ touchio/__init__.c \ diff --git a/ports/atmel-samd/asf4 b/ports/atmel-samd/asf4 index 0efc3407dd..aaa0f42811 160000 --- a/ports/atmel-samd/asf4 +++ b/ports/atmel-samd/asf4 @@ -1 +1 @@ -Subproject commit 0efc3407dd97ef617a5655674a3516693897a961 +Subproject commit aaa0f428111fbea7d56ab548053b11c9f12068f1 diff --git a/ports/atmel-samd/asf4_conf/samd21/hpl_gclk_config.h b/ports/atmel-samd/asf4_conf/samd21/hpl_gclk_config.h index fa9bb661cc..90df195cd8 100644 --- a/ports/atmel-samd/asf4_conf/samd21/hpl_gclk_config.h +++ b/ports/atmel-samd/asf4_conf/samd21/hpl_gclk_config.h @@ -1,3 +1,14 @@ +// Circuit Python SAMD21 clock tree: +// DFLL48M (with USBCRM on to sync with external USB ref) -> GCLK0 +// GCLK0 (48MHz) -> peripherals + +// We'd like to use XOSC32K as a ref for DFLL48M on boards with a 32kHz crystal, +// but haven't figured that out yet. + +// Used in hpl/core/hpl_init.c to define which clocks should be initialized first. +#define CIRCUITPY_GCLK_INIT_1ST (1 << 0) + + /* Auto-generated config file hpl_gclk_config.h */ #ifndef HPL_GCLK_CONFIG_H #define HPL_GCLK_CONFIG_H diff --git a/ports/atmel-samd/asf4_conf/samd21/hpl_sercom_config.h b/ports/atmel-samd/asf4_conf/samd21/hpl_sercom_config.h index 91141bcfcf..85d05fc504 100644 --- a/ports/atmel-samd/asf4_conf/samd21/hpl_sercom_config.h +++ b/ports/atmel-samd/asf4_conf/samd21/hpl_sercom_config.h @@ -3,14 +3,16 @@ // // SERCOM0: SPI with hal_spi_m_sync.c driver: spi master synchronous // SERCOM1: I2C with hal_i2c_m_sync.c driver: i2c master synchronous -// SERCOM2: USART with hal_usart_sync.c driver: usart synchronous +// SERCOM2: USART with hal_usart_async.c driver: usart asynchronous +// SERCOM3: SPI with hal_spi_m_dma.c: spi master DMA #define PROTOTYPE_SERCOM_SPI_M_SYNC SERCOM0 #define PROTOTYPE_SERCOM_SPI_M_SYNC_CLOCK_FREQUENCY CONF_GCLK_SERCOM0_CORE_FREQUENCY #define PROTOTYPE_SERCOM_I2CM_SYNC SERCOM1 -#define PROTOTYPE_SERCOM_USART_SYNC SERCOM2 +#define PROTOTYPE_SERCOM_USART_ASYNC SERCOM2 +#define PROTOTYPE_SERCOM_USART_ASYNC_CLOCK_FREQUENCY CONF_GCLK_SERCOM2_CORE_FREQUENCY /* Auto-generated config file hpl_sercom_config.h */ #ifndef HPL_SERCOM_CONFIG_H @@ -543,6 +545,188 @@ #endif #endif +#include + +// Enable configuration of module +#ifndef CONF_SERCOM_3_SPI_ENABLE +#define CONF_SERCOM_3_SPI_ENABLE 1 +#endif + +// SPI DMA TX Channel <0-32> +// This defines DMA channel to be used +// spi_master_dma_tx_channel +#ifndef CONF_SERCOM_3_SPI_M_DMA_TX_CHANNEL +#define CONF_SERCOM_3_SPI_M_DMA_TX_CHANNEL 0 +#endif + +// SPI RX Channel Enable +// spi_master_rx_channel +#ifndef CONF_SERCOM_3_SPI_RX_CHANNEL +#define CONF_SERCOM_3_SPI_RX_CHANNEL 1 +#endif + +// DMA Channel <0-32> +// This defines DMA channel to be used +// spi_master_dma_rx_channel +#ifndef CONF_SERCOM_3_SPI_M_DMA_RX_CHANNEL +#define CONF_SERCOM_3_SPI_M_DMA_RX_CHANNEL 1 +#endif + +// + +// Set module in SPI Master mode +#ifndef CONF_SERCOM_3_SPI_MODE +#define CONF_SERCOM_3_SPI_MODE 0x03 +#endif + +// Basic Configuration + +// Receive buffer enable +// Enable receive buffer to receive data from slave (RXEN) +// spi_master_rx_enable +#ifndef CONF_SERCOM_3_SPI_RXEN +#define CONF_SERCOM_3_SPI_RXEN 0x1 +#endif + +// Character Size +// Bit size for all characters sent over the SPI bus (CHSIZE) +// <0x0=>8 bits +// <0x1=>9 bits +// spi_master_character_size +#ifndef CONF_SERCOM_3_SPI_CHSIZE +#define CONF_SERCOM_3_SPI_CHSIZE 0x0 +#endif + +// Baud rate <1-12000000> +// The SPI data transfer rate +// spi_master_baud_rate +#ifndef CONF_SERCOM_3_SPI_BAUD +#define CONF_SERCOM_3_SPI_BAUD 50000 +#endif + +// + +// Advanced Configuration +// spi_master_advanced +#ifndef CONF_SERCOM_3_SPI_ADVANCED +#define CONF_SERCOM_3_SPI_ADVANCED 0 +#endif + +// Dummy byte <0x00-0x1ff> +// spi_master_dummybyte +// Dummy byte used when reading data from the slave without sending any data +#ifndef CONF_SERCOM_3_SPI_DUMMYBYTE +#define CONF_SERCOM_3_SPI_DUMMYBYTE 0x1ff +#endif + +// Data Order +// <0=>MSB first +// <1=>LSB first +// I least significant or most significant bit is shifted out first (DORD) +// spi_master_arch_dord +#ifndef CONF_SERCOM_3_SPI_DORD +#define CONF_SERCOM_3_SPI_DORD 0x0 +#endif + +// Clock Polarity +// <0=>SCK is low when idle +// <1=>SCK is high when idle +// Determines if the leading edge is rising or falling with a corresponding opposite edge at the trailing edge. (CPOL) +// spi_master_arch_cpol +#ifndef CONF_SERCOM_3_SPI_CPOL +#define CONF_SERCOM_3_SPI_CPOL 0x0 +#endif + +// Clock Phase +// <0x0=>Sample input on leading edge +// <0x1=>Sample input on trailing edge +// Determines if input data is sampled on leading or trailing SCK edge. (CPHA) +// spi_master_arch_cpha +#ifndef CONF_SERCOM_3_SPI_CPHA +#define CONF_SERCOM_3_SPI_CPHA 0x0 +#endif + +// Immediate Buffer Overflow Notification +// Controls when OVF is asserted (IBON) +// <0x0=>In data stream +// <0x1=>On buffer overflow +// spi_master_arch_ibon +#ifndef CONF_SERCOM_3_SPI_IBON +#define CONF_SERCOM_3_SPI_IBON 0x0 +#endif + +// Run in stand-by +// Module stays active in stand-by sleep mode. (RUNSTDBY) +// spi_master_arch_runstdby +#ifndef CONF_SERCOM_3_SPI_RUNSTDBY +#define CONF_SERCOM_3_SPI_RUNSTDBY 0x0 +#endif + +// Debug Stop Mode +// Behavior of the baud-rate generator when CPU is halted by external debugger. (DBGSTOP) +// <0=>Keep running +// <1=>Halt +// spi_master_arch_dbgstop +#ifndef CONF_SERCOM_3_SPI_DBGSTOP +#define CONF_SERCOM_3_SPI_DBGSTOP 0 +#endif + +// + +// Address mode disabled in master mode +#ifndef CONF_SERCOM_3_SPI_AMODE_EN +#define CONF_SERCOM_3_SPI_AMODE_EN 0 +#endif + +#ifndef CONF_SERCOM_3_SPI_AMODE +#define CONF_SERCOM_3_SPI_AMODE 0 +#endif + +#ifndef CONF_SERCOM_3_SPI_ADDR +#define CONF_SERCOM_3_SPI_ADDR 0 +#endif + +#ifndef CONF_SERCOM_3_SPI_ADDRMASK +#define CONF_SERCOM_3_SPI_ADDRMASK 0 +#endif + +#ifndef CONF_SERCOM_3_SPI_SSDE +#define CONF_SERCOM_3_SPI_SSDE 0 +#endif + +#ifndef CONF_SERCOM_3_SPI_MSSEN +#define CONF_SERCOM_3_SPI_MSSEN 0x0 +#endif + +#ifndef CONF_SERCOM_3_SPI_PLOADEN +#define CONF_SERCOM_3_SPI_PLOADEN 0 +#endif + +// Receive Data Pinout +// <0x0=>PAD[0] +// <0x1=>PAD[1] +// <0x2=>PAD[2] +// <0x3=>PAD[3] +// spi_master_rxpo +#ifndef CONF_SERCOM_3_SPI_RXPO +#define CONF_SERCOM_3_SPI_RXPO 0 +#endif + +// Transmit Data Pinout +// <0x0=>PAD[0,1]_DO_SCK +// <0x1=>PAD[2,3]_DO_SCK +// <0x2=>PAD[3,1]_DO_SCK +// <0x3=>PAD[0,3]_DO_SCK +// spi_master_txpo +#ifndef CONF_SERCOM_3_SPI_TXPO +#define CONF_SERCOM_3_SPI_TXPO 1 +#endif + +// Calculate baud register value from requested baudrate value +#ifndef CONF_SERCOM_3_SPI_BAUD_RATE +#define CONF_SERCOM_3_SPI_BAUD_RATE ((float)CONF_GCLK_SERCOM3_CORE_FREQUENCY / (float)(2 * CONF_SERCOM_3_SPI_BAUD)) - 1 +#endif + // <<< end of configuration section >>> #endif // HPL_SERCOM_CONFIG_H diff --git a/ports/atmel-samd/asf4_conf/samd21/peripheral_clk_config.h b/ports/atmel-samd/asf4_conf/samd21/peripheral_clk_config.h index b8080d059c..84fc6b9e4a 100644 --- a/ports/atmel-samd/asf4_conf/samd21/peripheral_clk_config.h +++ b/ports/atmel-samd/asf4_conf/samd21/peripheral_clk_config.h @@ -4,6 +4,38 @@ // <<< Use Configuration Wizard in Context Menu >>> +// ADC Clock Source +// adc_gclk_selection + +// Generic clock generator 0 + +// Generic clock generator 1 + +// Generic clock generator 2 + +// Generic clock generator 3 + +// Generic clock generator 4 + +// Generic clock generator 5 + +// Generic clock generator 6 + +// Generic clock generator 7 + +// Select the clock source for ADC. +#ifndef CONF_GCLK_ADC_SRC +#define CONF_GCLK_ADC_SRC GCLK_CLKCTRL_GEN_GCLK0_Val +#endif + +/** + * \def CONF_GCLK_ADC_FREQUENCY + * \brief ADC's Clock frequency + */ +#ifndef CONF_GCLK_ADC_FREQUENCY +#define CONF_GCLK_ADC_FREQUENCY 48000000 +#endif + /** * \def CONF_CPU_FREQUENCY * \brief CPU's Clock frequency @@ -268,134 +300,6 @@ #define CONF_GCLK_SERCOM3_SLOW_FREQUENCY 400000 #endif -// Core Clock Source -// core_gclk_selection - -// Generic clock generator 0 - -// Generic clock generator 1 - -// Generic clock generator 2 - -// Generic clock generator 3 - -// Generic clock generator 4 - -// Generic clock generator 5 - -// Generic clock generator 6 - -// Generic clock generator 7 - -// Select the clock source for CORE. -#ifndef CONF_GCLK_SERCOM4_CORE_SRC -#define CONF_GCLK_SERCOM4_CORE_SRC GCLK_CLKCTRL_GEN_GCLK0_Val -#endif - -// Slow Clock Source -// slow_gclk_selection - -// Generic clock generator 0 - -// Generic clock generator 1 - -// Generic clock generator 2 - -// Generic clock generator 3 - -// Generic clock generator 4 - -// Generic clock generator 5 - -// Generic clock generator 6 - -// Generic clock generator 7 - -// Select the slow clock source. -#ifndef CONF_GCLK_SERCOM4_SLOW_SRC -#define CONF_GCLK_SERCOM4_SLOW_SRC GCLK_CLKCTRL_GEN_GCLK3_Val -#endif - -/** - * \def CONF_GCLK_SERCOM4_CORE_FREQUENCY - * \brief SERCOM4's Core Clock frequency - */ -#ifndef CONF_GCLK_SERCOM4_CORE_FREQUENCY -#define CONF_GCLK_SERCOM4_CORE_FREQUENCY 48000000 -#endif - -/** - * \def CONF_GCLK_SERCOM4_SLOW_FREQUENCY - * \brief SERCOM4's Slow Clock frequency - */ -#ifndef CONF_GCLK_SERCOM4_SLOW_FREQUENCY -#define CONF_GCLK_SERCOM4_SLOW_FREQUENCY 400000 -#endif - -// Core Clock Source -// core_gclk_selection - -// Generic clock generator 0 - -// Generic clock generator 1 - -// Generic clock generator 2 - -// Generic clock generator 3 - -// Generic clock generator 4 - -// Generic clock generator 5 - -// Generic clock generator 6 - -// Generic clock generator 7 - -// Select the clock source for CORE. -#ifndef CONF_GCLK_SERCOM5_CORE_SRC -#define CONF_GCLK_SERCOM5_CORE_SRC GCLK_CLKCTRL_GEN_GCLK0_Val -#endif - -// Slow Clock Source -// slow_gclk_selection - -// Generic clock generator 0 - -// Generic clock generator 1 - -// Generic clock generator 2 - -// Generic clock generator 3 - -// Generic clock generator 4 - -// Generic clock generator 5 - -// Generic clock generator 6 - -// Generic clock generator 7 - -// Select the slow clock source. -#ifndef CONF_GCLK_SERCOM5_SLOW_SRC -#define CONF_GCLK_SERCOM5_SLOW_SRC GCLK_CLKCTRL_GEN_GCLK3_Val -#endif - -/** - * \def CONF_GCLK_SERCOM5_CORE_FREQUENCY - * \brief SERCOM5's Core Clock frequency - */ -#ifndef CONF_GCLK_SERCOM5_CORE_FREQUENCY -#define CONF_GCLK_SERCOM5_CORE_FREQUENCY 48000000 -#endif - -/** - * \def CONF_GCLK_SERCOM5_SLOW_FREQUENCY - * \brief SERCOM5's Slow Clock frequency - */ -#ifndef CONF_GCLK_SERCOM5_SLOW_FREQUENCY -#define CONF_GCLK_SERCOM5_SLOW_FREQUENCY 400000 -#endif - // RTC Clock Source // rtc_clk_selection @@ -425,7 +329,7 @@ * \brief RTC's Clock frequency */ #ifndef CONF_GCLK_RTC_FREQUENCY -#define CONF_GCLK_RTC_FREQUENCY 1000000 +#define CONF_GCLK_RTC_FREQUENCY 48000000 #endif // TC Clock Source @@ -457,7 +361,7 @@ * \brief TC3's Clock frequency */ #ifndef CONF_GCLK_TC3_FREQUENCY -#define CONF_GCLK_TC3_FREQUENCY 1000000 +#define CONF_GCLK_TC3_FREQUENCY 48000000 #endif // DAC Clock Source @@ -489,7 +393,7 @@ * \brief DAC's Clock frequency */ #ifndef CONF_GCLK_DAC_FREQUENCY -#define CONF_GCLK_DAC_FREQUENCY 1000000 +#define CONF_GCLK_DAC_FREQUENCY 48000000 #endif // USB Clock Source diff --git a/ports/atmel-samd/asf4_conf/samd51/hpl_gclk_config.h b/ports/atmel-samd/asf4_conf/samd51/hpl_gclk_config.h index 9a0081c79b..300db2716d 100644 --- a/ports/atmel-samd/asf4_conf/samd51/hpl_gclk_config.h +++ b/ports/atmel-samd/asf4_conf/samd51/hpl_gclk_config.h @@ -1,7 +1,17 @@ -// The clock tree starts with 48mhz DFLL48M based on USB. GCLK5 divides it down -// to 2mhz which DPLL0 boosts to 120mhz. This is then used by GCLK0 to clock the -// core and main bus. GCLK1 is 48mhz based on DFLL48M which is used for USB. -// GCLK4 also outputs the 120mhz clock for monitoring. +// Circuit Python SAMD51 clock tree: +// DFLL48M (with USBCRM on to sync with external USB ref) -> GCLK1, GCLK5 +// GCLK1 (48MHz) -> peripherals +// GCLK5 (divided down to 2 MHz) -> DPLL0 +// DPLL0 (multiplied up to 120 MHz) -> GCLK0, GCLK4 (output for monitoring) + +// We'd like to use XOSC32K as a ref for DFLL48M on boards with a 32kHz crystal, +// but haven't figured that out yet. + +// Used in hpl/core/hpl_init.c to define which clocks should be initialized first. +// Not clear why all these need to be specified, but it doesn't work properly otherwise. + +//#define CIRCUITPY_GCLK_INIT_1ST (1 << 0 | 1 << 1 | 1 << 3 | 1 <<5) +#define CIRCUITPY_GCLK_INIT_1ST 0xffff /* Auto-generated config file hpl_gclk_config.h */ #ifndef HPL_GCLK_CONFIG_H diff --git a/ports/atmel-samd/asf4_conf/samd51/hpl_sercom_config.h b/ports/atmel-samd/asf4_conf/samd51/hpl_sercom_config.h index 1830c54900..cd411154c7 100644 --- a/ports/atmel-samd/asf4_conf/samd51/hpl_sercom_config.h +++ b/ports/atmel-samd/asf4_conf/samd51/hpl_sercom_config.h @@ -3,13 +3,16 @@ // // SERCOM0: SPI with hal_spi_m_sync.c driver: spi master synchronous // SERCOM1: I2C with hal_i2c_m_sync.c driver: i2c master synchronous -// SERCOM2: USART with hal_usart_sync.c driver: usart synchronous +// SERCOM2: USART with hal_usart_async.c driver: usart asynchronous +// SERCOM3: SPI with hal_spi_m_dma.c: spi master DMA #define PROTOTYPE_SERCOM_SPI_M_SYNC SERCOM0 #define PROTOTYPE_SERCOM_SPI_M_SYNC_CLOCK_FREQUENCY CONF_GCLK_SERCOM0_CORE_FREQUENCY #define PROTOTYPE_SERCOM_I2CM_SYNC SERCOM1 -#define PROTOTYPE_SERCOM_USART_SYNC SERCOM2 + +#define PROTOTYPE_SERCOM_USART_ASYNC SERCOM2 +#define PROTOTYPE_SERCOM_USART_ASYNC_CLOCK_FREQUENCY CONF_GCLK_SERCOM2_CORE_FREQUENCY /* Auto-generated config file hpl_sercom_config.h */ #ifndef HPL_SERCOM_CONFIG_H @@ -59,7 +62,7 @@ // Advanced Configuration // spi_master_advanced #ifndef CONF_SERCOM_0_SPI_ADVANCED -#define CONF_SERCOM_0_SPI_ADVANCED 0 +#define CONF_SERCOM_0_SPI_ADVANCED 1 #endif // Dummy byte <0x00-0x1ff> @@ -201,7 +204,7 @@ // Advanced // i2c_master_advanced #ifndef CONF_SERCOM_1_I2CM_ADVANCED_CONFIG -#define CONF_SERCOM_1_I2CM_ADVANCED_CONFIG 0 +#define CONF_SERCOM_1_I2CM_ADVANCED_CONFIG 1 #endif // TRise (ns) <0-300> @@ -377,7 +380,7 @@ // Advanced configuration // usart_advanced #ifndef CONF_SERCOM_2_USART_ADVANCED_CONFIG -#define CONF_SERCOM_2_USART_ADVANCED_CONFIG 0 +#define CONF_SERCOM_2_USART_ADVANCED_CONFIG 1 #endif // Run in stand-by @@ -561,6 +564,188 @@ #endif #endif +#include + +// Enable configuration of module +#ifndef CONF_SERCOM_3_SPI_ENABLE +#define CONF_SERCOM_3_SPI_ENABLE 1 +#endif + +// SPI DMA TX Channel <0-32> +// This defines DMA channel to be used +// spi_master_dma_tx_channel +#ifndef CONF_SERCOM_3_SPI_M_DMA_TX_CHANNEL +#define CONF_SERCOM_3_SPI_M_DMA_TX_CHANNEL 0 +#endif + +// SPI RX Channel Enable +// spi_master_rx_channel +#ifndef CONF_SERCOM_3_SPI_RX_CHANNEL +#define CONF_SERCOM_3_SPI_RX_CHANNEL 1 +#endif + +// DMA Channel <0-32> +// This defines DMA channel to be used +// spi_master_dma_rx_channel +#ifndef CONF_SERCOM_3_SPI_M_DMA_RX_CHANNEL +#define CONF_SERCOM_3_SPI_M_DMA_RX_CHANNEL 1 +#endif + +// + +// Set module in SPI Master mode +#ifndef CONF_SERCOM_3_SPI_MODE +#define CONF_SERCOM_3_SPI_MODE 0x03 +#endif + +// Basic Configuration + +// Receive buffer enable +// Enable receive buffer to receive data from slave (RXEN) +// spi_master_rx_enable +#ifndef CONF_SERCOM_3_SPI_RXEN +#define CONF_SERCOM_3_SPI_RXEN 0x1 +#endif + +// Character Size +// Bit size for all characters sent over the SPI bus (CHSIZE) +// <0x0=>8 bits +// <0x1=>9 bits +// spi_master_character_size +#ifndef CONF_SERCOM_3_SPI_CHSIZE +#define CONF_SERCOM_3_SPI_CHSIZE 0x0 +#endif + +// Baud rate <1-12000000> +// The SPI data transfer rate +// spi_master_baud_rate +#ifndef CONF_SERCOM_3_SPI_BAUD +#define CONF_SERCOM_3_SPI_BAUD 50000 +#endif + +// + +// Advanced Configuration +// spi_master_advanced +#ifndef CONF_SERCOM_3_SPI_ADVANCED +#define CONF_SERCOM_3_SPI_ADVANCED 0 +#endif + +// Dummy byte <0x00-0x1ff> +// spi_master_dummybyte +// Dummy byte used when reading data from the slave without sending any data +#ifndef CONF_SERCOM_3_SPI_DUMMYBYTE +#define CONF_SERCOM_3_SPI_DUMMYBYTE 0x1ff +#endif + +// Data Order +// <0=>MSB first +// <1=>LSB first +// I least significant or most significant bit is shifted out first (DORD) +// spi_master_arch_dord +#ifndef CONF_SERCOM_3_SPI_DORD +#define CONF_SERCOM_3_SPI_DORD 0x0 +#endif + +// Clock Polarity +// <0=>SCK is low when idle +// <1=>SCK is high when idle +// Determines if the leading edge is rising or falling with a corresponding opposite edge at the trailing edge. (CPOL) +// spi_master_arch_cpol +#ifndef CONF_SERCOM_3_SPI_CPOL +#define CONF_SERCOM_3_SPI_CPOL 0x0 +#endif + +// Clock Phase +// <0x0=>Sample input on leading edge +// <0x1=>Sample input on trailing edge +// Determines if input data is sampled on leading or trailing SCK edge. (CPHA) +// spi_master_arch_cpha +#ifndef CONF_SERCOM_3_SPI_CPHA +#define CONF_SERCOM_3_SPI_CPHA 0x0 +#endif + +// Immediate Buffer Overflow Notification +// Controls when OVF is asserted (IBON) +// <0x0=>In data stream +// <0x1=>On buffer overflow +// spi_master_arch_ibon +#ifndef CONF_SERCOM_3_SPI_IBON +#define CONF_SERCOM_3_SPI_IBON 0x0 +#endif + +// Run in stand-by +// Module stays active in stand-by sleep mode. (RUNSTDBY) +// spi_master_arch_runstdby +#ifndef CONF_SERCOM_3_SPI_RUNSTDBY +#define CONF_SERCOM_3_SPI_RUNSTDBY 0x0 +#endif + +// Debug Stop Mode +// Behavior of the baud-rate generator when CPU is halted by external debugger. (DBGSTOP) +// <0=>Keep running +// <1=>Halt +// spi_master_arch_dbgstop +#ifndef CONF_SERCOM_3_SPI_DBGSTOP +#define CONF_SERCOM_3_SPI_DBGSTOP 0 +#endif + +// + +// Address mode disabled in master mode +#ifndef CONF_SERCOM_3_SPI_AMODE_EN +#define CONF_SERCOM_3_SPI_AMODE_EN 0 +#endif + +#ifndef CONF_SERCOM_3_SPI_AMODE +#define CONF_SERCOM_3_SPI_AMODE 0 +#endif + +#ifndef CONF_SERCOM_3_SPI_ADDR +#define CONF_SERCOM_3_SPI_ADDR 0 +#endif + +#ifndef CONF_SERCOM_3_SPI_ADDRMASK +#define CONF_SERCOM_3_SPI_ADDRMASK 0 +#endif + +#ifndef CONF_SERCOM_3_SPI_SSDE +#define CONF_SERCOM_3_SPI_SSDE 0 +#endif + +#ifndef CONF_SERCOM_3_SPI_MSSEN +#define CONF_SERCOM_3_SPI_MSSEN 0x0 +#endif + +#ifndef CONF_SERCOM_3_SPI_PLOADEN +#define CONF_SERCOM_3_SPI_PLOADEN 0 +#endif + +// Receive Data Pinout +// <0x0=>PAD[0] +// <0x1=>PAD[1] +// <0x2=>PAD[2] +// <0x3=>PAD[3] +// spi_master_rxpo +#ifndef CONF_SERCOM_3_SPI_RXPO +#define CONF_SERCOM_3_SPI_RXPO 2 +#endif + +// Transmit Data Pinout +// <0x0=>PAD[0,1]_DO_SCK +// <0x1=>PAD[2,3]_DO_SCK +// <0x2=>PAD[3,1]_DO_SCK +// <0x3=>PAD[0,3]_DO_SCK +// spi_master_txpo +#ifndef CONF_SERCOM_3_SPI_TXPO +#define CONF_SERCOM_3_SPI_TXPO 0 +#endif + +// Calculate baud register value from requested baudrate value +#ifndef CONF_SERCOM_3_SPI_BAUD_RATE +#define CONF_SERCOM_3_SPI_BAUD_RATE ((float)CONF_GCLK_SERCOM3_CORE_FREQUENCY / (float)(2 * CONF_SERCOM_3_SPI_BAUD)) - 1 +#endif + // <<< end of configuration section >>> #endif // HPL_SERCOM_CONFIG_H diff --git a/ports/atmel-samd/asf4_conf/samd51/peripheral_clk_config.h b/ports/atmel-samd/asf4_conf/samd51/peripheral_clk_config.h index 830f0e83b5..c1df632113 100644 --- a/ports/atmel-samd/asf4_conf/samd51/peripheral_clk_config.h +++ b/ports/atmel-samd/asf4_conf/samd51/peripheral_clk_config.h @@ -33,7 +33,7 @@ // Select the clock source for ADC. #ifndef CONF_GCLK_ADC0_SRC -#define CONF_GCLK_ADC0_SRC GCLK_PCHCTRL_GEN_GCLK0_Val +#define CONF_GCLK_ADC0_SRC GCLK_PCHCTRL_GEN_GCLK1_Val #endif /** @@ -41,7 +41,7 @@ * \brief ADC0's Clock frequency */ #ifndef CONF_GCLK_ADC0_FREQUENCY -#define CONF_GCLK_ADC0_FREQUENCY 120000000 +#define CONF_GCLK_ADC0_FREQUENCY 48000000 #endif // DAC Clock Source @@ -73,7 +73,7 @@ // dac_gclk_selection // Select the clock source for DAC. #ifndef CONF_GCLK_DAC_SRC -#define CONF_GCLK_DAC_SRC GCLK_PCHCTRL_GEN_GCLK0_Val +#define CONF_GCLK_DAC_SRC GCLK_PCHCTRL_GEN_GCLK1_Val #endif /** @@ -81,7 +81,7 @@ * \brief DAC's Clock frequency */ #ifndef CONF_GCLK_DAC_FREQUENCY -#define CONF_GCLK_DAC_FREQUENCY 120000000 +#define CONF_GCLK_DAC_FREQUENCY 48000000 #endif // EVSYS Channel 0 Clock Source @@ -113,7 +113,7 @@ // Select the clock source for channel 0. #ifndef CONF_GCLK_EVSYS_CHANNEL_0_SRC -#define CONF_GCLK_EVSYS_CHANNEL_0_SRC GCLK_PCHCTRL_GEN_GCLK0_Val +#define CONF_GCLK_EVSYS_CHANNEL_0_SRC GCLK_PCHCTRL_GEN_GCLK1_Val #endif /** @@ -122,7 +122,7 @@ */ #ifndef CONF_GCLK_EVSYS_CHANNEL_0_FREQUENCY -#define CONF_GCLK_EVSYS_CHANNEL_0_FREQUENCY 120000000.0 +#define CONF_GCLK_EVSYS_CHANNEL_0_FREQUENCY 48000000.0 #endif // EVSYS Channel 1 Clock Source @@ -154,7 +154,7 @@ // Select the clock source for channel 1. #ifndef CONF_GCLK_EVSYS_CHANNEL_1_SRC -#define CONF_GCLK_EVSYS_CHANNEL_1_SRC GCLK_PCHCTRL_GEN_GCLK0_Val +#define CONF_GCLK_EVSYS_CHANNEL_1_SRC GCLK_PCHCTRL_GEN_GCLK1_Val #endif /** @@ -163,7 +163,7 @@ */ #ifndef CONF_GCLK_EVSYS_CHANNEL_1_FREQUENCY -#define CONF_GCLK_EVSYS_CHANNEL_1_FREQUENCY 120000000.0 +#define CONF_GCLK_EVSYS_CHANNEL_1_FREQUENCY 48000000.0 #endif // EVSYS Channel 2 Clock Source @@ -195,7 +195,7 @@ // Select the clock source for channel 2. #ifndef CONF_GCLK_EVSYS_CHANNEL_2_SRC -#define CONF_GCLK_EVSYS_CHANNEL_2_SRC GCLK_PCHCTRL_GEN_GCLK0_Val +#define CONF_GCLK_EVSYS_CHANNEL_2_SRC GCLK_PCHCTRL_GEN_GCLK1_Val #endif /** @@ -204,7 +204,7 @@ */ #ifndef CONF_GCLK_EVSYS_CHANNEL_2_FREQUENCY -#define CONF_GCLK_EVSYS_CHANNEL_2_FREQUENCY 120000000.0 +#define CONF_GCLK_EVSYS_CHANNEL_2_FREQUENCY 48000000.0 #endif // EVSYS Channel 3 Clock Source @@ -236,7 +236,7 @@ // Select the clock source for channel 3. #ifndef CONF_GCLK_EVSYS_CHANNEL_3_SRC -#define CONF_GCLK_EVSYS_CHANNEL_3_SRC GCLK_PCHCTRL_GEN_GCLK0_Val +#define CONF_GCLK_EVSYS_CHANNEL_3_SRC GCLK_PCHCTRL_GEN_GCLK1_Val #endif /** @@ -245,7 +245,7 @@ */ #ifndef CONF_GCLK_EVSYS_CHANNEL_3_FREQUENCY -#define CONF_GCLK_EVSYS_CHANNEL_3_FREQUENCY 120000000.0 +#define CONF_GCLK_EVSYS_CHANNEL_3_FREQUENCY 48000000.0 #endif // EVSYS Channel 4 Clock Source @@ -277,7 +277,7 @@ // Select the clock source for channel 4. #ifndef CONF_GCLK_EVSYS_CHANNEL_4_SRC -#define CONF_GCLK_EVSYS_CHANNEL_4_SRC GCLK_PCHCTRL_GEN_GCLK0_Val +#define CONF_GCLK_EVSYS_CHANNEL_4_SRC GCLK_PCHCTRL_GEN_GCLK1_Val #endif /** @@ -286,7 +286,7 @@ */ #ifndef CONF_GCLK_EVSYS_CHANNEL_4_FREQUENCY -#define CONF_GCLK_EVSYS_CHANNEL_4_FREQUENCY 120000000.0 +#define CONF_GCLK_EVSYS_CHANNEL_4_FREQUENCY 48000000.0 #endif // EVSYS Channel 5 Clock Source @@ -318,7 +318,7 @@ // Select the clock source for channel 5. #ifndef CONF_GCLK_EVSYS_CHANNEL_5_SRC -#define CONF_GCLK_EVSYS_CHANNEL_5_SRC GCLK_PCHCTRL_GEN_GCLK0_Val +#define CONF_GCLK_EVSYS_CHANNEL_5_SRC GCLK_PCHCTRL_GEN_GCLK1_Val #endif /** @@ -327,7 +327,7 @@ */ #ifndef CONF_GCLK_EVSYS_CHANNEL_5_FREQUENCY -#define CONF_GCLK_EVSYS_CHANNEL_5_FREQUENCY 120000000.0 +#define CONF_GCLK_EVSYS_CHANNEL_5_FREQUENCY 48000000.0 #endif // EVSYS Channel 6 Clock Source @@ -359,7 +359,7 @@ // Select the clock source for channel 6. #ifndef CONF_GCLK_EVSYS_CHANNEL_6_SRC -#define CONF_GCLK_EVSYS_CHANNEL_6_SRC GCLK_PCHCTRL_GEN_GCLK0_Val +#define CONF_GCLK_EVSYS_CHANNEL_6_SRC GCLK_PCHCTRL_GEN_GCLK1_Val #endif /** @@ -368,7 +368,7 @@ */ #ifndef CONF_GCLK_EVSYS_CHANNEL_6_FREQUENCY -#define CONF_GCLK_EVSYS_CHANNEL_6_FREQUENCY 120000000.0 +#define CONF_GCLK_EVSYS_CHANNEL_6_FREQUENCY 48000000.0 #endif // EVSYS Channel 7 Clock Source @@ -400,7 +400,7 @@ // Select the clock source for channel 7. #ifndef CONF_GCLK_EVSYS_CHANNEL_7_SRC -#define CONF_GCLK_EVSYS_CHANNEL_7_SRC GCLK_PCHCTRL_GEN_GCLK0_Val +#define CONF_GCLK_EVSYS_CHANNEL_7_SRC GCLK_PCHCTRL_GEN_GCLK1_Val #endif /** @@ -409,7 +409,7 @@ */ #ifndef CONF_GCLK_EVSYS_CHANNEL_7_FREQUENCY -#define CONF_GCLK_EVSYS_CHANNEL_7_FREQUENCY 120000000.0 +#define CONF_GCLK_EVSYS_CHANNEL_7_FREQUENCY 48000000.0 #endif // EVSYS Channel 8 Clock Source @@ -441,7 +441,7 @@ // Select the clock source for channel 8. #ifndef CONF_GCLK_EVSYS_CHANNEL_8_SRC -#define CONF_GCLK_EVSYS_CHANNEL_8_SRC GCLK_PCHCTRL_GEN_GCLK0_Val +#define CONF_GCLK_EVSYS_CHANNEL_8_SRC GCLK_PCHCTRL_GEN_GCLK1_Val #endif /** @@ -450,7 +450,7 @@ */ #ifndef CONF_GCLK_EVSYS_CHANNEL_8_FREQUENCY -#define CONF_GCLK_EVSYS_CHANNEL_8_FREQUENCY 120000000.0 +#define CONF_GCLK_EVSYS_CHANNEL_8_FREQUENCY 48000000.0 #endif // EVSYS Channel 9 Clock Source @@ -482,7 +482,7 @@ // Select the clock source for channel 9. #ifndef CONF_GCLK_EVSYS_CHANNEL_9_SRC -#define CONF_GCLK_EVSYS_CHANNEL_9_SRC GCLK_PCHCTRL_GEN_GCLK0_Val +#define CONF_GCLK_EVSYS_CHANNEL_9_SRC GCLK_PCHCTRL_GEN_GCLK1_Val #endif /** @@ -491,7 +491,7 @@ */ #ifndef CONF_GCLK_EVSYS_CHANNEL_9_FREQUENCY -#define CONF_GCLK_EVSYS_CHANNEL_9_FREQUENCY 120000000.0 +#define CONF_GCLK_EVSYS_CHANNEL_9_FREQUENCY 48000000.0 #endif // EVSYS Channel 10 Clock Source @@ -523,7 +523,7 @@ // Select the clock source for channel 10. #ifndef CONF_GCLK_EVSYS_CHANNEL_10_SRC -#define CONF_GCLK_EVSYS_CHANNEL_10_SRC GCLK_PCHCTRL_GEN_GCLK0_Val +#define CONF_GCLK_EVSYS_CHANNEL_10_SRC GCLK_PCHCTRL_GEN_GCLK1_Val #endif /** @@ -532,7 +532,7 @@ */ #ifndef CONF_GCLK_EVSYS_CHANNEL_10_FREQUENCY -#define CONF_GCLK_EVSYS_CHANNEL_10_FREQUENCY 120000000.0 +#define CONF_GCLK_EVSYS_CHANNEL_10_FREQUENCY 48000000.0 #endif // EVSYS Channel 11 Clock Source @@ -564,7 +564,7 @@ // Select the clock source for channel 11. #ifndef CONF_GCLK_EVSYS_CHANNEL_11_SRC -#define CONF_GCLK_EVSYS_CHANNEL_11_SRC GCLK_PCHCTRL_GEN_GCLK0_Val +#define CONF_GCLK_EVSYS_CHANNEL_11_SRC GCLK_PCHCTRL_GEN_GCLK1_Val #endif /** @@ -573,7 +573,7 @@ */ #ifndef CONF_GCLK_EVSYS_CHANNEL_11_FREQUENCY -#define CONF_GCLK_EVSYS_CHANNEL_11_FREQUENCY 120000000.0 +#define CONF_GCLK_EVSYS_CHANNEL_11_FREQUENCY 48000000.0 #endif /** @@ -840,6 +840,86 @@ #define CONF_GCLK_SERCOM2_SLOW_FREQUENCY 32768 #endif +// Core Clock Source +// core_gclk_selection + +// Generic clock generator 0 + +// Generic clock generator 1 + +// Generic clock generator 2 + +// Generic clock generator 3 + +// Generic clock generator 4 + +// Generic clock generator 5 + +// Generic clock generator 6 + +// Generic clock generator 7 + +// Generic clock generator 8 + +// Generic clock generator 9 + +// Generic clock generator 10 + +// Generic clock generator 11 + +// Select the clock source for CORE. +#ifndef CONF_GCLK_SERCOM3_CORE_SRC +#define CONF_GCLK_SERCOM3_CORE_SRC GCLK_PCHCTRL_GEN_GCLK1_Val +#endif + +// Slow Clock Source +// slow_gclk_selection + +// Generic clock generator 0 + +// Generic clock generator 1 + +// Generic clock generator 2 + +// Generic clock generator 3 + +// Generic clock generator 4 + +// Generic clock generator 5 + +// Generic clock generator 6 + +// Generic clock generator 7 + +// Generic clock generator 8 + +// Generic clock generator 9 + +// Generic clock generator 10 + +// Generic clock generator 11 + +// Select the slow clock source. +#ifndef CONF_GCLK_SERCOM3_SLOW_SRC +#define CONF_GCLK_SERCOM3_SLOW_SRC GCLK_PCHCTRL_GEN_GCLK3_Val +#endif + +/** + * \def CONF_GCLK_SERCOM3_CORE_FREQUENCY + * \brief SERCOM3's Core Clock frequency + */ +#ifndef CONF_GCLK_SERCOM3_CORE_FREQUENCY +#define CONF_GCLK_SERCOM3_CORE_FREQUENCY 48000000 +#endif + +/** + * \def CONF_GCLK_SERCOM3_SLOW_FREQUENCY + * \brief SERCOM3's Slow Clock frequency + */ +#ifndef CONF_GCLK_SERCOM3_SLOW_FREQUENCY +#define CONF_GCLK_SERCOM3_SLOW_FREQUENCY 32768 +#endif + // TC Clock Source // tc_gclk_selection @@ -869,7 +949,7 @@ // Select the clock source for TC. #ifndef CONF_GCLK_TC0_SRC -#define CONF_GCLK_TC0_SRC GCLK_PCHCTRL_GEN_GCLK0_Val +#define CONF_GCLK_TC0_SRC GCLK_PCHCTRL_GEN_GCLK1_Val #endif /** @@ -877,7 +957,7 @@ * \brief TC0's Clock frequency */ #ifndef CONF_GCLK_TC0_FREQUENCY -#define CONF_GCLK_TC0_FREQUENCY 120000000 +#define CONF_GCLK_TC0_FREQUENCY 48000000 #endif // USB Clock Source diff --git a/ports/atmel-samd/boards/metro_m4_express/pins.c b/ports/atmel-samd/boards/metro_m4_express/pins.c index 5889c6c685..33b69b32b3 100644 --- a/ports/atmel-samd/boards/metro_m4_express/pins.c +++ b/ports/atmel-samd/boards/metro_m4_express/pins.c @@ -13,7 +13,9 @@ STATIC const mp_map_elem_t board_global_dict_table[] = { { MP_OBJ_NEW_QSTR(MP_QSTR_D0), (mp_obj_t)&pin_PA23 }, + { MP_OBJ_NEW_QSTR(MP_QSTR_RX), (mp_obj_t)&pin_PA23 }, { MP_OBJ_NEW_QSTR(MP_QSTR_D1), (mp_obj_t)&pin_PA22 }, + { MP_OBJ_NEW_QSTR(MP_QSTR_TX), (mp_obj_t)&pin_PA22 }, { MP_OBJ_NEW_QSTR(MP_QSTR_D2), (mp_obj_t)&pin_PA04 }, { MP_OBJ_NEW_QSTR(MP_QSTR_D3), (mp_obj_t)&pin_PB16 }, { MP_OBJ_NEW_QSTR(MP_QSTR_D4), (mp_obj_t)&pin_PB13 }, diff --git a/ports/atmel-samd/common-hal/busio/SPI.c b/ports/atmel-samd/common-hal/busio/SPI.c index ca98d1d2f2..c4cd6e66f8 100644 --- a/ports/atmel-samd/common-hal/busio/SPI.c +++ b/ports/atmel-samd/common-hal/busio/SPI.c @@ -117,6 +117,8 @@ void common_hal_busio_spi_construct(busio_spi_obj_t *self, mp_raise_OSError(MP_EIO); } + // Pads must be set after spi_m_sync_init(), which uses default values from + // the prototypical SERCOM. hri_sercomspi_write_CTRLA_DOPO_bf(sercom, dopo); hri_sercomspi_write_CTRLA_DIPO_bf(sercom, miso_pad); diff --git a/ports/atmel-samd/common-hal/busio/UART.c b/ports/atmel-samd/common-hal/busio/UART.c index 79f7cf4a9e..292e01e60e 100644 --- a/ports/atmel-samd/common-hal/busio/UART.c +++ b/ports/atmel-samd/common-hal/busio/UART.c @@ -30,97 +30,25 @@ #include "mpconfigport.h" #include "py/gc.h" #include "py/mperrno.h" -#include "py/nlr.h" #include "py/runtime.h" #include "py/stream.h" -#include "samd21_pins.h" + #include "tick.h" -#include "asf/sam0/drivers/sercom/sercom_interrupt.h" +#include "hpl_sercom_config.h" +#include "peripheral_clk_config.h" -#undef ENABLE +#include "hal/include/hal_gpio.h" +#include "hal/include/hal_usart_async.h" +#include "hal/include/hpl_usart_async.h" -busio_uart_obj_t *_uart_instances[SERCOM_INST_NUM]; +#include "peripherals.h" +#include "pins.h" -static void _sercom_default_handler( - const uint8_t instance) -{ - Assert(false); -} - -static void _busio_uart_interrupt_handler(uint8_t instance) -{ - /* Temporary variables */ - uint16_t interrupt_status; - uint8_t error_code; - - /* Get device instance from the look-up table */ - struct usart_module *module - = (struct usart_module *)_sercom_instances[instance]; - - busio_uart_obj_t *self = _uart_instances[instance]; - - /* Pointer to the hardware module instance */ - SercomUsart *const usart_hw = &(module->hw->USART); - - /* Wait for the synchronization to complete */ - _usart_wait_for_sync(module); - - /* Read and mask interrupt flag register */ - interrupt_status = usart_hw->INTFLAG.reg; - interrupt_status &= usart_hw->INTENSET.reg; - - /* Check if the Receive Complete interrupt has occurred, and that - * there's more data to receive */ - if (interrupt_status & SERCOM_USART_INTFLAG_RXC) { - /* Read out the status code and mask away all but the 4 LSBs*/ - error_code = (uint8_t)(usart_hw->STATUS.reg & SERCOM_USART_STATUS_MASK); - /* CTS status should not be considered as an error */ - if(error_code & SERCOM_USART_STATUS_CTS) { - error_code &= ~SERCOM_USART_STATUS_CTS; - } - /* Check if an error has occurred during the receiving */ - if (error_code) { - /* Check which error occurred */ - if (error_code & SERCOM_USART_STATUS_FERR) { - /* Store the error code and clear flag by writing 1 to it */ - usart_hw->STATUS.reg = SERCOM_USART_STATUS_FERR; - } else if (error_code & SERCOM_USART_STATUS_BUFOVF) { - /* Store the error code and clear flag by writing 1 to it */ - usart_hw->STATUS.reg = SERCOM_USART_STATUS_BUFOVF; - } else if (error_code & SERCOM_USART_STATUS_PERR) { - /* Store the error code and clear flag by writing 1 to it */ - usart_hw->STATUS.reg = SERCOM_USART_STATUS_PERR; - } - self->rx_error = true; - } else { - /* Read current packet from DATA register, - * increment buffer pointer and decrement buffer length */ - uint16_t received_data = (usart_hw->DATA.reg & SERCOM_USART_DATA_MASK); - - common_hal_mcu_disable_interrupts(); - /* Read value will be at least 8-bits long */ - uint32_t buffer_end = (self->buffer_start + self->buffer_size) % self->buffer_length; - self->buffer[buffer_end] = received_data; - self->buffer_size++; - - if (module->character_size == USART_CHARACTER_SIZE_9BIT) { - buffer_end = (self->buffer_start + self->buffer_size) % self->buffer_length; - /* 9-bit data, write next received byte to the buffer */ - self->buffer[buffer_end] = (received_data >> 8); - self->buffer_size++; - } - - if (self->buffer_size > self->buffer_length) { - self->buffer_start++; - if (module->character_size == USART_CHARACTER_SIZE_9BIT) { - self->buffer_start++; - } - self->buffer_size = self->buffer_length; - } - common_hal_mcu_enable_interrupts(); - } - } +// Do-nothing callback needed so that usart_async code will enable rx interrupts. +// See comment below re usart_async_register_callback() +static void usart_async_rxc_callback(const struct usart_async_descriptor *const descr) { + // Nothing needs to be done by us. } void common_hal_busio_uart_construct(busio_uart_obj_t *self, @@ -128,34 +56,55 @@ void common_hal_busio_uart_construct(busio_uart_obj_t *self, uint8_t bits, uart_parity_t parity, uint8_t stop, uint32_t timeout, uint8_t receiver_buffer_size) { Sercom* sercom = NULL; - uint32_t rx_pinmux = PINMUX_UNUSED; - uint8_t rx_pad = 5; // Unset pad - uint32_t tx_pinmux = PINMUX_UNUSED; - uint8_t tx_pad = 5; // Unset pad + uint8_t sercom_index; + uint32_t rx_pinmux = 0; + uint8_t rx_pad = 255; // Unset pad + uint32_t tx_pinmux = 0; + uint8_t tx_pad = 255; // Unset pad + + if (bits > 8) { + mp_raise_NotImplementedError("bytes > 8 bits not supported"); + } + + bool have_tx = tx != mp_const_none; + bool have_rx = rx != mp_const_none; + if (!have_tx && !have_rx) { + mp_raise_ValueError("tx and rx cannot both be None"); + } + + self->baudrate = baudrate; + self->character_bits = bits; + self->timeout_ms = timeout; + + // This assignment is only here because the usart_async routines take a *const argument. + struct usart_async_descriptor * const usart_desc_p = (struct usart_async_descriptor * const) &self->usart_desc; + for (int i = 0; i < NUM_SERCOMS_PER_PIN; i++) { Sercom* potential_sercom = NULL; - if (tx != NULL) { + if (have_tx) { potential_sercom = tx->sercom[i].sercom; + sercom_index = tx->sercom[i].index; if (potential_sercom == NULL || - potential_sercom->I2CM.CTRLA.bit.ENABLE != 0 || + potential_sercom->USART.CTRLA.bit.ENABLE != 0 || !(tx->sercom[i].pad == 0 || tx->sercom[i].pad == 2)) { continue; } tx_pinmux = PINMUX(tx->pin, (i == 0) ? MUX_C : MUX_D); tx_pad = tx->sercom[i].pad; - if (rx == NULL) { + if (rx == mp_const_none) { sercom = potential_sercom; break; } } for (int j = 0; j < NUM_SERCOMS_PER_PIN; j++) { - if (((tx == NULL && rx->sercom[j].sercom->I2CM.CTRLA.bit.ENABLE == 0) || + if (((!have_tx && rx->sercom[j].sercom->USART.CTRLA.bit.ENABLE == 0) || potential_sercom == rx->sercom[j].sercom) && rx->sercom[j].pad != tx_pad) { rx_pinmux = PINMUX(rx->pin, (j == 0) ? MUX_C : MUX_D); rx_pad = rx->sercom[j].pad; sercom = rx->sercom[j].sercom; + sercom_index = rx->sercom[j].index; break; } } @@ -166,81 +115,96 @@ void common_hal_busio_uart_construct(busio_uart_obj_t *self, if (sercom == NULL) { mp_raise_ValueError("Invalid pins"); } - if (tx == NULL) { + if (!have_tx) { tx_pad = 0; if (rx_pad == 0) { tx_pad = 2; } } - if (rx == NULL) { + if (!have_rx) { rx_pad = (tx_pad + 1) % 4; } - struct usart_config config_usart; - usart_get_config_defaults(&config_usart); - config_usart.mux_setting = (SERCOM_USART_CTRLA_RXPO(rx_pad) | SERCOM_USART_CTRLA_TXPO(tx_pad / 2)); - if (parity == PARITY_ODD) { - config_usart.parity = USART_PARITY_ODD; - } else if (parity == PARITY_EVEN) { - config_usart.parity = USART_PARITY_EVEN; - } - config_usart.stopbits = stop - 1; - config_usart.character_size = bits % 8; - config_usart.baudrate = baudrate; + // Set up clocks on SERCOM. + samd_peripherals_sercom_clock_init(sercom, sercom_index); - // Map pad to pinmux through a short array. - uint32_t *pinmuxes[4] = {&config_usart.pinmux_pad0, - &config_usart.pinmux_pad1, - &config_usart.pinmux_pad2, - &config_usart.pinmux_pad3}; - // Pin muxes have a default pin, set them to unused so that no other pins are changed. - for (int i = 0; i < 4; i++) { - *pinmuxes[i] = PINMUX_UNUSED; + if (rx && receiver_buffer_size > 0) { + self->buffer_length = receiver_buffer_size; + self->buffer = (uint8_t *) gc_alloc(self->buffer_length * sizeof(uint8_t), false, false); + if (self->buffer == NULL) { + common_hal_busio_uart_deinit(self); + mp_raise_msg(&mp_type_MemoryError, "Failed to allocate RX buffer"); + } + } else { + self->buffer_length = 0; + self->buffer = NULL; } - self->rx_pin = NO_PIN; - config_usart.receiver_enable = rx != NULL; - if (rx != NULL) { - *pinmuxes[rx_pad] = rx_pinmux; - self->rx_pin = rx->pin; - claim_pin(rx); + if (usart_async_init(usart_desc_p, sercom, self->buffer, self->buffer_length, NULL) != ERR_NONE) { + mp_raise_ValueError("Could not initialize UART"); } - self->tx_pin = NO_PIN; - config_usart.transmitter_enable = tx != NULL; - if (tx != NULL) { - *pinmuxes[tx_pad] = tx_pinmux; - self->tx_pin = tx->pin; + // usart_async_init() sets a number of defaults based on a prototypical SERCOM + // which don't necessarily match what we need. After calling it, set the values + // specific to this instantiation of UART. + + // Set pads computed for this SERCOM. + // TXPO: + // 0x0: TX pad 0; no RTS/CTS + // 0x1: TX pad 2; no RTS/CTS + // 0x2: TX pad 0; RTS: pad 2, CTS: pad 3 (not used by us right now) + // So divide by 2 to map pad to value. + hri_sercomusart_write_CTRLA_TXPO_bf(sercom, tx_pad / 2); + // RXPO: + // 0x0: RX pad 0 + // 0x1: RX pad 1 + // 0x2: RX pad 2 + // 0x3: RX pad 3 + hri_sercomusart_write_CTRLA_RXPO_bf(sercom, rx_pad); + + // Enable tx and/or rx based on whether the pins were specified. + hri_sercomusart_write_CTRLB_TXEN_bit(sercom, have_tx); + hri_sercomusart_write_CTRLB_RXEN_bit(sercom, have_rx); + + // Set parity, baud rate, stop bits, etc. 9-bit bytes not supported. + usart_async_set_parity(usart_desc_p, parity == PARITY_NONE ? USART_PARITY_NONE : + (parity == PARITY_ODD ? USART_PARITY_ODD : USART_PARITY_EVEN)); + usart_async_set_stopbits(usart_desc_p, stop == 1 ? USART_STOP_BITS_ONE : USART_STOP_BITS_TWO); + // This field is 0 for 8 bits, 5, 6, 7 for 5, 6, 7 bits. 1 for 9 bits, but we don't support that. + usart_async_set_character_size(usart_desc_p, bits % 8); + common_hal_busio_uart_set_baudrate(self, baudrate); + + // Turn on rx interrupt handling. The UART async driver has its own set of internal callbacks, + // which are set up by uart_async_init(). These in turn can call user-specified callbacks. + // In fact, the actual interrupts are not enabled unless we set up a user-specified callback. + // This is confusing. It's explained in the Atmel START User Guide -> Implementation Description -> + // Different read function behavior in some asynchronous drivers. As of this writing: + // http://start.atmel.com/static/help/index.html?GUID-79201A5A-226F-4FBB-B0B8-AB0BE0554836 + // Look at the ASFv4 code example for async USART. + usart_async_register_callback(usart_desc_p, USART_ASYNC_RXC_CB, usart_async_rxc_callback); + + + if (have_tx) { + gpio_set_pin_direction(tx->pin, GPIO_DIRECTION_OUT); + gpio_set_pin_pull_mode(tx->pin, GPIO_PULL_OFF); + gpio_set_pin_function(tx->pin, tx_pinmux); + self->tx_pin = tx->pin; claim_pin(tx); + } else { + self->tx_pin = NO_PIN; + } + + if (have_rx) { + gpio_set_pin_direction(rx->pin, GPIO_DIRECTION_IN); + gpio_set_pin_pull_mode(rx->pin, GPIO_PULL_OFF); + gpio_set_pin_function(rx->pin, rx_pinmux); + self->rx_pin = rx->pin; + claim_pin(rx); + } else { + self->rx_pin = NO_PIN; } - self->timeout_ms = timeout; - - self->buffer_length = receiver_buffer_size; - self->buffer_length *= (bits + 7) / 8; - self->buffer = (uint8_t *) gc_alloc(self->buffer_length * sizeof(uint8_t), false); - if (self->buffer == NULL) { - common_hal_busio_uart_deinit(self); - mp_raise_msg(&mp_type_MemoryError, "Failed to allocate RX buffer"); - } - - if (usart_init(&self->uart_instance, sercom, &config_usart) != STATUS_OK) { - common_hal_busio_uart_deinit(self); - mp_raise_OSError(MP_EIO); - } - - // We use our own interrupt handler because we want a circular buffer - // instead of the jobs that ASF provides. - uint8_t instance_index = _sercom_get_sercom_inst_index(self->uart_instance.hw); - _sercom_set_handler(instance_index, _busio_uart_interrupt_handler); - _sercom_instances[instance_index] = &self->uart_instance; - _uart_instances[instance_index] = self; - - /* Enable Global interrupt for module */ - system_interrupt_enable(_sercom_get_interrupt_vector(self->uart_instance.hw)); - - usart_enable(&self->uart_instance); - self->uart_instance.hw->USART.INTENSET.bit.RXC = true; + usart_async_enable(usart_desc_p); } bool common_hal_busio_uart_deinited(busio_uart_obj_t *self) { @@ -251,16 +215,10 @@ void common_hal_busio_uart_deinit(busio_uart_obj_t *self) { if (common_hal_busio_uart_deinited(self)) { return; } - self->uart_instance.hw->USART.INTENCLR.bit.RXC = true; - - uint8_t instance_index = _sercom_get_sercom_inst_index(self->uart_instance.hw); - _sercom_set_handler(instance_index, &_sercom_default_handler); - _sercom_instances[instance_index] = NULL; - _uart_instances[instance_index] = NULL; - - system_interrupt_disable(_sercom_get_interrupt_vector(self->uart_instance.hw)); - - usart_disable(&self->uart_instance); + // This assignment is only here because the usart_async routines take a *const argument. + struct usart_async_descriptor * const usart_desc_p = (struct usart_async_descriptor * const) &self->usart_desc; + usart_async_disable(usart_desc_p); + usart_async_deinit(usart_desc_p); reset_pin(self->rx_pin); reset_pin(self->tx_pin); self->rx_pin = NO_PIN; @@ -269,123 +227,120 @@ void common_hal_busio_uart_deinit(busio_uart_obj_t *self) { // Read characters. size_t common_hal_busio_uart_read(busio_uart_obj_t *self, uint8_t *data, size_t len, int *errcode) { + if (self->rx_pin == NO_PIN) { + mp_raise_ValueError("No RX pin"); + } + + // This assignment is only here because the usart_async routines take a *const argument. + struct usart_async_descriptor * const usart_desc_p = (struct usart_async_descriptor * const) &self->usart_desc; + + if (len == 0) { + // Nothing to read. + return 0; + } + + struct io_descriptor *io; + usart_async_get_io_descriptor(usart_desc_p, &io); + size_t total_read = 0; uint64_t start_ticks = ticks_ms; - while (total_read < len && ticks_ms - start_ticks < self->timeout_ms) { - if (self->buffer_size > 0) { - common_hal_mcu_disable_interrupts(); - data[total_read] = self->buffer[self->buffer_start]; - if (self->uart_instance.character_size == USART_CHARACTER_SIZE_9BIT) { - data[total_read + 1] = self->buffer[self->buffer_start + 1]; - self->buffer_start += 2; - self->buffer_size -= 2; - } else { - self->buffer_start++; - self->buffer_size--; - } - self->buffer_start = self->buffer_start % self->buffer_length; - common_hal_mcu_enable_interrupts(); - // Reset the timeout every character read. - total_read++; + + // Busy-wait until timeout or until we've read enough chars. + while (ticks_ms - start_ticks < self->timeout_ms) { + // Read as many chars as we can right now, up to len. + size_t num_read = io_read(io, data, len); + + // Advance pointer in data buffer, and decrease how many chars left to read. + data += num_read; + len -= num_read; + total_read += num_read; + if (len == 0) { + // Don't need to read any more: data buf is full. + break; + } + if (num_read > 0) { + // Reset the timeout on every character read. start_ticks = ticks_ms; } - #ifdef MICROPY_VM_HOOK_LOOP - MICROPY_VM_HOOK_LOOP - #endif - } - if (total_read == 0) { - *errcode = MP_EAGAIN; - return MP_STREAM_ERROR; +#ifdef MICROPY_VM_HOOK_LOOP + MICROPY_VM_HOOK_LOOP +#endif } + return total_read; } // Write characters. size_t common_hal_busio_uart_write(busio_uart_obj_t *self, const uint8_t *data, size_t len, int *errcode) { - /* Check that the transmitter is enabled */ - if (!(self->uart_instance.transmitter_enabled)) { - *errcode = MP_EIO; - return MP_STREAM_ERROR; + if (self->tx_pin == NO_PIN) { + mp_raise_ValueError("No TX pin"); } - /* Get a pointer to the hardware module instance */ - SercomUsart *const usart_hw = &(self->uart_instance.hw->USART); + // This assignment is only here because the usart_async routines take a *const argument. + struct usart_async_descriptor * const usart_desc_p = (struct usart_async_descriptor * const) &self->usart_desc; - /* Wait until synchronization is complete */ - _usart_wait_for_sync(&self->uart_instance); + struct io_descriptor *io; + usart_async_get_io_descriptor(usart_desc_p, &io); - uint16_t tx_pos = 0; - - bool ok = true; - uint64_t start_ticks = 0; - /* Blocks while buffer is being transferred */ - while (len--) { - /* Wait for the USART to be ready for new data and abort - * operation if it doesn't get ready within the timeout*/ - ok = false; - start_ticks = ticks_ms; - while (ticks_ms - start_ticks < self->timeout_ms) { - if (usart_hw->INTFLAG.reg & SERCOM_USART_INTFLAG_DRE) { - ok = true; - break; - } - #ifdef MICROPY_VM_HOOK_LOOP - MICROPY_VM_HOOK_LOOP - #endif - } - - if (!ok) { - break; - } - - /* Data to send is at least 8 bits long */ - uint16_t data_to_send = data[tx_pos++]; - - /* Check if the character size exceeds 8 bit */ - if (self->uart_instance.character_size == USART_CHARACTER_SIZE_9BIT) { - data_to_send |= (data[tx_pos++] << 8); - } - - /* Send the data through the USART module */ - - enum status_code status = usart_write_wait(&self->uart_instance, data_to_send); - if (status != STATUS_OK) { - ok = false; - } - } - - /* Wait until Transmit is complete or timeout */ - if (ok) { - ok = false; - start_ticks = ticks_ms; - while (ticks_ms - start_ticks < self->timeout_ms) { - if (usart_hw->INTFLAG.reg & SERCOM_USART_INTFLAG_TXC) { - ok = true; - break; - } - #ifdef MICROPY_VM_HOOK_LOOP - MICROPY_VM_HOOK_LOOP - #endif - } - } - - if (!ok && tx_pos == 0) { + if (io_write(io, data, len) < 0) { *errcode = MP_EAGAIN; return MP_STREAM_ERROR; } - return tx_pos; + + // Wait until write is complete or timeout. + bool done = false; + uint64_t start_ticks = ticks_ms; + // Busy-wait for timeout. + while (ticks_ms - start_ticks < self->timeout_ms) { + if (usart_async_is_tx_empty(usart_desc_p)) { + done = true; + break; + } + #ifdef MICROPY_VM_HOOK_LOOP + MICROPY_VM_HOOK_LOOP + #endif + } + + if (!done) { + *errcode = MP_EAGAIN; + return MP_STREAM_ERROR; + } + + struct usart_async_status async_status; + // Could return ERR_BUSY, but if that's true there's already a problem. + usart_async_get_status(usart_desc_p, &async_status); + return async_status.txcnt; +} + +uint32_t common_hal_busio_uart_get_baudrate(busio_uart_obj_t *self) { + return self->baudrate; +} + +void common_hal_busio_uart_set_baudrate(busio_uart_obj_t *self, uint32_t baudrate) { + // This assignment is only here because the usart_async routines take a *const argument. + struct usart_async_descriptor * const usart_desc_p = (struct usart_async_descriptor * const) &self->usart_desc; + usart_async_set_baud_rate(usart_desc_p, + // Samples and ARITHMETIC vs FRACTIONAL must correspond to USART_SAMPR in + // hpl_sercom_config.h. + _usart_async_calculate_baud_rate(baudrate, // e.g. 9600 baud + PROTOTYPE_SERCOM_USART_ASYNC_CLOCK_FREQUENCY, + 16, // samples + USART_BAUDRATE_ASYNCH_ARITHMETIC, + 0 // fraction - not used for ARITHMETIC + )); + self->baudrate = baudrate; } uint32_t common_hal_busio_uart_rx_characters_available(busio_uart_obj_t *self) { - if (self->uart_instance.character_size == USART_CHARACTER_SIZE_9BIT) { - return self->buffer_size / 2; - } return self->buffer_size; } bool common_hal_busio_uart_ready_to_tx(busio_uart_obj_t *self) { - if (!(self->uart_instance.transmitter_enabled)) { + if (self->tx_pin == NO_PIN) { return false; } - return self->uart_instance.hw->USART.INTFLAG.bit.DRE; + // This assignment is only here because the usart_async routines take a *const argument. + const struct _usart_async_device * const usart_device_p = + (struct _usart_async_device * const) &self->usart_desc.device; + return _usart_async_is_byte_sent(usart_device_p); } diff --git a/ports/atmel-samd/common-hal/busio/UART.h b/ports/atmel-samd/common-hal/busio/UART.h index 5adc115147..685755a5d1 100644 --- a/ports/atmel-samd/common-hal/busio/UART.h +++ b/ports/atmel-samd/common-hal/busio/UART.h @@ -29,22 +29,25 @@ #include "common-hal/microcontroller/Pin.h" -#include "asf/sam0/drivers/sercom/usart/usart.h" +#include "hal/include/hal_usart_async.h" + #include "py/obj.h" typedef struct { - mp_obj_base_t base; - struct usart_module uart_instance; - uint8_t rx_pin; - uint8_t tx_pin; - uint32_t timeout_ms; - bool rx_error; - // Index of the oldest received character. - uint32_t buffer_start; - // Index of the next available spot to store a character. - uint32_t buffer_size; - uint32_t buffer_length; - uint8_t* buffer; + mp_obj_base_t base; + struct usart_async_descriptor usart_desc; + uint8_t rx_pin; + uint8_t tx_pin; + uint8_t character_bits; + bool rx_error; + uint32_t baudrate; + uint32_t timeout_ms; + // Index of the oldest received character. + uint32_t buffer_start; + // Index of the next available spot to store a character. + uint32_t buffer_size; + uint32_t buffer_length; + uint8_t* buffer; } busio_uart_obj_t; #endif // MICROPY_INCLUDED_ATMEL_SAMD_COMMON_HAL_BUSIO_UART_H diff --git a/ports/atmel-samd/common-hal/neopixel_write/__init__.c b/ports/atmel-samd/common-hal/neopixel_write/__init__.c index 6133415f48..5530d04085 100644 --- a/ports/atmel-samd/common-hal/neopixel_write/__init__.c +++ b/ports/atmel-samd/common-hal/neopixel_write/__init__.c @@ -32,6 +32,9 @@ #include "tick.h" #ifdef SAMD51 +#include "hri/hri_cmcc_d51.h" +#include "hri/hri_nvmctrl_d51.h" + // This magical macro makes sure the delay isn't optimized out and is the // minimal three instructions. #define delay_cycles(cycles) \ @@ -62,11 +65,30 @@ void common_hal_neopixel_write(const digitalio_digitalinout_obj_t* digitalinout, // Turn off interrupts of any kind during timing-sensitive code. mp_hal_disable_all_interrupts(); + #ifdef SAMD21 // Make sure the NVM cache is consistently timed. NVMCTRL->CTRLB.bit.READMODE = NVMCTRL_CTRLB_READMODE_DETERMINISTIC_Val; #endif + #ifdef SAMD51 + // When this routine is positioned at certain addresses, the timing logic + // below can be too fast by about 2.5x. This is some kind of (un)fortunate code + // positiong with respect to a cache line. + // Theoretically we should turn on off the CMCC caches and the + // NVM caches to ensure consistent timing. Testing shows the the NVMCTRL + // cache disabling seems to make the difference. But turn both off to make sure. + // It's difficult to test because additions to the code before the timing loop + // below change instruction placement. Testing was done by adding cache changes + // below the loop (so only the first time through is wrong). + // + // Turn off instruction, data, and NVM caches to force consistent timing. + // Invalidate existing cache entries. + hri_cmcc_set_CFG_reg(CMCC, CMCC_CFG_DCDIS | CMCC_CFG_ICDIS); + hri_cmcc_write_MAINT0_reg(CMCC, CMCC_MAINT0_INVALL); + hri_nvmctrl_set_CTRLA_CACHEDIS0_bit(NVMCTRL); + hri_nvmctrl_set_CTRLA_CACHEDIS1_bit(NVMCTRL); + #endif uint32_t pin = digitalinout->pin->pin; port = &PORT->Group[GPIO_PORT(pin)]; // Convert GPIO # to port register @@ -124,7 +146,7 @@ void common_hal_neopixel_write(const digitalio_digitalinout_obj_t* digitalinout, if(ptr >= end) break; p = *ptr++; bitMask = 0x80; - // This is the delay between bytes. Its similar to the other branch + // This is the delay between bytes. It's similar to the other branch // in the if statement except its tuned to account for the time the // above operations take. // For the SK6812 its 0.6us +- 0.15us @@ -139,6 +161,14 @@ void common_hal_neopixel_write(const digitalio_digitalinout_obj_t* digitalinout, NVMCTRL->CTRLB.bit.READMODE = NVMCTRL_CTRLB_READMODE_NO_MISS_PENALTY_Val; #endif + #ifdef SAMD51 + // Turn instruction, data, and NVM caches back on. + hri_cmcc_clear_CFG_reg(CMCC, CMCC_CFG_DCDIS | CMCC_CFG_ICDIS); + hri_nvmctrl_clear_CTRLA_CACHEDIS0_bit(NVMCTRL); + hri_nvmctrl_clear_CTRLA_CACHEDIS1_bit(NVMCTRL); + + #endif + // ticks_ms may be out of date at this point because we stopped the // interrupt. We'll risk it anyway. current_tick(&next_start_tick_ms, &next_start_tick_us); diff --git a/ports/atmel-samd/supervisor/port.c b/ports/atmel-samd/supervisor/port.c index 726a48d060..fe65915106 100644 --- a/ports/atmel-samd/supervisor/port.c +++ b/ports/atmel-samd/supervisor/port.c @@ -114,23 +114,6 @@ safe_mode_t port_init(void) { // Configure millisecond timer initialization. tick_init(); - // Uncomment to init PIN_PA17 for debugging. - // struct port_config pin_conf; - // port_get_config_defaults(&pin_conf); - // - // pin_conf.direction = PORT_PIN_DIR_OUTPUT; - // port_pin_set_config(MICROPY_HW_LED1, &pin_conf); - // port_pin_set_output_level(MICROPY_HW_LED1, false); - - // Output clocks for debugging. - // not supported by SAMD51G; uncomment for SAMD51J or update for 51G - // #ifdef SAMD51 - // gpio_set_pin_function(PIN_PA10, GPIO_PIN_FUNCTION_M); // GCLK4, D3 - // gpio_set_pin_function(PIN_PA11, GPIO_PIN_FUNCTION_M); // GCLK5, A4 - // gpio_set_pin_function(PIN_PB14, GPIO_PIN_FUNCTION_M); // GCLK0, D5 - // gpio_set_pin_function(PIN_PB15, GPIO_PIN_FUNCTION_M); // GCLK1, D6 - // #endif - // Init the nvm controller. // struct nvm_config config_nvm; // nvm_get_config_defaults(&config_nvm); @@ -221,7 +204,26 @@ void reset_port(void) { analogout_reset(); reset_all_pins(); -// + + // Set up debugging pins after reset_all_pins(). + + // Uncomment to init PIN_PA17 for debugging. + // struct port_config pin_conf; + // port_get_config_defaults(&pin_conf); + // + // pin_conf.direction = PORT_PIN_DIR_OUTPUT; + // port_pin_set_config(MICROPY_HW_LED1, &pin_conf); + // port_pin_set_output_level(MICROPY_HW_LED1, false); + + // Output clocks for debugging. + // not supported by SAMD51G; uncomment for SAMD51J or update for 51G + // #ifdef SAMD51 + // gpio_set_pin_function(PIN_PA10, GPIO_PIN_FUNCTION_M); // GCLK4, D3 + // gpio_set_pin_function(PIN_PA11, GPIO_PIN_FUNCTION_M); // GCLK5, A4 + // gpio_set_pin_function(PIN_PB14, GPIO_PIN_FUNCTION_M); // GCLK0, D5 + // gpio_set_pin_function(PIN_PB15, GPIO_PIN_FUNCTION_M); // GCLK1, D6 + // #endif + // // usb_hid_reset(); // diff --git a/shared-bindings/busio/UART.c b/shared-bindings/busio/UART.c index 3a3cb42463..1b63d8d0e0 100644 --- a/shared-bindings/busio/UART.c +++ b/shared-bindings/busio/UART.c @@ -33,6 +33,7 @@ #include "lib/utils/context_manager_helpers.h" #include "py/ioctl.h" +#include "py/objproperty.h" #include "py/runtime.h" #include "py/stream.h" @@ -48,11 +49,11 @@ //| A common bidirectional serial protocol that uses an an agreed upon speed //| rather than a shared clock line. //| -//| :param ~microcontroller.Pin tx: the pin to transmit with -//| :param ~microcontroller.Pin rx: the pin to receive on -//| :param int baudrate: the transmit and receive speed +//| :param ~microcontroller.Pin tx: the pin to transmit with, or ``None`` if this ``UART`` is receive-only. +//| :param ~microcontroller.Pin rx: the pin to receive on, or ``None`` if this ``UART`` is transmit-only. +//| :param int baudrate: the transmit and receive speed. /// :param int bits: the number of bits per byte, 7, 8 or 9. -/// :param Parity parity: the parity used for error checking +/// :param Parity parity: the parity used for error checking. /// :param int stop: the number of stop bits, 1 or 2. /// :param int timeout: the timeout in milliseconds to wait for the first character and between subsequent characters. /// :param int receiver_buffer_size: the character length of the read buffer (0 to disable). (When a character is 9 bits the buffer will be 2 * receiver_buffer_size bytes.) @@ -220,6 +221,33 @@ STATIC mp_uint_t busio_uart_ioctl(mp_obj_t self_in, mp_uint_t request, mp_uint_t return ret; } +//| .. attribute:: baudrate +//| +//| The current baudrate. +//| +STATIC mp_obj_t busio_uart_obj_get_baudrate(mp_obj_t self_in) { + busio_uart_obj_t *self = MP_OBJ_TO_PTR(self_in); + raise_error_if_deinited(common_hal_busio_uart_deinited(self)); + return MP_OBJ_NEW_SMALL_INT(common_hal_busio_uart_get_baudrate(self)); +} +MP_DEFINE_CONST_FUN_OBJ_1(busio_uart_get_baudrate_obj, busio_uart_obj_get_baudrate); + +STATIC mp_obj_t busio_uart_obj_set_baudrate(mp_obj_t self_in, mp_obj_t baudrate) { + busio_uart_obj_t *self = MP_OBJ_TO_PTR(self_in); + raise_error_if_deinited(common_hal_busio_uart_deinited(self)); + common_hal_busio_uart_set_baudrate(self, mp_obj_get_int(baudrate)); + return mp_const_none; +} +MP_DEFINE_CONST_FUN_OBJ_2(busio_uart_set_baudrate_obj, busio_uart_obj_set_baudrate); + + +const mp_obj_property_t busio_uart_baudrate_obj = { + .base.type = &mp_type_property, + .proxy = {(mp_obj_t)&busio_uart_get_baudrate_obj, + (mp_obj_t)&busio_uart_set_baudrate_obj, + (mp_obj_t)&mp_const_none_obj}, +}; + //| .. class:: busio.UART.Parity //| //| Enum-like class to define the parity used to verify correct data transfer. @@ -274,6 +302,9 @@ STATIC const mp_rom_map_elem_t busio_uart_locals_dict_table[] = { { MP_OBJ_NEW_QSTR(MP_QSTR_readinto), MP_ROM_PTR(&mp_stream_readinto_obj) }, { MP_OBJ_NEW_QSTR(MP_QSTR_write), MP_ROM_PTR(&mp_stream_write_obj) }, + // Properties + { MP_ROM_QSTR(MP_QSTR_baudrate), MP_ROM_PTR(&busio_uart_baudrate_obj) }, + // Nested Enum-like Classes. { MP_ROM_QSTR(MP_QSTR_Parity), MP_ROM_PTR(&busio_uart_parity_type) }, }; diff --git a/shared-bindings/busio/UART.h b/shared-bindings/busio/UART.h index 28196931a9..fa39d8ad5f 100644 --- a/shared-bindings/busio/UART.h +++ b/shared-bindings/busio/UART.h @@ -55,6 +55,10 @@ extern size_t common_hal_busio_uart_read(busio_uart_obj_t *self, extern size_t common_hal_busio_uart_write(busio_uart_obj_t *self, const uint8_t *data, size_t len, int *errcode); +extern uint32_t common_hal_busio_uart_get_baudrate(busio_uart_obj_t *self); +extern void common_hal_busio_uart_set_baudrate(busio_uart_obj_t *self, uint32_t baudrate); + + extern uint32_t common_hal_busio_uart_rx_characters_available(busio_uart_obj_t *self); extern bool common_hal_busio_uart_ready_to_tx(busio_uart_obj_t *self); diff --git a/shared-bindings/busio/__init__.c b/shared-bindings/busio/__init__.c index 6956e3c3d3..958ee062af 100644 --- a/shared-bindings/busio/__init__.c +++ b/shared-bindings/busio/__init__.c @@ -32,9 +32,9 @@ #include "shared-bindings/microcontroller/Pin.h" #include "shared-bindings/busio/__init__.h" #include "shared-bindings/busio/I2C.h" -//xxxx #include "shared-bindings/busio/OneWire.h" +#include "shared-bindings/busio/OneWire.h" #include "shared-bindings/busio/SPI.h" -//xxxx #include "shared-bindings/busio/UART.h" +#include "shared-bindings/busio/UART.h" #include "shared-bindings/busio/__init__.h" #include "py/runtime.h" @@ -89,8 +89,8 @@ STATIC const mp_rom_map_elem_t busio_module_globals_table[] = { { MP_ROM_QSTR(MP_QSTR___name__), MP_ROM_QSTR(MP_QSTR_busio) }, { MP_ROM_QSTR(MP_QSTR_I2C), MP_ROM_PTR(&busio_i2c_type) }, { MP_ROM_QSTR(MP_QSTR_SPI), MP_ROM_PTR(&busio_spi_type) }, - //xxxx { MP_ROM_QSTR(MP_QSTR_OneWire), MP_ROM_PTR(&busio_onewire_type) }, - //xxxx { MP_ROM_QSTR(MP_QSTR_UART), MP_ROM_PTR(&busio_uart_type) }, + { MP_ROM_QSTR(MP_QSTR_OneWire), MP_ROM_PTR(&busio_onewire_type) }, + { MP_ROM_QSTR(MP_QSTR_UART), MP_ROM_PTR(&busio_uart_type) }, }; STATIC MP_DEFINE_CONST_DICT(busio_module_globals, busio_module_globals_table); From 5f101f3535d29f0a522440e6529525e642856696 Mon Sep 17 00:00:00 2001 From: Dan Halbert Date: Wed, 21 Feb 2018 22:52:33 -0500 Subject: [PATCH 067/135] Add dummy UART implementation to nrf so it builds with UART turned on. Also add OneWire. --- ports/nrf/Makefile | 8 ++- ports/nrf/common-hal/busio/OneWire.h | 33 +++++++++++ ports/nrf/common-hal/busio/UART.c | 89 ++++++++++++++++++++++++++++ ports/nrf/common-hal/busio/UART.h | 50 ++++++++++++++++ 4 files changed, 177 insertions(+), 3 deletions(-) create mode 100644 ports/nrf/common-hal/busio/OneWire.h create mode 100644 ports/nrf/common-hal/busio/UART.c create mode 100644 ports/nrf/common-hal/busio/UART.h diff --git a/ports/nrf/Makefile b/ports/nrf/Makefile index c1bef46723..7ed14aa47c 100644 --- a/ports/nrf/Makefile +++ b/ports/nrf/Makefile @@ -202,6 +202,7 @@ SRC_COMMON_HAL += \ busio/__init__.c\ busio/I2C.c \ busio/SPI.c \ + busio/UART.c \ pulseio/__init__.c \ pulseio/PulseIn.c \ pulseio/PulseOut.c \ @@ -211,6 +212,7 @@ SRC_COMMON_HAL += \ # These don't have corresponding files in each port but are still located in # shared-bindings to make it clear what the contents of the modules are. SRC_BINDINGS_ENUMS = \ + busio/OneWire.c \ digitalio/Direction.c \ digitalio/DriveMode.c \ digitalio/Pull.c \ @@ -234,10 +236,10 @@ SRC_SHARED_MODULE = \ bitbangio/__init__.c \ bitbangio/I2C.c \ bitbangio/OneWire.c \ - bitbangio/SPI.c + bitbangio/SPI.c \ + busio/OneWire.c \ -# busio/OneWire.c \ - uheap/__init__.c \ +# uheap/__init__.c \ ustack/__init__.c SRC_SHARED_BINDINGS = \ diff --git a/ports/nrf/common-hal/busio/OneWire.h b/ports/nrf/common-hal/busio/OneWire.h new file mode 100644 index 0000000000..821cc64c1e --- /dev/null +++ b/ports/nrf/common-hal/busio/OneWire.h @@ -0,0 +1,33 @@ +/* + * This file is part of the MicroPython project, http://micropython.org/ + * + * The MIT License (MIT) + * + * Copyright (c) 2016 Scott Shawcroft + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +#ifndef MICROPY_INCLUDED_NRF_COMMON_HAL_BUSIO_ONEWIRE_H +#define MICROPY_INCLUDED_NRF_COMMON_HAL_BUSIO_ONEWIRE_H + +// Use bitbangio. +#include "shared-module/busio/OneWire.h" + +#endif // MICROPY_INCLUDED_NRF_COMMON_HAL_BUSIO_ONEWIRE_H diff --git a/ports/nrf/common-hal/busio/UART.c b/ports/nrf/common-hal/busio/UART.c new file mode 100644 index 0000000000..dbc6a85331 --- /dev/null +++ b/ports/nrf/common-hal/busio/UART.c @@ -0,0 +1,89 @@ +/* + * This file is part of the MicroPython project, http://micropython.org/ + * + * The MIT License (MIT) + * + * Copyright (c) 2016 Damien P. George + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +#include "shared-bindings/microcontroller/__init__.h" +#include "shared-bindings/busio/UART.h" + +#include "mpconfigport.h" +#include "py/gc.h" +#include "py/mperrno.h" +#include "py/runtime.h" +#include "py/stream.h" + +#include "tick.h" + +#include "pins.h" + +void common_hal_busio_uart_construct(busio_uart_obj_t *self, + const mcu_pin_obj_t * tx, const mcu_pin_obj_t * rx, uint32_t baudrate, + uint8_t bits, uart_parity_t parity, uint8_t stop, uint32_t timeout, + uint8_t receiver_buffer_size) { + mp_raise_NotImplementedError("busio.UART not yet implemented"); +} + +bool common_hal_busio_uart_deinited(busio_uart_obj_t *self) { + mp_raise_NotImplementedError("busio.UART not yet implemented"); +} + +void common_hal_busio_uart_deinit(busio_uart_obj_t *self) { + mp_raise_NotImplementedError("busio.UART not yet implemented"); + if (common_hal_busio_uart_deinited(self)) { + return; + } + // Do deinit; +} + +// Read characters. +size_t common_hal_busio_uart_read(busio_uart_obj_t *self, uint8_t *data, size_t len, int *errcode) { + mp_raise_NotImplementedError("busio.UART not yet implemented"); + return 0; +} + +// Write characters. +size_t common_hal_busio_uart_write(busio_uart_obj_t *self, const uint8_t *data, size_t len, int *errcode) { + mp_raise_NotImplementedError("busio.UART not yet implemented"); + return 0; +} + +uint32_t common_hal_busio_uart_get_baudrate(busio_uart_obj_t *self) { + mp_raise_NotImplementedError("busio.UART not yet implemented"); + return self->baudrate; +} + +void common_hal_busio_uart_set_baudrate(busio_uart_obj_t *self, uint32_t baudrate) { + mp_raise_NotImplementedError("busio.UART not yet implemented"); + self->baudrate = baudrate; +} + +uint32_t common_hal_busio_uart_rx_characters_available(busio_uart_obj_t *self) { + mp_raise_NotImplementedError("busio.UART not yet implemented"); + return 0; +} + +bool common_hal_busio_uart_ready_to_tx(busio_uart_obj_t *self) { + mp_raise_NotImplementedError("busio.UART not yet implemented"); + return false; +} diff --git a/ports/nrf/common-hal/busio/UART.h b/ports/nrf/common-hal/busio/UART.h new file mode 100644 index 0000000000..7c0493e37e --- /dev/null +++ b/ports/nrf/common-hal/busio/UART.h @@ -0,0 +1,50 @@ +/* + * This file is part of the MicroPython project, http://micropython.org/ + * + * The MIT License (MIT) + * + * Copyright (c) 2016 Scott Shawcroft + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +#ifndef MICROPY_INCLUDED_NRF_COMMON_HAL_BUSIO_UART_H +#define MICROPY_INCLUDED_NRF_COMMON_HAL_BUSIO_UART_H + +#include "common-hal/microcontroller/Pin.h" + +#include "py/obj.h" + +typedef struct { + mp_obj_base_t base; + uint8_t rx_pin; + uint8_t tx_pin; + uint8_t character_bits; + bool rx_error; + uint32_t baudrate; + uint32_t timeout_ms; + // Index of the oldest received character. + uint32_t buffer_start; + // Index of the next available spot to store a character. + uint32_t buffer_size; + uint32_t buffer_length; + uint8_t* buffer; +} busio_uart_obj_t; + +#endif // MICROPY_INCLUDED_NRF_COMMON_HAL_BUSIO_UART_H From 957a82b5921664ab6f1527ee79587eb59b6e32de Mon Sep 17 00:00:00 2001 From: Dan Halbert Date: Fri, 23 Feb 2018 09:54:39 -0500 Subject: [PATCH 068/135] add board.RX and .TX pins to metro_m4_express_revb --- ports/atmel-samd/boards/metro_m4_express_revb/pins.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/ports/atmel-samd/boards/metro_m4_express_revb/pins.c b/ports/atmel-samd/boards/metro_m4_express_revb/pins.c index f6ad05f2da..a18906f73d 100644 --- a/ports/atmel-samd/boards/metro_m4_express_revb/pins.c +++ b/ports/atmel-samd/boards/metro_m4_express_revb/pins.c @@ -13,7 +13,9 @@ STATIC const mp_map_elem_t board_global_dict_table[] = { { MP_OBJ_NEW_QSTR(MP_QSTR_D0), (mp_obj_t)&pin_PA23 }, + { MP_OBJ_NEW_QSTR(MP_QSTR_RX), (mp_obj_t)&pin_PA23 }, { MP_OBJ_NEW_QSTR(MP_QSTR_D1), (mp_obj_t)&pin_PA22 }, + { MP_OBJ_NEW_QSTR(MP_QSTR_TX), (mp_obj_t)&pin_PA22 }, { MP_OBJ_NEW_QSTR(MP_QSTR_D2), (mp_obj_t)&pin_PA08 }, { MP_OBJ_NEW_QSTR(MP_QSTR_D3), (mp_obj_t)&pin_PA10 }, { MP_OBJ_NEW_QSTR(MP_QSTR_D4), (mp_obj_t)&pin_PB12 }, From 641a44e3e9d69349bdc525865b164c983e7ca40c Mon Sep 17 00:00:00 2001 From: Dan Halbert Date: Fri, 23 Feb 2018 10:57:59 -0500 Subject: [PATCH 069/135] Remove obsolete periphal drivers in esp module --- esp8266/Makefile | 6 -- esp8266/espapa102.c | 115 ------------------------------------- esp8266/espapa102.h | 31 ---------- esp8266/modesp.c | 35 ----------- esp8266/modules/apa102.py | 17 ------ esp8266/modules/dht.py | 32 ----------- esp8266/modules/ds18x20.py | 1 - esp8266/modules/onewire.py | 1 - esp8266/mpconfigport.h | 1 - 9 files changed, 239 deletions(-) delete mode 100644 esp8266/espapa102.c delete mode 100644 esp8266/espapa102.h delete mode 100644 esp8266/modules/apa102.py delete mode 100644 esp8266/modules/dht.py delete mode 120000 esp8266/modules/ds18x20.py delete mode 120000 esp8266/modules/onewire.py diff --git a/esp8266/Makefile b/esp8266/Makefile index d177bee58c..1eaa3a0bed 100644 --- a/esp8266/Makefile +++ b/esp8266/Makefile @@ -78,7 +78,6 @@ SRC_C = \ espuart.c \ esppwm.c \ espneopixel.c \ - espapa102.c \ intr.c \ modpyb.c \ modmachine.c \ @@ -190,10 +189,6 @@ LIB_SRC_C += \ lib/oofatfs/option/unicode.c endif -DRIVERS_SRC_C = $(addprefix drivers/,\ - dht/dht.c \ - ) - SRC_S = \ gchelper.s \ @@ -206,7 +201,6 @@ OBJ += $(addprefix $(BUILD)/, $(SRC_SHARED_MODULE_EXPANDED:.c=.o)) OBJ += $(addprefix $(BUILD)/, $(STM_SRC_C:.c=.o)) OBJ += $(addprefix $(BUILD)/, $(EXTMOD_SRC_C:.c=.o)) OBJ += $(addprefix $(BUILD)/, $(LIB_SRC_C:.c=.o)) -OBJ += $(addprefix $(BUILD)/, $(DRIVERS_SRC_C:.c=.o)) #OBJ += $(BUILD)/pins_$(BOARD).o # List of sources for qstr extraction diff --git a/esp8266/espapa102.c b/esp8266/espapa102.c deleted file mode 100644 index 4295fe42d8..0000000000 --- a/esp8266/espapa102.c +++ /dev/null @@ -1,115 +0,0 @@ -/* - * This file is part of the MicroPython project, http://micropython.org/ - * - * The MIT License (MIT) - * - * Copyright (c) 2016 Robert Foss, Daniel Busch - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ - -#include "py/mpconfig.h" -#if MICROPY_ESP8266_APA102 - -#include -#include "c_types.h" -#include "eagle_soc.h" -#include "user_interface.h" -#include "espapa102.h" - -#define NOP asm volatile(" nop \n\t") - -static inline void _esp_apa102_send_byte(uint32_t clockPinMask, uint32_t dataPinMask, uint8_t byte) { - for (uint32_t i = 0; i < 8; i++) { - if (byte & 0x80) { - // set data pin high - GPIO_REG_WRITE(GPIO_OUT_W1TS_ADDRESS, dataPinMask); - } else { - // set data pin low - GPIO_REG_WRITE(GPIO_OUT_W1TC_ADDRESS, dataPinMask); - } - - // set clock pin high - GPIO_REG_WRITE(GPIO_OUT_W1TS_ADDRESS, clockPinMask); - byte <<= 1; - NOP; - NOP; - - // set clock pin low - GPIO_REG_WRITE(GPIO_OUT_W1TC_ADDRESS, clockPinMask); - NOP; - NOP; - } -} - -static inline void _esp_apa102_send_colors(uint32_t clockPinMask, uint32_t dataPinMask, uint8_t *pixels, uint32_t numBytes) { - for (uint32_t i = 0; i < numBytes / 4; i++) { - _esp_apa102_send_byte(clockPinMask, dataPinMask, pixels[i * 4 + 3] | 0xE0); - _esp_apa102_send_byte(clockPinMask, dataPinMask, pixels[i * 4 + 2]); - _esp_apa102_send_byte(clockPinMask, dataPinMask, pixels[i * 4 + 1]); - _esp_apa102_send_byte(clockPinMask, dataPinMask, pixels[i * 4]); - } -} - -static inline void _esp_apa102_start_frame(uint32_t clockPinMask, uint32_t dataPinMask) { - for (uint32_t i = 0; i < 4; i++) { - _esp_apa102_send_byte(clockPinMask, dataPinMask, 0x00); - } -} - -static inline void _esp_apa102_append_additionial_cycles(uint32_t clockPinMask, uint32_t dataPinMask, uint32_t numBytes) { - GPIO_REG_WRITE(GPIO_OUT_W1TS_ADDRESS, dataPinMask); - - // we need to write some more clock cycles, because each led - // delays the data by one edge after inverting the clock - for (uint32_t i = 0; i < numBytes / 8 + ((numBytes / 4) % 2); i++) { - GPIO_REG_WRITE(GPIO_OUT_W1TS_ADDRESS, clockPinMask); - NOP; - NOP; - - GPIO_REG_WRITE(GPIO_OUT_W1TC_ADDRESS, clockPinMask); - NOP; - NOP; - } -} - -static inline void _esp_apa102_end_frame(uint32_t clockPinMask, uint32_t dataPinMask) { - for (uint32_t i = 0; i < 4; i++) { - _esp_apa102_send_byte(clockPinMask, dataPinMask, 0xFF); - } -} - -void esp_apa102_write(uint8_t clockPin, uint8_t dataPin, uint8_t *pixels, uint32_t numBytes) { - uint32_t clockPinMask, dataPinMask; - - clockPinMask = 1 << clockPin; - dataPinMask = 1 << dataPin; - - // start the frame - _esp_apa102_start_frame(clockPinMask, dataPinMask); - - // write pixels - _esp_apa102_send_colors(clockPinMask, dataPinMask, pixels, numBytes); - - // end the frame - _esp_apa102_append_additionial_cycles(clockPinMask, dataPinMask, numBytes); - _esp_apa102_end_frame(clockPinMask, dataPinMask); -} - -#endif diff --git a/esp8266/espapa102.h b/esp8266/espapa102.h deleted file mode 100644 index dd7c5ab729..0000000000 --- a/esp8266/espapa102.h +++ /dev/null @@ -1,31 +0,0 @@ -/* - * This file is part of the MicroPython project, http://micropython.org/ - * - * The MIT License (MIT) - * - * Copyright (c) 2016 Robert Foss, Daniel Busch - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -#ifndef MICROPY_INCLUDED_ESP8266_ESPAPA102_H -#define MICROPY_INCLUDED_ESP8266_ESPAPA102_H - -void esp_apa102_write(uint8_t clockPin, uint8_t dataPin, uint8_t *pixels, uint32_t numBytes); - -#endif // MICROPY_INCLUDED_ESP8266_ESPAPA102_H diff --git a/esp8266/modesp.c b/esp8266/modesp.c index cecedeb03f..6df79e889d 100644 --- a/esp8266/modesp.c +++ b/esp8266/modesp.c @@ -30,12 +30,9 @@ #include "py/runtime.h" #include "py/mperrno.h" #include "py/mphal.h" -#include "drivers/dht/dht.h" #include "espuart.h" #include "user_interface.h" #include "mem.h" -#include "espneopixel.h" -#include "espapa102.h" #include "modmachine.h" #define MODESP_INCLUDE_CONSTANTS (1) @@ -193,31 +190,6 @@ STATIC mp_obj_t esp_check_fw(void) { } STATIC MP_DEFINE_CONST_FUN_OBJ_0(esp_check_fw_obj, esp_check_fw); - -STATIC mp_obj_t esp_neopixel_write_(mp_obj_t pin, mp_obj_t buf, mp_obj_t is800k) { - mp_buffer_info_t bufinfo; - mp_get_buffer_raise(buf, &bufinfo, MP_BUFFER_READ); - if (!mp_obj_is_true(is800k)) { - nlr_raise(mp_obj_new_exception_msg(&mp_type_ValueError, "Only 800khz neopixels are supported.")); - } - esp_neopixel_write(mp_obj_get_pin_obj(pin)->phys_port, - (uint8_t*)bufinfo.buf, bufinfo.len); - return mp_const_none; -} -STATIC MP_DEFINE_CONST_FUN_OBJ_3(esp_neopixel_write_obj, esp_neopixel_write_); - -#if MICROPY_ESP8266_APA102 -STATIC mp_obj_t esp_apa102_write_(mp_obj_t clockPin, mp_obj_t dataPin, mp_obj_t buf) { - mp_buffer_info_t bufinfo; - mp_get_buffer_raise(buf, &bufinfo, MP_BUFFER_READ); - esp_apa102_write(mp_obj_get_pin_obj(clockPin)->phys_port, - mp_obj_get_pin_obj(dataPin)->phys_port, - (uint8_t*)bufinfo.buf, bufinfo.len); - return mp_const_none; -} -STATIC MP_DEFINE_CONST_FUN_OBJ_3(esp_apa102_write_obj, esp_apa102_write_); -#endif - STATIC mp_obj_t esp_freemem() { return MP_OBJ_NEW_SMALL_INT(system_get_free_heap_size()); } @@ -362,13 +334,6 @@ STATIC const mp_rom_map_elem_t esp_module_globals_table[] = { { MP_ROM_QSTR(MP_QSTR_flash_erase), MP_ROM_PTR(&esp_flash_erase_obj) }, { MP_ROM_QSTR(MP_QSTR_flash_size), MP_ROM_PTR(&esp_flash_size_obj) }, { MP_ROM_QSTR(MP_QSTR_flash_user_start), MP_ROM_PTR(&esp_flash_user_start_obj) }, - #if MICROPY_ESP8266_NEOPIXEL - { MP_ROM_QSTR(MP_QSTR_neopixel_write), MP_ROM_PTR(&esp_neopixel_write_obj) }, - #endif - #if MICROPY_ESP8266_APA102 - { MP_ROM_QSTR(MP_QSTR_apa102_write), MP_ROM_PTR(&esp_apa102_write_obj) }, - #endif - { MP_ROM_QSTR(MP_QSTR_dht_readinto), MP_ROM_PTR(&dht_readinto_obj) }, { MP_ROM_QSTR(MP_QSTR_freemem), MP_ROM_PTR(&esp_freemem_obj) }, { MP_ROM_QSTR(MP_QSTR_meminfo), MP_ROM_PTR(&esp_meminfo_obj) }, { MP_ROM_QSTR(MP_QSTR_check_fw), MP_ROM_PTR(&esp_check_fw_obj) }, diff --git a/esp8266/modules/apa102.py b/esp8266/modules/apa102.py deleted file mode 100644 index 41b7c0485c..0000000000 --- a/esp8266/modules/apa102.py +++ /dev/null @@ -1,17 +0,0 @@ -# APA102 driver for MicroPython on ESP8266 -# MIT license; Copyright (c) 2016 Robert Foss, Daniel Busch - -from esp import apa102_write -from neopixel import NeoPixel - - -class APA102(NeoPixel): - ORDER = (0, 1, 2, 3) - - def __init__(self, clock_pin, data_pin, n, bpp=4): - super().__init__(data_pin, n, bpp) - self.clock_pin = clock_pin - self.clock_pin.init(clock_pin.OUT) - - def write(self): - apa102_write(self.clock_pin, self.pin, self.buf) diff --git a/esp8266/modules/dht.py b/esp8266/modules/dht.py deleted file mode 100644 index 9a69e7e07e..0000000000 --- a/esp8266/modules/dht.py +++ /dev/null @@ -1,32 +0,0 @@ -# DHT11/DHT22 driver for MicroPython on ESP8266 -# MIT license; Copyright (c) 2016 Damien P. George - -import esp - -class DHTBase: - def __init__(self, pin): - self.pin = pin - self.buf = bytearray(5) - - def measure(self): - buf = self.buf - esp.dht_readinto(self.pin, buf) - if (buf[0] + buf[1] + buf[2] + buf[3]) & 0xff != buf[4]: - raise Exception("checksum error") - -class DHT11(DHTBase): - def humidity(self): - return self.buf[0] - - def temperature(self): - return self.buf[2] - -class DHT22(DHTBase): - def humidity(self): - return (self.buf[0] << 8 | self.buf[1]) * 0.1 - - def temperature(self): - t = ((self.buf[2] & 0x7f) << 8 | self.buf[3]) * 0.1 - if self.buf[2] & 0x80: - t = -t - return t diff --git a/esp8266/modules/ds18x20.py b/esp8266/modules/ds18x20.py deleted file mode 120000 index faae59d909..0000000000 --- a/esp8266/modules/ds18x20.py +++ /dev/null @@ -1 +0,0 @@ -../../drivers/onewire/ds18x20.py \ No newline at end of file diff --git a/esp8266/modules/onewire.py b/esp8266/modules/onewire.py deleted file mode 120000 index f6ec745e85..0000000000 --- a/esp8266/modules/onewire.py +++ /dev/null @@ -1 +0,0 @@ -../../drivers/onewire/onewire.py \ No newline at end of file diff --git a/esp8266/mpconfigport.h b/esp8266/mpconfigport.h index 1542147ad6..b0021ddcb6 100644 --- a/esp8266/mpconfigport.h +++ b/esp8266/mpconfigport.h @@ -106,7 +106,6 @@ #define MICROPY_FATFS_MAX_SS (4096) #define MICROPY_FATFS_LFN_CODE_PAGE (437) /* 1=SFN/ANSI 437=LFN/U.S.(OEM) */ #define MICROPY_VFS_FAT (1) -#define MICROPY_ESP8266_APA102 (1) #define MICROPY_ESP8266_NEOPIXEL (1) extern void ets_event_poll(void); From 907b4417c08cb7cfb6b1ce9a1baa7af481fa398b Mon Sep 17 00:00:00 2001 From: Dan Halbert Date: Sat, 24 Feb 2018 15:45:15 -0500 Subject: [PATCH 070/135] Add .baudrate support to ESP8266. busio.UART on ESP8266 provides a TX-only UART on GPIO2. Fixed some bugs in the implementation. --- ports/esp8266/common-hal/busio/UART.c | 18 ++++++++++++++++-- ports/esp8266/common-hal/busio/UART.h | 1 + 2 files changed, 17 insertions(+), 2 deletions(-) diff --git a/ports/esp8266/common-hal/busio/UART.c b/ports/esp8266/common-hal/busio/UART.c index 8d6e0b7bcf..9b5d86ef5c 100644 --- a/ports/esp8266/common-hal/busio/UART.c +++ b/ports/esp8266/common-hal/busio/UART.c @@ -40,11 +40,13 @@ void common_hal_busio_uart_construct(busio_uart_obj_t *self, const mcu_pin_obj_t * tx, const mcu_pin_obj_t * rx, uint32_t baudrate, uint8_t bits, uart_parity_t parity, uint8_t stop, uint32_t timeout, uint8_t receiver_buffer_size) { - if (rx != NULL || tx != &pin_GPIO2) { + if (rx != mp_const_none || tx != &pin_GPIO2) { nlr_raise(mp_obj_new_exception_msg(&mp_type_OSError, "Only tx supported on UART1 (GPIO2).")); } + // set baudrate UartDev.baut_rate = baudrate; + self->baudrate = baudrate; // set data bits switch (bits) { @@ -90,6 +92,7 @@ void common_hal_busio_uart_construct(busio_uart_obj_t *self, } uart_setup(UART1); + self->deinited = false; } bool common_hal_busio_uart_deinited(busio_uart_obj_t *self) { @@ -100,7 +103,8 @@ void common_hal_busio_uart_deinit(busio_uart_obj_t *self) { if (common_hal_busio_uart_deinited(self)) { return; } - PIN_FUNC_SELECT(FUNC_U1TXD_BK, 0); + // Switch GPIO2 back to a GPIO pin. + PIN_FUNC_SELECT(PERIPHS_IO_MUX_GPIO2_U, FUNC_GPIO2); self->deinited = true; } @@ -119,6 +123,16 @@ size_t common_hal_busio_uart_write(busio_uart_obj_t *self, const uint8_t *data, return len; } +uint32_t common_hal_busio_uart_get_baudrate(busio_uart_obj_t *self) { + return self->baudrate; +} + +void common_hal_busio_uart_set_baudrate(busio_uart_obj_t *self, uint32_t baudrate) { + UartDev.baut_rate = baudrate; + uart_setup(UART1); + self->baudrate = baudrate; +} + uint32_t common_hal_busio_uart_rx_characters_available(busio_uart_obj_t *self) { return 0; } diff --git a/ports/esp8266/common-hal/busio/UART.h b/ports/esp8266/common-hal/busio/UART.h index d5dd138add..9b75b66a33 100644 --- a/ports/esp8266/common-hal/busio/UART.h +++ b/ports/esp8266/common-hal/busio/UART.h @@ -33,6 +33,7 @@ typedef struct { mp_obj_base_t base; + uint32_t baudrate; bool deinited; } busio_uart_obj_t; From cc7acfd491370d08eae3a5e96a64da3095075ce5 Mon Sep 17 00:00:00 2001 From: Dan Halbert Date: Mon, 26 Feb 2018 17:37:03 -0500 Subject: [PATCH 071/135] consistently brand Itsy Bitsy M0 as 'Express' --- .../boards/{itsybitsy_m0 => itsybitsy_m0_express}/board.c | 0 .../{itsybitsy_m0 => itsybitsy_m0_express}/mpconfigboard.h | 2 +- .../{itsybitsy_m0 => itsybitsy_m0_express}/mpconfigboard.mk | 0 .../boards/{itsybitsy_m0 => itsybitsy_m0_express}/pins.c | 0 4 files changed, 1 insertion(+), 1 deletion(-) rename ports/atmel-samd/boards/{itsybitsy_m0 => itsybitsy_m0_express}/board.c (100%) rename ports/atmel-samd/boards/{itsybitsy_m0 => itsybitsy_m0_express}/mpconfigboard.h (96%) rename ports/atmel-samd/boards/{itsybitsy_m0 => itsybitsy_m0_express}/mpconfigboard.mk (100%) rename ports/atmel-samd/boards/{itsybitsy_m0 => itsybitsy_m0_express}/pins.c (100%) diff --git a/ports/atmel-samd/boards/itsybitsy_m0/board.c b/ports/atmel-samd/boards/itsybitsy_m0_express/board.c similarity index 100% rename from ports/atmel-samd/boards/itsybitsy_m0/board.c rename to ports/atmel-samd/boards/itsybitsy_m0_express/board.c diff --git a/ports/atmel-samd/boards/itsybitsy_m0/mpconfigboard.h b/ports/atmel-samd/boards/itsybitsy_m0_express/mpconfigboard.h similarity index 96% rename from ports/atmel-samd/boards/itsybitsy_m0/mpconfigboard.h rename to ports/atmel-samd/boards/itsybitsy_m0_express/mpconfigboard.h index 15a9922211..82c5bbc614 100644 --- a/ports/atmel-samd/boards/itsybitsy_m0/mpconfigboard.h +++ b/ports/atmel-samd/boards/itsybitsy_m0_express/mpconfigboard.h @@ -1,4 +1,4 @@ -#define MICROPY_HW_BOARD_NAME "Adafruit ItsyBitsy M0" +#define MICROPY_HW_BOARD_NAME "Adafruit ItsyBitsy M0 Express" #define MICROPY_HW_MCU_NAME "samd21g18" #define CIRCUITPY_BITBANG_APA102 diff --git a/ports/atmel-samd/boards/itsybitsy_m0/mpconfigboard.mk b/ports/atmel-samd/boards/itsybitsy_m0_express/mpconfigboard.mk similarity index 100% rename from ports/atmel-samd/boards/itsybitsy_m0/mpconfigboard.mk rename to ports/atmel-samd/boards/itsybitsy_m0_express/mpconfigboard.mk diff --git a/ports/atmel-samd/boards/itsybitsy_m0/pins.c b/ports/atmel-samd/boards/itsybitsy_m0_express/pins.c similarity index 100% rename from ports/atmel-samd/boards/itsybitsy_m0/pins.c rename to ports/atmel-samd/boards/itsybitsy_m0_express/pins.c From 83635f22c448063656bd5f36be34c0af40ceb9d6 Mon Sep 17 00:00:00 2001 From: Dan Halbert Date: Mon, 26 Feb 2018 17:42:29 -0500 Subject: [PATCH 072/135] add itsybitsy_m0_express and metro_m4_express_revb to travis builds --- .travis.yml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.travis.yml b/.travis.yml index 77aea6e2b5..75cf139693 100644 --- a/.travis.yml +++ b/.travis.yml @@ -11,8 +11,10 @@ env: - TRAVIS_BOARD=feather_m0_rfm69 - TRAVIS_BOARD=feather_m0_rfm9x - TRAVIS_BOARD=feather_m0_express + - TRAVIS_BOARD=itsybitsy_m0_express - TRAVIS_BOARD=metro_m0_express - TRAVIS_BOARD=metro_m4_express + - TRAVIS_BOARD=metro_m4_express_revb - TRAVIS_BOARD=trinket_m0 - TRAVIS_BOARD=gemma_m0 - TRAVIS_BOARD=feather52 From e42209a6b21ac840208139f8cf07f14015754e51 Mon Sep 17 00:00:00 2001 From: Bryan Siepert Date: Tue, 27 Feb 2018 00:42:40 -0800 Subject: [PATCH 073/135] fixes timer number assumptions for samd51s for issue #646 --- ports/atmel-samd/timers.c | 18 ++++++++++++++++-- ports/atmel-samd/timers.h | 2 +- 2 files changed, 17 insertions(+), 3 deletions(-) diff --git a/ports/atmel-samd/timers.c b/ports/atmel-samd/timers.c index 7b5d06cb0c..2e8541f242 100644 --- a/ports/atmel-samd/timers.c +++ b/ports/atmel-samd/timers.c @@ -73,8 +73,16 @@ const uint8_t tc_gclk_ids[TC_INST_NUM] = {TC0_GCLK_ID, TC7_GCLK_ID, #endif }; -const uint8_t tcc_gclk_ids[5] = {TCC0_GCLK_ID, TCC1_GCLK_ID, TCC2_GCLK_ID, TCC3_GCLK_ID, - TCC4_GCLK_ID}; +const uint8_t tcc_gclk_ids[TCC_INST_NUM] = {TCC0_GCLK_ID, + TCC1_GCLK_ID, + TCC2_GCLK_ID, +#ifdef TCC3_GCLK_ID + TCC3_GCLK_ID, +#endif +#ifdef TCC4_GCLK_ID + TCC4_GCLK_ID +#endif + }; #endif Tc* const tc_insts[TC_INST_NUM] = TC_INSTS; Tcc* const tcc_insts[TCC_INST_NUM] = TCC_INSTS; @@ -89,9 +97,15 @@ IRQn_Type const tc_irq[TC_INST_NUM] = { #ifdef TC2 TC2_IRQn, #endif +#ifdef TC3 TC3_IRQn, +#endif +#ifdef TC4 TC4_IRQn, +#endif +#ifdef TC5 TC5_IRQn, +#endif #ifdef TC6 TC6_IRQn, #endif diff --git a/ports/atmel-samd/timers.h b/ports/atmel-samd/timers.h index a22ec74844..bb3ab5ee7c 100644 --- a/ports/atmel-samd/timers.h +++ b/ports/atmel-samd/timers.h @@ -36,7 +36,7 @@ const uint8_t tcc_gclk_ids[3]; #ifdef SAMD51 const uint8_t tcc_cc_num[5]; const uint8_t tc_gclk_ids[TC_INST_NUM]; -const uint8_t tcc_gclk_ids[5]; +const uint8_t tcc_gclk_ids[TCC_INST_NUM]; #endif Tc* const tc_insts[TC_INST_NUM]; Tcc* const tcc_insts[TCC_INST_NUM]; From 4895a9d1d83699ee273ab80aa1d4113b996bbc2c Mon Sep 17 00:00:00 2001 From: Dan Halbert Date: Tue, 27 Feb 2018 15:44:27 -0500 Subject: [PATCH 074/135] Use safe clock freqs for AnalogOut; use DAC REFRESH on SAMD51. --- ports/atmel-samd/asf4_conf/samd21/hpl_gclk_config.h | 11 ++++++----- .../asf4_conf/samd21/peripheral_clk_config.h | 4 ++-- ports/atmel-samd/asf4_conf/samd51/hpl_dac_config.h | 4 ++-- ports/atmel-samd/asf4_conf/samd51/hpl_gclk_config.h | 4 ++-- .../asf4_conf/samd51/peripheral_clk_config.h | 4 ++-- ports/atmel-samd/common-hal/analogio/AnalogOut.c | 6 ++++-- 6 files changed, 18 insertions(+), 15 deletions(-) diff --git a/ports/atmel-samd/asf4_conf/samd21/hpl_gclk_config.h b/ports/atmel-samd/asf4_conf/samd21/hpl_gclk_config.h index 90df195cd8..d4c9bf2abe 100644 --- a/ports/atmel-samd/asf4_conf/samd21/hpl_gclk_config.h +++ b/ports/atmel-samd/asf4_conf/samd21/hpl_gclk_config.h @@ -1,12 +1,13 @@ // Circuit Python SAMD21 clock tree: -// DFLL48M (with USBCRM on to sync with external USB ref) -> GCLK0 +// DFLL48M (with USBCRM on to sync with external USB ref) -> GCLK0, GCLK1 // GCLK0 (48MHz) -> peripherals +// GLCK1 (48MHz divided by 150 = 320Khz) -> DAC peripheral (DAC requires 350KHz or lower) // We'd like to use XOSC32K as a ref for DFLL48M on boards with a 32kHz crystal, // but haven't figured that out yet. // Used in hpl/core/hpl_init.c to define which clocks should be initialized first. -#define CIRCUITPY_GCLK_INIT_1ST (1 << 0) +#define CIRCUITPY_GCLK_INIT_1ST (1 << 0 | 1 << 1) /* Auto-generated config file hpl_gclk_config.h */ @@ -127,7 +128,7 @@ // Indicates whether Output Enable is enabled or not // gclk_arch_gen_1_oe #ifndef CONF_GCLK_GEN_1_OE -#define CONF_GCLK_GEN_1_OE 0 +#define CONF_GCLK_GEN_1_OE 1 #endif // Output Off Value @@ -172,7 +173,7 @@ // This defines the clock source for generic clock generator 1 // gclk_gen_1_oscillator #ifndef CONF_GCLK_GEN_1_SRC -#define CONF_GCLK_GEN_1_SRC GCLK_GENCTRL_SRC_XOSC32K +#define CONF_GCLK_GEN_1_SRC GCLK_GENCTRL_SRC_DFLL48M #endif //
@@ -181,7 +182,7 @@ // // gclk_gen_1_div #ifndef CONF_GCLK_GEN_1_DIV -#define CONF_GCLK_GEN_1_DIV 1 +#define CONF_GCLK_GEN_1_DIV 150 #endif // diff --git a/ports/atmel-samd/asf4_conf/samd21/peripheral_clk_config.h b/ports/atmel-samd/asf4_conf/samd21/peripheral_clk_config.h index 84fc6b9e4a..cb7dad2041 100644 --- a/ports/atmel-samd/asf4_conf/samd21/peripheral_clk_config.h +++ b/ports/atmel-samd/asf4_conf/samd21/peripheral_clk_config.h @@ -385,7 +385,7 @@ // Select the clock source for DAC. #ifndef CONF_GCLK_DAC_SRC -#define CONF_GCLK_DAC_SRC GCLK_CLKCTRL_GEN_GCLK0_Val +#define CONF_GCLK_DAC_SRC GCLK_CLKCTRL_GEN_GCLK1_Val #endif /** @@ -393,7 +393,7 @@ * \brief DAC's Clock frequency */ #ifndef CONF_GCLK_DAC_FREQUENCY -#define CONF_GCLK_DAC_FREQUENCY 48000000 +#define CONF_GCLK_DAC_FREQUENCY 320000 #endif // USB Clock Source diff --git a/ports/atmel-samd/asf4_conf/samd51/hpl_dac_config.h b/ports/atmel-samd/asf4_conf/samd51/hpl_dac_config.h index 6e530941e7..d6f1898db8 100644 --- a/ports/atmel-samd/asf4_conf/samd51/hpl_dac_config.h +++ b/ports/atmel-samd/asf4_conf/samd51/hpl_dac_config.h @@ -72,7 +72,7 @@ // This defines the refresh period. If it is 0, the refresh mode is disabled, else the refresh period is: value * 500us // dac0_arch_refresh #ifndef CONF_DAC0_REFRESH -#define CONF_DAC0_REFRESH 0 +#define CONF_DAC0_REFRESH 2 #endif // // Channel 1 configuration @@ -111,7 +111,7 @@ // This defines the refresh period. If it is 0, the refresh mode is disabled, else the refresh period is: value * 500us // dac1_arch_refresh #ifndef CONF_DAC1_REFRESH -#define CONF_DAC1_REFRESH 0 +#define CONF_DAC1_REFRESH 2 #endif // diff --git a/ports/atmel-samd/asf4_conf/samd51/hpl_gclk_config.h b/ports/atmel-samd/asf4_conf/samd51/hpl_gclk_config.h index 300db2716d..77793b69a5 100644 --- a/ports/atmel-samd/asf4_conf/samd51/hpl_gclk_config.h +++ b/ports/atmel-samd/asf4_conf/samd51/hpl_gclk_config.h @@ -1,7 +1,7 @@ // Circuit Python SAMD51 clock tree: // DFLL48M (with USBCRM on to sync with external USB ref) -> GCLK1, GCLK5 -// GCLK1 (48MHz) -> peripherals -// GCLK5 (divided down to 2 MHz) -> DPLL0 +// GCLK1 (48MHz) -> 48 MHz peripherals +// GCLK5 (48 MHz divided down to 2 MHz) -> DPLL0, DAC peripherals // DPLL0 (multiplied up to 120 MHz) -> GCLK0, GCLK4 (output for monitoring) // We'd like to use XOSC32K as a ref for DFLL48M on boards with a 32kHz crystal, diff --git a/ports/atmel-samd/asf4_conf/samd51/peripheral_clk_config.h b/ports/atmel-samd/asf4_conf/samd51/peripheral_clk_config.h index c1df632113..41efca755e 100644 --- a/ports/atmel-samd/asf4_conf/samd51/peripheral_clk_config.h +++ b/ports/atmel-samd/asf4_conf/samd51/peripheral_clk_config.h @@ -73,7 +73,7 @@ // dac_gclk_selection // Select the clock source for DAC. #ifndef CONF_GCLK_DAC_SRC -#define CONF_GCLK_DAC_SRC GCLK_PCHCTRL_GEN_GCLK1_Val +#define CONF_GCLK_DAC_SRC GCLK_PCHCTRL_GEN_GCLK5_Val #endif /** @@ -81,7 +81,7 @@ * \brief DAC's Clock frequency */ #ifndef CONF_GCLK_DAC_FREQUENCY -#define CONF_GCLK_DAC_FREQUENCY 48000000 +#define CONF_GCLK_DAC_FREQUENCY 2000000 #endif // EVSYS Channel 0 Clock Source diff --git a/ports/atmel-samd/common-hal/analogio/AnalogOut.c b/ports/atmel-samd/common-hal/analogio/AnalogOut.c index 1d53781b16..44258c3c1d 100644 --- a/ports/atmel-samd/common-hal/analogio/AnalogOut.c +++ b/ports/atmel-samd/common-hal/analogio/AnalogOut.c @@ -65,12 +65,14 @@ void common_hal_analogio_analogout_construct(analogio_analogout_obj_t* self, #ifdef SAMD51 hri_mclk_set_APBDMASK_DAC_bit(MCLK); + // This clock should be <= 12 MHz, per datasheet section 47.6.3. hri_gclk_write_PCHCTRL_reg(GCLK, DAC_GCLK_ID, GCLK_PCHCTRL_GEN_GCLK5_Val | (1 << GCLK_PCHCTRL_CHEN_Pos)); #endif #ifdef SAMD21 _pm_enable_bus_clock(PM_BUS_APBC, DAC); - _gclk_enable_channel(DAC_GCLK_ID, GCLK_CLKCTRL_GEN_GCLK0_Val); + // This clock should be <= 350kHz, per datasheet table 37-6. + _gclk_enable_channel(DAC_GCLK_ID, GCLK_CLKCTRL_GEN_GCLK1_Val); #endif // Don't double init the DAC on the SAMD51 when both outputs are in use. We use the free state @@ -123,7 +125,7 @@ void common_hal_analogio_analogout_deinit(analogio_analogout_obj_t *self) { void common_hal_analogio_analogout_set_value(analogio_analogout_obj_t *self, uint16_t value) { - // Input is 16 bit so make sure and set LEFTADJ to 1 to it takes the top + // Input is 16 bit so make sure and set LEFTADJ to 1 so it takes the top // bits. This is currently done in asf4_conf/*/hpl_dac_config.h. dac_sync_write(&self->descriptor, self->channel, &value, 1); } From 5c24023240be492ddcf0cacec21318a182933391 Mon Sep 17 00:00:00 2001 From: Dan Halbert Date: Tue, 27 Feb 2018 17:21:03 -0500 Subject: [PATCH 075/135] use CONF_GCLK_DAC_SRC and refactor a bit --- ports/atmel-samd/common-hal/analogio/AnalogOut.c | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/ports/atmel-samd/common-hal/analogio/AnalogOut.c b/ports/atmel-samd/common-hal/analogio/AnalogOut.c index 44258c3c1d..97299a8634 100644 --- a/ports/atmel-samd/common-hal/analogio/AnalogOut.c +++ b/ports/atmel-samd/common-hal/analogio/AnalogOut.c @@ -36,6 +36,7 @@ #include "atmel_start_pins.h" #include "hal/include/hal_dac_sync.h" #include "hpl/gclk/hpl_gclk_base.h" +#include "peripheral_clk_config.h" #ifdef SAMD21 #include "hpl/pm/hpl_pm_base.h" @@ -65,16 +66,16 @@ void common_hal_analogio_analogout_construct(analogio_analogout_obj_t* self, #ifdef SAMD51 hri_mclk_set_APBDMASK_DAC_bit(MCLK); - // This clock should be <= 12 MHz, per datasheet section 47.6.3. - hri_gclk_write_PCHCTRL_reg(GCLK, DAC_GCLK_ID, GCLK_PCHCTRL_GEN_GCLK5_Val | (1 << GCLK_PCHCTRL_CHEN_Pos)); #endif #ifdef SAMD21 _pm_enable_bus_clock(PM_BUS_APBC, DAC); - // This clock should be <= 350kHz, per datasheet table 37-6. - _gclk_enable_channel(DAC_GCLK_ID, GCLK_CLKCTRL_GEN_GCLK1_Val); #endif + // SAMD21: This clock should be <= 12 MHz, per datasheet section 47.6.3. + // SAMD51: This clock should be <= 350kHz, per datasheet table 37-6. + _gclk_enable_channel(DAC_GCLK_ID, CONF_GCLK_DAC_SRC); + // Don't double init the DAC on the SAMD51 when both outputs are in use. We use the free state // of each output pin to determine DAC state. int32_t result = ERR_NONE; From ebf326f565f6380b2021ad2162bf74e8f1ed50eb Mon Sep 17 00:00:00 2001 From: Scott Shawcroft Date: Tue, 27 Feb 2018 15:38:28 -0800 Subject: [PATCH 076/135] Build sphinx on Travis --- .travis.yml | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/.travis.yml b/.travis.yml index 75cf139693..7912057230 100644 --- a/.travis.yml +++ b/.travis.yml @@ -20,6 +20,7 @@ env: - TRAVIS_BOARD=feather52 - TRAVIS_TEST=qemu - TRAVIS_TEST=unix + - TRAVIS_TEST=docs addons: artifacts: @@ -28,12 +29,6 @@ addons: target_paths: / notifications: - webhooks: - urls: - - https://webhooks.gitter.im/e/c38b3bb3a3e131d955a1 - on_success: change # options: [always|never|change] default: always - on_failure: always # options: [always|never|change] default: always - on_start: never # options: [always|never|change] default: always webhooks: urls: - https://rosie-ci.ngrok.io/travis @@ -56,6 +51,7 @@ before_script: - ([[ $TRAVIS_BOARD != "feather52" ]] || sudo ports/nrf/drivers/bluetooth/download_ble_stack.sh) # For coverage testing (upgrade is used to get latest urllib3 version) - ([[ -z "$TRAVIS_TEST" ]] || sudo pip install --upgrade cpp-coveralls) + - ([[ $TRAVIS_TEST != "docs" ]] || sudo pip install Sphinx sphinx-rtd-theme) - gcc --version - ([[ -z "$TRAVIS_BOARD" ]] || arm-none-eabi-gcc --version) - python3 --version @@ -101,6 +97,11 @@ script: - ([[ $TRAVIS_TEST != "unix" ]] || (cd tests && MICROPY_CPYTHON3=python3.4 MICROPY_MICROPYTHON=../ports/unix/micropython_coverage ./run-tests --via-mpy -d basics float)) - echo -en 'travis_fold:end:test_mpy\\r' + - (echo 'Building docs' && echo -en 'travis_fold:start:build_docs\\r') + - ([[ $TRAVIS_TEST != "docs" ]] || sphinx-build -E -W -b html . _build/html) + - echo -en 'travis_fold:end:build_docs\\r' + + # run coveralls coverage analysis (try to, even if some builds/tests failed) #- (cd ports/unix && coveralls --root ../.. --build-root . --gcov $(which gcov) --gcov-options '\-o build-coverage/' --include py --include extmod) From 737007cdd8b3184fa2bcc1c679aabfa123974a4e Mon Sep 17 00:00:00 2001 From: Scott Shawcroft Date: Tue, 27 Feb 2018 15:57:00 -0800 Subject: [PATCH 077/135] Install recommonmark too. --- .travis.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index 7912057230..a698403339 100644 --- a/.travis.yml +++ b/.travis.yml @@ -51,7 +51,7 @@ before_script: - ([[ $TRAVIS_BOARD != "feather52" ]] || sudo ports/nrf/drivers/bluetooth/download_ble_stack.sh) # For coverage testing (upgrade is used to get latest urllib3 version) - ([[ -z "$TRAVIS_TEST" ]] || sudo pip install --upgrade cpp-coveralls) - - ([[ $TRAVIS_TEST != "docs" ]] || sudo pip install Sphinx sphinx-rtd-theme) + - ([[ $TRAVIS_TEST != "docs" ]] || sudo pip install Sphinx sphinx-rtd-theme recommonmark) - gcc --version - ([[ -z "$TRAVIS_BOARD" ]] || arm-none-eabi-gcc --version) - python3 --version From ea633117d01d94e8d56ed94344e4b3e46b4eef03 Mon Sep 17 00:00:00 2001 From: Scott Shawcroft Date: Tue, 27 Feb 2018 18:08:49 -0800 Subject: [PATCH 078/135] Remove bad c2rst and fix the other for sphinx 1.7.1 --- c2rst.py | 17 ----------------- conf.py | 1 + docs/c2rst.py | 20 ++++++++++++++------ 3 files changed, 15 insertions(+), 23 deletions(-) delete mode 100644 c2rst.py diff --git a/c2rst.py b/c2rst.py deleted file mode 100644 index 7f9e8d23db..0000000000 --- a/c2rst.py +++ /dev/null @@ -1,17 +0,0 @@ -import docutils.parsers -import docutils.parsers.rst as rst - -class CStrip(docutils.parsers.Parser): - def __init__(self): - self.rst_parser = rst.Parser() - - def parse(self, inputstring, document): - stripped = [] - for line in inputstring.split("\n"): - line = line.strip() - if line == "//|": - stripped.append("") - elif line.startswith("//| "): - stripped.append(line[len("//| "):]) - stripped = "\r\n".join(stripped) - self.rst_parser.parse(stripped, document) diff --git a/conf.py b/conf.py index 8264a9166d..df0ea0a1c4 100644 --- a/conf.py +++ b/conf.py @@ -21,6 +21,7 @@ from recommonmark.parser import CommonMarkParser # If extensions (or modules to document with autodoc) are in another directory, # add these directories to sys.path here. If the directory is relative to the # documentation root, use os.path.abspath to make it absolute, like shown here. +sys.path.insert(0, os.path.abspath('docs')) sys.path.insert(0, os.path.abspath('.')) master_doc = 'docs/index' diff --git a/docs/c2rst.py b/docs/c2rst.py index 3018e62aff..9ca8bc1bb3 100644 --- a/docs/c2rst.py +++ b/docs/c2rst.py @@ -1,10 +1,18 @@ import sphinx.parsers -import docutils.parsers.rst as rst class CStrip(sphinx.parsers.Parser): - def __init(self): - self.rst_parser = rst.Parser() + def __init__(self): + self.rst_parser = sphinx.parsers.RSTParser() - def parse(self, inputstring, document): - print(inputstring) - self.rst_parser(stripped, document) + def parse(self, inputstring, document): + # This setting is missing starting with Sphinx 1.7.1 so we set it ourself. + document.settings.tab_width = 4 + stripped = [] + for line in inputstring.split("\n"): + line = line.strip() + if line == "//|": + stripped.append("") + elif line.startswith("//| "): + stripped.append(line[len("//| "):]) + stripped = "\r\n".join(stripped) + self.rst_parser.parse(stripped, document) From 2ab923862b4adca6946cf89b4c08c4744635220a Mon Sep 17 00:00:00 2001 From: Scott Shawcroft Date: Wed, 28 Feb 2018 19:15:54 -0800 Subject: [PATCH 079/135] Structify flash device definitions. --- .../circuitplayground_express/mpconfigboard.h | 6 +- .../boards/metro_m4_express/mpconfigboard.h | 10 +- ports/atmel-samd/external_flash/devices.h | 180 ++++++++++++++++++ .../external_flash/devices/AT25DF081A.h | 52 ----- .../external_flash/devices/GD25Q16C.h | 56 ------ .../external_flash/devices/S25FL064L.h | 56 ------ .../external_flash/devices/S25FL116K.h | 55 ------ .../external_flash/devices/S25FL216K.h | 55 ------ .../external_flash/devices/W25Q16FW.h | 53 ------ .../external_flash/devices/W25Q32BV.h | 52 ----- .../external_flash/devices/W25Q80DV.h | 52 ----- .../external_flash/external_flash.c | 145 +++++++------- ports/atmel-samd/external_flash/qspi_flash.c | 4 +- 13 files changed, 264 insertions(+), 512 deletions(-) create mode 100644 ports/atmel-samd/external_flash/devices.h delete mode 100644 ports/atmel-samd/external_flash/devices/AT25DF081A.h delete mode 100644 ports/atmel-samd/external_flash/devices/GD25Q16C.h delete mode 100644 ports/atmel-samd/external_flash/devices/S25FL064L.h delete mode 100644 ports/atmel-samd/external_flash/devices/S25FL116K.h delete mode 100644 ports/atmel-samd/external_flash/devices/S25FL216K.h delete mode 100644 ports/atmel-samd/external_flash/devices/W25Q16FW.h delete mode 100644 ports/atmel-samd/external_flash/devices/W25Q32BV.h delete mode 100644 ports/atmel-samd/external_flash/devices/W25Q80DV.h diff --git a/ports/atmel-samd/boards/circuitplayground_express/mpconfigboard.h b/ports/atmel-samd/boards/circuitplayground_express/mpconfigboard.h index cc09d7f790..599dac56de 100644 --- a/ports/atmel-samd/boards/circuitplayground_express/mpconfigboard.h +++ b/ports/atmel-samd/boards/circuitplayground_express/mpconfigboard.h @@ -38,7 +38,7 @@ #define SPEAKER_ENABLE_PIN (&pin_PA30) -#include "external_flash/external_flash.h" +#include "external_flash/devices.h" // If you change this, then make sure to update the linker scripts as well to // make sure you don't overwrite code. @@ -47,8 +47,8 @@ #define BOARD_FLASH_SIZE (0x00040000 - 0x2000 - CIRCUITPY_INTERNAL_NVM_SIZE) -#include "external_flash/devices/S25FL216K.h" -#include "external_flash/devices/GD25Q16C.h" +#define EXTERNAL_FLASH_DEVICES 25FL216K, \ + GD25Q16C #define CALIBRATE_CRYSTALLESS 1 diff --git a/ports/atmel-samd/boards/metro_m4_express/mpconfigboard.h b/ports/atmel-samd/boards/metro_m4_express/mpconfigboard.h index 18d65df2b2..98f69ba804 100644 --- a/ports/atmel-samd/boards/metro_m4_express/mpconfigboard.h +++ b/ports/atmel-samd/boards/metro_m4_express/mpconfigboard.h @@ -20,8 +20,6 @@ #define AUTORESET_DELAY_MS 500 -#include "external_flash/external_flash.h" - // If you change this, then make sure to update the linker scripts as well to // make sure you don't overwrite code // #define CIRCUITPY_INTERNAL_NVM_SIZE 256 @@ -29,5 +27,9 @@ #define BOARD_FLASH_SIZE (FLASH_SIZE - 0x4000 - CIRCUITPY_INTERNAL_NVM_SIZE) -#include "external_flash/devices/S25FL116K.h" -#include "external_flash/devices/GD25Q16C.h" +#include "external_flash/devices.h" + +#define EXTERNAL_FLASH_DEVICE_COUNT 2 +#define EXTERNAL_FLASH_DEVICES S25FL116K, GD25Q16C + +#include "external_flash/external_flash.h" diff --git a/ports/atmel-samd/external_flash/devices.h b/ports/atmel-samd/external_flash/devices.h new file mode 100644 index 0000000000..a02d268287 --- /dev/null +++ b/ports/atmel-samd/external_flash/devices.h @@ -0,0 +1,180 @@ +/* + * This file is part of the MicroPython project, http://micropython.org/ + * + * The MIT License (MIT) + * + * Copyright (c) 2018 Scott Shawcroft for Adafruit Industries LLC + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ +#ifndef MICROPY_INCLUDED_ATMEL_SAMD_EXTERNAL_FLASH_DEVICES_H +#define MICROPY_INCLUDED_ATMEL_SAMD_EXTERNAL_FLASH_DEVICES_H + +#include +#include + +typedef struct { + uint32_t total_size; + uint16_t erase_size; + uint16_t page_size; + uint16_t start_up_time_us; + uint8_t manufacturer_id; + uint8_t memory_type; + uint8_t capacity; + uint8_t max_clock_speed_mhz; + bool has_sector_protection; + bool supports_qspi; + bool supports_qspi_writes; +} external_flash_device; + +// Settings for the Adesto Tech AT25DF081A 1MiB SPI flash. Its on the SAMD21 +// Xplained board. +// Datasheet: https://www.adestotech.com/wp-content/uploads/doc8715.pdf +#define AT25DF081A {\ + .total_size = (1 << 20), /* 1 MiB */ \ + .erase_size = (1 << 12), /* 4 KiB */ \ + .page_size = 256, /*256 bytes */ \ + .start_up_time_us = 10000, \ + .manufacturer_id = 0x1f, \ + .memory_type = 0x45, \ + .capacity = 0x01, \ + .max_clock_speed_mhz = 104, \ + .has_sector_protection = true, \ + .supports_qspi = true, \ + .supports_qspi_writes = false, \ +} + +// Settings for the Gigadevice GD25Q16C 2MiB SPI flash. +// Datasheet: http://www.gigadevice.com/wp-content/uploads/2017/12/DS-00086-GD25Q16C-Rev2.6.pdf + +#define GD25Q16C {\ + .total_size = (1 << 21), /* 2 MiB */ \ + .erase_size = (1 << 12), /* 4 KiB */ \ + .page_size = 256, /*256 bytes */ \ + .start_up_time_us = 5000, \ + .manufacturer_id = 0xc8, \ + .memory_type = 0x40, \ + .capacity = 0x15, \ + .max_clock_speed_mhz = 104, \ + .has_sector_protection = true, \ + .supports_qspi = true, \ + .supports_qspi_writes = false, \ +} + +// Settings for the Cypress (was Spansion) S25FL064L 8MiB SPI flash. +// Datasheet: http://www.cypress.com/file/316661/download +#define S25FL064L {\ + .total_size = (1 << 23), /* 8 MiB */ \ + .erase_size = (1 << 12), /* 4 KiB */ \ + .page_size = 256, /*256 bytes */ \ + .start_up_time_us = 300, \ + .manufacturer_id = 0x01, \ + .memory_type = 0x60, \ + .capacity = 0x17, \ + .max_clock_speed_mhz = 104, \ + .has_sector_protection = true, \ + .supports_qspi = true, \ + .supports_qspi_writes = false, \ +} + +// Settings for the Cypress (was Spansion) S25FL116K 2MiB SPI flash. +// Datasheet: http://www.cypress.com/file/196886/download +#define S25FL116K {\ + .total_size = (1 << 21), /* 2 MiB */ \ + .erase_size = (1 << 12), /* 4 KiB */ \ + .page_size = 256, /*256 bytes */ \ + .start_up_time_us = 10000, \ + .manufacturer_id = 0x01, \ + .memory_type = 0x40, \ + .capacity = 0x15, \ + .max_clock_speed_mhz = 104, \ + .has_sector_protection = true, \ + .supports_qspi = true, \ + .supports_qspi_writes = false, \ +} + + +// Settings for the Cypress (was Spansion) S25FL216K 2MiB SPI flash. +// Datasheet: http://www.cypress.com/file/197346/download + +#define S25FL216K {\ + .total_size = (1 << 21), /* 2 MiB */ \ + .erase_size = (1 << 12), /* 4 KiB */ \ + .page_size = 256, /*256 bytes */ \ + .start_up_time_us = 10000, \ + .manufacturer_id = 0x01, \ + .memory_type = 0x40, \ + .capacity = 0x15, \ + .max_clock_speed_mhz = 104, \ + .has_sector_protection = false, \ + .supports_qspi = true, \ + .supports_qspi_writes = false, \ +} + +// Settings for the Winbond W25Q16FW 2MiB SPI flash. +// Datasheet: https://www.winbond.com/resource-files/w25q16fw%20revj%2005182017%20sfdp.pdf + +#define W25Q16FW {\ + .total_size = (1 << 21), /* 2 MiB */ \ + .erase_size = (1 << 12), /* 4 KiB */ \ + .page_size = 256, /*256 bytes */ \ + .start_up_time_us = 5000, \ + .manufacturer_id = 0xef, \ + .memory_type = 0x60, \ + .capacity = 0x15, \ + .max_clock_speed_mhz = 104, \ + .has_sector_protection = false, \ + .supports_qspi = true, \ + .supports_qspi_writes = false, \ +} + +// Settings for the Winbond W25Q32BV 2MiB SPI flash. +// Datasheet: https://www.winbond.com/resource-files/w25q32bv_revi_100413_wo_automotive.pdf + +#define W25Q32BV {\ + .total_size = (1 << 21), /* 2 MiB */ \ + .erase_size = (1 << 12), /* 4 KiB */ \ + .page_size = 256, /*256 bytes */ \ + .start_up_time_us = 5000, \ + .manufacturer_id = 0xef, \ + .memory_type = 0x60, \ + .capacity = 0x16, \ + .max_clock_speed_mhz = 104, \ + .has_sector_protection = false, \ + .supports_qspi = true, \ + .supports_qspi_writes = false, \ +} + +// Settings for the Winbond W25Q80DL 1MiB SPI flash. +// Datasheet: https://www.winbond.com/resource-files/w25q80dv%20dl_revh_10022015.pdf +#define W25Q80DL {\ + .total_size = (1 << 20), /* 1 MiB */ \ + .erase_size = (1 << 12), /* 4 KiB */ \ + .page_size = 256, /*256 bytes */ \ + .start_up_time_us = 5000, \ + .manufacturer_id = 0xef, \ + .memory_type = 0x60, \ + .capacity = 0x14, \ + .max_clock_speed_mhz = 104, \ + .has_sector_protection = false, \ + .supports_qspi = true, \ + .supports_qspi_writes = false, \ +} + +#endif // MICROPY_INCLUDED_ATMEL_SAMD_EXTERNAL_FLASH_DEVICES_H diff --git a/ports/atmel-samd/external_flash/devices/AT25DF081A.h b/ports/atmel-samd/external_flash/devices/AT25DF081A.h deleted file mode 100644 index ba0fc6659b..0000000000 --- a/ports/atmel-samd/external_flash/devices/AT25DF081A.h +++ /dev/null @@ -1,52 +0,0 @@ -/* - * This file is part of the MicroPython project, http://micropython.org/ - * - * The MIT License (MIT) - * - * Copyright (c) 2017 Scott Shawcroft for Adafruit Industries - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ - -#ifndef MICROPY_INCLUDED_ATMEL_SAMD_BOARD_FLASH_AT25DF081A_H -#define MICROPY_INCLUDED_ATMEL_SAMD_BOARD_FLASH_AT25DF081A_H - -// Settings for the Adesto Tech AT25DF081A 1MiB SPI flash. Its on the SAMD21 -// Xplained board. -// Datasheet: https://www.adestotech.com/wp-content/uploads/doc8715.pdf - -// The total flash size in bytes. -#define SPI_FLASH_TOTAL_SIZE (1 << 20) // 2 MiB - -// The size of the smallest erase unit thats erased with command 0x20. -#define SPI_FLASH_ERASE_SIZE (1 << 12) // 4 KiB - -// The size of a page that is programmed with page program command 0x02. -#define SPI_FLASH_PAGE_SIZE (256) // 256 bytes - -// These are the first three response bytes to the JEDEC ID command 0x9f that is -// used to confirm we're talking to the flash we expect. The data sheet calls -// them something else so we just match it byte for byte. -#define SPI_FLASH_JEDEC_MANUFACTURER 0x1F -#define SPI_FLASH_JEDEC_MEMORY_TYPE 0x45 -#define SPI_FLASH_JEDEC_CAPACITY 0x01 - -#define SPI_FLASH_SECTOR_PROTECTION - -#endif // MICROPY_INCLUDED_ATMEL_SAMD_BOARD_FLASH_AT25DF081A_H diff --git a/ports/atmel-samd/external_flash/devices/GD25Q16C.h b/ports/atmel-samd/external_flash/devices/GD25Q16C.h deleted file mode 100644 index e123265e29..0000000000 --- a/ports/atmel-samd/external_flash/devices/GD25Q16C.h +++ /dev/null @@ -1,56 +0,0 @@ -/* - * This file is part of the MicroPython project, http://micropython.org/ - * - * The MIT License (MIT) - * - * Copyright (c) 2017 Scott Shawcroft for Adafruit Industries - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ - -#ifndef MICROPY_INCLUDED_ATMEL_SAMD_BOARD_FLASH_GD25Q16C_H -#define MICROPY_INCLUDED_ATMEL_SAMD_BOARD_FLASH_GD25Q16C_H - -// Settings for the Gigadevice GD25Q16C 2MiB SPI flash. -// Datasheet: http://www.gigadevice.com/product/download/410.html?locale=en_US - -// The total flash size in bytes. -#define SPI_FLASH_TOTAL_SIZE (1 << 21) // 2 MiB - -// The size of the smallest erase unit thats erased with command 0x20. -#define SPI_FLASH_ERASE_SIZE (1 << 12) // 4 KiB - -// The size of a page that is programmed with page program command 0x02. -#define SPI_FLASH_PAGE_SIZE (256) // 256 bytes - -#ifndef SPI_FLASH_JEDEC_MANUFACTURER -// These are the first three response bytes to the JEDEC ID command 0x9f that is -// used to confirm we're talking to the flash we expect. -#define SPI_FLASH_JEDEC_MANUFACTURER 0xc8 -#define SPI_FLASH_SECTOR_PROTECTION true -#define SPI_FLASH_JEDEC_MEMORY_TYPE 0x40 -#else -#define SPI_FLASH_JEDEC_MANUFACTURER_2 0xc8 -#define SPI_FLASH_SECTOR_PROTECTION_2 true -#define SPI_FLASH_JEDEC_MEMORY_TYPE_2 0x40 -#endif -#define SPI_FLASH_JEDEC_CAPACITY 0x15 - - -#endif // MICROPY_INCLUDED_ATMEL_SAMD_BOARD_FLASH_GD25Q16C_H diff --git a/ports/atmel-samd/external_flash/devices/S25FL064L.h b/ports/atmel-samd/external_flash/devices/S25FL064L.h deleted file mode 100644 index 5a38836874..0000000000 --- a/ports/atmel-samd/external_flash/devices/S25FL064L.h +++ /dev/null @@ -1,56 +0,0 @@ -/* - * This file is part of the MicroPython project, http://micropython.org/ - * - * The MIT License (MIT) - * - * Copyright (c) 2017 Scott Shawcroft for Adafruit Industries - * Copyright (c) 2017 Dave Astels - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ - -#ifndef MICROPY_INCLUDED_ATMEL_SAMD_BOARD_FLASH_S25FL064L_H -#define MICROPY_INCLUDED_ATMEL_SAMD_BOARD_FLASH_S25FL064L_H - -// Settings for the Cypress (was Spansion) S25FL064L 8MiB SPI flash. -// Datasheet: http://www.cypress.com/file/316661/download - -// The total flash size in bytes. -#define SPI_FLASH_TOTAL_SIZE (1 << 23) // 8 MiB - -// The size of the smallest erase unit thats erased with command 0x20. -#define SPI_FLASH_ERASE_SIZE (1 << 12) // 4 KiB - -// The size of a page that is programmed with page program command 0x02. -#define SPI_FLASH_PAGE_SIZE (256) // 256 bytes - -// These are the first three response bytes to the JEDEC ID command 0x9f that is -// used to confirm we're talking to the flash we expect. -#ifndef SPI_FLASH_JEDEC_MANUFACTURER -#define SPI_FLASH_JEDEC_MANUFACTURER 0x01 -#define SPI_FLASH_SECTOR_PROTECTION false -#define SPI_FLASH_JEDEC_MEMORY_TYPE 0x60 -#else -#define SPI_FLASH_JEDEC_MANUFACTURER_2 0x013 -#define SPI_FLASH_SECTOR_PROTECTION_2 false -#define SPI_FLASH_JEDEC_MEMORY_TYPE_2 0x60 -#endif -#define SPI_FLASH_JEDEC_CAPACITY 0x17 - -#endif // MICROPY_INCLUDED_ATMEL_SAMD_BOARD_FLASH_S25FL216K_H diff --git a/ports/atmel-samd/external_flash/devices/S25FL116K.h b/ports/atmel-samd/external_flash/devices/S25FL116K.h deleted file mode 100644 index 0ccb58ed07..0000000000 --- a/ports/atmel-samd/external_flash/devices/S25FL116K.h +++ /dev/null @@ -1,55 +0,0 @@ -/* - * This file is part of the MicroPython project, http://micropython.org/ - * - * The MIT License (MIT) - * - * Copyright (c) 2017 Scott Shawcroft for Adafruit Industries - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ - -#ifndef MICROPY_INCLUDED_ATMEL_SAMD_BOARD_FLASH_S25FL116K_H -#define MICROPY_INCLUDED_ATMEL_SAMD_BOARD_FLASH_S25FL116K_H - -// Settings for the Cypress (was Spansion) S25FL116K 2MiB SPI flash. -// Datasheet: http://www.cypress.com/file/196886/download - -// The total flash size in bytes. -#define SPI_FLASH_TOTAL_SIZE (1 << 21) // 2 MiB - -// The size of the smallest erase unit thats erased with command 0x20. -#define SPI_FLASH_ERASE_SIZE (1 << 12) // 4 KiB - -// The size of a page that is programmed with page program command 0x02. -#define SPI_FLASH_PAGE_SIZE (256) // 256 bytes - -// These are the first three response bytes to the JEDEC ID command 0x9f that is -// used to confirm we're talking to the flash we expect. -#ifndef SPI_FLASH_JEDEC_MANUFACTURER -#define SPI_FLASH_JEDEC_MANUFACTURER 0x01 -#define SPI_FLASH_SECTOR_PROTECTION false -#define SPI_FLASH_JEDEC_MEMORY_TYPE 0x40 -#else -#define SPI_FLASH_JEDEC_MANUFACTURER_2 0x01 -#define SPI_FLASH_SECTOR_PROTECTION_2 false -#define SPI_FLASH_JEDEC_MEMORY_TYPE_2 0x40 -#endif -#define SPI_FLASH_JEDEC_CAPACITY 0x15 - -#endif // MICROPY_INCLUDED_ATMEL_SAMD_BOARD_FLASH_S25FL216K_H diff --git a/ports/atmel-samd/external_flash/devices/S25FL216K.h b/ports/atmel-samd/external_flash/devices/S25FL216K.h deleted file mode 100644 index a6a0a12fa2..0000000000 --- a/ports/atmel-samd/external_flash/devices/S25FL216K.h +++ /dev/null @@ -1,55 +0,0 @@ -/* - * This file is part of the MicroPython project, http://micropython.org/ - * - * The MIT License (MIT) - * - * Copyright (c) 2017 Scott Shawcroft for Adafruit Industries - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ - -#ifndef MICROPY_INCLUDED_ATMEL_SAMD_BOARD_FLASH_S25FL216K_H -#define MICROPY_INCLUDED_ATMEL_SAMD_BOARD_FLASH_S25FL216K_H - -// Settings for the Cypress (was Spansion) S25FL216K 2MiB SPI flash. -// Datasheet: http://www.cypress.com/file/197346/download - -// The total flash size in bytes. -#define SPI_FLASH_TOTAL_SIZE (1 << 21) // 2 MiB - -// The size of the smallest erase unit thats erased with command 0x20. -#define SPI_FLASH_ERASE_SIZE (1 << 12) // 4 KiB - -// The size of a page that is programmed with page program command 0x02. -#define SPI_FLASH_PAGE_SIZE (256) // 256 bytes - -// These are the first three response bytes to the JEDEC ID command 0x9f that is -// used to confirm we're talking to the flash we expect. -#ifndef SPI_FLASH_JEDEC_MANUFACTURER -#define SPI_FLASH_JEDEC_MANUFACTURER 0x01 -#define SPI_FLASH_SECTOR_PROTECTION false -#define SPI_FLASH_JEDEC_MEMORY_TYPE 0x40 -#else -#define SPI_FLASH_JEDEC_MANUFACTURER_2 0x01 -#define SPI_FLASH_SECTOR_PROTECTION_2 false -#define SPI_FLASH_JEDEC_MEMORY_TYPE_2 0x40 -#endif -#define SPI_FLASH_JEDEC_CAPACITY 0x15 - -#endif // MICROPY_INCLUDED_ATMEL_SAMD_BOARD_FLASH_S25FL216K_H diff --git a/ports/atmel-samd/external_flash/devices/W25Q16FW.h b/ports/atmel-samd/external_flash/devices/W25Q16FW.h deleted file mode 100644 index 219a7f058f..0000000000 --- a/ports/atmel-samd/external_flash/devices/W25Q16FW.h +++ /dev/null @@ -1,53 +0,0 @@ -/* - * This file is part of the MicroPython project, http://micropython.org/ - * - * The MIT License (MIT) - * - * Copyright (c) 2017 Scott Shawcroft for Adafruit Industries - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ - -#ifndef MICROPY_INCLUDED_ATMEL_SAMD_BOARD_FLASH_W25Q16FW_H -#define MICROPY_INCLUDED_ATMEL_SAMD_BOARD_FLASH_W25Q16FW_H - -// The total flash size in bytes. -#define SPI_FLASH_TOTAL_SIZE (1 << 21) // 2 MiB - -// The size of the smallest erase unit thats erased with command 0x20. -#define SPI_FLASH_ERASE_SIZE (1 << 12) // 4 KiB - -// The size of a page that is programmed with page program command 0x02. -#define SPI_FLASH_PAGE_SIZE (256) // 256 bytes - -// These are the first three response bytes to the JEDEC ID command 0x9f that is -// used to confirm we're talking to the flash we expect. -#ifndef SPI_FLASH_JEDEC_MANUFACTURER - #define SPI_FLASH_JEDEC_MANUFACTURER 0xef - #define SPI_FLASH_SECTOR_PROTECTION false - #define SPI_FLASH_JEDEC_MEMORY_TYPE 0x60 -#else - #define SPI_FLASH_JEDEC_MANUFACTURER_2 0xef - #define SPI_FLASH_SECTOR_PROTECTION_2 false - #define SPI_FLASH_JEDEC_MEMORY_TYPE_2 0x60 -#endif - -#define SPI_FLASH_JEDEC_CAPACITY 0x15 - -#endif // MICROPY_INCLUDED_ATMEL_SAMD_BOARD_FLASH_W25Q16BV_H diff --git a/ports/atmel-samd/external_flash/devices/W25Q32BV.h b/ports/atmel-samd/external_flash/devices/W25Q32BV.h deleted file mode 100644 index d71771babc..0000000000 --- a/ports/atmel-samd/external_flash/devices/W25Q32BV.h +++ /dev/null @@ -1,52 +0,0 @@ -/* - * This file is part of the MicroPython project, http://micropython.org/ - * - * The MIT License (MIT) - * - * Copyright (c) 2017 Scott Shawcroft for Adafruit Industries - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ - -#ifndef MICROPY_INCLUDED_ATMEL_SAMD_BOARD_FLASH_W25Q32BV_H -#define MICROPY_INCLUDED_ATMEL_SAMD_BOARD_FLASH_W25Q32BV_H - -// The total flash size in bytes. -#define SPI_FLASH_TOTAL_SIZE (1 << 21) // 2 MiB - -// The size of the smallest erase unit thats erased with command 0x20. -#define SPI_FLASH_ERASE_SIZE (1 << 12) // 4 KiB - -// The size of a page that is programmed with page program command 0x02. -#define SPI_FLASH_PAGE_SIZE (256) // 256 bytes - -// These are the first three response bytes to the JEDEC ID command 0x9f that is -// used to confirm we're talking to the flash we expect. -#ifndef SPI_FLASH_JEDEC_MANUFACTURER -#define SPI_FLASH_JEDEC_MANUFACTURER 0xef -#define SPI_FLASH_SECTOR_PROTECTION false -#define SPI_FLASH_JEDEC_MEMORY_TYPE 0x40 -#else -#define SPI_FLASH_JEDEC_MANUFACTURER_2 0xef -#define SPI_FLASH_SECTOR_PROTECTION_2 false -#define SPI_FLASH_JEDEC_MEMORY_TYPE_2 0x40 -#endif -#define SPI_FLASH_JEDEC_CAPACITY 0x16 - -#endif // MICROPY_INCLUDED_ATMEL_SAMD_BOARD_FLASH_W25Q32BV_H diff --git a/ports/atmel-samd/external_flash/devices/W25Q80DV.h b/ports/atmel-samd/external_flash/devices/W25Q80DV.h deleted file mode 100644 index de12e3fd44..0000000000 --- a/ports/atmel-samd/external_flash/devices/W25Q80DV.h +++ /dev/null @@ -1,52 +0,0 @@ -/* - * This file is part of the MicroPython project, http://micropython.org/ - * - * The MIT License (MIT) - * - * Copyright (c) 2017 Scott Shawcroft for Adafruit Industries - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ - -#ifndef MICROPY_INCLUDED_ATMEL_SAMD_BOARD_FLASH_W25Q80DV_H -#define MICROPY_INCLUDED_ATMEL_SAMD_BOARD_FLASH_W25Q80DV_H - -// The total flash size in bytes. -#define SPI_FLASH_TOTAL_SIZE (1 << 20) // 1 MiB - -// The size of the smallest erase unit thats erased with command 0x20. -#define SPI_FLASH_ERASE_SIZE (1 << 12) // 4 KiB - -// The size of a page that is programmed with page program command 0x02. -#define SPI_FLASH_PAGE_SIZE (256) // 256 bytes - -// These are the first three response bytes to the JEDEC ID command 0x9f that is -// used to confirm we're talking to the flash we expect. -#ifndef SPI_FLASH_JEDEC_MANUFACTURER -#define SPI_FLASH_JEDEC_MANUFACTURER 0xef -#define SPI_FLASH_SECTOR_PROTECTION false -#define SPI_FLASH_JEDEC_MEMORY_TYPE 0x40 -#else -#define SPI_FLASH_JEDEC_MANUFACTURER_2 0xef -#define SPI_FLASH_SECTOR_PROTECTION_2 false -#define SPI_FLASH_JEDEC_MEMORY_TYPE_2 0x40 -#endif -#define SPI_FLASH_JEDEC_CAPACITY 0x14 - -#endif // MICROPY_INCLUDED_ATMEL_SAMD_BOARD_FLASH_W25Q80DV_H diff --git a/ports/atmel-samd/external_flash/external_flash.c b/ports/atmel-samd/external_flash/external_flash.c index b432567ef2..26437e975c 100644 --- a/ports/atmel-samd/external_flash/external_flash.c +++ b/ports/atmel-samd/external_flash/external_flash.c @@ -37,6 +37,7 @@ #include "py/runtime.h" #include "lib/oofatfs/ff.h" #include "peripherals.h" +#include "shared-bindings/microcontroller/__init__.h" #include "supervisor/shared/rgb_led_status.h" //#include "shared_dma.h" @@ -48,20 +49,19 @@ #define NO_SECTOR_LOADED 0xFFFFFFFF -static bool spi_flash_is_initialised = false; - struct spi_m_sync_descriptor spi_flash_desc; // The currently cached sector in the cache, ram or flash based. static uint32_t current_sector; +external_flash_device possible_devices[EXTERNAL_FLASH_DEVICE_COUNT] = {EXTERNAL_FLASH_DEVICES}; + +static external_flash_device* flash_device = NULL; + // Track which blocks (up to 32) in the current sector currently live in the // cache. static uint32_t dirty_mask; -// Address of the scratch flash sector. -#define SCRATCH_SECTOR (SPI_FLASH_TOTAL_SIZE - SPI_FLASH_ERASE_SIZE) - // Wait until both the write enable and write in progress bits have cleared. static bool wait_for_flash_ready(void) { uint8_t read_status_response[1] = {0x00}; @@ -80,7 +80,7 @@ static bool write_enable(void) { // Read data_length's worth of bytes starting at address into data. static bool read_flash(uint32_t address, uint8_t* data, uint32_t data_length) { - if (!spi_flash_is_initialised) { + if (flash_device == NULL) { return false; } if (!wait_for_flash_ready()) { @@ -93,7 +93,7 @@ static bool read_flash(uint32_t address, uint8_t* data, uint32_t data_length) { // that the sector that address resides in has already been erased. So make sure // to run erase_sector. static bool write_flash(uint32_t address, const uint8_t* data, uint32_t data_length) { - if (!spi_flash_is_initialised) { + if (flash_device == NULL) { return false; } // Don't bother writing if the data is all 1s. Thats equivalent to the flash @@ -111,13 +111,13 @@ static bool write_flash(uint32_t address, const uint8_t* data, uint32_t data_len for (uint32_t bytes_written = 0; bytes_written < data_length; - bytes_written += SPI_FLASH_PAGE_SIZE) { + bytes_written += flash_device->page_size) { if (!wait_for_flash_ready() || !write_enable()) { return false; } if (!spi_flash_write_data(address + bytes_written, (uint8_t*) data + bytes_written, - SPI_FLASH_PAGE_SIZE)) { + flash_device->page_size)) { return false; } } @@ -168,12 +168,13 @@ static bool erase_sector(uint32_t sector_address) { // Sector is really 24 bits. static bool copy_block(uint32_t src_address, uint32_t dest_address) { // Copy page by page to minimize RAM buffer. - uint8_t buffer[SPI_FLASH_PAGE_SIZE]; - for (uint32_t i = 0; i < FILESYSTEM_BLOCK_SIZE / SPI_FLASH_PAGE_SIZE; i++) { - if (!read_flash(src_address + i * SPI_FLASH_PAGE_SIZE, buffer, SPI_FLASH_PAGE_SIZE)) { + uint16_t page_size = flash_device->page_size; + uint8_t buffer[page_size]; + for (uint32_t i = 0; i < FILESYSTEM_BLOCK_SIZE / page_size; i++) { + if (!read_flash(src_address + i * page_size, buffer, page_size)) { return false; } - if (!write_flash(dest_address + i * SPI_FLASH_PAGE_SIZE, buffer, SPI_FLASH_PAGE_SIZE)) { + if (!write_flash(dest_address + i * page_size, buffer, page_size)) { return false; } } @@ -181,12 +182,41 @@ static bool copy_block(uint32_t src_address, uint32_t dest_address) { } void external_flash_init(void) { - if (spi_flash_is_initialised) { + if (flash_device != NULL) { return; } + uint8_t num_possible_devices = sizeof(*possible_devices) / sizeof(external_flash_device); + + // Delay to give the SPI Flash time to get going. + // TODO(tannewt): Only do this when we know power was applied vs a reset. + uint16_t max_start_up_delay_us = 0; + for (uint8_t i = 0; i < num_possible_devices; i++) { + if (possible_devices[i].start_up_time_us > max_start_up_delay_us) { + max_start_up_delay_us = possible_devices[i].start_up_time_us; + } + } + common_hal_mcu_delay_us(max_start_up_delay_us); spi_flash_init(); + + for (uint8_t i = 0; i < num_possible_devices; i++) { + external_flash_device* possible_device = &possible_devices[i]; + uint8_t jedec_id_response[3] = {0x00, 0x00, 0x00}; + spi_flash_read_command(CMD_READ_JEDEC_ID, jedec_id_response, 3); + if (jedec_id_response[0] == possible_device->manufacturer_id && + jedec_id_response[1] == possible_device->memory_type && + jedec_id_response[2] == possible_device->capacity) { + flash_device = possible_device; + break; + } + } + + if (flash_device == NULL) { + asm("bkpt"); + return; + } + // Activity LED for flash writes. #ifdef MICROPY_HW_LED_MSC gpio_set_pin_function(SPI_FLASH_CS_PIN, GPIO_PIN_FUNCTION_OFF); @@ -195,33 +225,7 @@ void external_flash_init(void) { gpio_set_pin_level(MICROPY_HW_LED_MSC, false); #endif - uint8_t jedec_id_response[3] = {0x00, 0x00, 0x00}; - spi_flash_read_command(CMD_READ_JEDEC_ID, jedec_id_response, 3); - - uint8_t manufacturer = jedec_id_response[0]; - if ((jedec_id_response[0] == SPI_FLASH_JEDEC_MANUFACTURER -#ifdef SPI_FLASH_JEDEC_MANUFACTURER_2 - || jedec_id_response[0] == SPI_FLASH_JEDEC_MANUFACTURER_2 -#endif - ) && - (jedec_id_response[1] == SPI_FLASH_JEDEC_MEMORY_TYPE -#ifdef SPI_FLASH_JEDEC_MANUFACTURER_2 - || jedec_id_response[1] == SPI_FLASH_JEDEC_MEMORY_TYPE_2 -#endif - ) && - jedec_id_response[2] == SPI_FLASH_JEDEC_CAPACITY) { - spi_flash_is_initialised = true; - } else { - // Unknown flash chip! - spi_flash_is_initialised = false; - return; - } - - if ((manufacturer == SPI_FLASH_JEDEC_MANUFACTURER && SPI_FLASH_SECTOR_PROTECTION) -#ifdef SPI_FLASH_JEDEC_MANUFACTURER_2 - || (manufacturer == SPI_FLASH_JEDEC_MANUFACTURER_2 && SPI_FLASH_SECTOR_PROTECTION_2) -#endif - ) { + if (flash_device->has_sector_protection) { write_enable(); // Turn off sector protection @@ -237,8 +241,6 @@ void external_flash_init(void) { current_sector = NO_SECTOR_LOADED; dirty_mask = 0; MP_STATE_VM(flash_ram_cache) = NULL; - - spi_flash_is_initialised = true; } // The size of each individual block. @@ -250,7 +252,7 @@ uint32_t external_flash_get_block_size(void) { uint32_t external_flash_get_block_count(void) { // We subtract one erase sector size because we may use it as a staging area // for writes. - return SPI_FLASH_PART1_START_BLOCK + (SPI_FLASH_TOTAL_SIZE - SPI_FLASH_ERASE_SIZE) / FILESYSTEM_BLOCK_SIZE; + return SPI_FLASH_PART1_START_BLOCK + (flash_device->total_size - flash_device->erase_size) / FILESYSTEM_BLOCK_SIZE; } // Flush the cache that was written to the scratch portion of flash. Only used @@ -259,11 +261,12 @@ static bool flush_scratch_flash(void) { // First, copy out any blocks that we haven't touched from the sector we've // cached. bool copy_to_scratch_ok = true; - for (uint8_t i = 0; i < SPI_FLASH_ERASE_SIZE / FILESYSTEM_BLOCK_SIZE; i++) { + uint32_t scratch_sector = flash_device->total_size - flash_device->erase_size; + for (uint8_t i = 0; i < flash_device->erase_size / FILESYSTEM_BLOCK_SIZE; i++) { if ((dirty_mask & (1 << i)) == 0) { copy_to_scratch_ok = copy_to_scratch_ok && copy_block(current_sector + i * FILESYSTEM_BLOCK_SIZE, - SCRATCH_SECTOR + i * FILESYSTEM_BLOCK_SIZE); + scratch_sector + i * FILESYSTEM_BLOCK_SIZE); } } if (!copy_to_scratch_ok) { @@ -274,8 +277,8 @@ static bool flush_scratch_flash(void) { // Second, erase the current sector. erase_sector(current_sector); // Finally, copy the new version into it. - for (uint8_t i = 0; i < SPI_FLASH_ERASE_SIZE / FILESYSTEM_BLOCK_SIZE; i++) { - copy_block(SCRATCH_SECTOR + i * FILESYSTEM_BLOCK_SIZE, + for (uint8_t i = 0; i < flash_device->erase_size / FILESYSTEM_BLOCK_SIZE; i++) { + copy_block(scratch_sector + i * FILESYSTEM_BLOCK_SIZE, current_sector + i * FILESYSTEM_BLOCK_SIZE); } return true; @@ -285,8 +288,8 @@ static bool flush_scratch_flash(void) { // ram. Each page is allocated separately so that the GC doesn't need to provide // one huge block. We can free it as we write if we want to also. static bool allocate_ram_cache(void) { - uint8_t blocks_per_sector = SPI_FLASH_ERASE_SIZE / FILESYSTEM_BLOCK_SIZE; - uint8_t pages_per_block = FILESYSTEM_BLOCK_SIZE / SPI_FLASH_PAGE_SIZE; + uint8_t blocks_per_sector = flash_device->erase_size / FILESYSTEM_BLOCK_SIZE; + uint8_t pages_per_block = FILESYSTEM_BLOCK_SIZE / flash_device->page_size; MP_STATE_VM(flash_ram_cache) = m_malloc_maybe(blocks_per_sector * pages_per_block * sizeof(uint32_t), false); if (MP_STATE_VM(flash_ram_cache) == NULL) { return false; @@ -298,7 +301,7 @@ static bool allocate_ram_cache(void) { bool success = true; for (i = 0; i < blocks_per_sector; i++) { for (j = 0; j < pages_per_block; j++) { - uint8_t *page_cache = m_malloc_maybe(SPI_FLASH_PAGE_SIZE, false); + uint8_t *page_cache = m_malloc_maybe(flash_device->page_size, false); if (page_cache == NULL) { success = false; break; @@ -333,14 +336,14 @@ static bool flush_ram_cache(bool keep_cache) { // we've cached. If we don't do this we'll erase the data during the sector // erase below. bool copy_to_ram_ok = true; - uint8_t pages_per_block = FILESYSTEM_BLOCK_SIZE / SPI_FLASH_PAGE_SIZE; - for (uint8_t i = 0; i < SPI_FLASH_ERASE_SIZE / FILESYSTEM_BLOCK_SIZE; i++) { + uint8_t pages_per_block = FILESYSTEM_BLOCK_SIZE / flash_device->page_size; + for (uint8_t i = 0; i < flash_device->erase_size / FILESYSTEM_BLOCK_SIZE; i++) { if ((dirty_mask & (1 << i)) == 0) { for (uint8_t j = 0; j < pages_per_block; j++) { copy_to_ram_ok = read_flash( - current_sector + (i * pages_per_block + j) * SPI_FLASH_PAGE_SIZE, + current_sector + (i * pages_per_block + j) * flash_device->page_size, MP_STATE_VM(flash_ram_cache)[i * pages_per_block + j], - SPI_FLASH_PAGE_SIZE); + flash_device->page_size); if (!copy_to_ram_ok) { break; } @@ -357,11 +360,11 @@ static bool flush_ram_cache(bool keep_cache) { // Second, erase the current sector. erase_sector(current_sector); // Lastly, write all the data in ram that we've cached. - for (uint8_t i = 0; i < SPI_FLASH_ERASE_SIZE / FILESYSTEM_BLOCK_SIZE; i++) { + for (uint8_t i = 0; i < flash_device->erase_size / FILESYSTEM_BLOCK_SIZE; i++) { for (uint8_t j = 0; j < pages_per_block; j++) { - write_flash(current_sector + (i * pages_per_block + j) * SPI_FLASH_PAGE_SIZE, + write_flash(current_sector + (i * pages_per_block + j) * flash_device->page_size, MP_STATE_VM(flash_ram_cache)[i * pages_per_block + j], - SPI_FLASH_PAGE_SIZE); + flash_device->page_size); if (!keep_cache) { m_free(MP_STATE_VM(flash_ram_cache)[i * pages_per_block + j]); } @@ -485,21 +488,21 @@ bool external_flash_read_block(uint8_t *dest, uint32_t block) { } // Mask out the lower bits that designate the address within the sector. - uint32_t this_sector = address & (~(SPI_FLASH_ERASE_SIZE - 1)); - uint8_t block_index = (address / FILESYSTEM_BLOCK_SIZE) % (SPI_FLASH_ERASE_SIZE / FILESYSTEM_BLOCK_SIZE); + uint32_t this_sector = address & (~(flash_device->erase_size - 1)); + uint8_t block_index = (address / FILESYSTEM_BLOCK_SIZE) % (flash_device->erase_size / FILESYSTEM_BLOCK_SIZE); uint8_t mask = 1 << (block_index); // We're reading from the currently cached sector. if (current_sector == this_sector && (mask & dirty_mask) > 0) { if (MP_STATE_VM(flash_ram_cache) != NULL) { - uint8_t pages_per_block = FILESYSTEM_BLOCK_SIZE / SPI_FLASH_PAGE_SIZE; + uint8_t pages_per_block = FILESYSTEM_BLOCK_SIZE / flash_device->page_size; for (int i = 0; i < pages_per_block; i++) { - memcpy(dest + i * SPI_FLASH_PAGE_SIZE, + memcpy(dest + i * flash_device->page_size, MP_STATE_VM(flash_ram_cache)[block_index * pages_per_block + i], - SPI_FLASH_PAGE_SIZE); + flash_device->page_size); } return true; } else { - uint32_t scratch_address = SCRATCH_SECTOR + block_index * FILESYSTEM_BLOCK_SIZE; + uint32_t scratch_address = flash_device->total_size - flash_device->erase_size + block_index * FILESYSTEM_BLOCK_SIZE; return read_flash(scratch_address, dest, FILESYSTEM_BLOCK_SIZE); } } @@ -521,8 +524,8 @@ bool external_flash_write_block(const uint8_t *data, uint32_t block) { // Wait for any previous writes to finish. wait_for_flash_ready(); // Mask out the lower bits that designate the address within the sector. - uint32_t this_sector = address & (~(SPI_FLASH_ERASE_SIZE - 1)); - uint8_t block_index = (address / FILESYSTEM_BLOCK_SIZE) % (SPI_FLASH_ERASE_SIZE / FILESYSTEM_BLOCK_SIZE); + uint32_t this_sector = address & (~(flash_device->erase_size - 1)); + uint8_t block_index = (address / FILESYSTEM_BLOCK_SIZE) % (flash_device->erase_size / FILESYSTEM_BLOCK_SIZE); uint8_t mask = 1 << (block_index); // Flush the cache if we're moving onto a sector or we're writing the // same block again. @@ -536,7 +539,7 @@ bool external_flash_write_block(const uint8_t *data, uint32_t block) { spi_flash_flush_keep_cache(true); } if (MP_STATE_VM(flash_ram_cache) == NULL && !allocate_ram_cache()) { - erase_sector(SCRATCH_SECTOR); + erase_sector(flash_device->total_size - flash_device->erase_size); wait_for_flash_ready(); } current_sector = this_sector; @@ -545,15 +548,15 @@ bool external_flash_write_block(const uint8_t *data, uint32_t block) { dirty_mask |= mask; // Copy the block to the appropriate cache. if (MP_STATE_VM(flash_ram_cache) != NULL) { - uint8_t pages_per_block = FILESYSTEM_BLOCK_SIZE / SPI_FLASH_PAGE_SIZE; + uint8_t pages_per_block = FILESYSTEM_BLOCK_SIZE / flash_device->page_size; for (int i = 0; i < pages_per_block; i++) { memcpy(MP_STATE_VM(flash_ram_cache)[block_index * pages_per_block + i], - data + i * SPI_FLASH_PAGE_SIZE, - SPI_FLASH_PAGE_SIZE); + data + i * flash_device->page_size, + flash_device->page_size); } return true; } else { - uint32_t scratch_address = SCRATCH_SECTOR + block_index * FILESYSTEM_BLOCK_SIZE; + uint32_t scratch_address = flash_device->total_size - flash_device->erase_size + block_index * FILESYSTEM_BLOCK_SIZE; return write_flash(scratch_address, data, FILESYSTEM_BLOCK_SIZE); } } diff --git a/ports/atmel-samd/external_flash/qspi_flash.c b/ports/atmel-samd/external_flash/qspi_flash.c index d9dc3bf01e..54f1af0dce 100644 --- a/ports/atmel-samd/external_flash/qspi_flash.c +++ b/ports/atmel-samd/external_flash/qspi_flash.c @@ -167,7 +167,7 @@ void spi_flash_init(void) { QSPI->CTRLA.reg = QSPI_CTRLA_SWRST; // We don't need to wait because we're running as fast as the CPU. - QSPI->BAUD.bit.BAUD = 10; + QSPI->BAUD.bit.BAUD = 1; QSPI->CTRLB.reg = QSPI_CTRLB_MODE_MEMORY | QSPI_CTRLB_DATALEN_8BITS | QSPI_CTRLB_CSMODE_LASTXFER; @@ -191,6 +191,4 @@ void spi_flash_init(void) { spi_flash_command(CMD_ENABLE_WRITE); spi_flash_write_command(0x01, full_status, 3); } - - asm("nop"); } From 01aceaae50e913840064691d3e7c6915e820939f Mon Sep 17 00:00:00 2001 From: Scott Shawcroft Date: Thu, 1 Mar 2018 12:45:12 -0800 Subject: [PATCH 080/135] Support all boards and remove erase and page sizes because they never change. --- .../circuitplayground_express/mpconfigboard.h | 7 +- .../boards/feather_m0_express/mpconfigboard.h | 9 +- .../feather_m0_supersized/mpconfigboard.h | 7 +- .../itsybitsy_m0_express/mpconfigboard.h | 11 +- .../boards/metro_m0_express/mpconfigboard.h | 11 +- .../boards/metro_m4_express/mpconfigboard.h | 4 +- .../metro_m4_express_revb/mpconfigboard.h | 9 +- .../trinket_m0_haxpress/mpconfigboard.h | 7 +- .../atmel-samd/boards/ugame10/mpconfigboard.h | 8 +- ports/atmel-samd/external_flash/devices.h | 108 +++++++++++------- .../external_flash/external_flash.c | 66 +++++------ .../external_flash/external_flash.h | 4 + 12 files changed, 157 insertions(+), 94 deletions(-) diff --git a/ports/atmel-samd/boards/circuitplayground_express/mpconfigboard.h b/ports/atmel-samd/boards/circuitplayground_express/mpconfigboard.h index 599dac56de..02802a6a90 100644 --- a/ports/atmel-samd/boards/circuitplayground_express/mpconfigboard.h +++ b/ports/atmel-samd/boards/circuitplayground_express/mpconfigboard.h @@ -47,9 +47,14 @@ #define BOARD_FLASH_SIZE (0x00040000 - 0x2000 - CIRCUITPY_INTERNAL_NVM_SIZE) -#define EXTERNAL_FLASH_DEVICES 25FL216K, \ +#include "external_flash/devices.h" + +#define EXTERNAL_FLASH_DEVICE_COUNT 2 +#define EXTERNAL_FLASH_DEVICES S25FL216K, \ GD25Q16C +#include "external_flash/external_flash.h" + #define CALIBRATE_CRYSTALLESS 1 // Explanation of how a user got into safe mode. diff --git a/ports/atmel-samd/boards/feather_m0_express/mpconfigboard.h b/ports/atmel-samd/boards/feather_m0_express/mpconfigboard.h index 378b0891ad..ef13bcafec 100644 --- a/ports/atmel-samd/boards/feather_m0_express/mpconfigboard.h +++ b/ports/atmel-samd/boards/feather_m0_express/mpconfigboard.h @@ -40,5 +40,10 @@ #define BOARD_FLASH_SIZE (0x00040000 - 0x2000 - CIRCUITPY_INTERNAL_NVM_SIZE) -#include "external_flash/devices/S25FL216K.h" -#include "external_flash/devices/GD25Q16C.h" +#include "external_flash/devices.h" + +#define EXTERNAL_FLASH_DEVICE_COUNT 2 +#define EXTERNAL_FLASH_DEVICES S25FL216K, \ + GD25Q16C + +#include "external_flash/external_flash.h" diff --git a/ports/atmel-samd/boards/feather_m0_supersized/mpconfigboard.h b/ports/atmel-samd/boards/feather_m0_supersized/mpconfigboard.h index b5ed682962..883d7a2e53 100644 --- a/ports/atmel-samd/boards/feather_m0_supersized/mpconfigboard.h +++ b/ports/atmel-samd/boards/feather_m0_supersized/mpconfigboard.h @@ -42,4 +42,9 @@ #define BOARD_FLASH_SIZE (0x00040000 - 0x2000 - CIRCUITPY_INTERNAL_NVM_SIZE) -#include "external_flash/devices/S25FL064L.h" +#include "external_flash/devices.h" + +#define EXTERNAL_FLASH_DEVICE_COUNT 1 +#define EXTERNAL_FLASH_DEVICES S25FL064L + +#include "external_flash/external_flash.h" diff --git a/ports/atmel-samd/boards/itsybitsy_m0_express/mpconfigboard.h b/ports/atmel-samd/boards/itsybitsy_m0_express/mpconfigboard.h index 46eb8c8d9e..ca39792a92 100644 --- a/ports/atmel-samd/boards/itsybitsy_m0_express/mpconfigboard.h +++ b/ports/atmel-samd/boards/itsybitsy_m0_express/mpconfigboard.h @@ -33,13 +33,16 @@ #define MICROPY_PORT_B (PORT_PB22 | PORT_PB23 | PORT_PB03 ) #define MICROPY_PORT_C (0) -#include "external_flash/external_flash.h" - // If you change this, then make sure to update the linker scripts as well to // make sure you don't overwrite code. // #define CIRCUITPY_INTERNAL_NVM_SIZE 256 #define CIRCUITPY_INTERNAL_NVM_SIZE 0 #define BOARD_FLASH_SIZE (0x00040000 - 0x2000 - CIRCUITPY_INTERNAL_NVM_SIZE) -#include "external_flash/devices/GD25Q16C.h" -#include "external_flash/devices/W25Q16FW.h" +#include "external_flash/devices.h" + +#define EXTERNAL_FLASH_DEVICE_COUNT 2 +#define EXTERNAL_FLASH_DEVICES W25Q16FW, \ + GD25Q16C + +#include "external_flash/external_flash.h" diff --git a/ports/atmel-samd/boards/metro_m0_express/mpconfigboard.h b/ports/atmel-samd/boards/metro_m0_express/mpconfigboard.h index 70e830620d..c8ceaa386b 100644 --- a/ports/atmel-samd/boards/metro_m0_express/mpconfigboard.h +++ b/ports/atmel-samd/boards/metro_m0_express/mpconfigboard.h @@ -34,8 +34,6 @@ #define MICROPY_PORT_B (PORT_PB03 | PORT_PB22 | PORT_PB23) #define MICROPY_PORT_C (0) -#include "external_flash/external_flash.h" - // If you change this, then make sure to update the linker scripts as well to // make sure you don't overwrite code. // #define CIRCUITPY_INTERNAL_NVM_SIZE 256 @@ -43,5 +41,10 @@ #define BOARD_FLASH_SIZE (0x00040000 - 0x2000 - CIRCUITPY_INTERNAL_NVM_SIZE) -#include "external_flash/devices/S25FL216K.h" -#include "external_flash/devices/GD25Q16C.h" +#include "external_flash/devices.h" + +#define EXTERNAL_FLASH_DEVICE_COUNT 2 +#define EXTERNAL_FLASH_DEVICES S25FL216K, \ + GD25Q16C + +#include "external_flash/external_flash.h" diff --git a/ports/atmel-samd/boards/metro_m4_express/mpconfigboard.h b/ports/atmel-samd/boards/metro_m4_express/mpconfigboard.h index 98f69ba804..b541af80c9 100644 --- a/ports/atmel-samd/boards/metro_m4_express/mpconfigboard.h +++ b/ports/atmel-samd/boards/metro_m4_express/mpconfigboard.h @@ -29,7 +29,7 @@ #include "external_flash/devices.h" -#define EXTERNAL_FLASH_DEVICE_COUNT 2 -#define EXTERNAL_FLASH_DEVICES S25FL116K, GD25Q16C +#define EXTERNAL_FLASH_DEVICE_COUNT 3 +#define EXTERNAL_FLASH_DEVICES S25FL116K, S25FL216K, GD25Q16C #include "external_flash/external_flash.h" diff --git a/ports/atmel-samd/boards/metro_m4_express_revb/mpconfigboard.h b/ports/atmel-samd/boards/metro_m4_express_revb/mpconfigboard.h index 7c51bae870..70c92ea444 100644 --- a/ports/atmel-samd/boards/metro_m4_express_revb/mpconfigboard.h +++ b/ports/atmel-samd/boards/metro_m4_express_revb/mpconfigboard.h @@ -54,5 +54,10 @@ #define BOARD_FLASH_SIZE (FLASH_SIZE - 0x4000 - CIRCUITPY_INTERNAL_NVM_SIZE) -#include "external_flash/devices/S25FL216K.h" -#include "external_flash/devices/GD25Q16C.h" +#include "external_flash/devices.h" + +#define EXTERNAL_FLASH_DEVICE_COUNT 2 +#define EXTERNAL_FLASH_DEVICES S25FL216K, \ + GD25Q16C + +#include "external_flash/external_flash.h" diff --git a/ports/atmel-samd/boards/trinket_m0_haxpress/mpconfigboard.h b/ports/atmel-samd/boards/trinket_m0_haxpress/mpconfigboard.h index 62bca9a413..340e25e59b 100644 --- a/ports/atmel-samd/boards/trinket_m0_haxpress/mpconfigboard.h +++ b/ports/atmel-samd/boards/trinket_m0_haxpress/mpconfigboard.h @@ -48,4 +48,9 @@ #define CIRCUITPY_INTERNAL_NVM_SIZE 0 #define BOARD_FLASH_SIZE (0x00040000 - 0x2000 - CIRCUITPY_INTERNAL_NVM_SIZE) -#include "external_flash/devices/W25Q32BV.h" +#include "external_flash/devices.h" + +#define EXTERNAL_FLASH_DEVICE_COUNT 1 +#define EXTERNAL_FLASH_DEVICES W25Q32BV + +#include "external_flash/external_flash.h" diff --git a/ports/atmel-samd/boards/ugame10/mpconfigboard.h b/ports/atmel-samd/boards/ugame10/mpconfigboard.h index d0d9296a40..b9ae952a8c 100644 --- a/ports/atmel-samd/boards/ugame10/mpconfigboard.h +++ b/ports/atmel-samd/boards/ugame10/mpconfigboard.h @@ -41,5 +41,9 @@ #define CIRCUITPY_INTERNAL_NVM_SIZE 0 #define BOARD_FLASH_SIZE (0x00040000 - 0x2000 - CIRCUITPY_INTERNAL_NVM_SIZE) -//#include "external_flash/devices/W25Q32BV.h" -#include "external_flash/devices/S25FL216K.h" +#include "external_flash/devices.h" + +#define EXTERNAL_FLASH_DEVICE_COUNT 1 +#define EXTERNAL_FLASH_DEVICES S25FL216K + +#include "external_flash/external_flash.h" diff --git a/ports/atmel-samd/external_flash/devices.h b/ports/atmel-samd/external_flash/devices.h index a02d268287..ce2c6c3dc0 100644 --- a/ports/atmel-samd/external_flash/devices.h +++ b/ports/atmel-samd/external_flash/devices.h @@ -31,16 +31,29 @@ typedef struct { uint32_t total_size; - uint16_t erase_size; - uint16_t page_size; uint16_t start_up_time_us; + + // Three response bytes to 0x9f JEDEC ID command. uint8_t manufacturer_id; uint8_t memory_type; uint8_t capacity; + + // Max clock speed for all operations and the fastest read mode. uint8_t max_clock_speed_mhz; - bool has_sector_protection; - bool supports_qspi; - bool supports_qspi_writes; + bool has_sector_protection : 1; + + // Supports the 0x0b fast read command with 8 dummy cycles. + bool supports_fast_read : 1; + + // Supports the fast read, quad output command 0x6b with 8 dummy cycles. + bool supports_qspi : 1; + + // Requires quad enable set in status bit 9. + bool has_quad_enable : 1; + + // Supports the quad input page program command 0x32. This is known as 1-1-4 because it only + // uses all four lines for data. + bool supports_qspi_writes: 1; } external_flash_device; // Settings for the Adesto Tech AT25DF081A 1MiB SPI flash. Its on the SAMD21 @@ -48,116 +61,127 @@ typedef struct { // Datasheet: https://www.adestotech.com/wp-content/uploads/doc8715.pdf #define AT25DF081A {\ .total_size = (1 << 20), /* 1 MiB */ \ - .erase_size = (1 << 12), /* 4 KiB */ \ - .page_size = 256, /*256 bytes */ \ .start_up_time_us = 10000, \ .manufacturer_id = 0x1f, \ .memory_type = 0x45, \ .capacity = 0x01, \ - .max_clock_speed_mhz = 104, \ + .max_clock_speed_mhz = 85, \ .has_sector_protection = true, \ - .supports_qspi = true, \ + .supports_fast_read = true, \ + .supports_qspi = false, \ + .has_quad_enable = false, \ .supports_qspi_writes = false, \ } // Settings for the Gigadevice GD25Q16C 2MiB SPI flash. // Datasheet: http://www.gigadevice.com/wp-content/uploads/2017/12/DS-00086-GD25Q16C-Rev2.6.pdf - #define GD25Q16C {\ .total_size = (1 << 21), /* 2 MiB */ \ - .erase_size = (1 << 12), /* 4 KiB */ \ - .page_size = 256, /*256 bytes */ \ .start_up_time_us = 5000, \ .manufacturer_id = 0xc8, \ .memory_type = 0x40, \ .capacity = 0x15, \ - .max_clock_speed_mhz = 104, \ - .has_sector_protection = true, \ + .max_clock_speed_mhz = 104, /* if we need 120 then we can turn on high performance mode */ \ + .has_sector_protection = false, \ + .supports_fast_read = true, \ .supports_qspi = true, \ - .supports_qspi_writes = false, \ + .has_quad_enable = true, \ + .supports_qspi_writes = true, \ } // Settings for the Cypress (was Spansion) S25FL064L 8MiB SPI flash. // Datasheet: http://www.cypress.com/file/316661/download #define S25FL064L {\ .total_size = (1 << 23), /* 8 MiB */ \ - .erase_size = (1 << 12), /* 4 KiB */ \ - .page_size = 256, /*256 bytes */ \ .start_up_time_us = 300, \ .manufacturer_id = 0x01, \ .memory_type = 0x60, \ .capacity = 0x17, \ - .max_clock_speed_mhz = 104, \ - .has_sector_protection = true, \ + .max_clock_speed_mhz = 108, \ + .has_sector_protection = false, \ + .supports_fast_read = true, \ .supports_qspi = true, \ - .supports_qspi_writes = false, \ + .has_quad_enable = true, \ + .supports_qspi_writes = true, \ } // Settings for the Cypress (was Spansion) S25FL116K 2MiB SPI flash. // Datasheet: http://www.cypress.com/file/196886/download #define S25FL116K {\ .total_size = (1 << 21), /* 2 MiB */ \ - .erase_size = (1 << 12), /* 4 KiB */ \ - .page_size = 256, /*256 bytes */ \ .start_up_time_us = 10000, \ .manufacturer_id = 0x01, \ .memory_type = 0x40, \ .capacity = 0x15, \ - .max_clock_speed_mhz = 104, \ - .has_sector_protection = true, \ + .max_clock_speed_mhz = 108, \ + .has_sector_protection = false, \ + .supports_fast_read = true, \ .supports_qspi = true, \ + .has_quad_enable = true, \ .supports_qspi_writes = false, \ } - // Settings for the Cypress (was Spansion) S25FL216K 2MiB SPI flash. // Datasheet: http://www.cypress.com/file/197346/download - #define S25FL216K {\ .total_size = (1 << 21), /* 2 MiB */ \ - .erase_size = (1 << 12), /* 4 KiB */ \ - .page_size = 256, /*256 bytes */ \ .start_up_time_us = 10000, \ .manufacturer_id = 0x01, \ .memory_type = 0x40, \ .capacity = 0x15, \ - .max_clock_speed_mhz = 104, \ + .max_clock_speed_mhz = 65, \ .has_sector_protection = false, \ - .supports_qspi = true, \ + .supports_fast_read = true, \ + .supports_qspi = false, \ + .has_quad_enable = false, \ .supports_qspi_writes = false, \ } // Settings for the Winbond W25Q16FW 2MiB SPI flash. // Datasheet: https://www.winbond.com/resource-files/w25q16fw%20revj%2005182017%20sfdp.pdf - #define W25Q16FW {\ .total_size = (1 << 21), /* 2 MiB */ \ - .erase_size = (1 << 12), /* 4 KiB */ \ - .page_size = 256, /*256 bytes */ \ .start_up_time_us = 5000, \ .manufacturer_id = 0xef, \ .memory_type = 0x60, \ .capacity = 0x15, \ - .max_clock_speed_mhz = 104, \ + .max_clock_speed_mhz = 133, \ .has_sector_protection = false, \ + .supports_fast_read = true, \ .supports_qspi = true, \ - .supports_qspi_writes = false, \ + .has_quad_enable = true, \ + .supports_qspi_writes = true, \ +} + +// Settings for the Winbond W25Q16JV 2MiB SPI flash. +// Datasheet: https://www.winbond.com/resource-files/w25q16jv%20spi%20revf%2005092017.pdf +#define W25Q16JV {\ + .total_size = (1 << 21), /* 2 MiB */ \ + .start_up_time_us = 5000, \ + .manufacturer_id = 0xef, \ + .memory_type = 0x40, \ + .capacity = 0x15, \ + .max_clock_speed_mhz = 133, \ + .has_sector_protection = false, \ + .supports_fast_read = true, \ + .supports_qspi = true, \ + .has_quad_enable = true, \ + .supports_qspi_writes = true, \ } // Settings for the Winbond W25Q32BV 2MiB SPI flash. // Datasheet: https://www.winbond.com/resource-files/w25q32bv_revi_100413_wo_automotive.pdf - #define W25Q32BV {\ - .total_size = (1 << 21), /* 2 MiB */ \ - .erase_size = (1 << 12), /* 4 KiB */ \ - .page_size = 256, /*256 bytes */ \ - .start_up_time_us = 5000, \ + .total_size = (1 << 22), /* 4 MiB */ \ + .start_up_time_us = 10000, \ .manufacturer_id = 0xef, \ .memory_type = 0x60, \ .capacity = 0x16, \ .max_clock_speed_mhz = 104, \ .has_sector_protection = false, \ + .supports_fast_read = true, \ .supports_qspi = true, \ + .has_quad_enable = true, \ .supports_qspi_writes = false, \ } @@ -165,15 +189,15 @@ typedef struct { // Datasheet: https://www.winbond.com/resource-files/w25q80dv%20dl_revh_10022015.pdf #define W25Q80DL {\ .total_size = (1 << 20), /* 1 MiB */ \ - .erase_size = (1 << 12), /* 4 KiB */ \ - .page_size = 256, /*256 bytes */ \ .start_up_time_us = 5000, \ .manufacturer_id = 0xef, \ .memory_type = 0x60, \ .capacity = 0x14, \ .max_clock_speed_mhz = 104, \ .has_sector_protection = false, \ + .supports_fast_read = true, \ .supports_qspi = true, \ + .has_quad_enable = true, \ .supports_qspi_writes = false, \ } diff --git a/ports/atmel-samd/external_flash/external_flash.c b/ports/atmel-samd/external_flash/external_flash.c index 26437e975c..ca8121bc93 100644 --- a/ports/atmel-samd/external_flash/external_flash.c +++ b/ports/atmel-samd/external_flash/external_flash.c @@ -54,9 +54,9 @@ struct spi_m_sync_descriptor spi_flash_desc; // The currently cached sector in the cache, ram or flash based. static uint32_t current_sector; -external_flash_device possible_devices[EXTERNAL_FLASH_DEVICE_COUNT] = {EXTERNAL_FLASH_DEVICES}; +const external_flash_device possible_devices[EXTERNAL_FLASH_DEVICE_COUNT] = {EXTERNAL_FLASH_DEVICES}; -static external_flash_device* flash_device = NULL; +static const external_flash_device* flash_device = NULL; // Track which blocks (up to 32) in the current sector currently live in the // cache. @@ -111,13 +111,13 @@ static bool write_flash(uint32_t address, const uint8_t* data, uint32_t data_len for (uint32_t bytes_written = 0; bytes_written < data_length; - bytes_written += flash_device->page_size) { + bytes_written += SPI_FLASH_PAGE_SIZE) { if (!wait_for_flash_ready() || !write_enable()) { return false; } if (!spi_flash_write_data(address + bytes_written, (uint8_t*) data + bytes_written, - flash_device->page_size)) { + SPI_FLASH_PAGE_SIZE)) { return false; } } @@ -168,7 +168,7 @@ static bool erase_sector(uint32_t sector_address) { // Sector is really 24 bits. static bool copy_block(uint32_t src_address, uint32_t dest_address) { // Copy page by page to minimize RAM buffer. - uint16_t page_size = flash_device->page_size; + uint16_t page_size = SPI_FLASH_PAGE_SIZE; uint8_t buffer[page_size]; for (uint32_t i = 0; i < FILESYSTEM_BLOCK_SIZE / page_size; i++) { if (!read_flash(src_address + i * page_size, buffer, page_size)) { @@ -201,7 +201,7 @@ void external_flash_init(void) { for (uint8_t i = 0; i < num_possible_devices; i++) { - external_flash_device* possible_device = &possible_devices[i]; + const external_flash_device* possible_device = &possible_devices[i]; uint8_t jedec_id_response[3] = {0x00, 0x00, 0x00}; spi_flash_read_command(CMD_READ_JEDEC_ID, jedec_id_response, 3); if (jedec_id_response[0] == possible_device->manufacturer_id && @@ -252,7 +252,7 @@ uint32_t external_flash_get_block_size(void) { uint32_t external_flash_get_block_count(void) { // We subtract one erase sector size because we may use it as a staging area // for writes. - return SPI_FLASH_PART1_START_BLOCK + (flash_device->total_size - flash_device->erase_size) / FILESYSTEM_BLOCK_SIZE; + return SPI_FLASH_PART1_START_BLOCK + (flash_device->total_size - SPI_FLASH_ERASE_SIZE) / FILESYSTEM_BLOCK_SIZE; } // Flush the cache that was written to the scratch portion of flash. Only used @@ -261,8 +261,8 @@ static bool flush_scratch_flash(void) { // First, copy out any blocks that we haven't touched from the sector we've // cached. bool copy_to_scratch_ok = true; - uint32_t scratch_sector = flash_device->total_size - flash_device->erase_size; - for (uint8_t i = 0; i < flash_device->erase_size / FILESYSTEM_BLOCK_SIZE; i++) { + uint32_t scratch_sector = flash_device->total_size - SPI_FLASH_ERASE_SIZE; + for (uint8_t i = 0; i < SPI_FLASH_ERASE_SIZE / FILESYSTEM_BLOCK_SIZE; i++) { if ((dirty_mask & (1 << i)) == 0) { copy_to_scratch_ok = copy_to_scratch_ok && copy_block(current_sector + i * FILESYSTEM_BLOCK_SIZE, @@ -277,7 +277,7 @@ static bool flush_scratch_flash(void) { // Second, erase the current sector. erase_sector(current_sector); // Finally, copy the new version into it. - for (uint8_t i = 0; i < flash_device->erase_size / FILESYSTEM_BLOCK_SIZE; i++) { + for (uint8_t i = 0; i < SPI_FLASH_ERASE_SIZE / FILESYSTEM_BLOCK_SIZE; i++) { copy_block(scratch_sector + i * FILESYSTEM_BLOCK_SIZE, current_sector + i * FILESYSTEM_BLOCK_SIZE); } @@ -288,8 +288,8 @@ static bool flush_scratch_flash(void) { // ram. Each page is allocated separately so that the GC doesn't need to provide // one huge block. We can free it as we write if we want to also. static bool allocate_ram_cache(void) { - uint8_t blocks_per_sector = flash_device->erase_size / FILESYSTEM_BLOCK_SIZE; - uint8_t pages_per_block = FILESYSTEM_BLOCK_SIZE / flash_device->page_size; + uint8_t blocks_per_sector = SPI_FLASH_ERASE_SIZE / FILESYSTEM_BLOCK_SIZE; + uint8_t pages_per_block = FILESYSTEM_BLOCK_SIZE / SPI_FLASH_PAGE_SIZE; MP_STATE_VM(flash_ram_cache) = m_malloc_maybe(blocks_per_sector * pages_per_block * sizeof(uint32_t), false); if (MP_STATE_VM(flash_ram_cache) == NULL) { return false; @@ -301,7 +301,7 @@ static bool allocate_ram_cache(void) { bool success = true; for (i = 0; i < blocks_per_sector; i++) { for (j = 0; j < pages_per_block; j++) { - uint8_t *page_cache = m_malloc_maybe(flash_device->page_size, false); + uint8_t *page_cache = m_malloc_maybe(SPI_FLASH_PAGE_SIZE, false); if (page_cache == NULL) { success = false; break; @@ -336,14 +336,14 @@ static bool flush_ram_cache(bool keep_cache) { // we've cached. If we don't do this we'll erase the data during the sector // erase below. bool copy_to_ram_ok = true; - uint8_t pages_per_block = FILESYSTEM_BLOCK_SIZE / flash_device->page_size; - for (uint8_t i = 0; i < flash_device->erase_size / FILESYSTEM_BLOCK_SIZE; i++) { + uint8_t pages_per_block = FILESYSTEM_BLOCK_SIZE / SPI_FLASH_PAGE_SIZE; + for (uint8_t i = 0; i < SPI_FLASH_ERASE_SIZE / FILESYSTEM_BLOCK_SIZE; i++) { if ((dirty_mask & (1 << i)) == 0) { for (uint8_t j = 0; j < pages_per_block; j++) { copy_to_ram_ok = read_flash( - current_sector + (i * pages_per_block + j) * flash_device->page_size, + current_sector + (i * pages_per_block + j) * SPI_FLASH_PAGE_SIZE, MP_STATE_VM(flash_ram_cache)[i * pages_per_block + j], - flash_device->page_size); + SPI_FLASH_PAGE_SIZE); if (!copy_to_ram_ok) { break; } @@ -360,11 +360,11 @@ static bool flush_ram_cache(bool keep_cache) { // Second, erase the current sector. erase_sector(current_sector); // Lastly, write all the data in ram that we've cached. - for (uint8_t i = 0; i < flash_device->erase_size / FILESYSTEM_BLOCK_SIZE; i++) { + for (uint8_t i = 0; i < SPI_FLASH_ERASE_SIZE / FILESYSTEM_BLOCK_SIZE; i++) { for (uint8_t j = 0; j < pages_per_block; j++) { - write_flash(current_sector + (i * pages_per_block + j) * flash_device->page_size, + write_flash(current_sector + (i * pages_per_block + j) * SPI_FLASH_PAGE_SIZE, MP_STATE_VM(flash_ram_cache)[i * pages_per_block + j], - flash_device->page_size); + SPI_FLASH_PAGE_SIZE); if (!keep_cache) { m_free(MP_STATE_VM(flash_ram_cache)[i * pages_per_block + j]); } @@ -488,21 +488,21 @@ bool external_flash_read_block(uint8_t *dest, uint32_t block) { } // Mask out the lower bits that designate the address within the sector. - uint32_t this_sector = address & (~(flash_device->erase_size - 1)); - uint8_t block_index = (address / FILESYSTEM_BLOCK_SIZE) % (flash_device->erase_size / FILESYSTEM_BLOCK_SIZE); + uint32_t this_sector = address & (~(SPI_FLASH_ERASE_SIZE - 1)); + uint8_t block_index = (address / FILESYSTEM_BLOCK_SIZE) % (SPI_FLASH_ERASE_SIZE / FILESYSTEM_BLOCK_SIZE); uint8_t mask = 1 << (block_index); // We're reading from the currently cached sector. if (current_sector == this_sector && (mask & dirty_mask) > 0) { if (MP_STATE_VM(flash_ram_cache) != NULL) { - uint8_t pages_per_block = FILESYSTEM_BLOCK_SIZE / flash_device->page_size; + uint8_t pages_per_block = FILESYSTEM_BLOCK_SIZE / SPI_FLASH_PAGE_SIZE; for (int i = 0; i < pages_per_block; i++) { - memcpy(dest + i * flash_device->page_size, + memcpy(dest + i * SPI_FLASH_PAGE_SIZE, MP_STATE_VM(flash_ram_cache)[block_index * pages_per_block + i], - flash_device->page_size); + SPI_FLASH_PAGE_SIZE); } return true; } else { - uint32_t scratch_address = flash_device->total_size - flash_device->erase_size + block_index * FILESYSTEM_BLOCK_SIZE; + uint32_t scratch_address = flash_device->total_size - SPI_FLASH_ERASE_SIZE + block_index * FILESYSTEM_BLOCK_SIZE; return read_flash(scratch_address, dest, FILESYSTEM_BLOCK_SIZE); } } @@ -524,8 +524,8 @@ bool external_flash_write_block(const uint8_t *data, uint32_t block) { // Wait for any previous writes to finish. wait_for_flash_ready(); // Mask out the lower bits that designate the address within the sector. - uint32_t this_sector = address & (~(flash_device->erase_size - 1)); - uint8_t block_index = (address / FILESYSTEM_BLOCK_SIZE) % (flash_device->erase_size / FILESYSTEM_BLOCK_SIZE); + uint32_t this_sector = address & (~(SPI_FLASH_ERASE_SIZE - 1)); + uint8_t block_index = (address / FILESYSTEM_BLOCK_SIZE) % (SPI_FLASH_ERASE_SIZE / FILESYSTEM_BLOCK_SIZE); uint8_t mask = 1 << (block_index); // Flush the cache if we're moving onto a sector or we're writing the // same block again. @@ -539,7 +539,7 @@ bool external_flash_write_block(const uint8_t *data, uint32_t block) { spi_flash_flush_keep_cache(true); } if (MP_STATE_VM(flash_ram_cache) == NULL && !allocate_ram_cache()) { - erase_sector(flash_device->total_size - flash_device->erase_size); + erase_sector(flash_device->total_size - SPI_FLASH_ERASE_SIZE); wait_for_flash_ready(); } current_sector = this_sector; @@ -548,15 +548,15 @@ bool external_flash_write_block(const uint8_t *data, uint32_t block) { dirty_mask |= mask; // Copy the block to the appropriate cache. if (MP_STATE_VM(flash_ram_cache) != NULL) { - uint8_t pages_per_block = FILESYSTEM_BLOCK_SIZE / flash_device->page_size; + uint8_t pages_per_block = FILESYSTEM_BLOCK_SIZE / SPI_FLASH_PAGE_SIZE; for (int i = 0; i < pages_per_block; i++) { memcpy(MP_STATE_VM(flash_ram_cache)[block_index * pages_per_block + i], - data + i * flash_device->page_size, - flash_device->page_size); + data + i * SPI_FLASH_PAGE_SIZE, + SPI_FLASH_PAGE_SIZE); } return true; } else { - uint32_t scratch_address = flash_device->total_size - flash_device->erase_size + block_index * FILESYSTEM_BLOCK_SIZE; + uint32_t scratch_address = flash_device->total_size - SPI_FLASH_ERASE_SIZE + block_index * FILESYSTEM_BLOCK_SIZE; return write_flash(scratch_address, data, FILESYSTEM_BLOCK_SIZE); } } diff --git a/ports/atmel-samd/external_flash/external_flash.h b/ports/atmel-samd/external_flash/external_flash.h index 5a43b10c84..f8ec5673ce 100644 --- a/ports/atmel-samd/external_flash/external_flash.h +++ b/ports/atmel-samd/external_flash/external_flash.h @@ -37,6 +37,10 @@ // Erase sector size. #define SPI_FLASH_SECTOR_SIZE (0x1000 - 100) +// These are common across all NOR Flash. +#define SPI_FLASH_ERASE_SIZE (1 << 12) +#define SPI_FLASH_PAGE_SIZE (256) + #define SPI_FLASH_SYSTICK_MASK (0x1ff) // 512ms #define SPI_FLASH_IDLE_TICK(tick) (((tick) & SPI_FLASH_SYSTICK_MASK) == 2) From f16619ad3cc8d19d739902632d52628b43dcf390 Mon Sep 17 00:00:00 2001 From: Scott Shawcroft Date: Tue, 6 Mar 2018 16:54:13 -0800 Subject: [PATCH 081/135] Update driver links including categories! --- conf.py | 2 +- docs/drivers.rst | 197 ++++++++++++++++++++++++++++++++++++++++------- 2 files changed, 170 insertions(+), 29 deletions(-) diff --git a/conf.py b/conf.py index cb46b13a5d..7353ad0387 100644 --- a/conf.py +++ b/conf.py @@ -334,5 +334,5 @@ texinfo_documents = [ # Example configuration for intersphinx: refer to the Python standard library. intersphinx_mapping = {"cpython": ('https://docs.python.org/3/', None), - "bus_device": ('https://circuitpython.readthedocs.io/projects/bus_device/en/latest/', None), + "bus_device": ('https://circuitpython.readthedocs.io/projects/busdevice/en/latest/', None), "register": ('https://circuitpython.readthedocs.io/projects/register/en/latest/', None)} diff --git a/docs/drivers.rst b/docs/drivers.rst index d1baed8e1e..40f56b2b05 100644 --- a/docs/drivers.rst +++ b/docs/drivers.rst @@ -13,10 +13,10 @@ Bundle ------ We provide a bundle of all our libraries to ease installation of drivers and -their dependencies. he bundle is primarily geared to the Adafruit Express line -of boards which will feature a relatively large external flash. With Express -boards, its easy to copy them all onto the filesystem. However, if you don't -have enough space simply copy things over as they are needed. +their dependencies. The bundle is primarily geared to the Adafruit Express line +of boards which feature a relatively large external flash. With Express boards, +its easy to copy them all onto the filesystem. However, if you don't have +enough space simply copy things over as they are needed. The bundles are available `on GitHub `_. @@ -26,8 +26,8 @@ To install them: and unzip the latest zip that's not a source zip. #. Copy the ``lib`` folder to the ``CIRCUITPY`` or ``MICROPYTHON``. -Foundational Libraries ----------------------- +Foundational +------------ These libraries provide critical functionality to many of the drivers below. It is recommended to always have them installed onto the CircuitPython file system in @@ -36,37 +36,178 @@ the ``lib/`` directory. Some drivers may not work without them. .. toctree:: Register Library - BusDevice Library + BusDevice Library + +Board-specific Helpers +---------------------- + +These libraries tie lower-level libraries together to provide an easy, out-of-box experience for +specific boards. + +.. toctree:: + + Adafruit CircuitPlayground Express + Adafruit FeatherWings Helper Libraries ----------------- +----------------- These libraries build on top of the low level APIs to simplify common tasks. .. toctree:: - USB Human Interface Device (Keyboard and Mouse) + USB Human Interface Device (Keyboard and Mouse) + Waveform Generation + OneWire + Ring Tone Text Transfer Language (RTTTL) + InfraRed Remote + Fancy LED (similar to FastLED) + SimpleIO + AVR programming + DC Motor and Servo + SD Card -Drivers -------- +Blinky +-------- -Drivers provide easy access to sensors and other chips without requiring a -knowledge of the interface details of the chip itself. +Multi-color led drivers. .. toctree:: - NeoPixel - SimpleIO - RGB Displays - SD Card - Analog-to-digital converters: ADS1015 and ADS1115 - DS3231 Real-time Clock (Precision RTC) - DS1307 Real-time Clock (5V RTC Breakout) - PCF8523 Real-time Clock (Adalogger RTC) - TCS34725 Color Sensor - TSL2561 Light Sensor - PCA9685 Motor and Servo Controllers - HT16K33 LED Matrices and Segment Displays - IS31FL3731 Charlieplexed LED Matrix - MAX7219 LED Matrix - DotStar + NeoPixel + DotStar + +Displays +------------- + +Drivers used to display information. Either pixel or segment based. + +.. toctree:: + + RGB Displays + Character LCD + HT16K33 LED Matrices and Segment Displays + IS31FL3731 Charlieplexed LED Matrix + MAX7219 LED Matrix + SSD1306 OLED Driver + +Real-time clocks +----------------- + +Chips that keep current calendar time with a backup battery. The current date and time is available +through ``datetime``. + +.. toctree:: + + DS1307 Real-time Clock (5V RTC Breakout) + DS3231 Real-time Clock (Precision RTC) + PCF8523 Real-time Clock (Adalogger RTC) + +Motion Sensors +---------------- + +Motion relating sensing including ``acceleration``, ``magnetic``, ``gyro``, and ``orientation``. + +.. toctree:: + BNO055 Accelerometer, Magnetometer, Gyroscope and Absolution Orientation + FXAS21002C Gyroscope + FXOS8700 Accelerometer + GPS Global Position + LIS3DH Accelerometer + LSM303 Accelerometer and Magnetometer + LSM9DS0 Accelerometer, Magnetometer, Gyroscope and Temperature + LSM9DS1 Accelerometer, Magnetometer, Gyroscope and Temperature + MMA8451 3 axis accelerometer + +Environmental Sensors +---------------------- + +Sense attributes of the environment including ``temperature``, ``relative_humidity``, ``pressure``, +equivalent carbon dioxide (``eco2`` / ``eCO2``), and total volatile organic compounds (``tvoc`` / +``TVOC``). + +.. toctree:: + + BME280 Temperature, Humidity and Pressure + BME680 Temperature, Humidity, Pressure and Gas + BMP280 Barometric Pressure and Altitude + CCS811 Air Quality + DHT Temperature and Humidity + DS18x20 Temperature + MAX31865 Thermocouple Amplifier, Temperature + MAX31855 Thermocouple Amplifier, Temperature + MCP9808 Temperature + MPL3115A2 Barometric Pressure, Altitude and Temperature Sensor + SGP30 Air Quality + SHT31-D Temperature and Humidity + Si7021 Temperature and Humidity + Thermistor Temperature + +Light Sensors +--------------- + +These sensors detect light related attributes such as ``color``, ``light`` (unit-less), and +``lux`` (light in SI lux). + +.. toctree:: + + APDS9960 Proximity, Light, RGB, and Gesture + TCS34725 Color Sensor + TSL2561 Light Sensor + TSL2591 High Dynamic Range Light Sensor + VCNL4010 Proximity and Light + VEML6070 UV Index + +Distance Sensors +------------------ + +These sensors measure the ``distance`` to another object and may also measure light level (``light`` and ``lux``). + +.. toctree:: + + VL6180x 5 - 100 mm + VL53L0x ~30 - 1000 mm + +Radio +-------- + +These chips communicate to other's over radio. + +.. toctree:: + + RFM9x LoRa + RFM69 Packet Radio + +IO Expansion +-------------- + +These provide functionality similar to `analogio`, `digitalio`, `pulseio`, and `touchio`. + +.. toctree:: + + Adafruit SeeSaw + ADS1x15 Analog-to-Digital Converter + DS2413 OneWire GPIO Expander + FocalTech Capacitive Touch + MCP4725 Digital-to-Analog Converter + PCA9685 16 x 12-bit PWM Driver + TLC5947 24 x 12-bit PWM Driver + TLC59711 12 x 16-bit PWM Driver + MCP4725 Capacitive Touch Sensor + + +Miscellaneous +---------------- + +.. toctree:: + + Si4713 Stereo FM Transmitter + AMG88xx Grid-Eye IR Camera + Trellis 4x4 Keypad + DRV2605 Haptic Motor Controller + MAX9744 Audio Amplifier + Si5351 Clock Generator + Thermal Printer + VC0706 TTL Camera + INA219 High Side Current + Fingerprint From 4f55205bf5e4dcdaf8bce3e34b1f0145fe5aa535 Mon Sep 17 00:00:00 2001 From: Scott Shawcroft Date: Tue, 6 Mar 2018 18:24:56 -0800 Subject: [PATCH 082/135] Fix links. Adding the en/latest/ circumvents a ReadTheDocs bug which redirects projects incorrectly. --- docs/drivers.rst | 147 ++++++++++++++++++++++++----------------------- 1 file changed, 74 insertions(+), 73 deletions(-) diff --git a/docs/drivers.rst b/docs/drivers.rst index 40f56b2b05..23c0c0b323 100644 --- a/docs/drivers.rst +++ b/docs/drivers.rst @@ -56,16 +56,16 @@ These libraries build on top of the low level APIs to simplify common tasks. .. toctree:: - USB Human Interface Device (Keyboard and Mouse) - Waveform Generation - OneWire - Ring Tone Text Transfer Language (RTTTL) - InfraRed Remote - Fancy LED (similar to FastLED) - SimpleIO - AVR programming - DC Motor and Servo - SD Card + USB Human Interface Device (Keyboard and Mouse) + Waveform Generation + OneWire + Ring Tone Text Transfer Language (RTTTL) + InfraRed Remote + Fancy LED (similar to FastLED) + SimpleIO + AVR programming + DC Motor and Servo + SD Card Blinky -------- @@ -74,8 +74,8 @@ Multi-color led drivers. .. toctree:: - NeoPixel - DotStar + NeoPixel + DotStar Displays ------------- @@ -84,12 +84,12 @@ Drivers used to display information. Either pixel or segment based. .. toctree:: - RGB Displays - Character LCD - HT16K33 LED Matrices and Segment Displays - IS31FL3731 Charlieplexed LED Matrix - MAX7219 LED Matrix - SSD1306 OLED Driver + RGB Displays + Character LCD + HT16K33 LED Matrices and Segment Displays + IS31FL3731 Charlieplexed LED Matrix + MAX7219 LED Matrix + SSD1306 OLED Driver Real-time clocks ----------------- @@ -99,9 +99,9 @@ through ``datetime``. .. toctree:: - DS1307 Real-time Clock (5V RTC Breakout) - DS3231 Real-time Clock (Precision RTC) - PCF8523 Real-time Clock (Adalogger RTC) + DS1307 Real-time Clock (5V RTC Breakout) + DS3231 Real-time Clock (Precision RTC) + PCF8523 Real-time Clock (Adalogger RTC) Motion Sensors ---------------- @@ -109,15 +109,16 @@ Motion Sensors Motion relating sensing including ``acceleration``, ``magnetic``, ``gyro``, and ``orientation``. .. toctree:: - BNO055 Accelerometer, Magnetometer, Gyroscope and Absolution Orientation - FXAS21002C Gyroscope - FXOS8700 Accelerometer - GPS Global Position - LIS3DH Accelerometer - LSM303 Accelerometer and Magnetometer - LSM9DS0 Accelerometer, Magnetometer, Gyroscope and Temperature - LSM9DS1 Accelerometer, Magnetometer, Gyroscope and Temperature - MMA8451 3 axis accelerometer + + BNO055 Accelerometer, Magnetometer, Gyroscope and Absolution Orientation + FXAS21002C Gyroscope + FXOS8700 Accelerometer + GPS Global Position + LIS3DH Accelerometer + LSM303 Accelerometer and Magnetometer + LSM9DS0 Accelerometer, Magnetometer, Gyroscope and Temperature + LSM9DS1 Accelerometer, Magnetometer, Gyroscope and Temperature + MMA8451 3 axis accelerometer Environmental Sensors ---------------------- @@ -128,20 +129,20 @@ equivalent carbon dioxide (``eco2`` / ``eCO2``), and total volatile organic comp .. toctree:: - BME280 Temperature, Humidity and Pressure - BME680 Temperature, Humidity, Pressure and Gas - BMP280 Barometric Pressure and Altitude - CCS811 Air Quality - DHT Temperature and Humidity - DS18x20 Temperature - MAX31865 Thermocouple Amplifier, Temperature - MAX31855 Thermocouple Amplifier, Temperature - MCP9808 Temperature - MPL3115A2 Barometric Pressure, Altitude and Temperature Sensor - SGP30 Air Quality - SHT31-D Temperature and Humidity - Si7021 Temperature and Humidity - Thermistor Temperature + BME280 Temperature, Humidity and Pressure + BME680 Temperature, Humidity, Pressure and Gas + BMP280 Barometric Pressure and Altitude + CCS811 Air Quality + DHT Temperature and Humidity + DS18x20 Temperature + MAX31865 Thermocouple Amplifier, Temperature + MAX31855 Thermocouple Amplifier, Temperature + MCP9808 Temperature + MPL3115A2 Barometric Pressure, Altitude and Temperature Sensor + SGP30 Air Quality + SHT31-D Temperature and Humidity + Si7021 Temperature and Humidity + Thermistor Temperature Light Sensors --------------- @@ -151,12 +152,12 @@ These sensors detect light related attributes such as ``color``, ``light`` (unit .. toctree:: - APDS9960 Proximity, Light, RGB, and Gesture - TCS34725 Color Sensor - TSL2561 Light Sensor - TSL2591 High Dynamic Range Light Sensor - VCNL4010 Proximity and Light - VEML6070 UV Index + APDS9960 Proximity, Light, RGB, and Gesture + TCS34725 Color Sensor + TSL2561 Light Sensor + TSL2591 High Dynamic Range Light Sensor + VCNL4010 Proximity and Light + VEML6070 UV Index Distance Sensors ------------------ @@ -165,8 +166,8 @@ These sensors measure the ``distance`` to another object and may also measure li .. toctree:: - VL6180x 5 - 100 mm - VL53L0x ~30 - 1000 mm + VL6180x 5 - 100 mm + VL53L0x ~30 - 1000 mm Radio -------- @@ -175,8 +176,8 @@ These chips communicate to other's over radio. .. toctree:: - RFM9x LoRa - RFM69 Packet Radio + RFM9x LoRa + RFM69 Packet Radio IO Expansion -------------- @@ -185,15 +186,15 @@ These provide functionality similar to `analogio`, `digitalio`, `pulseio`, and ` .. toctree:: - Adafruit SeeSaw - ADS1x15 Analog-to-Digital Converter - DS2413 OneWire GPIO Expander - FocalTech Capacitive Touch - MCP4725 Digital-to-Analog Converter - PCA9685 16 x 12-bit PWM Driver - TLC5947 24 x 12-bit PWM Driver - TLC59711 12 x 16-bit PWM Driver - MCP4725 Capacitive Touch Sensor + Adafruit SeeSaw + ADS1x15 Analog-to-Digital Converter + DS2413 OneWire GPIO Expander + FocalTech Capacitive Touch + MCP4725 Digital-to-Analog Converter + PCA9685 16 x 12-bit PWM Driver + TLC5947 24 x 12-bit PWM Driver + TLC59711 12 x 16-bit PWM Driver + MPR121 Capacitive Touch Sensor Miscellaneous @@ -201,13 +202,13 @@ Miscellaneous .. toctree:: - Si4713 Stereo FM Transmitter - AMG88xx Grid-Eye IR Camera - Trellis 4x4 Keypad - DRV2605 Haptic Motor Controller - MAX9744 Audio Amplifier - Si5351 Clock Generator - Thermal Printer - VC0706 TTL Camera - INA219 High Side Current - Fingerprint + Si4713 Stereo FM Transmitter + AMG88xx Grid-Eye IR Camera + Trellis 4x4 Keypad + DRV2605 Haptic Motor Controller + MAX9744 Audio Amplifier + Si5351 Clock Generator + Thermal Printer + VC0706 TTL Camera + INA219 High Side Current + Fingerprint From 2de471950aea7ec503e160b59b3b5c59a3b10d87 Mon Sep 17 00:00:00 2001 From: Kattni Date: Wed, 7 Mar 2018 17:25:43 -0500 Subject: [PATCH 083/135] Added AM2320 to driver list --- docs/drivers.rst | 1 + 1 file changed, 1 insertion(+) diff --git a/docs/drivers.rst b/docs/drivers.rst index 23c0c0b323..d1dad2b6ad 100644 --- a/docs/drivers.rst +++ b/docs/drivers.rst @@ -143,6 +143,7 @@ equivalent carbon dioxide (``eco2`` / ``eCO2``), and total volatile organic comp SHT31-D Temperature and Humidity Si7021 Temperature and Humidity Thermistor Temperature + AM2320 Temperature and Humidity Light Sensors --------------- From fa8f1a29e520e5d5fe3abeacbe24fb0835f371c1 Mon Sep 17 00:00:00 2001 From: Kattni Date: Wed, 7 Mar 2018 23:10:25 -0500 Subject: [PATCH 084/135] moved to top of list for alphabetical order --- docs/drivers.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/drivers.rst b/docs/drivers.rst index d1dad2b6ad..523316b096 100644 --- a/docs/drivers.rst +++ b/docs/drivers.rst @@ -129,6 +129,7 @@ equivalent carbon dioxide (``eco2`` / ``eCO2``), and total volatile organic comp .. toctree:: + AM2320 Temperature and Humidity BME280 Temperature, Humidity and Pressure BME680 Temperature, Humidity, Pressure and Gas BMP280 Barometric Pressure and Altitude @@ -143,7 +144,6 @@ equivalent carbon dioxide (``eco2`` / ``eCO2``), and total volatile organic comp SHT31-D Temperature and Humidity Si7021 Temperature and Humidity Thermistor Temperature - AM2320 Temperature and Humidity Light Sensors --------------- From 942b7ffbe0f0ec04a11e65c1586adf959b9eea7a Mon Sep 17 00:00:00 2001 From: Bryan Siepert Date: Thu, 8 Mar 2018 20:39:47 -0800 Subject: [PATCH 085/135] fixes hardware dotstar support for 3.0 and addresses issue #514 --- ports/atmel-samd/boards/trinket_m0/mpconfigboard.h | 4 ++-- ports/atmel-samd/common-hal/busio/SPI.c | 7 ++++++- supervisor/shared/rgb_led_status.c | 4 ++-- 3 files changed, 10 insertions(+), 5 deletions(-) diff --git a/ports/atmel-samd/boards/trinket_m0/mpconfigboard.h b/ports/atmel-samd/boards/trinket_m0/mpconfigboard.h index eace9bc9db..05033ad38b 100644 --- a/ports/atmel-samd/boards/trinket_m0/mpconfigboard.h +++ b/ports/atmel-samd/boards/trinket_m0/mpconfigboard.h @@ -2,8 +2,8 @@ #define MICROPY_HW_MCU_NAME "samd21e18" // Rev B - Black -// #define MICROPY_HW_APA102_MOSI (&pin_PA00) -// #define MICROPY_HW_APA102_SCK (&pin_PA01) +#define MICROPY_HW_APA102_MOSI (&pin_PA00) +#define MICROPY_HW_APA102_SCK (&pin_PA01) #define MICROPY_PORT_A (PORT_PA00 | PORT_PA01 | PORT_PA24 | PORT_PA25) #define MICROPY_PORT_B (0) diff --git a/ports/atmel-samd/common-hal/busio/SPI.c b/ports/atmel-samd/common-hal/busio/SPI.c index c4cd6e66f8..43288cc8bb 100644 --- a/ports/atmel-samd/common-hal/busio/SPI.c +++ b/ports/atmel-samd/common-hal/busio/SPI.c @@ -34,6 +34,7 @@ #include "hal/include/hal_gpio.h" #include "hal/include/hal_spi_m_sync.h" #include "hal/include/hpl_spi_m_sync.h" +#include "supervisor/shared/rgb_led_status.h" #include "peripherals.h" #include "pins.h" @@ -59,7 +60,7 @@ void common_hal_busio_spi_construct(busio_spi_obj_t *self, if (potential_sercom == NULL || #if defined(MICROPY_HW_APA102_SCK) && defined(MICROPY_HW_APA102_MOSI) && !defined(CIRCUITPY_BITBANG_APA102) (potential_sercom->SPI.CTRLA.bit.ENABLE != 0 && - potential_sercom != status_apa102.spi_master_instance.hw && + potential_sercom != status_apa102.spi_desc.dev.prvt && !apa102_sck_in_use)) { #else potential_sercom->SPI.CTRLA.bit.ENABLE != 0) { @@ -113,6 +114,10 @@ void common_hal_busio_spi_construct(busio_spi_obj_t *self, // Set up SPI clocks on SERCOM. samd_peripherals_sercom_clock_init(sercom, sercom_index); + #if defined(MICROPY_HW_APA102_SCK) && defined(MICROPY_HW_APA102_MOSI) && !defined(CIRCUITPY_BITBANG_APA102) + // if we're re-using the dotstar sercom, make sure it is disabled or the init will fail out + hri_sercomspi_clear_CTRLA_ENABLE_bit(sercom); + #endif if (spi_m_sync_init(&self->spi_desc, sercom) != ERR_NONE) { mp_raise_OSError(MP_EIO); } diff --git a/supervisor/shared/rgb_led_status.c b/supervisor/shared/rgb_led_status.c index 2899c1f5d8..5b55c1ba2d 100644 --- a/supervisor/shared/rgb_led_status.c +++ b/supervisor/shared/rgb_led_status.c @@ -70,11 +70,11 @@ void rgb_led_status_init() { MICROPY_HW_APA102_MOSI, mp_const_none); #else - if (status_apa102.current_baudrate > 0) { + if (!common_hal_busio_spi_deinited(&status_apa102)) { // Don't use spi_deinit because that leads to infinite // recursion because reset_pin may call // rgb_led_status_init. - spi_disable(&status_apa102.spi_master_instance); + spi_m_sync_disable(&status_apa102.spi_desc); } common_hal_busio_spi_construct(&status_apa102, MICROPY_HW_APA102_SCK, From e7fc0b6aa7eafb1977f3a8a70e46364d0a8f393c Mon Sep 17 00:00:00 2001 From: Scott Shawcroft Date: Fri, 9 Mar 2018 12:05:12 -0800 Subject: [PATCH 086/135] Use DMA for long SPI transactions including those to the SPI Flash. QSPI is not currently working so its commented out. This is progress on #652. --- ports/atmel-samd/Makefile | 4 +- .../itsybitsy_m0_express/mpconfigboard.h | 2 +- .../metro_m4_express_revb/mpconfigboard.h | 2 +- ports/atmel-samd/common-hal/busio/SPI.c | 40 +- .../external_flash/external_flash.c | 2 - ports/atmel-samd/external_flash/qspi_flash.c | 12 +- ports/atmel-samd/external_flash/spi_flash.c | 19 +- ports/atmel-samd/shared_dma.c | 523 ++++++++++++------ ports/atmel-samd/shared_dma.h | 18 +- ports/atmel-samd/supervisor/port.c | 5 +- 10 files changed, 411 insertions(+), 216 deletions(-) diff --git a/ports/atmel-samd/Makefile b/ports/atmel-samd/Makefile index 4660d575ec..73799e5f28 100644 --- a/ports/atmel-samd/Makefile +++ b/ports/atmel-samd/Makefile @@ -217,9 +217,6 @@ endif SRC_ASF := $(addprefix asf4/$(CHIP_FAMILY)/, $(SRC_ASF)) -# Skip this source for now. -# shared_dma.c \ - SRC_C = \ background.c \ fatfs_port.c \ @@ -229,6 +226,7 @@ SRC_C = \ $(CHIP_FAMILY)_peripherals.c \ peripherals.c \ $(CHIP_FAMILY)_pins.c \ + shared_dma.c \ tick.c \ timers.c \ usb.c \ diff --git a/ports/atmel-samd/boards/itsybitsy_m0_express/mpconfigboard.h b/ports/atmel-samd/boards/itsybitsy_m0_express/mpconfigboard.h index ca39792a92..675b9a30db 100644 --- a/ports/atmel-samd/boards/itsybitsy_m0_express/mpconfigboard.h +++ b/ports/atmel-samd/boards/itsybitsy_m0_express/mpconfigboard.h @@ -5,7 +5,7 @@ #define MICROPY_HW_APA102_MOSI (&pin_PA01) #define MICROPY_HW_APA102_SCK (&pin_PA00) -// Salae reads 12mhz which is the limit even though we set it to the safer 8mhz. +// Saleae reads 12mhz which is the limit even though we set it to the safer 8mhz. #define SPI_FLASH_BAUDRATE (8000000) #define SPI_FLASH_MOSI_PIN PIN_PB22 diff --git a/ports/atmel-samd/boards/metro_m4_express_revb/mpconfigboard.h b/ports/atmel-samd/boards/metro_m4_express_revb/mpconfigboard.h index 70c92ea444..7af9767caa 100644 --- a/ports/atmel-samd/boards/metro_m4_express_revb/mpconfigboard.h +++ b/ports/atmel-samd/boards/metro_m4_express_revb/mpconfigboard.h @@ -11,7 +11,7 @@ #define MICROPY_HW_NEOPIXEL (&pin_PB17) -#define SPI_FLASH_BAUDRATE (8000000) +#define SPI_FLASH_BAUDRATE (60000000) // Rev B: single channel SPI // Rev C will be QSPI diff --git a/ports/atmel-samd/common-hal/busio/SPI.c b/ports/atmel-samd/common-hal/busio/SPI.c index 43288cc8bb..eca73be78a 100644 --- a/ports/atmel-samd/common-hal/busio/SPI.c +++ b/ports/atmel-samd/common-hal/busio/SPI.c @@ -38,7 +38,7 @@ #include "peripherals.h" #include "pins.h" -//#include "shared_dma.h" +#include "shared_dma.h" void common_hal_busio_spi_construct(busio_spi_obj_t *self, const mcu_pin_obj_t * clock, const mcu_pin_obj_t * mosi, @@ -113,7 +113,7 @@ void common_hal_busio_spi_construct(busio_spi_obj_t *self, // Set up SPI clocks on SERCOM. samd_peripherals_sercom_clock_init(sercom, sercom_index); - + #if defined(MICROPY_HW_APA102_SCK) && defined(MICROPY_HW_APA102_MOSI) && !defined(CIRCUITPY_BITBANG_APA102) // if we're re-using the dotstar sercom, make sure it is disabled or the init will fail out hri_sercomspi_clear_CTRLA_ENABLE_bit(sercom); @@ -121,7 +121,7 @@ void common_hal_busio_spi_construct(busio_spi_obj_t *self, if (spi_m_sync_init(&self->spi_desc, sercom) != ERR_NONE) { mp_raise_OSError(MP_EIO); } - + // Pads must be set after spi_m_sync_init(), which uses default values from // the prototypical SERCOM. hri_sercomspi_write_CTRLA_DOPO_bf(sercom, dopo); @@ -135,7 +135,7 @@ void common_hal_busio_spi_construct(busio_spi_obj_t *self, // busy or not mp_raise_OSError(MP_EIO); } - + gpio_set_pin_direction(clock->pin, GPIO_DIRECTION_OUT); gpio_set_pin_pull_mode(clock->pin, GPIO_PULL_OFF); gpio_set_pin_function(clock->pin, clock_pinmux); @@ -194,7 +194,7 @@ bool common_hal_busio_spi_configure(busio_spi_obj_t *self, return true; } - // Disable, set values (most or all are enable-protected), and re-enable. + // Disable, set values (most or all are enable-protected), and re-enable. spi_m_sync_disable(&self->spi_desc); hri_sercomspi_wait_for_sync(hw, SERCOM_SPI_SYNCBUSY_MASK); @@ -235,14 +235,14 @@ bool common_hal_busio_spi_write(busio_spi_obj_t *self, return true; } int32_t status; -// if (len >= 16) { -// status = shared_dma_write(self->spi_desc.dev.prvt, data, len); -// } else { + if (len >= 16) { + status = sercom_dma_write(self->spi_desc.dev.prvt, data, len); + } else { struct io_descriptor *spi_io; spi_m_sync_get_io_descriptor(&self->spi_desc, &spi_io); status = spi_io->write(spi_io, data, len); -// } - return status >= 0; // Status is number of chars read or an error code < 0. + } + return status >= 0; // Status is number of chars read or an error code < 0. } bool common_hal_busio_spi_read(busio_spi_obj_t *self, @@ -251,17 +251,17 @@ bool common_hal_busio_spi_read(busio_spi_obj_t *self, return true; } int32_t status; -// if (len >= 16) { -// status = shared_dma_read(self->spi_desc.dev.prvt, data, len, write_value); -// } else { + if (len >= 16) { + status = sercom_dma_read(self->spi_desc.dev.prvt, data, len, write_value); + } else { self->spi_desc.dev.dummy_byte = write_value; struct io_descriptor *spi_io; spi_m_sync_get_io_descriptor(&self->spi_desc, &spi_io); status = spi_io->read(spi_io, data, len); -// } - return status >= 0; // Status is number of chars read or an error code < 0. + } + return status >= 0; // Status is number of chars read or an error code < 0. } bool common_hal_busio_spi_transfer(busio_spi_obj_t *self, uint8_t *data_out, uint8_t *data_in, size_t len) { @@ -269,16 +269,16 @@ bool common_hal_busio_spi_transfer(busio_spi_obj_t *self, uint8_t *data_out, uin return true; } int32_t status; -// if (len >= 16) { -// status = shared_dma_transfer(self->spi_master_instance.hw, data_out, data_in, len, 0 /*ignored*/); -// } else { + if (len >= 16) { + status = sercom_dma_transfer(self->spi_desc.dev.prvt, data_out, data_in, len); + } else { struct spi_xfer xfer; xfer.txbuf = data_out; xfer.rxbuf = data_in; xfer.size = len; status = spi_m_sync_transfer(&self->spi_desc, &xfer); -// } - return status >= 0; // Status is number of chars read or an error code < 0. + } + return status >= 0; // Status is number of chars read or an error code < 0. } uint32_t common_hal_busio_spi_get_frequency(busio_spi_obj_t* self) { diff --git a/ports/atmel-samd/external_flash/external_flash.c b/ports/atmel-samd/external_flash/external_flash.c index ca8121bc93..304bf6462b 100644 --- a/ports/atmel-samd/external_flash/external_flash.c +++ b/ports/atmel-samd/external_flash/external_flash.c @@ -199,7 +199,6 @@ void external_flash_init(void) { spi_flash_init(); - for (uint8_t i = 0; i < num_possible_devices; i++) { const external_flash_device* possible_device = &possible_devices[i]; uint8_t jedec_id_response[3] = {0x00, 0x00, 0x00}; @@ -213,7 +212,6 @@ void external_flash_init(void) { } if (flash_device == NULL) { - asm("bkpt"); return; } diff --git a/ports/atmel-samd/external_flash/qspi_flash.c b/ports/atmel-samd/external_flash/qspi_flash.c index 54f1af0dce..46e3cb92a3 100644 --- a/ports/atmel-samd/external_flash/qspi_flash.c +++ b/ports/atmel-samd/external_flash/qspi_flash.c @@ -30,6 +30,7 @@ #include #include "external_flash/common_commands.h" +#include "shared_dma.h" #include "atmel_start_pins.h" #include "hal_gpio.h" @@ -125,6 +126,8 @@ bool spi_flash_write_data(uint32_t address, uint8_t* data, uint32_t length) { QSPI_INSTRFRAME_DATAEN; memcpy(((uint8_t *) QSPI_AHB) + address, data, length); + // TODO(tannewt): Fix DMA and enable it. + // qspi_dma_write(address, data, length); QSPI->CTRLA.reg = QSPI_CTRLA_ENABLE | QSPI_CTRLA_LASTXFER; @@ -148,6 +151,8 @@ bool spi_flash_read_data(uint32_t address, uint8_t* data, uint32_t length) { QSPI_INSTRFRAME_DUMMYLEN(8); memcpy(data, ((uint8_t *) QSPI_AHB) + address, length); + // TODO(tannewt): Fix DMA and enable it. + // qspi_dma_read(address, data, length); QSPI->CTRLA.reg = QSPI_CTRLA_ENABLE | QSPI_CTRLA_LASTXFER; @@ -167,12 +172,15 @@ void spi_flash_init(void) { QSPI->CTRLA.reg = QSPI_CTRLA_SWRST; // We don't need to wait because we're running as fast as the CPU. - QSPI->BAUD.bit.BAUD = 1; + // Slow, good for debugging with Saleae + // QSPI->BAUD.bit.BAUD = 32; + // Super fast + QSPI->BAUD.bit.BAUD = 2; QSPI->CTRLB.reg = QSPI_CTRLB_MODE_MEMORY | QSPI_CTRLB_DATALEN_8BITS | QSPI_CTRLB_CSMODE_LASTXFER; - QSPI->CTRLA.bit.ENABLE = 1; + QSPI->CTRLA.reg = QSPI_CTRLA_ENABLE; // The QSPI is only connected to one set of pins in the SAMD51 so we can hard code it. uint32_t pins[6] = {PIN_PA08, PIN_PA09, PIN_PA10, PIN_PA11, PIN_PB10, PIN_PB11}; diff --git a/ports/atmel-samd/external_flash/spi_flash.c b/ports/atmel-samd/external_flash/spi_flash.c index 4b63132eea..fcaedcaaca 100644 --- a/ports/atmel-samd/external_flash/spi_flash.c +++ b/ports/atmel-samd/external_flash/spi_flash.c @@ -30,6 +30,7 @@ #include "external_flash/common_commands.h" #include "peripherals.h" +#include "shared_dma.h" #include "hal_gpio.h" #include "hal_spi_m_sync.h" @@ -91,14 +92,28 @@ bool spi_flash_write_data(uint32_t address, uint8_t* data, uint32_t data_length) uint8_t request[4] = {CMD_PAGE_PROGRAM, 0x00, 0x00, 0x00}; // Write the SPI flash write address into the bytes following the command byte. address_to_bytes(address, request + 1); - return transfer(request, 4, data, NULL, data_length); + struct spi_xfer xfer = { request, NULL, 4 }; + flash_enable(); + int32_t status = spi_m_sync_transfer(&spi_flash_desc, &xfer); + if (status >= 0) { + status = sercom_dma_write(spi_flash_desc.dev.prvt, data, data_length); + } + flash_disable(); + return status >= 0; } bool spi_flash_read_data(uint32_t address, uint8_t* data, uint32_t data_length) { uint8_t request[4] = {CMD_READ_DATA, 0x00, 0x00, 0x00}; // Write the SPI flash write address into the bytes following the command byte. address_to_bytes(address, request + 1); - return transfer(request, 4, NULL, data, data_length); + struct spi_xfer xfer = { request, NULL, 4 }; + flash_enable(); + int32_t status = spi_m_sync_transfer(&spi_flash_desc, &xfer); + if (status >= 0) { + status = sercom_dma_read(spi_flash_desc.dev.prvt, data, data_length, 0xff); + } + flash_disable(); + return status >= 0; } void spi_flash_init(void) { diff --git a/ports/atmel-samd/shared_dma.c b/ports/atmel-samd/shared_dma.c index 59fca30c81..8a6a606bbd 100644 --- a/ports/atmel-samd/shared_dma.c +++ b/ports/atmel-samd/shared_dma.c @@ -23,245 +23,414 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ - -#include #include "shared_dma.h" +#include + #include "py/gc.h" #include "py/mpstate.h" -#undef ENABLE +#include "hal/utils/include/utils.h" -// We allocate two DMA resources for the entire lifecycle of the board (not the +#include "shared-bindings/microcontroller/__init__.h" + +// We allocate three DMA resources for the entire lifecycle of the board (not the // vm) because the general_dma resource will be shared between the REPL and SPI // flash. Both uses must block each other in order to prevent conflict. -struct dma_resource audio_dma; -struct dma_resource general_dma_tx; -struct dma_resource general_dma_rx; +COMPILER_ALIGNED(16) static DmacDescriptor dma_descriptors[3]; + +// Don't use these directly. They are used by the DMA engine itself. +COMPILER_ALIGNED(16) static DmacDescriptor write_back_descriptors[3]; + +#define AUDIO_DMA_CHANNEL 0 +#define SHARED_TX_CHANNEL 1 +#define SHARED_RX_CHANNEL 2 + + +#ifdef SAMD21 +#define FIRST_SERCOM_RX_TRIGSRC 0x01 +#define FIRST_SERCOM_TX_TRIGSRC 0x02 +#endif +#ifdef SAMD51 +#define FIRST_SERCOM_RX_TRIGSRC 0x04 +#define FIRST_SERCOM_TX_TRIGSRC 0x05 +#endif + +// static void dma_configure_audio(uint8_t channel) { +// system_interrupt_enter_critical_section(); +// /** Select the DMA channel and clear software trigger */ +// DMAC->CHID.reg = DMAC_CHID_ID(channel); +// DMAC->CHCTRLA.reg &= ~DMAC_CHCTRLA_ENABLE; +// DMAC->CHCTRLA.reg = DMAC_CHCTRLA_SWRST; +// DMAC->SWTRIGCTRL.reg &= (uint32_t)(~(1 << channel)); +// uint32_t event_output_enable = 0; +// if (output_event) { +// event_output_enable = DMAC_CHCTRLB_EVOE; +// } +// DMAC->CHCTRLB.reg = DMAC_CHCTRLB_LVL(DMA_PRIORITY_LEVEL_0) | +// DMAC_CHCTRLB_TRIGSRC(trigsrc) | +// DMAC_CHCTRLB_TRIGACT(DMA_TRIGGER_ACTION_BEAT) | +// event_output_enable; +// // config.peripheral_trigger = DAC_DMAC_ID_EMPTY; +// // config.trigger_action = DMA_TRIGGER_ACTION_BEAT; +// // config.event_config.input_action = DMA_EVENT_INPUT_TRIG; +// // config.event_config.event_output_enable = true; +// system_interrupt_leave_critical_section(); +// } void init_shared_dma(void) { - struct dma_resource_config config; - dma_get_config_defaults(&config); + // Turn on the clocks + #ifdef SAMD51 + MCLK->AHBMASK.reg |= MCLK_AHBMASK_DMAC; + #endif - // See asf4_conf/hpl_dmac_config.h for initial settings for DMA channels - // DMA Channel 0: audio, highest priority, - // normal transfer on input, DAC 0 empty is trigger source, trigger on each beat, beat is one byte - // output enable true. - // asf3 settings: - //config.peripheral_trigger = DAC_DMAC_ID_EMPTY; - //config.trigger_action = DMA_TRIGGER_ACTION_BEAT; - //config.event_config.input_action = DMA_EVENT_INPUT_TRIG; - //config.event_config.event_output_enable = true; + #ifdef SAMD21 + PM->AHBMASK.reg |= PM_AHBMASK_DMAC; + PM->APBBMASK.reg |= PM_APBBMASK_DMAC; + #endif - // Turn on the transfer complete interrupt so that the job_status changes to done. - g_chan_interrupt_flag[audio_dma.channel_id] |= (1UL << DMA_CALLBACK_TRANSFER_DONE); + DMAC->CTRL.reg = DMAC_CTRL_SWRST; - // Prioritize the RX channel over the TX channel because TX can cause an RX - // overflow. - - // DMA Channel 1: rx channel, - // normal transfer on input, trigger on each beat, beat is one byte - //config.trigger_action = DMA_TRIGGER_ACTION_BEAT; - //config.event_config.input_action = DMA_EVENT_INPUT_TRIG; - dma_allocate(&general_dma_rx, &config); - g_chan_interrupt_flag[general_dma_rx.channel_id] |= (1UL << DMA_CALLBACK_TRANSFER_DONE); + DMAC->BASEADDR.reg = (uint32_t) dma_descriptors; + DMAC->WRBADDR.reg = (uint32_t) write_back_descriptors; - // DMA Channel 1: rx channel, - // normal transfer on input, trigger on each beat, beat is one byte - //config.trigger_action = DMA_TRIGGER_ACTION_BEAT; - //config.event_config.input_action = DMA_EVENT_INPUT_TRIG; - g_chan_interrupt_flag[general_dma_tx.channel_id] |= (1UL << DMA_CALLBACK_TRANSFER_DONE); + DMAC->CTRL.reg = DMAC_CTRL_DMAENABLE | DMAC_CTRL_LVLEN0; - // Be sneaky and reuse the active descriptor memory. - audio_dma.descriptor = &descriptor_section[audio_dma.channel_id]; - general_dma_rx.descriptor = &descriptor_section[general_dma_rx.channel_id]; - general_dma_tx.descriptor = &descriptor_section[general_dma_tx.channel_id]; + // This allocates the lowest channel first so make sure the audio is first + // so it gets the highest priority. + // dma_configure_audio(0); } static uint8_t sercom_index(Sercom* sercom) { + #ifdef SAMD21 return ((uint32_t) sercom - (uint32_t) SERCOM0) / 0x400; + #else + const Sercom* sercoms[SERCOM_INST_NUM] = SERCOM_INSTS; + for (uint8_t i = 0; i < SERCOM_INST_NUM; i++) { + if (sercoms[i] == sercom) { + return i; + } + } + return 0; + #endif } -static void dma_configure(uint8_t channel, uint8_t trigsrc, bool output_event) { - system_interrupt_enter_critical_section(); +static void dma_configure(uint8_t channel_number, uint8_t trigsrc, bool output_event) { + #ifdef SAMD21 + common_hal_mcu_disable_interrupts(); /** Select the DMA channel and clear software trigger */ - DMAC->CHID.reg = DMAC_CHID_ID(channel); + DMAC->CHID.reg = DMAC_CHID_ID(channel_number); DMAC->CHCTRLA.reg &= ~DMAC_CHCTRLA_ENABLE; DMAC->CHCTRLA.reg = DMAC_CHCTRLA_SWRST; - DMAC->SWTRIGCTRL.reg &= (uint32_t)(~(1 << channel)); + DMAC->SWTRIGCTRL.reg &= (uint32_t)(~(1 << channel_number)); uint32_t event_output_enable = 0; if (output_event) { event_output_enable = DMAC_CHCTRLB_EVOE; } - DMAC->CHCTRLB.reg = DMAC_CHCTRLB_LVL(DMA_PRIORITY_LEVEL_0) | + DMAC->CHCTRLB.reg = DMAC_CHCTRLB_LVL_LVL0 | DMAC_CHCTRLB_TRIGSRC(trigsrc) | - DMAC_CHCTRLB_TRIGACT(DMA_TRIGGER_ACTION_BEAT) | + DMAC_CHCTRLB_TRIGACT_BEAT | event_output_enable; - system_interrupt_leave_critical_section(); + common_hal_mcu_enable_interrupts(); + #endif + + #ifdef SAMD51 + DmacChannel* channel = &DMAC->Channel[channel_number]; + channel->CHCTRLA.reg &= ~DMAC_CHCTRLA_ENABLE; + channel->CHCTRLA.reg = DMAC_CHCTRLA_SWRST; + if (output_event) { + channel->CHEVCTRL.reg = DMAC_CHEVCTRL_EVOE; + } + channel->CHCTRLA.reg = DMAC_CHCTRLA_TRIGSRC(trigsrc) | + DMAC_CHCTRLA_TRIGACT_BURST | + DMAC_CHCTRLA_BURSTLEN_SINGLE; + #endif } -int32_t shared_dma_write(Sercom* sercom, const uint8_t* buffer, uint32_t length) { - if (general_dma_tx.job_status != STATUS_OK) { - return general_dma_tx.job_status; - } - dma_configure(general_dma_tx.channel_id, sercom_index(sercom) * 2 + 2, false); +static void enable_channel(uint8_t channel_number) { + #ifdef SAMD21 + common_hal_mcu_disable_interrupts(); + /** Select the DMA channel and clear software trigger */ + DMAC->CHID.reg = DMAC_CHID_ID(channel_number); + DMAC->CHCTRLA.bit.ENABLE = true; + common_hal_mcu_enable_interrupts(); + #endif - // Set up TX. There is no RX job. - struct dma_descriptor_config descriptor_config; - dma_descriptor_get_config_defaults(&descriptor_config); - descriptor_config.beat_size = DMA_BEAT_SIZE_BYTE; - descriptor_config.dst_increment_enable = false; - descriptor_config.block_transfer_count = length; - descriptor_config.source_address = ((uint32_t)buffer + length); - // DATA register is consistently addressed across all SERCOM modes. - descriptor_config.destination_address = ((uint32_t)&sercom->SPI.DATA.reg); - - dma_descriptor_create(general_dma_tx.descriptor, &descriptor_config); - enum status_code status = dma_start_transfer_job(&general_dma_tx); - if (status != ERR_NONE) { - return status; - } - - // Wait for the dma transfer to finish. - while (general_dma_tx.job_status == STATUS_BUSY) {} - - // Wait for the SPI transfer to complete. - while (sercom->SPI.INTFLAG.bit.TXC == 0) {} - - // This transmit will cause the RX buffer overflow but we're OK with that. - // So, read the garbage and clear the overflow flag. - while (sercom->SPI.INTFLAG.bit.RXC == 1) { - sercom->SPI.DATA.reg; - } - sercom->SPI.STATUS.bit.BUFOVF = 1; - sercom->SPI.INTFLAG.reg = SERCOM_SPI_INTFLAG_ERROR; - - return general_dma_tx.job_status; + #ifdef SAMD51 + DmacChannel* channel = &DMAC->Channel[channel_number]; + channel->CHCTRLA.bit.ENABLE = true; + #endif } -int32_t shared_dma_read(Sercom* sercom, uint8_t* buffer, uint32_t length, uint8_t tx) { - if (general_dma_tx.job_status != ERR_NONE) { +static uint8_t transfer_status(uint8_t channel_number) { + #ifdef SAMD21 + common_hal_mcu_disable_interrupts(); + /** Select the DMA channel and clear software trigger */ + DMAC->CHID.reg = DMAC_CHID_ID(channel_number); + uint8_t status = DMAC->CHINTFLAG.reg; + common_hal_mcu_enable_interrupts(); + return status; + #endif + + #ifdef SAMD51 + DmacChannel* channel = &DMAC->Channel[channel_number]; + return channel->CHINTFLAG.reg; + #endif +} + +static bool channel_free(uint8_t channel_number) { + #ifdef SAMD21 + common_hal_mcu_disable_interrupts(); + /** Select the DMA channel and clear software trigger */ + DMAC->CHID.reg = DMAC_CHID_ID(channel_number); + bool channel_free = DMAC->CHSTATUS.reg == 0; + common_hal_mcu_enable_interrupts(); + return channel_free; + #endif + + #ifdef SAMD51 + DmacChannel* channel = &DMAC->Channel[channel_number]; + return channel->CHSTATUS.reg == 0; + #endif } // Do write and read simultaneously. If buffer_out is NULL, write the tx byte over and over. // If buffer_out is a real buffer, ignore tx. -enum status_code shared_dma_transfer(Sercom* sercom, uint8_t* buffer_out, uint8_t* buffer_in, uint32_t length, uint8_t tx) { - return general_dma_tx.job_status; +// DMAs buffer_out -> dest +// DMAs src -> buffer_in +static int32_t shared_dma_transfer(void* peripheral, + const uint8_t* buffer_out, volatile uint32_t* dest, + volatile uint32_t* src, uint8_t* buffer_in, + uint32_t length, uint8_t tx) { + if (!channel_free(SHARED_TX_CHANNEL) || + (buffer_in != NULL && !channel_free(SHARED_RX_CHANNEL))) { + return -1; } - dma_configure(general_dma_tx.channel_id, sercom_index(sercom) * 2 + 2, false); - dma_configure(general_dma_rx.channel_id, sercom_index(sercom) * 2 + 1, false); + uint32_t beat_size = DMAC_BTCTRL_BEATSIZE_BYTE; + bool sercom = true; + bool tx_active = false; + bool rx_active = false; + uint16_t beat_length = length; + #ifdef SAMD51 + if (peripheral == QSPI) { + // Check input alignment on word boundaries. + if ((((uint32_t) buffer_in) & 0x3) != 0 || + (((uint32_t) buffer_out) & 0x3) != 0) { + return -3; + } + beat_size = DMAC_BTCTRL_BEATSIZE_WORD | DMAC_BTCTRL_SRCINC | DMAC_BTCTRL_DSTINC; + beat_length /= 4; + sercom = false; + if (buffer_out != NULL) { + dma_configure(SHARED_TX_CHANNEL, QSPI_DMAC_ID_TX, false); + tx_active = true; + } else { + dma_configure(SHARED_RX_CHANNEL, QSPI_DMAC_ID_RX, false); + rx_active = true; + } + + } else { + #endif + + // sercom index is incorrect for SAMD51 + dma_configure(SHARED_TX_CHANNEL, sercom_index(peripheral) * 2 + FIRST_SERCOM_TX_TRIGSRC, false); + tx_active = true; + if (buffer_in != NULL) { + dma_configure(SHARED_RX_CHANNEL, sercom_index(peripheral) * 2 + FIRST_SERCOM_RX_TRIGSRC, false); + rx_active = true; + } + + #ifdef SAMD51 + } + #endif // Set up RX first. - struct dma_descriptor_config descriptor_config; - dma_descriptor_get_config_defaults(&descriptor_config); - descriptor_config.beat_size = DMA_BEAT_SIZE_BYTE; - descriptor_config.src_increment_enable = false; - descriptor_config.dst_increment_enable = true; - descriptor_config.block_transfer_count = length; - // DATA register is consistently addressed across all SERCOM modes. - descriptor_config.source_address = ((uint32_t)&sercom->SPI.DATA.reg); - descriptor_config.destination_address = ((uint32_t)buffer_in + length); - - dma_descriptor_create(general_dma_rx.descriptor, &descriptor_config); + if (rx_active) { + DmacDescriptor* rx_descriptor = &dma_descriptors[SHARED_RX_CHANNEL]; + rx_descriptor->BTCTRL.reg = beat_size | DMAC_BTCTRL_DSTINC; + rx_descriptor->BTCNT.reg = beat_length; + rx_descriptor->SRCADDR.reg = ((uint32_t) src); + #ifdef SAMD51 + if (peripheral == QSPI) { + rx_descriptor->SRCADDR.reg = ((uint32_t) src + length); + } + #endif + rx_descriptor->DSTADDR.reg = ((uint32_t)buffer_in + length); + rx_descriptor->BTCTRL.bit.VALID = true; + } // Set up TX second. - dma_descriptor_get_config_defaults(&descriptor_config); - descriptor_config.beat_size = DMA_BEAT_SIZE_BYTE; - // Increment write address only if we have a real buffer. - descriptor_config.src_increment_enable = buffer_out != NULL; - descriptor_config.dst_increment_enable = false; - descriptor_config.block_transfer_count = length; - // - descriptor_config.source_address = ((uint32_t) (buffer_out != NULL ? buffer_out + length : &tx)); - // DATA register is consistently addressed across all SERCOM modes. - descriptor_config.destination_address = ((uint32_t)&sercom->SPI.DATA.reg); - - dma_descriptor_create(general_dma_tx.descriptor, &descriptor_config); + if (tx_active) { + DmacDescriptor* tx_descriptor = &dma_descriptors[SHARED_TX_CHANNEL]; + tx_descriptor->BTCTRL.reg = beat_size; + tx_descriptor->BTCNT.reg = beat_length; + if (buffer_out != NULL) { + tx_descriptor->SRCADDR.reg = ((uint32_t)buffer_out + length); + tx_descriptor->BTCTRL.reg |= DMAC_BTCTRL_SRCINC; + } else { + tx_descriptor->SRCADDR.reg = ((uint32_t) &tx); + } + tx_descriptor->DSTADDR.reg = ((uint32_t) dest); + tx_descriptor->BTCTRL.bit.VALID = true; + } + if (sercom) { + SercomSpi *s = &((Sercom*) peripheral)->SPI; + s->INTFLAG.reg = SERCOM_SPI_INTFLAG_RXC | SERCOM_SPI_INTFLAG_DRE; + } else { + //QSPI->INTFLAG.reg = QSPI_INTFLAG_RXC | QSPI_INTFLAG_DRE; + } // Start the RX job first so we don't miss the first byte. The TX job clocks // the output. - general_dma_rx.transfered_size = 0; - dma_start_transfer_job(&general_dma_rx); - general_dma_tx.transfered_size = 0; - dma_start_transfer_job(&general_dma_tx); + if (rx_active) { + enable_channel(SHARED_RX_CHANNEL); + } + if (tx_active) { + enable_channel(SHARED_TX_CHANNEL); + } - // Wait for the transfer to finish. - while (general_dma_rx.job_status == STATUS_BUSY) {} - while (sercom->SPI.INTFLAG.bit.RXC == 1) {} - return general_dma_rx.job_status; -} + if (sercom) { + //DMAC->SWTRIGCTRL.reg |= (1 << SHARED_TX_CHANNEL); + } else { + // Do a manual copy to trigger then DMA. We do 32-bit accesses to match the DMA. + #pragma GCC diagnostic push + #pragma GCC diagnostic ignored "-Wcast-align" + if (rx_active) { + //buffer_in[0] = *src; + DMAC->SWTRIGCTRL.reg |= (1 << SHARED_RX_CHANNEL); + } else { + //*(uint32_t*)dest = ((uint32_t*) buffer_out)[0]; + } + #pragma GCC diagnostic pop + } -bool allocate_block_counter() { - // Find a timer to count DMA block completions. - Tc *t = NULL; - Tc *tcs[TC_INST_NUM] = TC_INSTS; - for (uint8_t i = TC_INST_NUM; i > 0; i--) { - if (tcs[i - 1]->COUNT16.CTRLA.bit.ENABLE == 0) { - t = tcs[i - 1]; - break; + // Channels cycle between Suspend -> Pending -> Busy and back while transfering. So, we check + // the channels transfer status for an error or completion. + if (rx_active) { + while ((transfer_status(SHARED_RX_CHANNEL) & 0x3) == 0) {} + } + if (tx_active) { + while ((transfer_status(SHARED_TX_CHANNEL) & 0x3) == 0) {} + } + + if (sercom) { + Sercom* s = (Sercom*) peripheral; + // Wait for the SPI transfer to complete. + while (s->SPI.INTFLAG.bit.TXC == 0) {} + + // This transmit will cause the RX buffer overflow but we're OK with that. + // So, read the garbage and clear the overflow flag. + if (!rx_active) { + while (s->SPI.INTFLAG.bit.RXC == 1) { + s->SPI.DATA.reg; + } + s->SPI.STATUS.bit.BUFOVF = 1; + s->SPI.INTFLAG.reg = SERCOM_SPI_INTFLAG_ERROR; } } - if (t == NULL) { - return false; - } - MP_STATE_VM(audiodma_block_counter) = gc_alloc(sizeof(struct tc_module), false); - if (MP_STATE_VM(audiodma_block_counter) == NULL) { - return false; + + if ((!rx_active || transfer_status(SHARED_RX_CHANNEL) == DMAC_CHINTFLAG_TCMPL) && + (!tx_active || transfer_status(SHARED_TX_CHANNEL) == DMAC_CHINTFLAG_TCMPL)) { + return length; } + return -2; +} - // Don't bother setting the period. We set it before you playback anything. - struct tc_config config_tc; - tc_get_config_defaults(&config_tc); - config_tc.counter_size = TC_COUNTER_SIZE_16BIT; - config_tc.clock_prescaler = TC_CLOCK_PRESCALER_DIV1; - if (tc_init(MP_STATE_VM(audiodma_block_counter), t, &config_tc) != STATUS_OK) { - return false; - }; - struct tc_events events_tc; - events_tc.generate_event_on_overflow = false; - events_tc.on_event_perform_action = true; - events_tc.event_action = TC_EVENT_ACTION_INCREMENT_COUNTER; - tc_enable_events(MP_STATE_VM(audiodma_block_counter), &events_tc); +int32_t sercom_dma_transfer(Sercom* sercom, const uint8_t* buffer_out, uint8_t* buffer_in, + uint32_t length) { + return shared_dma_transfer(sercom, buffer_out, &sercom->SPI.DATA.reg, &sercom->SPI.DATA.reg, buffer_in, length, 0); +} - // Connect the timer overflow event, which happens at the target frequency, - // to the DAC conversion trigger. - MP_STATE_VM(audiodma_block_event) = gc_alloc(sizeof(struct events_resource), false); - if (MP_STATE_VM(audiodma_block_event) == NULL) { - return false; - } - struct events_config config; - events_get_config_defaults(&config); +int32_t sercom_dma_write(Sercom* sercom, const uint8_t* buffer, uint32_t length) { + return shared_dma_transfer(sercom, buffer, &sercom->SPI.DATA.reg, NULL, NULL, length, 0); +} - uint8_t user = EVSYS_ID_USER_TC3_EVU; - if (t == TC4) { - user = EVSYS_ID_USER_TC4_EVU; - } else if (t == TC5) { - user = EVSYS_ID_USER_TC5_EVU; -#ifdef TC6 - } else if (t == TC6) { - user = EVSYS_ID_USER_TC6_EVU; +int32_t sercom_dma_read(Sercom* sercom, uint8_t* buffer, uint32_t length, uint8_t tx) { + return shared_dma_transfer(sercom, NULL, &sercom->SPI.DATA.reg, &sercom->SPI.DATA.reg, buffer, length, tx); +} + +#ifdef SAMD51 +int32_t qspi_dma_write(uint32_t address, const uint8_t* buffer, uint32_t length) { + return shared_dma_transfer(QSPI, buffer, (uint32_t*) (QSPI_AHB + address), NULL, NULL, length, 0); +} + +int32_t qspi_dma_read(uint32_t address, uint8_t* buffer, uint32_t length) { + return shared_dma_transfer(QSPI, NULL, NULL, (uint32_t*) (QSPI_AHB + address), buffer, length, 0); +} #endif -#ifdef TC7 - } else if (t == TC7) { - user = EVSYS_ID_USER_TC7_EVU; -#endif - } - config.generator = EVSYS_ID_GEN_DMAC_CH_0; - config.path = EVENTS_PATH_ASYNCHRONOUS; - if (events_allocate(MP_STATE_VM(audiodma_block_event), &config) != STATUS_OK || - events_attach_user(MP_STATE_VM(audiodma_block_event), user) != STATUS_OK) { - return false; - } - - tc_enable(MP_STATE_VM(audiodma_block_counter)); - tc_stop_counter(MP_STATE_VM(audiodma_block_counter)); +bool allocate_block_counter() { +// // Find a timer to count DMA block completions. +// Tc *t = NULL; +// Tc *tcs[TC_INST_NUM] = TC_INSTS; +// for (uint8_t i = TC_INST_NUM; i > 0; i--) { +// if (tcs[i - 1]->COUNT16.CTRLA.bit.ENABLE == 0) { +// t = tcs[i - 1]; +// break; +// } +// } +// if (t == NULL) { +// return false; +// } +// MP_STATE_VM(audiodma_block_counter) = gc_alloc(sizeof(struct tc_module), false); +// if (MP_STATE_VM(audiodma_block_counter) == NULL) { +// return false; +// } +// +// // Don't bother setting the period. We set it before you playback anything. +// struct tc_config config_tc; +// tc_get_config_defaults(&config_tc); +// config_tc.counter_size = TC_COUNTER_SIZE_16BIT; +// config_tc.clock_prescaler = TC_CLOCK_PRESCALER_DIV1; +// if (tc_init(MP_STATE_VM(audiodma_block_counter), t, &config_tc) != STATUS_OK) { +// return false; +// }; +// +// struct tc_events events_tc; +// events_tc.generate_event_on_overflow = false; +// events_tc.on_event_perform_action = true; +// events_tc.event_action = TC_EVENT_ACTION_INCREMENT_COUNTER; +// tc_enable_events(MP_STATE_VM(audiodma_block_counter), &events_tc); +// +// // Connect the timer overflow event, which happens at the target frequency, +// // to the DAC conversion trigger. +// MP_STATE_VM(audiodma_block_event) = gc_alloc(sizeof(struct events_resource), false); +// if (MP_STATE_VM(audiodma_block_event) == NULL) { +// return false; +// } +// struct events_config config; +// events_get_config_defaults(&config); +// +// uint8_t user = EVSYS_ID_USER_TC3_EVU; +// if (t == TC4) { +// user = EVSYS_ID_USER_TC4_EVU; +// } else if (t == TC5) { +// user = EVSYS_ID_USER_TC5_EVU; +// #ifdef TC6 +// } else if (t == TC6) { +// user = EVSYS_ID_USER_TC6_EVU; +// #endif +// #ifdef TC7 +// } else if (t == TC7) { +// user = EVSYS_ID_USER_TC7_EVU; +// #endif +// } +// +// config.generator = EVSYS_ID_GEN_DMAC_CH_0; +// config.path = EVENTS_PATH_ASYNCHRONOUS; +// if (events_allocate(MP_STATE_VM(audiodma_block_event), &config) != STATUS_OK || +// events_attach_user(MP_STATE_VM(audiodma_block_event), user) != STATUS_OK) { +// return false; +// } +// +// tc_enable(MP_STATE_VM(audiodma_block_counter)); +// tc_stop_counter(MP_STATE_VM(audiodma_block_counter)); return true; } void switch_audiodma_trigger(uint8_t trigger_dmac_id) { - dma_configure(audio_dma.channel_id, trigger_dmac_id, true); + //dma_configure(audio_dma.channel_id, trigger_dmac_id, true); } diff --git a/ports/atmel-samd/shared_dma.h b/ports/atmel-samd/shared_dma.h index 2ddd81c4e4..536a95af33 100644 --- a/ports/atmel-samd/shared_dma.h +++ b/ports/atmel-samd/shared_dma.h @@ -27,17 +27,23 @@ #ifndef MICROPY_INCLUDED_ATMEL_SAMD_SHARED_DMA_H #define MICROPY_INCLUDED_ATMEL_SAMD_SHARED_DMA_H -extern struct dma_resource audio_dma; -extern struct dma_resource general_dma_tx; -extern struct dma_resource general_dma_rx; +#include +#include + +#include "include/sam.h" volatile bool audio_dma_in_use; void init_shared_dma(void); -enum status_code shared_dma_write(Sercom* sercom, const uint8_t* buffer, uint32_t length); -enum status_code shared_dma_read(Sercom* sercom, uint8_t* buffer, uint32_t length, uint8_t tx); -enum status_code shared_dma_transfer(Sercom* sercom, uint8_t* buffer_out, uint8_t* buffer_in, uint32_t length, uint8_t tx); +#ifdef SAMD51 +int32_t qspi_dma_write(uint32_t address, const uint8_t* buffer, uint32_t length); +int32_t qspi_dma_read(uint32_t address, uint8_t* buffer, uint32_t length); +#endif + +int32_t sercom_dma_write(Sercom* sercom, const uint8_t* buffer, uint32_t length); +int32_t sercom_dma_read(Sercom* sercom, uint8_t* buffer, uint32_t length, uint8_t tx); +int32_t sercom_dma_transfer(Sercom* sercom, const uint8_t* buffer_out, uint8_t* buffer_in, uint32_t length); // Allocate a counter to track how far along we are in a DMA double buffer. bool allocate_block_counter(void); diff --git a/ports/atmel-samd/supervisor/port.c b/ports/atmel-samd/supervisor/port.c index fe65915106..7935c87d37 100644 --- a/ports/atmel-samd/supervisor/port.c +++ b/ports/atmel-samd/supervisor/port.c @@ -49,6 +49,7 @@ #include "common-hal/pulseio/PulseIn.h" #include "common-hal/pulseio/PulseOut.h" #include "common-hal/pulseio/PWMOut.h" +#include "shared_dma.h" #include "tick.h" extern volatile bool mp_msc_enabled; @@ -120,7 +121,7 @@ safe_mode_t port_init(void) { // config_nvm.manual_page_write = false; // nvm_set_config(&config_nvm); - // init_shared_dma(); + init_shared_dma(); #ifdef CIRCUITPY_CANARY_WORD // Run in safe mode if the canary is corrupt. if (_ezero != CIRCUITPY_CANARY_WORD) { @@ -206,7 +207,7 @@ void reset_port(void) { reset_all_pins(); // Set up debugging pins after reset_all_pins(). - + // Uncomment to init PIN_PA17 for debugging. // struct port_config pin_conf; // port_get_config_defaults(&pin_conf); From 493c1452f38f185b48d3cebf94f3670d03c6b20a Mon Sep 17 00:00:00 2001 From: Radomir Dopieralski Date: Sun, 11 Mar 2018 12:01:48 +0100 Subject: [PATCH 087/135] _stage: use 16 bit for coordinates to support larger screens --- shared-bindings/_stage/__init__.c | 8 ++++---- shared-module/_stage/Layer.c | 2 +- shared-module/_stage/Layer.h | 2 +- shared-module/_stage/Text.c | 2 +- shared-module/_stage/Text.h | 2 +- shared-module/_stage/__init__.c | 9 +++------ shared-module/_stage/__init__.h | 2 +- 7 files changed, 12 insertions(+), 15 deletions(-) diff --git a/shared-bindings/_stage/__init__.c b/shared-bindings/_stage/__init__.c index 832b287716..24a3596645 100644 --- a/shared-bindings/_stage/__init__.c +++ b/shared-bindings/_stage/__init__.c @@ -71,10 +71,10 @@ //| This function is intended for internal use in the ``stage`` library //| and all the necessary checks are performed there. STATIC mp_obj_t stage_render(size_t n_args, const mp_obj_t *args) { - uint8_t x0 = mp_obj_get_int(args[0]); - uint8_t y0 = mp_obj_get_int(args[1]); - uint8_t x1 = mp_obj_get_int(args[2]); - uint8_t y1 = mp_obj_get_int(args[3]); + uint16_t x0 = mp_obj_get_int(args[0]); + uint16_t y0 = mp_obj_get_int(args[1]); + uint16_t x1 = mp_obj_get_int(args[2]); + uint16_t y1 = mp_obj_get_int(args[3]); size_t layers_size = 0; mp_obj_t *layers; diff --git a/shared-module/_stage/Layer.c b/shared-module/_stage/Layer.c index 4c9c46d7c6..d958f0d197 100644 --- a/shared-module/_stage/Layer.c +++ b/shared-module/_stage/Layer.c @@ -29,7 +29,7 @@ // Get the color of the pixel on the layer. -uint16_t get_layer_pixel(layer_obj_t *layer, int16_t x, uint16_t y) { +uint16_t get_layer_pixel(layer_obj_t *layer, uint16_t x, uint16_t y) { // Shift by the layer's position offset. x -= layer->x; diff --git a/shared-module/_stage/Layer.h b/shared-module/_stage/Layer.h index c46f71349f..17d101263f 100644 --- a/shared-module/_stage/Layer.h +++ b/shared-module/_stage/Layer.h @@ -43,6 +43,6 @@ typedef struct { uint8_t rotation; } layer_obj_t; -uint16_t get_layer_pixel(layer_obj_t *layer, int16_t x, uint16_t y); +uint16_t get_layer_pixel(layer_obj_t *layer, uint16_t x, uint16_t y); #endif // MICROPY_INCLUDED_SHARED_MODULE__STAGE_LAYER diff --git a/shared-module/_stage/Text.c b/shared-module/_stage/Text.c index 307f9bbfa7..df5bf80080 100644 --- a/shared-module/_stage/Text.c +++ b/shared-module/_stage/Text.c @@ -29,7 +29,7 @@ // Get the color of the pixel on the text. -uint16_t get_text_pixel(text_obj_t *text, int16_t x, uint16_t y) { +uint16_t get_text_pixel(text_obj_t *text, uint16_t x, uint16_t y) { // Shift by the text's position offset. x -= text->x; diff --git a/shared-module/_stage/Text.h b/shared-module/_stage/Text.h index bc111e49c1..b263fc7108 100644 --- a/shared-module/_stage/Text.h +++ b/shared-module/_stage/Text.h @@ -41,6 +41,6 @@ typedef struct { uint8_t width, height; } text_obj_t; -uint16_t get_text_pixel(text_obj_t *text, int16_t x, uint16_t y); +uint16_t get_text_pixel(text_obj_t *text, uint16_t x, uint16_t y); #endif // MICROPY_INCLUDED_SHARED_MODULE__STAGE_TEXT diff --git a/shared-module/_stage/__init__.c b/shared-module/_stage/__init__.c index 1931b89407..86f5ee7957 100644 --- a/shared-module/_stage/__init__.c +++ b/shared-module/_stage/__init__.c @@ -31,17 +31,14 @@ #include "shared-bindings/_stage/Text.h" -bool render_stage(uint8_t x0, uint8_t y0, uint8_t x1, uint8_t y1, +bool render_stage(uint16_t x0, uint16_t y0, uint16_t x1, uint16_t y1, mp_obj_t *layers, size_t layers_size, uint16_t *buffer, size_t buffer_size, busio_spi_obj_t *spi) { - // TODO(deshipu): Do a collision check of each layer with the - // rectangle, and only process the layers that overlap with it. - size_t index = 0; - for (uint8_t y = y0; y < y1; ++y) { - for (uint8_t x = x0; x < x1; ++x) { + for (uint16_t y = y0; y < y1; ++y) { + for (uint16_t x = x0; x < x1; ++x) { for (size_t layer = 0; layer < layers_size; ++layer) { uint16_t c = TRANSPARENT; layer_obj_t *obj = MP_OBJ_TO_PTR(layers[layer]); diff --git a/shared-module/_stage/__init__.h b/shared-module/_stage/__init__.h index 326c725599..d56a26940f 100644 --- a/shared-module/_stage/__init__.h +++ b/shared-module/_stage/__init__.h @@ -34,7 +34,7 @@ #define TRANSPARENT (0x1ff8) -bool render_stage(uint8_t x0, uint8_t y0, uint8_t x1, uint8_t y1, +bool render_stage(uint16_t x0, uint16_t y0, uint16_t x1, uint16_t y1, mp_obj_t *layers, size_t layers_size, uint16_t *buffer, size_t buffer_size, busio_spi_obj_t *spi); From 81ab2526e4c87b8f89aad470a106f06d6fc17176 Mon Sep 17 00:00:00 2001 From: Radomir Dopieralski Date: Sun, 11 Mar 2018 12:52:31 +0100 Subject: [PATCH 088/135] gamepad: Enable the gamepad module for express boards in 3.x --- ports/atmel-samd/mpconfigport.h | 4 ++-- ports/atmel-samd/supervisor/port.c | 12 ++++++++---- 2 files changed, 10 insertions(+), 6 deletions(-) diff --git a/ports/atmel-samd/mpconfigport.h b/ports/atmel-samd/mpconfigport.h index 2e14f7a8b2..1ce44ac8af 100644 --- a/ports/atmel-samd/mpconfigport.h +++ b/ports/atmel-samd/mpconfigport.h @@ -194,10 +194,10 @@ extern const struct _mp_obj_module_t usb_hid_module; #define CIRCUITPY_GAMEPAD_TICKS 0x1f #define EXTRA_BUILTIN_MODULES \ - { MP_OBJ_NEW_QSTR(MP_QSTR_bitbangio), (mp_obj_t)&bitbangio_module } + { MP_OBJ_NEW_QSTR(MP_QSTR_bitbangio), (mp_obj_t)&bitbangio_module }, \ + { MP_OBJ_NEW_QSTR(MP_QSTR_gamepad),(mp_obj_t)&gamepad_module } // { MP_OBJ_NEW_QSTR(MP_QSTR_audioio), (mp_obj_t)&audioio_module }, // { MP_OBJ_NEW_QSTR(MP_QSTR_audiobusio), (mp_obj_t)&audiobusio_module }, -// { MP_OBJ_NEW_QSTR(MP_QSTR_gamepad),(mp_obj_t)&gamepad_module }, #define EXPRESS_BOARD #else #define MICROPY_PY_BUILTINS_REVERSED (0) diff --git a/ports/atmel-samd/supervisor/port.c b/ports/atmel-samd/supervisor/port.c index 7935c87d37..cb8ffac47e 100644 --- a/ports/atmel-samd/supervisor/port.c +++ b/ports/atmel-samd/supervisor/port.c @@ -52,6 +52,10 @@ #include "shared_dma.h" #include "tick.h" +#ifdef CIRCUITPY_GAMEPAD_TICKS +#include "shared-module/gamepad/__init__.h" +#endif + extern volatile bool mp_msc_enabled; #if defined(SAMD21) && defined(ENABLE_MICRO_TRACE_BUFFER) @@ -198,10 +202,10 @@ void reset_port(void) { analogin_reset(); -// #ifdef CIRCUITPY_GAMEPAD_TICKS -// gamepad_reset(); -// #endif -// +#ifdef CIRCUITPY_GAMEPAD_TICKS + gamepad_reset(); +#endif + analogout_reset(); reset_all_pins(); From 945f2f5aa16f3dd4203bd745fe9ddf9440ddc0bc Mon Sep 17 00:00:00 2001 From: vesperk38 Date: Tue, 13 Mar 2018 13:42:29 -0400 Subject: [PATCH 089/135] line 172 has a typo correct 2MB to 4MB --- ports/atmel-samd/external_flash/devices.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ports/atmel-samd/external_flash/devices.h b/ports/atmel-samd/external_flash/devices.h index ce2c6c3dc0..d8baf5aca0 100644 --- a/ports/atmel-samd/external_flash/devices.h +++ b/ports/atmel-samd/external_flash/devices.h @@ -169,7 +169,7 @@ typedef struct { .supports_qspi_writes = true, \ } -// Settings for the Winbond W25Q32BV 2MiB SPI flash. +// Settings for the Winbond W25Q32BV 4MiB SPI flash. // Datasheet: https://www.winbond.com/resource-files/w25q32bv_revi_100413_wo_automotive.pdf #define W25Q32BV {\ .total_size = (1 << 22), /* 4 MiB */ \ From 81572481894bb371a65313ee75b8a9d3fcbbafcd Mon Sep 17 00:00:00 2001 From: Scott Shawcroft Date: Tue, 13 Mar 2018 11:29:29 -0700 Subject: [PATCH 090/135] Move usb read finish into interrupt. Having the `active_read = false` in the background function left a chance that a new_write occurs before active_read is set to false. In that case, we'll read the appropriate data rather than write it and never clear the active write. Hopefully fixes #655. --- ports/atmel-samd/usb_mass_storage.c | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/ports/atmel-samd/usb_mass_storage.c b/ports/atmel-samd/usb_mass_storage.c index 818736a782..b337839d5d 100644 --- a/ports/atmel-samd/usb_mass_storage.c +++ b/ports/atmel-samd/usb_mass_storage.c @@ -260,6 +260,9 @@ int32_t usb_msc_xfer_done(uint8_t lun) { if (active_read) { active_addr += 1; active_nblocks--; + if (active_nblocks == 0) { + active_read = false; + } } if (active_write) { @@ -278,10 +281,6 @@ int32_t usb_msc_xfer_done(uint8_t lun) { // sector. Once the sector is transmitted, xfer_done will be called. void usb_msc_background(void) { if (active_read && !usb_busy) { - if (active_nblocks == 0) { - active_read = false; - return; - } fs_user_mount_t * vfs = get_vfs(active_lun); disk_read(vfs, sector_buffer, active_addr, 1); CRITICAL_SECTION_ENTER(); From c37ade9aeba3c0608c8e8591e999871d96dadda8 Mon Sep 17 00:00:00 2001 From: Scott Shawcroft Date: Tue, 13 Mar 2018 12:44:00 -0700 Subject: [PATCH 091/135] Correct NO_TIMER index value for SAMD21. We check validity by ensuring it's lower than the total number of timers. 0 is a terrible number for the NO_TIMER value because its valid even though it shouldn't be. Fixes https://github.com/adafruit/Adafruit_CircuitPython_SimpleIO/issues/29 --- ports/atmel-samd/samd21_pins.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ports/atmel-samd/samd21_pins.c b/ports/atmel-samd/samd21_pins.c index f1d006de8b..a6b19730f7 100644 --- a/ports/atmel-samd/samd21_pins.c +++ b/ports/atmel-samd/samd21_pins.c @@ -57,7 +57,7 @@ .wave_output = p_wave_output \ } -#define NO_TIMER TCC(0, 0) +#define NO_TIMER TCC(0xff, 0) #define TOUCH(y_line) \ .has_touch = true, \ From 7a3f86d184c42a7957a135d9dfc23b1149e2708c Mon Sep 17 00:00:00 2001 From: Scott Shawcroft Date: Wed, 14 Mar 2018 10:32:41 -0700 Subject: [PATCH 092/135] Check usb_busy up front in usb background function. Waiting to do so risks accidentally queueing another response. Hopefully fixes #655 but we'll let @jerryneedell confirm. --- ports/atmel-samd/usb_mass_storage.c | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/ports/atmel-samd/usb_mass_storage.c b/ports/atmel-samd/usb_mass_storage.c index b337839d5d..9b6715158c 100644 --- a/ports/atmel-samd/usb_mass_storage.c +++ b/ports/atmel-samd/usb_mass_storage.c @@ -280,7 +280,14 @@ int32_t usb_msc_xfer_done(uint8_t lun) { // drive into our cache and trigger the USB DMA to output the // sector. Once the sector is transmitted, xfer_done will be called. void usb_msc_background(void) { - if (active_read && !usb_busy) { + // Check USB busy first because we never want to queue another transfer if it is. Checking + // active_read or active_write first leaves the possibility that they are true, an xfer done + // interrupt occurs (setting them false), turning off usb_busy and causing us to queue a + // spurious transfer. + if (usb_busy) { + return; + } + if (active_read) { fs_user_mount_t * vfs = get_vfs(active_lun); disk_read(vfs, sector_buffer, active_addr, 1); CRITICAL_SECTION_ENTER(); @@ -288,7 +295,7 @@ void usb_msc_background(void) { usb_busy = result == ERR_NONE; CRITICAL_SECTION_LEAVE(); } - if (active_write && !usb_busy) { + if (active_write) { if (sector_loaded) { fs_user_mount_t * vfs = get_vfs(active_lun); disk_write(vfs, sector_buffer, active_addr, 1); From 88aa0e2660e439fccac9c56b683a0e56b2399905 Mon Sep 17 00:00:00 2001 From: Scott Shawcroft Date: Wed, 14 Mar 2018 11:08:01 -0700 Subject: [PATCH 093/135] Remove SERCOM pointers from pin data structure because index is enough. This saves 380 bytes on the Arduino Zero build. (More pins == more savings.) --- ports/atmel-samd/common-hal/busio/I2C.c | 18 +++++++----- ports/atmel-samd/common-hal/busio/SPI.c | 11 ++++--- ports/atmel-samd/common-hal/busio/UART.c | 29 ++++++++++--------- .../common-hal/microcontroller/Pin.h | 5 ++-- ports/atmel-samd/peripherals.h | 2 ++ ports/atmel-samd/samd21_peripherals.c | 3 +- ports/atmel-samd/samd21_pins.c | 6 +--- ports/atmel-samd/samd51_peripherals.c | 3 +- ports/atmel-samd/samd51_pins.c | 8 ++--- 9 files changed, 44 insertions(+), 41 deletions(-) diff --git a/ports/atmel-samd/common-hal/busio/I2C.c b/ports/atmel-samd/common-hal/busio/I2C.c index 4182c86513..4ac1f340c6 100644 --- a/ports/atmel-samd/common-hal/busio/I2C.c +++ b/ports/atmel-samd/common-hal/busio/I2C.c @@ -46,19 +46,21 @@ void common_hal_busio_i2c_construct(busio_i2c_obj_t *self, uint32_t sda_pinmux = 0; uint32_t scl_pinmux = 0; for (int i = 0; i < NUM_SERCOMS_PER_PIN; i++) { - Sercom* potential_sercom = sda->sercom[i].sercom; - if (potential_sercom == NULL || - potential_sercom->I2CM.CTRLA.bit.ENABLE != 0 || + sercom_index = sda->sercom[i].index; + if (sercom_index >= SERCOM_INST_NUM) { + continue; + } + Sercom* potential_sercom = sercom_insts[sercom_index]; + if (potential_sercom->I2CM.CTRLA.bit.ENABLE != 0 || sda->sercom[i].pad != 0) { continue; } sda_pinmux = PINMUX(sda->pin, (i == 0) ? MUX_C : MUX_D); for (int j = 0; j < NUM_SERCOMS_PER_PIN; j++) { - if (potential_sercom == scl->sercom[j].sercom && + if (sercom_index == scl->sercom[j].index && scl->sercom[j].pad == 1) { scl_pinmux = PINMUX(scl->pin, (j == 0) ? MUX_C : MUX_D); sercom = potential_sercom; - sercom_index = scl->sercom[j].index; // 2 for SERCOM2, etc. break; } } @@ -77,7 +79,7 @@ void common_hal_busio_i2c_construct(busio_i2c_obj_t *self, if (i2c_m_sync_init(&self->i2c_desc, sercom) != ERR_NONE) { mp_raise_OSError(MP_EIO); } - + gpio_set_pin_pull_mode(sda->pin, GPIO_PULL_OFF); gpio_set_pin_function(sda->pin, sda_pinmux); @@ -85,7 +87,7 @@ void common_hal_busio_i2c_construct(busio_i2c_obj_t *self, gpio_set_pin_function(scl->pin, scl_pinmux); // clkrate is always 0. baud_rate is in kHz. - + // Frequency must be set before the I2C device is enabled. if (i2c_m_sync_set_baudrate(&self->i2c_desc, 0, frequency / 1000) != ERR_NONE) { mp_raise_ValueError("Unsupported baudrate"); @@ -113,7 +115,7 @@ void common_hal_busio_i2c_deinit(busio_i2c_obj_t *self) { i2c_m_sync_disable(&self->i2c_desc); i2c_m_sync_deinit(&self->i2c_desc); - + reset_pin(self->sda_pin); reset_pin(self->scl_pin); self->sda_pin = NO_PIN; diff --git a/ports/atmel-samd/common-hal/busio/SPI.c b/ports/atmel-samd/common-hal/busio/SPI.c index eca73be78a..a2bf30f054 100644 --- a/ports/atmel-samd/common-hal/busio/SPI.c +++ b/ports/atmel-samd/common-hal/busio/SPI.c @@ -55,9 +55,12 @@ void common_hal_busio_spi_construct(busio_spi_obj_t *self, uint8_t miso_pad = 0; uint8_t dopo = 255; for (int i = 0; i < NUM_SERCOMS_PER_PIN; i++) { - Sercom* potential_sercom = clock->sercom[i].sercom; sercom_index = clock->sercom[i].index; // 2 for SERCOM2, etc. - if (potential_sercom == NULL || + if (sercom_index >= SERCOM_INST_NUM) { + continue; + } + Sercom* potential_sercom = sercom_insts[sercom_index]; + if ( #if defined(MICROPY_HW_APA102_SCK) && defined(MICROPY_HW_APA102_MOSI) && !defined(CIRCUITPY_BITBANG_APA102) (potential_sercom->SPI.CTRLA.bit.ENABLE != 0 && potential_sercom != status_apa102.spi_desc.dev.prvt && @@ -74,7 +77,7 @@ void common_hal_busio_spi_construct(busio_spi_obj_t *self, } for (int j = 0; j < NUM_SERCOMS_PER_PIN; j++) { if (!mosi_none) { - if(potential_sercom == mosi->sercom[j].sercom) { + if (sercom_index == mosi->sercom[j].index) { mosi_pinmux = PINMUX(mosi->pin, (j == 0) ? MUX_C : MUX_D); mosi_pad = mosi->sercom[j].pad; dopo = samd_peripherals_get_spi_dopo(clock_pad, mosi_pad); @@ -91,7 +94,7 @@ void common_hal_busio_spi_construct(busio_spi_obj_t *self, } if (!miso_none) { for (int k = 0; k < NUM_SERCOMS_PER_PIN; k++) { - if (potential_sercom == miso->sercom[k].sercom) { + if (sercom_index == miso->sercom[k].index) { miso_pinmux = PINMUX(miso->pin, (k == 0) ? MUX_C : MUX_D); miso_pad = miso->sercom[k].pad; sercom = potential_sercom; diff --git a/ports/atmel-samd/common-hal/busio/UART.c b/ports/atmel-samd/common-hal/busio/UART.c index 292e01e60e..4cb7db2033 100644 --- a/ports/atmel-samd/common-hal/busio/UART.c +++ b/ports/atmel-samd/common-hal/busio/UART.c @@ -71,7 +71,7 @@ void common_hal_busio_uart_construct(busio_uart_obj_t *self, if (!have_tx && !have_rx) { mp_raise_ValueError("tx and rx cannot both be None"); } - + self->baudrate = baudrate; self->character_bits = bits; self->timeout_ms = timeout; @@ -82,10 +82,12 @@ void common_hal_busio_uart_construct(busio_uart_obj_t *self, for (int i = 0; i < NUM_SERCOMS_PER_PIN; i++) { Sercom* potential_sercom = NULL; if (have_tx) { - potential_sercom = tx->sercom[i].sercom; sercom_index = tx->sercom[i].index; - if (potential_sercom == NULL || - potential_sercom->USART.CTRLA.bit.ENABLE != 0 || + if (sercom_index >= SERCOM_INST_NUM) { + continue; + } + potential_sercom = sercom_insts[sercom_index]; + if (potential_sercom->USART.CTRLA.bit.ENABLE != 0 || !(tx->sercom[i].pad == 0 || tx->sercom[i].pad == 2)) { continue; @@ -98,12 +100,13 @@ void common_hal_busio_uart_construct(busio_uart_obj_t *self, } } for (int j = 0; j < NUM_SERCOMS_PER_PIN; j++) { - if (((!have_tx && rx->sercom[j].sercom->USART.CTRLA.bit.ENABLE == 0) || - potential_sercom == rx->sercom[j].sercom) && + if (((!have_tx && rx->sercom[j].index < SERCOM_INST_NUM && + sercom_insts[rx->sercom[j].index]->USART.CTRLA.bit.ENABLE == 0) || + sercom_index == rx->sercom[j].index) && rx->sercom[j].pad != tx_pad) { rx_pinmux = PINMUX(rx->pin, (j == 0) ? MUX_C : MUX_D); rx_pad = rx->sercom[j].pad; - sercom = rx->sercom[j].sercom; + sercom = sercom_insts[rx->sercom[j].index]; sercom_index = rx->sercom[j].index; break; } @@ -147,7 +150,7 @@ void common_hal_busio_uart_construct(busio_uart_obj_t *self, // usart_async_init() sets a number of defaults based on a prototypical SERCOM // which don't necessarily match what we need. After calling it, set the values // specific to this instantiation of UART. - + // Set pads computed for this SERCOM. // TXPO: // 0x0: TX pad 0; no RTS/CTS @@ -182,7 +185,7 @@ void common_hal_busio_uart_construct(busio_uart_obj_t *self, // http://start.atmel.com/static/help/index.html?GUID-79201A5A-226F-4FBB-B0B8-AB0BE0554836 // Look at the ASFv4 code example for async USART. usart_async_register_callback(usart_desc_p, USART_ASYNC_RXC_CB, usart_async_rxc_callback); - + if (have_tx) { gpio_set_pin_direction(tx->pin, GPIO_DIRECTION_OUT); @@ -193,7 +196,7 @@ void common_hal_busio_uart_construct(busio_uart_obj_t *self, } else { self->tx_pin = NO_PIN; } - + if (have_rx) { gpio_set_pin_direction(rx->pin, GPIO_DIRECTION_IN); gpio_set_pin_pull_mode(rx->pin, GPIO_PULL_OFF); @@ -238,7 +241,7 @@ size_t common_hal_busio_uart_read(busio_uart_obj_t *self, uint8_t *data, size_t // Nothing to read. return 0; } - + struct io_descriptor *io; usart_async_get_io_descriptor(usart_desc_p, &io); @@ -266,7 +269,7 @@ size_t common_hal_busio_uart_read(busio_uart_obj_t *self, uint8_t *data, size_t MICROPY_VM_HOOK_LOOP #endif } - + return total_read; } @@ -305,7 +308,7 @@ size_t common_hal_busio_uart_write(busio_uart_obj_t *self, const uint8_t *data, *errcode = MP_EAGAIN; return MP_STREAM_ERROR; } - + struct usart_async_status async_status; // Could return ERR_BUSY, but if that's true there's already a problem. usart_async_get_status(usart_desc_p, &async_status); diff --git a/ports/atmel-samd/common-hal/microcontroller/Pin.h b/ports/atmel-samd/common-hal/microcontroller/Pin.h index ca639eb849..4e21a14cd8 100644 --- a/ports/atmel-samd/common-hal/microcontroller/Pin.h +++ b/ports/atmel-samd/common-hal/microcontroller/Pin.h @@ -34,9 +34,8 @@ #include "include/component/sercom.h" typedef struct { - Sercom *const sercom; // SERCOM0, SERCOM1, etc. - uint8_t index; // 0, 1, etc. corresponding to SERCOM. - uint8_t pad; // which of the four SERCOM pads to use + uint8_t index:6; // 0, 1, etc. corresponding to SERCOM. + uint8_t pad:2; // which of the four SERCOM pads to use } pin_sercom_t; typedef struct { diff --git a/ports/atmel-samd/peripherals.h b/ports/atmel-samd/peripherals.h index bb01bc1acd..18c7f44d5c 100644 --- a/ports/atmel-samd/peripherals.h +++ b/ports/atmel-samd/peripherals.h @@ -35,6 +35,8 @@ uint8_t samd_peripherals_spi_baudrate_to_baud_reg_value(const uint32_t baudrate); uint32_t samd_peripherals_spi_baud_reg_value_to_baudrate(const uint8_t baud_reg_value); +Sercom* sercom_insts[SERCOM_INST_NUM]; + #ifdef SAMD21 #include "samd21_peripherals.h" #endif diff --git a/ports/atmel-samd/samd21_peripherals.c b/ports/atmel-samd/samd21_peripherals.c index 484c787cb0..a27e49e0e5 100644 --- a/ports/atmel-samd/samd21_peripherals.c +++ b/ports/atmel-samd/samd21_peripherals.c @@ -56,7 +56,8 @@ static const uint8_t SERCOMx_GCLK_ID_SLOW[] = { #endif }; - +Sercom* sercom_insts[SERCOM_INST_NUM] = SERCOM_INSTS; + // Clock initialization as done in Atmel START. void samd_peripherals_sercom_clock_init(Sercom* sercom, uint8_t sercom_index) { _pm_enable_bus_clock(PM_BUS_APBC, sercom); diff --git a/ports/atmel-samd/samd21_pins.c b/ports/atmel-samd/samd21_pins.c index a6b19730f7..eafc4b5fb6 100644 --- a/ports/atmel-samd/samd21_pins.c +++ b/ports/atmel-samd/samd21_pins.c @@ -30,15 +30,13 @@ #define SERCOM(sercom_index, p_pad) \ { \ - .sercom = SERCOM## sercom_index, \ .index = sercom_index, \ .pad = p_pad \ } #define NO_SERCOM \ { \ - .sercom = 0, \ - .index = 0, \ + .index = 0x3f, \ .pad = 0 \ } @@ -92,8 +90,6 @@ const mcu_pin_obj_t pin_## p_name = { \ .sercom = {p_primary_sercom, p_secondary_sercom}, \ } -#define NO_ADC_INPUT (0) - // Pins in datasheet order. // NOTE(tannewt): TC wave out 0 is commented out because the first channel is // used to vary the 16 bit timer's frequency. diff --git a/ports/atmel-samd/samd51_peripherals.c b/ports/atmel-samd/samd51_peripherals.c index e06f7f9df0..8f37bdfd11 100644 --- a/ports/atmel-samd/samd51_peripherals.c +++ b/ports/atmel-samd/samd51_peripherals.c @@ -60,7 +60,8 @@ static const uint8_t SERCOMx_GCLK_ID_SLOW[] = { #endif }; - +Sercom* sercom_insts[SERCOM_INST_NUM] = SERCOM_INSTS; + // Clock initialization as done in Atmel START. void samd_peripherals_sercom_clock_init(Sercom* sercom, uint8_t sercom_index) { hri_gclk_write_PCHCTRL_reg(GCLK, diff --git a/ports/atmel-samd/samd51_pins.c b/ports/atmel-samd/samd51_pins.c index 78bdf0553c..6d597b6e1a 100644 --- a/ports/atmel-samd/samd51_pins.c +++ b/ports/atmel-samd/samd51_pins.c @@ -30,15 +30,13 @@ #define SERCOM(sercom_index, p_pad) \ { \ - .sercom = SERCOM## sercom_index, \ .index = sercom_index, \ .pad = p_pad \ } #define NO_SERCOM \ { \ - .sercom = 0, \ - .index = 0, \ + .index = 0x3f, \ .pad = 0 \ } @@ -91,8 +89,6 @@ const mcu_pin_obj_t pin_## p_name = { \ .sercom = {p_primary_sercom, p_secondary_sercom}, \ } -#define NO_ADC_INPUT (0) - // Pins in datasheet order. // NOTE(tannewt): TC wave out 0 is commented out because the first channel is // used to vary the 16 bit timer's frequency. @@ -1139,7 +1135,7 @@ PIN(PA31, EXTINT_CHANNEL(15), NO_ADC, NO_ADC, NO_TOUCH, #else NO_SERCOM, #endif - SERCOM(1, 23), + SERCOM(1, 3), #ifdef TC6 TC(6, 1), #else From 04b4026666d8a8ef79a1f2ba14330863424936fc Mon Sep 17 00:00:00 2001 From: jerryneedell Date: Wed, 14 Mar 2018 21:28:56 -0400 Subject: [PATCH 094/135] fix dotstar for Gemma_M0 in CP3.0 Uncomment lines in mpconfigport.h for gemma_m0 to allow dotstar access. same issue as #514 for trinket_m0 --- ports/atmel-samd/boards/gemma_m0/mpconfigboard.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/ports/atmel-samd/boards/gemma_m0/mpconfigboard.h b/ports/atmel-samd/boards/gemma_m0/mpconfigboard.h index 4baafcb11e..6457d481f3 100644 --- a/ports/atmel-samd/boards/gemma_m0/mpconfigboard.h +++ b/ports/atmel-samd/boards/gemma_m0/mpconfigboard.h @@ -1,8 +1,8 @@ #define MICROPY_HW_BOARD_NAME "Adafruit Gemma M0" #define MICROPY_HW_MCU_NAME "samd21e18" -// #define MICROPY_HW_APA102_MOSI (&pin_PA00) -// #define MICROPY_HW_APA102_SCK (&pin_PA01) +#define MICROPY_HW_APA102_MOSI (&pin_PA00) +#define MICROPY_HW_APA102_SCK (&pin_PA01) // #define CIRCUITPY_BITBANG_APA102 From 05e2a7d1ac8a624f89f7081b1ae46e48230cabd6 Mon Sep 17 00:00:00 2001 From: Kattni Date: Thu, 15 Mar 2018 20:28:09 -0400 Subject: [PATCH 095/135] Added digital pin assignments --- ports/atmel-samd/boards/circuitplayground_express/pins.c | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/ports/atmel-samd/boards/circuitplayground_express/pins.c b/ports/atmel-samd/boards/circuitplayground_express/pins.c index 4be74f3773..aecd7f416a 100644 --- a/ports/atmel-samd/boards/circuitplayground_express/pins.c +++ b/ports/atmel-samd/boards/circuitplayground_express/pins.c @@ -2,17 +2,25 @@ STATIC const mp_rom_map_elem_t board_global_dict_table[] = { { MP_ROM_QSTR(MP_QSTR_A0), MP_ROM_PTR(&pin_PA02) }, + { MP_ROM_QSTR(MP_QSTR_D12), MP_ROM_PTR(&pin_PA02) }, { MP_ROM_QSTR(MP_QSTR_SPEAKER), MP_ROM_PTR(&pin_PA02) }, { MP_ROM_QSTR(MP_QSTR_A1), MP_ROM_PTR(&pin_PA05) }, + { MP_ROM_QSTR(MP_QSTR_D6), MP_ROM_PTR(&pin_PA05) }, { MP_ROM_QSTR(MP_QSTR_A2), MP_ROM_PTR(&pin_PA06) }, + { MP_ROM_QSTR(MP_QSTR_D9), MP_ROM_PTR(&pin_PA06) }, { MP_ROM_QSTR(MP_QSTR_A3), MP_ROM_PTR(&pin_PA07) }, + { MP_ROM_QSTR(MP_QSTR_D10), MP_ROM_PTR(&pin_PA07) }, { MP_ROM_QSTR(MP_QSTR_A4), MP_ROM_PTR(&pin_PB03) }, + { MP_ROM_QSTR(MP_QSTR_D3), MP_ROM_PTR(&pin_PB03) }, { MP_ROM_QSTR(MP_QSTR_SCL), MP_ROM_PTR(&pin_PB03) }, { MP_ROM_QSTR(MP_QSTR_A5), MP_ROM_PTR(&pin_PB02) }, + { MP_ROM_QSTR(MP_QSTR_D2), MP_ROM_PTR(&pin_PB02) }, { MP_ROM_QSTR(MP_QSTR_SDA), MP_ROM_PTR(&pin_PB02) }, { MP_ROM_QSTR(MP_QSTR_A6), MP_ROM_PTR(&pin_PB09) }, + { MP_ROM_QSTR(MP_QSTR_D0), MP_ROM_PTR(&pin_PB09) }, { MP_ROM_QSTR(MP_QSTR_RX), MP_ROM_PTR(&pin_PB09) }, { MP_ROM_QSTR(MP_QSTR_A7), MP_ROM_PTR(&pin_PB08) }, + { MP_ROM_QSTR(MP_QSTR_D1), MP_ROM_PTR(&pin_PB08) }, { MP_ROM_QSTR(MP_QSTR_TX), MP_ROM_PTR(&pin_PB08) }, { MP_ROM_QSTR(MP_QSTR_LIGHT), MP_ROM_PTR(&pin_PA11) }, { MP_ROM_QSTR(MP_QSTR_A8), MP_ROM_PTR(&pin_PA11) }, From dddfad6594d0e28497f82552a966729d270c7681 Mon Sep 17 00:00:00 2001 From: Jeff Epler Date: Mon, 19 Mar 2018 20:40:04 -0500 Subject: [PATCH 096/135] UART: Fix maybe-uninitialized diagnostic The following error occurs when building with gcc 5.4.1 (debian stretch): common-hal/busio/UART.c:104:83: error: 'sercom_index' may be used uninitialized in this function [-Werror=maybe-uninitialized] sercom_insts[rx->sercom[j].index]->USART.CTRLA.bit.ENABLE == 0) || It may be related to the addition of rx-only UARTs; gcc is unable to infer the intended relationship between have_tx and sercom_index being set (I am still not entirely confident of it myself) --- ports/atmel-samd/common-hal/busio/UART.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ports/atmel-samd/common-hal/busio/UART.c b/ports/atmel-samd/common-hal/busio/UART.c index 4cb7db2033..5376775206 100644 --- a/ports/atmel-samd/common-hal/busio/UART.c +++ b/ports/atmel-samd/common-hal/busio/UART.c @@ -56,7 +56,7 @@ void common_hal_busio_uart_construct(busio_uart_obj_t *self, uint8_t bits, uart_parity_t parity, uint8_t stop, uint32_t timeout, uint8_t receiver_buffer_size) { Sercom* sercom = NULL; - uint8_t sercom_index; + uint8_t sercom_index = 255; // Unset index uint32_t rx_pinmux = 0; uint8_t rx_pad = 255; // Unset pad uint32_t tx_pinmux = 0; From 002797a3b43d19fc4e289608038867312165b09d Mon Sep 17 00:00:00 2001 From: Jeff Epler Date: Mon, 19 Mar 2018 20:40:52 -0500 Subject: [PATCH 097/135] Fix array vs pointer error in declaration of circuitpython_help_text Building with gcc 5.4.1 (Debian Stretch) with the unsupported -Wno-error=lto-type-mismatch flag removed, the following diagnostic occurs: ../../py/builtin.h:121:19: error: type of 'circuitpython_help_text' does not match original declaration [-Werror] extern const char MICROPY_PY_BUILTINS_HELP_TEXT[]; ^ ../../shared-bindings/help.c:38:13: note: previously declared here const char *circuitpython_help_text = ^ lto1: all warnings being treated as errors lto-wrapper: fatal error: /usr/bin/arm-none-eabi-gcc returned 1 exit status --- shared-bindings/help.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/shared-bindings/help.c b/shared-bindings/help.c index cdd9a4a937..d8ffc13dd0 100644 --- a/shared-bindings/help.c +++ b/shared-bindings/help.c @@ -35,7 +35,7 @@ //| prints general port information. //| -const char *circuitpython_help_text = +const char circuitpython_help_text[] = "Welcome to Adafruit CircuitPython " MICROPY_GIT_TAG "!\r\n" "\r\n" "Please visit learn.adafruit.com/category/circuitpython for project guides.\r\n" From fa491b4c327646b90de2a92ffc0c16950946f9ee Mon Sep 17 00:00:00 2001 From: Jeff Epler Date: Mon, 19 Mar 2018 21:55:49 -0500 Subject: [PATCH 098/135] README.rst: spell out gcc version requirements .. the text was adapted from ports/stm32 and a conversation with Dan Halbert. --- ports/atmel-samd/README.rst | 18 +++++++++++++++++- 1 file changed, 17 insertions(+), 1 deletion(-) diff --git a/ports/atmel-samd/README.rst b/ports/atmel-samd/README.rst index 8785ccada9..cd1453b011 100644 --- a/ports/atmel-samd/README.rst +++ b/ports/atmel-samd/README.rst @@ -115,13 +115,29 @@ PB03 **Yes** **Yes** **Yes** **Yes** Setup ----- -Install required compiler packages: + +An ARM compiler is required for the build, along with the associated binary +utilities. On Ubuntu, these can be installed as follows: .. code-block:: shell sudo add-apt-repository ppa:team-gcc-arm-embedded/ppa sudo apt-get install gcc-arm-embedded +On Arch Linux the compiler is available for via the package +``arm-none-eabi-gcc``. + +For other systems, the `GNU Arm Embedded Toolchain `_ +may be available in binary form. + +The latest available package from team-gcc-arm-embedded is used to produce the +binaries shipped by AdaFruit. Other compiler versions, particularly older +ones, may not work properly. In particular, the ``gcc-arm-none-eabi`` package +in Debian Stretch is too old. + +The compiler can be changed using the ``CROSS_COMPILE`` variable when invoking +``make``. + Building -------- From 3f82fe8da9edf9f9a3285b307d8c1cca01dd978f Mon Sep 17 00:00:00 2001 From: Jeff Epler Date: Mon, 19 Mar 2018 21:56:32 -0500 Subject: [PATCH 099/135] README.rst: document mpy-cross gotcha This was biting me, leading to an odd error later on. --- ports/atmel-samd/README.rst | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/ports/atmel-samd/README.rst b/ports/atmel-samd/README.rst index cd1453b011..c74407b0a0 100644 --- a/ports/atmel-samd/README.rst +++ b/ports/atmel-samd/README.rst @@ -141,6 +141,17 @@ The compiler can be changed using the ``CROSS_COMPILE`` variable when invoking Building -------- +Before building the firmware for a given board the MicroPython cross-compiler +must be built; it will be used to pre-compile some of the built-in scripts to +bytecode. The cross-compiler is built and run on the host machine, using: + +.. code-block:: shell + + make -C mpy-cross + +This command should be executed from the root directory of this repository. +All other commands below should be executed from the ports/atmel-samd/ directory. + To build for the Arduino Zero: .. code-block:: shell From edfc76be4d3d5366b544d2ea243c5f4303ae20df Mon Sep 17 00:00:00 2001 From: Jeff Epler Date: Wed, 21 Mar 2018 21:11:24 -0500 Subject: [PATCH 100/135] README: delete reference to gitter "We don't use gitter anymore" -- the last message on https://gitter.im/adafruit/circuitpython on February 18 --- README.rst | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/README.rst b/README.rst index 7e234331ee..31c0cce595 100644 --- a/README.rst +++ b/README.rst @@ -83,8 +83,7 @@ Conduct `__ are welcome to submit pull requests and they will be promptly reviewed -by project admins. Please join the `Gitter -chat `__ or +by project admins. Please join the `Discord `__ too. -------------- From 9ddf60f8b45857b79e04a06e0ce17c4329109f87 Mon Sep 17 00:00:00 2001 From: Jeff Epler Date: Wed, 21 Mar 2018 21:35:07 -0500 Subject: [PATCH 101/135] CONTRIBUTING: delete reference to gitter --- CONTRIBUTING.md | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 5401892dda..2eb0214da4 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -8,8 +8,7 @@ so will result in corrective actions such as time out or ban from the project. ## Developer contact [@tannewt](https://github.com/tannewt) is the main developer of CircuitPython and is sponsored by [Adafruit Industries LLC](https://adafruit.com). He is -reachable on [Discord](https://adafru.it/discord) as tannewt and -[Gitter](gitter.im/adafruit/circuitpython) as tannewt during US West Coast +reachable on [Discord](https://adafru.it/discord) as tannewt during US West Coast working hours. He also checks GitHub issues and the [Adafruit support forum](https://forums.adafruit.com/viewforum.php?f=60). ## Licensing From a7e3c74fed3e6db841ab91443c3c71a8f5dc56fc Mon Sep 17 00:00:00 2001 From: Jeff Epler Date: Thu, 22 Mar 2018 08:06:36 -0500 Subject: [PATCH 102/135] Autocreate files that prevent MacOS indexing of the CIRCUITPYTHON dive .. the price of this appears to be about 112 bytes of flash and 12 bytes of RAM, according to the stats printed during the build. It also uses up 4 directory entries (out of 128), but does not reduce the number of blocks usable for storing file contents. These are the same items noted in the Adafruit README for Trinket M0 as preventing MacOS indexing. Closes: #689 --- ports/atmel-samd/supervisor/filesystem.c | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/ports/atmel-samd/supervisor/filesystem.c b/ports/atmel-samd/supervisor/filesystem.c index 45dc5667be..90478ad16d 100644 --- a/ports/atmel-samd/supervisor/filesystem.c +++ b/ports/atmel-samd/supervisor/filesystem.c @@ -42,6 +42,12 @@ fs_user_mount_t fs_user_mount_flash; mp_vfs_mount_t mp_vfs_mount_flash; +static void make_empty_file(FATFS *fatfs, const char *path) { + FIL fp; + f_open(fatfs, &fp, path, FA_WRITE | FA_CREATE_ALWAYS); + f_close(&fp); +} + // we don't make this function static because it needs a lot of stack and we // want it to be executed without using stack within main() function void filesystem_init(bool create_allowed) { @@ -65,6 +71,14 @@ void filesystem_init(bool create_allowed) { // set label f_setlabel(&vfs_fat->fatfs, "CIRCUITPY"); + + // inhibit file indexing on MacOS + f_mkdir(&vfs_fat->fatfs, "/.fseventsd"); + make_empty_file(&vfs_fat->fatfs, "/.metadata_never_index"); + make_empty_file(&vfs_fat->fatfs, "/.Trashes"); + make_empty_file(&vfs_fat->fatfs, "/.feventsd/no_log"); + + // and ensure everything is flushed flash_flush(); } else if (res != FR_OK) { return; From 3bf4d69f67728e50cfc4c5ac50c5a66a7f4bd9e5 Mon Sep 17 00:00:00 2001 From: Scott Shawcroft Date: Thu, 22 Mar 2018 16:42:47 -0700 Subject: [PATCH 103/135] Update Metro M4 to rev F and make flash reset on start. --- .../boards/metro_m4_express/mpconfigboard.h | 6 ++-- .../atmel-samd/boards/metro_m4_express/pins.c | 23 ++++++++------- .../external_flash/common_commands.h | 3 ++ .../external_flash/external_flash.c | 29 +++++++++++++++++-- ports/atmel-samd/external_flash/qspi_flash.c | 9 ++++-- ports/atmel-samd/external_flash/spi_flash.c | 4 +++ .../atmel-samd/external_flash/spi_flash_api.h | 3 ++ 7 files changed, 58 insertions(+), 19 deletions(-) diff --git a/ports/atmel-samd/boards/metro_m4_express/mpconfigboard.h b/ports/atmel-samd/boards/metro_m4_express/mpconfigboard.h index b541af80c9..e2b7f9982e 100644 --- a/ports/atmel-samd/boards/metro_m4_express/mpconfigboard.h +++ b/ports/atmel-samd/boards/metro_m4_express/mpconfigboard.h @@ -3,18 +3,18 @@ #define CIRCUITPY_MCU_FAMILY samd51 -// This is for Rev D which is light blue +// This is for Rev F which is green #define MICROPY_HW_LED_TX PIN_PA27 #define MICROPY_HW_LED_RX PIN_PB06 -#define MICROPY_HW_NEOPIXEL (&pin_PB17) +#define MICROPY_HW_NEOPIXEL (&pin_PB22) // These are pins not to reset. // QSPI Data pins and TX LED #define MICROPY_PORT_A (PORT_PA08 | PORT_PA09 | PORT_PA10 | PORT_PA11 | PORT_PA27) // RX LED, QSPI CS, QSPI SCK and NeoPixel pin -#define MICROPY_PORT_B ( PORT_PB06 | PORT_PB10 | PORT_PB11 | PORT_PB17) +#define MICROPY_PORT_B ( PORT_PB06 | PORT_PB10 | PORT_PB11 | PORT_PB22) #define MICROPY_PORT_C (0) #define MICROPY_PORT_D (0) diff --git a/ports/atmel-samd/boards/metro_m4_express/pins.c b/ports/atmel-samd/boards/metro_m4_express/pins.c index 33b69b32b3..32ecdf4923 100644 --- a/ports/atmel-samd/boards/metro_m4_express/pins.c +++ b/ports/atmel-samd/boards/metro_m4_express/pins.c @@ -7,36 +7,37 @@ STATIC const mp_map_elem_t board_global_dict_table[] = { { MP_OBJ_NEW_QSTR(MP_QSTR_A0), (mp_obj_t)&pin_PA02 }, { MP_OBJ_NEW_QSTR(MP_QSTR_A1), (mp_obj_t)&pin_PA05 }, { MP_OBJ_NEW_QSTR(MP_QSTR_A2), (mp_obj_t)&pin_PA06 }, - { MP_OBJ_NEW_QSTR(MP_QSTR_A3), (mp_obj_t)&pin_PB09 }, + { MP_OBJ_NEW_QSTR(MP_QSTR_A3), (mp_obj_t)&pin_PA04 }, { MP_OBJ_NEW_QSTR(MP_QSTR_A4), (mp_obj_t)&pin_PB08 }, - { MP_OBJ_NEW_QSTR(MP_QSTR_A5), (mp_obj_t)&pin_PA07 }, - + { MP_OBJ_NEW_QSTR(MP_QSTR_A5), (mp_obj_t)&pin_PB09 }, { MP_OBJ_NEW_QSTR(MP_QSTR_D0), (mp_obj_t)&pin_PA23 }, { MP_OBJ_NEW_QSTR(MP_QSTR_RX), (mp_obj_t)&pin_PA23 }, { MP_OBJ_NEW_QSTR(MP_QSTR_D1), (mp_obj_t)&pin_PA22 }, { MP_OBJ_NEW_QSTR(MP_QSTR_TX), (mp_obj_t)&pin_PA22 }, - { MP_OBJ_NEW_QSTR(MP_QSTR_D2), (mp_obj_t)&pin_PA04 }, + { MP_OBJ_NEW_QSTR(MP_QSTR_D2), (mp_obj_t)&pin_PB17 }, { MP_OBJ_NEW_QSTR(MP_QSTR_D3), (mp_obj_t)&pin_PB16 }, { MP_OBJ_NEW_QSTR(MP_QSTR_D4), (mp_obj_t)&pin_PB13 }, { MP_OBJ_NEW_QSTR(MP_QSTR_D5), (mp_obj_t)&pin_PB14 }, { MP_OBJ_NEW_QSTR(MP_QSTR_D6), (mp_obj_t)&pin_PB15 }, - { MP_OBJ_NEW_QSTR(MP_QSTR_D7), (mp_obj_t)&pin_PA14 }, - { MP_OBJ_NEW_QSTR(MP_QSTR_D8), (mp_obj_t)&pin_PA16 }, - { MP_OBJ_NEW_QSTR(MP_QSTR_D9), (mp_obj_t)&pin_PA17 }, + { MP_OBJ_NEW_QSTR(MP_QSTR_D7), (mp_obj_t)&pin_PB12 }, + { MP_OBJ_NEW_QSTR(MP_QSTR_D8), (mp_obj_t)&pin_PA21 }, + { MP_OBJ_NEW_QSTR(MP_QSTR_D9), (mp_obj_t)&pin_PA20 }, { MP_OBJ_NEW_QSTR(MP_QSTR_D10), (mp_obj_t)&pin_PA18 }, { MP_OBJ_NEW_QSTR(MP_QSTR_D11), (mp_obj_t)&pin_PA19 }, - { MP_OBJ_NEW_QSTR(MP_QSTR_D12), (mp_obj_t)&pin_PA20 }, - { MP_OBJ_NEW_QSTR(MP_QSTR_D13), (mp_obj_t)&pin_PA21 }, + { MP_OBJ_NEW_QSTR(MP_QSTR_D12), (mp_obj_t)&pin_PA17 }, + { MP_OBJ_NEW_QSTR(MP_QSTR_D13), (mp_obj_t)&pin_PA16 }, { MP_OBJ_NEW_QSTR(MP_QSTR_SDA), (mp_obj_t)&pin_PB02 }, { MP_OBJ_NEW_QSTR(MP_QSTR_SCL), (mp_obj_t)&pin_PB03 }, - { MP_OBJ_NEW_QSTR(MP_QSTR_NEOPIXEL), (mp_obj_t)&pin_PB17 }, + { MP_OBJ_NEW_QSTR(MP_QSTR_AREF), (mp_obj_t)&pin_PA03 }, + + { MP_OBJ_NEW_QSTR(MP_QSTR_NEOPIXEL), (mp_obj_t)&pin_PB22 }, { MP_OBJ_NEW_QSTR(MP_QSTR_SCK), (mp_obj_t)&pin_PA13 }, { MP_OBJ_NEW_QSTR(MP_QSTR_MOSI), (mp_obj_t)&pin_PA12 }, - { MP_OBJ_NEW_QSTR(MP_QSTR_MISO), (mp_obj_t)&pin_PA15 }, + { MP_OBJ_NEW_QSTR(MP_QSTR_MISO), (mp_obj_t)&pin_PA14 }, { MP_OBJ_NEW_QSTR(MP_QSTR_LED_RX), (mp_obj_t)&pin_PB06 }, { MP_OBJ_NEW_QSTR(MP_QSTR_LED_TX), (mp_obj_t)&pin_PA27 }, diff --git a/ports/atmel-samd/external_flash/common_commands.h b/ports/atmel-samd/external_flash/common_commands.h index fc05e70de7..79178af9cb 100644 --- a/ports/atmel-samd/external_flash/common_commands.h +++ b/ports/atmel-samd/external_flash/common_commands.h @@ -35,7 +35,10 @@ #define CMD_PAGE_PROGRAM 0x02 // #define CMD_PAGE_PROGRAM CMD_READ_JEDEC_ID #define CMD_READ_STATUS 0x05 +#define CMD_READ_STATUS2 0x35 #define CMD_WRITE_STATUS_BYTE1 0x01 #define CMD_QUAD_READ 0x6b +#define CMD_ENABLE_RESET 0x66 +#define CMD_RESET 0x99 #endif // MICROPY_INCLUDED_ATMEL_SAMD_EXTERNAL_FLASH_COMMON_COMMANDS_H diff --git a/ports/atmel-samd/external_flash/external_flash.c b/ports/atmel-samd/external_flash/external_flash.c index 304bf6462b..315eb7506f 100644 --- a/ports/atmel-samd/external_flash/external_flash.c +++ b/ports/atmel-samd/external_flash/external_flash.c @@ -199,10 +199,15 @@ void external_flash_init(void) { spi_flash_init(); + // The response will be 0xff if the flash needs more time to start up. + uint8_t jedec_id_response[3] = {0xff, 0xff, 0xff}; + while (jedec_id_response[0] == 0xff) { + spi_flash_read_command(CMD_READ_JEDEC_ID, jedec_id_response, 3); + } + for (uint8_t i = 0; i < num_possible_devices; i++) { const external_flash_device* possible_device = &possible_devices[i]; - uint8_t jedec_id_response[3] = {0x00, 0x00, 0x00}; - spi_flash_read_command(CMD_READ_JEDEC_ID, jedec_id_response, 3); + if (jedec_id_response[0] == possible_device->manufacturer_id && jedec_id_response[1] == possible_device->memory_type && jedec_id_response[2] == possible_device->capacity) { @@ -215,6 +220,26 @@ void external_flash_init(void) { return; } + // We don't know what state the flash is in so wait for any remaining writes and then reset. + uint8_t read_status_response[1] = {0x00}; + // The write in progress bit should be low. + do { + spi_flash_read_command(CMD_READ_STATUS, read_status_response, 1); + } while ((read_status_response[0] & 0x1) != 0); + // The suspended write/erase bit should be low. + do { + spi_flash_read_command(CMD_READ_STATUS2, read_status_response, 1); + } while ((read_status_response[0] & 0x80) != 0); + + + spi_flash_command(CMD_ENABLE_RESET); + spi_flash_command(CMD_RESET); + + // Wait 30us for the reset + common_hal_mcu_delay_us(30); + + spi_flash_init_device(flash_device); + // Activity LED for flash writes. #ifdef MICROPY_HW_LED_MSC gpio_set_pin_function(SPI_FLASH_CS_PIN, GPIO_PIN_FUNCTION_OFF); diff --git a/ports/atmel-samd/external_flash/qspi_flash.c b/ports/atmel-samd/external_flash/qspi_flash.c index 46e3cb92a3..4ebe30a909 100644 --- a/ports/atmel-samd/external_flash/qspi_flash.c +++ b/ports/atmel-samd/external_flash/qspi_flash.c @@ -189,14 +189,17 @@ void spi_flash_init(void) { gpio_set_pin_pull_mode(pins[i], GPIO_PULL_OFF); gpio_set_pin_function(pins[i], GPIO_PIN_FUNCTION_H); } +} +void spi_flash_init_device(const external_flash_device* device) { // Verify that QSPI mode is enabled. uint8_t status; - spi_flash_read_command(0x35, &status, 1); + spi_flash_read_command(CMD_READ_STATUS2, &status, 1); + // Bit 1 is Quad Enable if ((status & 0x2) == 0) { - uint8_t full_status[3] = { 0, status | 0x2, 0x70}; + uint8_t full_status[2] = { 0x0, 0x2}; spi_flash_command(CMD_ENABLE_WRITE); - spi_flash_write_command(0x01, full_status, 3); + spi_flash_write_command(CMD_WRITE_STATUS_BYTE1, full_status, 2); } } diff --git a/ports/atmel-samd/external_flash/spi_flash.c b/ports/atmel-samd/external_flash/spi_flash.c index fcaedcaaca..8a8cbaef81 100644 --- a/ports/atmel-samd/external_flash/spi_flash.c +++ b/ports/atmel-samd/external_flash/spi_flash.c @@ -152,3 +152,7 @@ void spi_flash_init(void) { spi_m_sync_enable(&spi_flash_desc); } + +void spi_flash_init_device(const external_flash_device* device) { + +} diff --git a/ports/atmel-samd/external_flash/spi_flash_api.h b/ports/atmel-samd/external_flash/spi_flash_api.h index b858ff0ea0..a6df0c4595 100644 --- a/ports/atmel-samd/external_flash/spi_flash_api.h +++ b/ports/atmel-samd/external_flash/spi_flash_api.h @@ -29,6 +29,8 @@ #include #include +#include "external_flash/devices.h" + // This API is implemented for both normal SPI peripherals and QSPI peripherals. bool spi_flash_command(uint8_t command); @@ -38,5 +40,6 @@ bool spi_flash_sector_command(uint8_t command, uint32_t address); bool spi_flash_write_data(uint32_t address, uint8_t* data, uint32_t data_length); bool spi_flash_read_data(uint32_t address, uint8_t* data, uint32_t data_length); void spi_flash_init(void); +void spi_flash_init_device(const external_flash_device* device); #endif // MICROPY_INCLUDED_ATMEL_SAMD_SPI_FLASH_H From 06b4c83f59fc073e582e64f7fc09af88b4a87819 Mon Sep 17 00:00:00 2001 From: Scott Shawcroft Date: Thu, 22 Mar 2018 17:44:44 -0700 Subject: [PATCH 104/135] Add reminder to remove Saleae when going fast. --- ports/atmel-samd/external_flash/qspi_flash.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ports/atmel-samd/external_flash/qspi_flash.c b/ports/atmel-samd/external_flash/qspi_flash.c index 4ebe30a909..fc6c8dfea5 100644 --- a/ports/atmel-samd/external_flash/qspi_flash.c +++ b/ports/atmel-samd/external_flash/qspi_flash.c @@ -174,7 +174,7 @@ void spi_flash_init(void) { // Slow, good for debugging with Saleae // QSPI->BAUD.bit.BAUD = 32; - // Super fast + // Super fast, may be unreliable when Saleae is connected to high speed lines. QSPI->BAUD.bit.BAUD = 2; QSPI->CTRLB.reg = QSPI_CTRLB_MODE_MEMORY | QSPI_CTRLB_DATALEN_8BITS | From fd7dcff4e99868ab83a3dff4720519aa7ce3467d Mon Sep 17 00:00:00 2001 From: Scott Shawcroft Date: Fri, 23 Mar 2018 00:00:13 -0700 Subject: [PATCH 105/135] Add Feather M4 Express support. * Also fixed detection of SPI flash chip to correct look in the 2+ spots. * Added support for using QSPI in dual read mode. --- .travis.yml | 1 + .../boards/feather_m4_express/board.c | 38 +++++++++++++++++++ .../boards/feather_m4_express/mpconfigboard.h | 34 +++++++++++++++++ .../feather_m4_express/mpconfigboard.mk | 10 +++++ .../boards/feather_m4_express/pins.c | 30 +++++++++++++++ .../external_flash/common_commands.h | 1 + .../external_flash/external_flash.c | 6 +-- ports/atmel-samd/external_flash/qspi_flash.c | 7 ++++ tools/build_adafruit_bins.sh | 2 +- 9 files changed, 124 insertions(+), 5 deletions(-) create mode 100644 ports/atmel-samd/boards/feather_m4_express/board.c create mode 100644 ports/atmel-samd/boards/feather_m4_express/mpconfigboard.h create mode 100644 ports/atmel-samd/boards/feather_m4_express/mpconfigboard.mk create mode 100644 ports/atmel-samd/boards/feather_m4_express/pins.c diff --git a/.travis.yml b/.travis.yml index a698403339..efb4ec35ff 100644 --- a/.travis.yml +++ b/.travis.yml @@ -11,6 +11,7 @@ env: - TRAVIS_BOARD=feather_m0_rfm69 - TRAVIS_BOARD=feather_m0_rfm9x - TRAVIS_BOARD=feather_m0_express + - TRAVIS_BOARD=feather_m4_express - TRAVIS_BOARD=itsybitsy_m0_express - TRAVIS_BOARD=metro_m0_express - TRAVIS_BOARD=metro_m4_express diff --git a/ports/atmel-samd/boards/feather_m4_express/board.c b/ports/atmel-samd/boards/feather_m4_express/board.c new file mode 100644 index 0000000000..8096b9b8ea --- /dev/null +++ b/ports/atmel-samd/boards/feather_m4_express/board.c @@ -0,0 +1,38 @@ +/* + * This file is part of the MicroPython project, http://micropython.org/ + * + * The MIT License (MIT) + * + * Copyright (c) 2017 Scott Shawcroft for Adafruit Industries + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +#include "boards/board.h" +#include "mpconfigboard.h" + +void board_init(void) { +} + +bool board_requests_safe_mode(void) { + return false; +} + +void reset_board(void) { +} diff --git a/ports/atmel-samd/boards/feather_m4_express/mpconfigboard.h b/ports/atmel-samd/boards/feather_m4_express/mpconfigboard.h new file mode 100644 index 0000000000..bd56a7bdfa --- /dev/null +++ b/ports/atmel-samd/boards/feather_m4_express/mpconfigboard.h @@ -0,0 +1,34 @@ +#define MICROPY_HW_BOARD_NAME "Feather M4 Express" +#define MICROPY_HW_MCU_NAME "samd51j19" + +#define CIRCUITPY_MCU_FAMILY samd51 + +// This is for Rev C which is green + +#define MICROPY_HW_NEOPIXEL (&pin_PB23) + +// These are pins not to reset. +// QSPI Data pins and TX LED +#define MICROPY_PORT_A (PORT_PA08 | PORT_PA09) +// RX LED, QSPI CS, QSPI SCK and NeoPixel pin +#define MICROPY_PORT_B (PORT_PB10 | PORT_PB11 | PORT_PB23 ) +#define MICROPY_PORT_C (0) +#define MICROPY_PORT_D (0) + +#define AUTORESET_DELAY_MS 500 + +// If you change this, then make sure to update the linker scripts as well to +// make sure you don't overwrite code +// #define CIRCUITPY_INTERNAL_NVM_SIZE 256 +#define CIRCUITPY_INTERNAL_NVM_SIZE 0 + +#define BOARD_FLASH_SIZE (FLASH_SIZE - 0x4000 - CIRCUITPY_INTERNAL_NVM_SIZE) + +#include "external_flash/devices.h" + +#define EXTERNAL_FLASH_DEVICE_COUNT 2 +#define EXTERNAL_FLASH_DEVICES W25Q16FW, GD25Q16C + +#define EXTERNAL_FLASH_QSPI_DUAL + +#include "external_flash/external_flash.h" diff --git a/ports/atmel-samd/boards/feather_m4_express/mpconfigboard.mk b/ports/atmel-samd/boards/feather_m4_express/mpconfigboard.mk new file mode 100644 index 0000000000..550909ddab --- /dev/null +++ b/ports/atmel-samd/boards/feather_m4_express/mpconfigboard.mk @@ -0,0 +1,10 @@ +LD_FILE = boards/samd51x19-bootloader-external-flash.ld +USB_VID = 0x239A +USB_PID = 0x8021 +USB_PRODUCT = "Feather M4 Express" +USB_MANUFACTURER = "Adafruit Industries LLC" + +QSPI_FLASH_FILESYSTEM = 1 + +CHIP_VARIANT = SAMD51J19A +CHIP_FAMILY = samd51 diff --git a/ports/atmel-samd/boards/feather_m4_express/pins.c b/ports/atmel-samd/boards/feather_m4_express/pins.c new file mode 100644 index 0000000000..c161e736ed --- /dev/null +++ b/ports/atmel-samd/boards/feather_m4_express/pins.c @@ -0,0 +1,30 @@ +#include "samd21_pins.h" + +STATIC const mp_rom_map_elem_t board_global_dict_table[] = { + { MP_ROM_QSTR(MP_QSTR_A0), MP_ROM_PTR(&pin_PA02) }, + { MP_ROM_QSTR(MP_QSTR_A1), MP_ROM_PTR(&pin_PA05) }, + { MP_ROM_QSTR(MP_QSTR_A2), MP_ROM_PTR(&pin_PB08) }, + { MP_ROM_QSTR(MP_QSTR_A3), MP_ROM_PTR(&pin_PB09) }, + { MP_ROM_QSTR(MP_QSTR_A4), MP_ROM_PTR(&pin_PA06) }, + { MP_ROM_QSTR(MP_QSTR_A5), MP_ROM_PTR(&pin_PA10) }, + { MP_ROM_QSTR(MP_QSTR_AREF), MP_ROM_PTR(&pin_PA03) }, + + { MP_ROM_QSTR(MP_QSTR_SCK), MP_ROM_PTR(&pin_PA17) }, + { MP_ROM_QSTR(MP_QSTR_MOSI), MP_ROM_PTR(&pin_PA19) }, + { MP_ROM_QSTR(MP_QSTR_MISO), MP_ROM_PTR(&pin_PA18) }, + { MP_ROM_QSTR(MP_QSTR_D0), MP_ROM_PTR(&pin_PA07) }, + { MP_ROM_QSTR(MP_QSTR_RX), MP_ROM_PTR(&pin_PA07) }, + { MP_ROM_QSTR(MP_QSTR_D1), MP_ROM_PTR(&pin_PA04) }, + { MP_ROM_QSTR(MP_QSTR_TX), MP_ROM_PTR(&pin_PA04) }, + { MP_ROM_QSTR(MP_QSTR_SDA), MP_ROM_PTR(&pin_PA12) }, + { MP_ROM_QSTR(MP_QSTR_SCL), MP_ROM_PTR(&pin_PA13) }, + { MP_ROM_QSTR(MP_QSTR_D5), MP_ROM_PTR(&pin_PA14) }, + { MP_ROM_QSTR(MP_QSTR_D6), MP_ROM_PTR(&pin_PA15) }, + { MP_ROM_QSTR(MP_QSTR_D9), MP_ROM_PTR(&pin_PA16) }, + { MP_ROM_QSTR(MP_QSTR_D10), MP_ROM_PTR(&pin_PA20) }, + { MP_ROM_QSTR(MP_QSTR_D11), MP_ROM_PTR(&pin_PA21) }, + { MP_ROM_QSTR(MP_QSTR_D12), MP_ROM_PTR(&pin_PA22) }, + { MP_ROM_QSTR(MP_QSTR_D13), MP_ROM_PTR(&pin_PA23) }, + { MP_ROM_QSTR(MP_QSTR_NEOPIXEL), MP_ROM_PTR(&pin_PB23) }, +}; +MP_DEFINE_CONST_DICT(board_module_globals, board_global_dict_table); diff --git a/ports/atmel-samd/external_flash/common_commands.h b/ports/atmel-samd/external_flash/common_commands.h index 79178af9cb..bb2060708c 100644 --- a/ports/atmel-samd/external_flash/common_commands.h +++ b/ports/atmel-samd/external_flash/common_commands.h @@ -37,6 +37,7 @@ #define CMD_READ_STATUS 0x05 #define CMD_READ_STATUS2 0x35 #define CMD_WRITE_STATUS_BYTE1 0x01 +#define CMD_DUAL_READ 0x3b #define CMD_QUAD_READ 0x6b #define CMD_ENABLE_RESET 0x66 #define CMD_RESET 0x99 diff --git a/ports/atmel-samd/external_flash/external_flash.c b/ports/atmel-samd/external_flash/external_flash.c index 315eb7506f..ccc47e5b14 100644 --- a/ports/atmel-samd/external_flash/external_flash.c +++ b/ports/atmel-samd/external_flash/external_flash.c @@ -185,12 +185,11 @@ void external_flash_init(void) { if (flash_device != NULL) { return; } - uint8_t num_possible_devices = sizeof(*possible_devices) / sizeof(external_flash_device); // Delay to give the SPI Flash time to get going. // TODO(tannewt): Only do this when we know power was applied vs a reset. uint16_t max_start_up_delay_us = 0; - for (uint8_t i = 0; i < num_possible_devices; i++) { + for (uint8_t i = 0; i < EXTERNAL_FLASH_DEVICE_COUNT; i++) { if (possible_devices[i].start_up_time_us > max_start_up_delay_us) { max_start_up_delay_us = possible_devices[i].start_up_time_us; } @@ -205,9 +204,8 @@ void external_flash_init(void) { spi_flash_read_command(CMD_READ_JEDEC_ID, jedec_id_response, 3); } - for (uint8_t i = 0; i < num_possible_devices; i++) { + for (uint8_t i = 0; i < EXTERNAL_FLASH_DEVICE_COUNT; i++) { const external_flash_device* possible_device = &possible_devices[i]; - if (jedec_id_response[0] == possible_device->manufacturer_id && jedec_id_response[1] == possible_device->memory_type && jedec_id_response[2] == possible_device->capacity) { diff --git a/ports/atmel-samd/external_flash/qspi_flash.c b/ports/atmel-samd/external_flash/qspi_flash.c index fc6c8dfea5..f4d5ec9041 100644 --- a/ports/atmel-samd/external_flash/qspi_flash.c +++ b/ports/atmel-samd/external_flash/qspi_flash.c @@ -29,6 +29,8 @@ #include #include +#include "mpconfigboard.h" // for EXTERNAL_FLASH_QSPI_DUAL + #include "external_flash/common_commands.h" #include "shared_dma.h" @@ -139,8 +141,13 @@ bool spi_flash_write_data(uint32_t address, uint8_t* data, uint32_t length) { } bool spi_flash_read_data(uint32_t address, uint8_t* data, uint32_t length) { + #ifdef EXTERNAL_FLASH_QSPI_DUAL + QSPI->INSTRCTRL.bit.INSTR = CMD_DUAL_READ; + uint32_t mode = QSPI_INSTRFRAME_WIDTH_DUAL_OUTPUT; + #else QSPI->INSTRCTRL.bit.INSTR = CMD_QUAD_READ; uint32_t mode = QSPI_INSTRFRAME_WIDTH_QUAD_OUTPUT; + #endif QSPI->INSTRFRAME.reg = mode | QSPI_INSTRFRAME_ADDRLEN_24BITS | diff --git a/tools/build_adafruit_bins.sh b/tools/build_adafruit_bins.sh index 0bc3d45515..34fae9d853 100755 --- a/tools/build_adafruit_bins.sh +++ b/tools/build_adafruit_bins.sh @@ -2,7 +2,7 @@ rm -rf ports/atmel-samd/build* rm -rf ports/esp8266/build* rm -rf ports/nrf/build* -ATMEL_BOARDS="arduino_zero circuitplayground_express feather_m0_basic feather_m0_adalogger itsybitsy_m0_express feather_m0_rfm69 feather_m0_rfm9x feather_m0_express metro_m0_express metro_m4_express pirkey_m0 trinket_m0 gemma_m0 feather52" +ATMEL_BOARDS="arduino_zero circuitplayground_express feather_m0_basic feather_m0_adalogger itsybitsy_m0_express feather_m0_rfm69 feather_m0_rfm9x feather_m0_express feather_m4_express metro_m0_express metro_m4_express pirkey_m0 trinket_m0 gemma_m0 feather52" ROSIE_SETUPS="rosie-ci" PARALLEL="-j 5" From cdb83b18ece63b13d6796e315f0737f833c1ee16 Mon Sep 17 00:00:00 2001 From: Jeff Epler Date: Thu, 22 Mar 2018 21:52:25 -0500 Subject: [PATCH 106/135] Implement * and *= for array.array --- py/objarray.c | 33 +++++++++++++++++++++++++++++++++ tests/basics/array_mul.py | 28 ++++++++++++++++++++++++++++ 2 files changed, 61 insertions(+) create mode 100644 tests/basics/array_mul.py diff --git a/py/objarray.c b/py/objarray.c index a1a979b56f..eb053bd8a9 100644 --- a/py/objarray.c +++ b/py/objarray.c @@ -241,6 +241,39 @@ STATIC mp_obj_t array_unary_op(mp_unary_op_t op, mp_obj_t o_in) { STATIC mp_obj_t array_binary_op(mp_binary_op_t op, mp_obj_t lhs_in, mp_obj_t rhs_in) { mp_obj_array_t *lhs = MP_OBJ_TO_PTR(lhs_in); switch (op) { + case MP_BINARY_OP_MULTIPLY: + case MP_BINARY_OP_INPLACE_MULTIPLY: { + if (!MP_OBJ_IS_INT(rhs_in)) { + return MP_OBJ_NULL; // op not supported + } + mp_uint_t repeat = mp_obj_get_int(rhs_in); + bool inplace = (op == MP_BINARY_OP_INPLACE_MULTIPLY); + mp_buffer_info_t lhs_bufinfo; + array_get_buffer(lhs_in, &lhs_bufinfo, MP_BUFFER_READ); + mp_obj_array_t *res; + byte *ptr; + size_t orig_lhs_bufinfo_len = lhs_bufinfo.len; + if(inplace) { + res = lhs; + size_t item_sz = mp_binary_get_size('@', lhs->typecode, NULL); + lhs->items = m_renew(byte, lhs->items, (lhs->len + lhs->free) * item_sz, lhs->len * repeat * item_sz); + lhs->len = lhs->len * repeat; + lhs->free = 0; + if (!repeat) + return MP_OBJ_FROM_PTR(res); + repeat--; + ptr = (byte*)res->items + orig_lhs_bufinfo_len; + } else { + res = array_new(lhs_bufinfo.typecode, lhs->len * repeat); + ptr = (byte*)res->items; + } + if(orig_lhs_bufinfo_len) { + for(;repeat--; ptr += orig_lhs_bufinfo_len) { + memcpy(ptr, lhs_bufinfo.buf, orig_lhs_bufinfo_len); + } + } + return MP_OBJ_FROM_PTR(res); + } case MP_BINARY_OP_ADD: { // allow to add anything that has the buffer protocol (extension to CPython) mp_buffer_info_t lhs_bufinfo; diff --git a/tests/basics/array_mul.py b/tests/basics/array_mul.py new file mode 100644 index 0000000000..bb5f3aa6b1 --- /dev/null +++ b/tests/basics/array_mul.py @@ -0,0 +1,28 @@ +try: + import array +except ImportError: + print("SKIP") + raise SystemExit + +a1 = array.array('I', [1]) +a2 = array.array('I', [2]) * 2 +a3 = (a1 + a2) +print(a3) + +a3 *= 5 +print(a3) + +a3 *= 0 +print(a3) + +a4 = a2 * 0 +print(a4) + +a4 *= 0 +print(a4) + +a4 = a4 * 2 +print(a4) + +a4 *= 2 +print(a4) From fa55b15ac6a15be0c11123753760324547518a18 Mon Sep 17 00:00:00 2001 From: Ayke van Laethem Date: Tue, 19 Dec 2017 23:47:07 +0100 Subject: [PATCH 107/135] extmod/vfs_fat_file: Implement SEEK_CUR for non-zero offset. CPython doesn't allow SEEK_CUR with non-zero offset for files in text mode, and uPy inherited this behaviour for both text and binary files. It makes sense to provide full support for SEEK_CUR of binary-mode files in uPy, and to do this in a minimal way means also allowing to use SEEK_CUR with non-zero offsets on text-mode files. That seems to be a fair compromise. --- extmod/vfs_fat_file.c | 6 +----- tests/extmod/vfs_fat_fileio1.py | 6 ++---- tests/extmod/vfs_fat_fileio1.py.exp | 2 +- 3 files changed, 4 insertions(+), 10 deletions(-) diff --git a/extmod/vfs_fat_file.c b/extmod/vfs_fat_file.c index f580184a7c..be9c8c7921 100644 --- a/extmod/vfs_fat_file.c +++ b/extmod/vfs_fat_file.c @@ -125,11 +125,7 @@ STATIC mp_uint_t file_obj_ioctl(mp_obj_t o_in, mp_uint_t request, uintptr_t arg, break; case 1: // SEEK_CUR - if (s->offset != 0) { - *errcode = MP_EOPNOTSUPP; - return MP_STREAM_ERROR; - } - // no-operation + f_lseek(&self->fp, f_tell(&self->fp) + s->offset); break; case 2: // SEEK_END diff --git a/tests/extmod/vfs_fat_fileio1.py b/tests/extmod/vfs_fat_fileio1.py index d19df120b5..8b9ff92eb8 100644 --- a/tests/extmod/vfs_fat_fileio1.py +++ b/tests/extmod/vfs_fat_fileio1.py @@ -91,10 +91,8 @@ with open("foo_file.txt") as f2: f2.seek(0, 1) # SEEK_CUR print(f2.read(1)) - try: - f2.seek(1, 1) # SEEK_END - except OSError as e: - print(e.args[0] == uerrno.EOPNOTSUPP) + f2.seek(2, 1) # SEEK_CUR + print(f2.read(1)) f2.seek(-2, 2) # SEEK_END print(f2.read(1)) diff --git a/tests/extmod/vfs_fat_fileio1.py.exp b/tests/extmod/vfs_fat_fileio1.py.exp index d777585cf7..a66f07605c 100644 --- a/tests/extmod/vfs_fat_fileio1.py.exp +++ b/tests/extmod/vfs_fat_fileio1.py.exp @@ -7,7 +7,7 @@ hello!world! 12 h e -True +o d True [('foo_dir', 16384, 0)] From d434635822ed7d712c60b3c7a17b957bc09d919e Mon Sep 17 00:00:00 2001 From: sommersoft Date: Fri, 23 Mar 2018 15:07:02 +0000 Subject: [PATCH 108/135] add buffer check before triggering new usb read --- ports/atmel-samd/usb.c | 29 ++++++++++++++++++++--------- 1 file changed, 20 insertions(+), 9 deletions(-) diff --git a/ports/atmel-samd/usb.c b/ports/atmel-samd/usb.c index 740486aa1e..a90308564e 100644 --- a/ports/atmel-samd/usb.c +++ b/ports/atmel-samd/usb.c @@ -25,6 +25,7 @@ */ #include "usb.h" +#include #include @@ -49,6 +50,7 @@ #include "usb_mass_storage.h" #include "supervisor/shared/autoreload.h" +#include "supervisor/serial.h" // Store received characters on our own so that we can filter control characters // and act immediately on CTRL-C for example. @@ -126,7 +128,7 @@ static bool read_complete(const uint8_t ep, const enum usb_xfer_code rc, const u atomic_leave_critical(&flags); return true; } - + for (uint16_t i = 0; i < count; i++) { uint8_t c = cdc_packet_buffer[i]; if (c == mp_interrupt_char) { @@ -150,15 +152,15 @@ static bool read_complete(const uint8_t ep, const enum usb_xfer_code rc, const u } } atomic_leave_critical(&flags); - + // Trigger a follow up read if we have space. - if (usb_rx_count < USB_RX_BUF_SIZE) { + /*if (usb_rx_count < USB_RX_BUF_SIZE - 64) { int32_t result = start_read(); if (result != ERR_NONE) { return true; } - } - + }*/ + /* No error. */ return false; } @@ -170,7 +172,9 @@ static bool write_complete(const uint8_t ep, return false; // No errors. } // This is called after writes are finished. + usb_transmitting = false; + /* No error. */ return false; } @@ -243,9 +247,16 @@ static bool cdc_enabled(void) { } bool usb_bytes_available(void) { + // Check if the buffer has data, but not enough + // space to hold another read. + if (usb_rx_count > 64) { + return usb_rx_count > 0; + } + // Buffer has enough room if (cdc_enabled() && !pending_read) { start_read(); } + // Buffer is empty and/or no new data is available if (usb_rx_count == 0) { return false; } @@ -263,16 +274,16 @@ int usb_read(void) { data = usb_rx_buf[usb_rx_buf_head]; usb_rx_buf_head++; usb_rx_count--; - if ((USB_RX_BUF_SIZE) == usb_rx_buf_head) { + if (usb_rx_buf_head == USB_RX_BUF_SIZE) { usb_rx_buf_head = 0; } CRITICAL_SECTION_LEAVE(); // Trigger a new read because we just cleared some space. - if (!pending_read && usb_rx_count == USB_RX_BUF_SIZE - 1) { + /*if (!pending_read && usb_rx_count == USB_RX_BUF_SIZE - 1) { start_read(); - } - + }*/ + return data; } From ccbe557e3026f0cf53f2e9e40137552b2f0f08cd Mon Sep 17 00:00:00 2001 From: sommersoft Date: Fri, 23 Mar 2018 15:45:30 +0000 Subject: [PATCH 109/135] removed leftover debugging bits --- ports/atmel-samd/usb.c | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/ports/atmel-samd/usb.c b/ports/atmel-samd/usb.c index a90308564e..c95ec06b78 100644 --- a/ports/atmel-samd/usb.c +++ b/ports/atmel-samd/usb.c @@ -25,7 +25,6 @@ */ #include "usb.h" -#include #include @@ -50,7 +49,6 @@ #include "usb_mass_storage.h" #include "supervisor/shared/autoreload.h" -#include "supervisor/serial.h" // Store received characters on our own so that we can filter control characters // and act immediately on CTRL-C for example. @@ -128,7 +126,7 @@ static bool read_complete(const uint8_t ep, const enum usb_xfer_code rc, const u atomic_leave_critical(&flags); return true; } - + for (uint16_t i = 0; i < count; i++) { uint8_t c = cdc_packet_buffer[i]; if (c == mp_interrupt_char) { @@ -152,7 +150,7 @@ static bool read_complete(const uint8_t ep, const enum usb_xfer_code rc, const u } } atomic_leave_critical(&flags); - + // Trigger a follow up read if we have space. /*if (usb_rx_count < USB_RX_BUF_SIZE - 64) { int32_t result = start_read(); @@ -160,7 +158,7 @@ static bool read_complete(const uint8_t ep, const enum usb_xfer_code rc, const u return true; } }*/ - + /* No error. */ return false; } @@ -283,7 +281,7 @@ int usb_read(void) { /*if (!pending_read && usb_rx_count == USB_RX_BUF_SIZE - 1) { start_read(); }*/ - + return data; } From 63d826a52ae92fb57b2cc8b6934c55d4d4583e7c Mon Sep 17 00:00:00 2001 From: Scott Shawcroft Date: Fri, 23 Mar 2018 09:34:02 -0700 Subject: [PATCH 110/135] Update USB PID --- ports/atmel-samd/boards/feather_m4_express/mpconfigboard.mk | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ports/atmel-samd/boards/feather_m4_express/mpconfigboard.mk b/ports/atmel-samd/boards/feather_m4_express/mpconfigboard.mk index 550909ddab..61620ffa28 100644 --- a/ports/atmel-samd/boards/feather_m4_express/mpconfigboard.mk +++ b/ports/atmel-samd/boards/feather_m4_express/mpconfigboard.mk @@ -1,6 +1,6 @@ LD_FILE = boards/samd51x19-bootloader-external-flash.ld USB_VID = 0x239A -USB_PID = 0x8021 +USB_PID = 0x8026 USB_PRODUCT = "Feather M4 Express" USB_MANUFACTURER = "Adafruit Industries LLC" From f237657e5ebc592c2a8f37546c19a421ee5f37f8 Mon Sep 17 00:00:00 2001 From: sommersoft Date: Fri, 23 Mar 2018 18:41:27 +0000 Subject: [PATCH 111/135] extended buffer check to usb_cdc_background --- ports/atmel-samd/usb.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/ports/atmel-samd/usb.c b/ports/atmel-samd/usb.c index c95ec06b78..6148c56ae6 100644 --- a/ports/atmel-samd/usb.c +++ b/ports/atmel-samd/usb.c @@ -331,6 +331,9 @@ bool usb_connected(void) { void usb_cdc_background() { // if (mp_interrupt_char != -1 && cdc_enabled() && !pending_read) { - start_read(); + // Make sure we have space in the buffer + if (usb_rx_count < 64) { + start_read(); + } } } From ef16109c5dbde3136ae901b55525eb59f1d1fb4f Mon Sep 17 00:00:00 2001 From: sommersoft Date: Sat, 24 Mar 2018 00:55:48 +0000 Subject: [PATCH 112/135] updated with requested changes --- ports/atmel-samd/usb.c | 28 +++++++--------------------- 1 file changed, 7 insertions(+), 21 deletions(-) diff --git a/ports/atmel-samd/usb.c b/ports/atmel-samd/usb.c index 6148c56ae6..af70be99af 100644 --- a/ports/atmel-samd/usb.c +++ b/ports/atmel-samd/usb.c @@ -102,12 +102,13 @@ static void init_hardware(void) { #endif } -COMPILER_ALIGNED(4) uint8_t cdc_packet_buffer[64]; +#define CDC_BULKOUT_SIZE CONF_USB_COMPOSITE_CDC_ACM_DATA_BULKOUT_MAXPKSZ +COMPILER_ALIGNED(4) uint8_t cdc_packet_buffer[CDC_BULKOUT_SIZE]; static volatile bool pending_read; static int32_t start_read(void) { pending_read = true; - int32_t result = cdcdf_acm_read(cdc_packet_buffer, 64); + int32_t result = cdcdf_acm_read(cdc_packet_buffer, CDC_BULKOUT_SIZE); if (result != ERR_NONE) { pending_read = false; } @@ -151,14 +152,6 @@ static bool read_complete(const uint8_t ep, const enum usb_xfer_code rc, const u } atomic_leave_critical(&flags); - // Trigger a follow up read if we have space. - /*if (usb_rx_count < USB_RX_BUF_SIZE - 64) { - int32_t result = start_read(); - if (result != ERR_NONE) { - return true; - } - }*/ - /* No error. */ return false; } @@ -247,7 +240,7 @@ static bool cdc_enabled(void) { bool usb_bytes_available(void) { // Check if the buffer has data, but not enough // space to hold another read. - if (usb_rx_count > 64) { + if (usb_rx_count > CDC_BULKOUT_SIZE) { return usb_rx_count > 0; } // Buffer has enough room @@ -277,11 +270,6 @@ int usb_read(void) { } CRITICAL_SECTION_LEAVE(); - // Trigger a new read because we just cleared some space. - /*if (!pending_read && usb_rx_count == USB_RX_BUF_SIZE - 1) { - start_read(); - }*/ - return data; } @@ -328,12 +316,10 @@ bool usb_connected(void) { // Poll for input if keyboard interrupts are enabled, // so that we can check for the interrupt char. read_complete() does the checking. +// also make sure we have enough room in the local buffer void usb_cdc_background() { // - if (mp_interrupt_char != -1 && cdc_enabled() && !pending_read) { - // Make sure we have space in the buffer - if (usb_rx_count < 64) { - start_read(); - } + if (mp_interrupt_char != -1 && cdc_enabled() && !pending_read && usb_rx_count < CDC_BULKOUT_SIZE) { + start_read(); } } From d80e54458de4e4be494ed3d3d7664eacc5799319 Mon Sep 17 00:00:00 2001 From: Jeff Epler Date: Sat, 24 Mar 2018 10:44:24 -0500 Subject: [PATCH 113/135] correct typo in filename --- ports/atmel-samd/supervisor/filesystem.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ports/atmel-samd/supervisor/filesystem.c b/ports/atmel-samd/supervisor/filesystem.c index 90478ad16d..bff78a41c2 100644 --- a/ports/atmel-samd/supervisor/filesystem.c +++ b/ports/atmel-samd/supervisor/filesystem.c @@ -76,7 +76,7 @@ void filesystem_init(bool create_allowed) { f_mkdir(&vfs_fat->fatfs, "/.fseventsd"); make_empty_file(&vfs_fat->fatfs, "/.metadata_never_index"); make_empty_file(&vfs_fat->fatfs, "/.Trashes"); - make_empty_file(&vfs_fat->fatfs, "/.feventsd/no_log"); + make_empty_file(&vfs_fat->fatfs, "/.fseventsd/no_log"); // and ensure everything is flushed flash_flush(); From c0029e1d978650bc0ea712a8ab42b94a5179da68 Mon Sep 17 00:00:00 2001 From: Jeff Epler Date: Sun, 25 Mar 2018 12:57:43 -0500 Subject: [PATCH 114/135] Don't lose half of the processor's serial number Before this change, `microcontroller.cpu.uid` returned values where the top 4 bits of each byte were zero, because of an incorrect bitmask used in this function. --- ports/atmel-samd/common-hal/microcontroller/Processor.c | 2 +- ports/nrf/common-hal/microcontroller/Processor.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/ports/atmel-samd/common-hal/microcontroller/Processor.c b/ports/atmel-samd/common-hal/microcontroller/Processor.c index 1c57808f7d..5c0d72c96a 100644 --- a/ports/atmel-samd/common-hal/microcontroller/Processor.c +++ b/ports/atmel-samd/common-hal/microcontroller/Processor.c @@ -243,7 +243,7 @@ void common_hal_mcu_processor_get_uid(uint8_t raw_id[]) { for (int i=0; i<4; i++) { for (int k=0; k<4; k++) { - raw_id[4 * i + k] = (*(id_addresses[i]) >> k * 8) & 0xf; + raw_id[4 * i + k] = (*(id_addresses[i]) >> k * 8) & 0xff; } } } diff --git a/ports/nrf/common-hal/microcontroller/Processor.c b/ports/nrf/common-hal/microcontroller/Processor.c index cf808cdf4c..0cceb6a665 100644 --- a/ports/nrf/common-hal/microcontroller/Processor.c +++ b/ports/nrf/common-hal/microcontroller/Processor.c @@ -76,7 +76,7 @@ void common_hal_mcu_processor_get_uid(uint8_t raw_id[]) { for (int i=0; i<2; i++) { for (int k=0; k<4; k++) { - raw_id[4 * i + k] = (*(id_addresses[i]) >> k * 8) & 0xf; + raw_id[4 * i + k] = (*(id_addresses[i]) >> k * 8) & 0xff; } } } From 922b7c313197a28aa8243710d2d26f1034575674 Mon Sep 17 00:00:00 2001 From: Jeff Epler Date: Sun, 25 Mar 2018 14:25:04 -0500 Subject: [PATCH 115/135] Don't assume the type of the prop->proxy objects This fixes a crash running the cpydiff/core_class_superproperty.py test, but it does not fix the difference to cpython3. Closes: #705 --- py/gc_long_lived.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/py/gc_long_lived.c b/py/gc_long_lived.c index c50bbcd836..d34fde5d9b 100644 --- a/py/gc_long_lived.c +++ b/py/gc_long_lived.c @@ -78,9 +78,9 @@ mp_obj_property_t *make_property_long_lived(mp_obj_property_t *prop, uint8_t max if (max_depth == 0) { return prop; } - prop->proxy[0] = make_fun_bc_long_lived((mp_obj_fun_bc_t*) prop->proxy[0], max_depth - 1); - prop->proxy[1] = make_fun_bc_long_lived((mp_obj_fun_bc_t*) prop->proxy[1], max_depth - 1); - prop->proxy[2] = make_fun_bc_long_lived((mp_obj_fun_bc_t*) prop->proxy[2], max_depth - 1); + prop->proxy[0] = make_obj_long_lived((mp_obj_fun_bc_t*) prop->proxy[0], max_depth - 1); + prop->proxy[1] = make_obj_long_lived((mp_obj_fun_bc_t*) prop->proxy[1], max_depth - 1); + prop->proxy[2] = make_obj_long_lived((mp_obj_fun_bc_t*) prop->proxy[2], max_depth - 1); return gc_make_long_lived(prop); } From 74fefe45a4cc6073d16af32e0fe35e1fd389d558 Mon Sep 17 00:00:00 2001 From: Jeff Epler Date: Sun, 25 Mar 2018 14:25:32 -0500 Subject: [PATCH 116/135] super(): Do the same lookup tasks as regular getattr .. in the presence of properties and descriptors --- py/objtype.c | 30 +++++++++++++++++++++++++++--- 1 file changed, 27 insertions(+), 3 deletions(-) diff --git a/py/objtype.c b/py/objtype.c index 1d6dc0b6cd..7262892bd8 100644 --- a/py/objtype.c +++ b/py/objtype.c @@ -567,6 +567,7 @@ STATIC void mp_obj_instance_load_attr(mp_obj_t self_in, qstr attr, mp_obj_t *des mp_obj_class_lookup(&lookup, self->base.type); mp_obj_t member = dest[0]; if (member != MP_OBJ_NULL) { + // changes here may may require changes to super_attr, below #if MICROPY_PY_BUILTINS_PROPERTY if (MP_OBJ_IS_TYPE(member, &mp_type_property)) { // object member is a property; delegate the load to the property @@ -1112,14 +1113,37 @@ STATIC void super_attr(mp_obj_t self_in, qstr attr, mp_obj_t *dest) { assert(MP_OBJ_IS_TYPE(items[i], &mp_type_type)); mp_obj_class_lookup(&lookup, (mp_obj_type_t*)MP_OBJ_TO_PTR(items[i])); if (dest[0] != MP_OBJ_NULL) { - return; + break; } } } else { mp_obj_class_lookup(&lookup, type->parent); - if (dest[0] != MP_OBJ_NULL) { - return; + } + + if (dest[0] != MP_OBJ_NULL) { + mp_obj_t member = dest[0]; + // changes to mp_obj_instance_load_attr may require changes + // here... + #if MICROPY_PY_BUILTINS_PROPERTY + if (MP_OBJ_IS_TYPE(member, &mp_type_property)) { + const mp_obj_t *proxy = mp_obj_property_get(member); + if (proxy[0] == mp_const_none) { + mp_raise_AttributeError("unreadable attribute"); + } else { + dest[0] = mp_call_function_n_kw(proxy[0], 1, 0, &self_in); + } } + #endif + #if MICROPY_PY_DESCRIPTORS + mp_obj_t attr_get_method[4]; + mp_load_method_maybe(member, MP_QSTR___get__, attr_get_method); + if (attr_get_method[0] != MP_OBJ_NULL) { + attr_get_method[2] = self_in; + attr_get_method[3] = MP_OBJ_FROM_PTR(mp_obj_get_type(self_in)); + dest[0] = mp_call_method_n_kw(2, 0, attr_get_method); + } + #endif + return; } mp_obj_class_lookup(&lookup, &mp_type_object); From d57397f9c872225fd9bf5d97132d47b4187d1b59 Mon Sep 17 00:00:00 2001 From: Jeff Epler Date: Tue, 20 Mar 2018 07:57:27 -0500 Subject: [PATCH 117/135] Remove an unneeded -Wno-error=lto-type-mismtach --- ports/atmel-samd/Makefile | 1 - 1 file changed, 1 deletion(-) diff --git a/ports/atmel-samd/Makefile b/ports/atmel-samd/Makefile index 73799e5f28..1bcf9c3501 100644 --- a/ports/atmel-samd/Makefile +++ b/ports/atmel-samd/Makefile @@ -72,7 +72,6 @@ BASE_CFLAGS = \ -Wnested-externs \ -Wunreachable-code \ -Wcast-align \ - -Wno-error=lto-type-mismatch \ -D__$(CHIP_VARIANT)__ \ -ffunction-sections \ -fdata-sections \ From 23009fdd6343d9536ae644faca27be5a253aa08e Mon Sep 17 00:00:00 2001 From: sommersoft Date: Mon, 26 Mar 2018 06:25:04 +0000 Subject: [PATCH 118/135] future-proof for buffer size changes --- ports/atmel-samd/usb.c | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/ports/atmel-samd/usb.c b/ports/atmel-samd/usb.c index af70be99af..0d0a7a2932 100644 --- a/ports/atmel-samd/usb.c +++ b/ports/atmel-samd/usb.c @@ -222,17 +222,17 @@ void init_usb(void) { } static bool cdc_enabled(void) { - if (mp_cdc_enabled) { - return true; - } if (!cdcdf_acm_is_enabled()) { + mp_cdc_enabled = false; return false; } - cdcdf_acm_register_callback(CDCDF_ACM_CB_READ, (FUNC_PTR)read_complete); - cdcdf_acm_register_callback(CDCDF_ACM_CB_WRITE, (FUNC_PTR)write_complete); - cdcdf_acm_register_callback(CDCDF_ACM_CB_STATE_C, (FUNC_PTR)usb_device_cb_state_c); - cdcdf_acm_register_callback(CDCDF_ACM_CB_LINE_CODING_C, (FUNC_PTR)usb_device_cb_line_coding_c); - mp_cdc_enabled = true; + if (!mp_cdc_enabled) { + cdcdf_acm_register_callback(CDCDF_ACM_CB_READ, (FUNC_PTR)read_complete); + cdcdf_acm_register_callback(CDCDF_ACM_CB_WRITE, (FUNC_PTR)write_complete); + cdcdf_acm_register_callback(CDCDF_ACM_CB_STATE_C, (FUNC_PTR)usb_device_cb_state_c); + cdcdf_acm_register_callback(CDCDF_ACM_CB_LINE_CODING_C, (FUNC_PTR)usb_device_cb_line_coding_c); + mp_cdc_enabled = true; + } return true; } @@ -240,7 +240,7 @@ static bool cdc_enabled(void) { bool usb_bytes_available(void) { // Check if the buffer has data, but not enough // space to hold another read. - if (usb_rx_count > CDC_BULKOUT_SIZE) { + if (usb_rx_count > USB_RX_BUF_SIZE - CDC_BULKOUT_SIZE) { return usb_rx_count > 0; } // Buffer has enough room @@ -319,7 +319,7 @@ bool usb_connected(void) { // also make sure we have enough room in the local buffer void usb_cdc_background() { // - if (mp_interrupt_char != -1 && cdc_enabled() && !pending_read && usb_rx_count < CDC_BULKOUT_SIZE) { + if (mp_interrupt_char != -1 && cdc_enabled() && !pending_read && (usb_rx_count < USB_RX_BUF_SIZE - CDC_BULKOUT_SIZE)) { start_read(); } } From 9bd55cf4c7af0d75cd678d9c9b15601d5b7b768d Mon Sep 17 00:00:00 2001 From: sommersoft Date: Mon, 26 Mar 2018 08:14:37 -0500 Subject: [PATCH 119/135] minor cleanup --- ports/atmel-samd/usb.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ports/atmel-samd/usb.c b/ports/atmel-samd/usb.c index 0d0a7a2932..fd939e22df 100644 --- a/ports/atmel-samd/usb.c +++ b/ports/atmel-samd/usb.c @@ -241,7 +241,7 @@ bool usb_bytes_available(void) { // Check if the buffer has data, but not enough // space to hold another read. if (usb_rx_count > USB_RX_BUF_SIZE - CDC_BULKOUT_SIZE) { - return usb_rx_count > 0; + return true; } // Buffer has enough room if (cdc_enabled() && !pending_read) { From 37538fc0e771ab20b21e25bca7dfd72a2fd82f16 Mon Sep 17 00:00:00 2001 From: Scott Shawcroft Date: Mon, 26 Mar 2018 15:13:52 -0700 Subject: [PATCH 120/135] Fix I2C init hang when the SCL pin is pulled low. We added a check to make sure the pins are in a high state before initing the bus. This leads to a friendly error message when someone forgets to add the pull up resistors to their circuit. --- ports/atmel-samd/common-hal/busio/I2C.c | 19 +++++++++++++------ 1 file changed, 13 insertions(+), 6 deletions(-) diff --git a/ports/atmel-samd/common-hal/busio/I2C.c b/ports/atmel-samd/common-hal/busio/I2C.c index 4ac1f340c6..9fbe2101d0 100644 --- a/ports/atmel-samd/common-hal/busio/I2C.c +++ b/ports/atmel-samd/common-hal/busio/I2C.c @@ -72,6 +72,19 @@ void common_hal_busio_i2c_construct(busio_i2c_obj_t *self, mp_raise_ValueError("Invalid pins"); } + // Test that the pins are in a high state. (Hopefully indicating they are pulled up.) + gpio_set_pin_function(sda->pin, GPIO_PIN_FUNCTION_OFF); + gpio_set_pin_function(scl->pin, GPIO_PIN_FUNCTION_OFF); + gpio_set_pin_direction(sda->pin, GPIO_DIRECTION_IN); + gpio_set_pin_direction(scl->pin, GPIO_DIRECTION_IN); + gpio_set_pin_pull_mode(sda->pin, GPIO_PULL_OFF); + gpio_set_pin_pull_mode(scl->pin, GPIO_PULL_OFF); + + if (!gpio_get_pin_level(sda->pin) || !gpio_get_pin_level(scl->pin)) { + mp_raise_RuntimeError("SDA or SCL need a pull up"); + } + gpio_set_pin_function(sda->pin, sda_pinmux); + gpio_set_pin_function(scl->pin, scl_pinmux); // Set up I2C clocks on sercom. samd_peripherals_sercom_clock_init(sercom, sercom_index); @@ -80,12 +93,6 @@ void common_hal_busio_i2c_construct(busio_i2c_obj_t *self, mp_raise_OSError(MP_EIO); } - gpio_set_pin_pull_mode(sda->pin, GPIO_PULL_OFF); - gpio_set_pin_function(sda->pin, sda_pinmux); - - gpio_set_pin_pull_mode(scl->pin, GPIO_PULL_OFF); - gpio_set_pin_function(scl->pin, scl_pinmux); - // clkrate is always 0. baud_rate is in kHz. // Frequency must be set before the I2C device is enabled. From 25ba8ee489f5d17053ec625590d608a55020793a Mon Sep 17 00:00:00 2001 From: Scott Shawcroft Date: Mon, 26 Mar 2018 15:21:08 -0700 Subject: [PATCH 121/135] Add an s because grammar. --- ports/atmel-samd/common-hal/busio/I2C.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ports/atmel-samd/common-hal/busio/I2C.c b/ports/atmel-samd/common-hal/busio/I2C.c index 9fbe2101d0..c5cd5d8b53 100644 --- a/ports/atmel-samd/common-hal/busio/I2C.c +++ b/ports/atmel-samd/common-hal/busio/I2C.c @@ -81,7 +81,7 @@ void common_hal_busio_i2c_construct(busio_i2c_obj_t *self, gpio_set_pin_pull_mode(scl->pin, GPIO_PULL_OFF); if (!gpio_get_pin_level(sda->pin) || !gpio_get_pin_level(scl->pin)) { - mp_raise_RuntimeError("SDA or SCL need a pull up"); + mp_raise_RuntimeError("SDA or SCL needs a pull up"); } gpio_set_pin_function(sda->pin, sda_pinmux); gpio_set_pin_function(scl->pin, scl_pinmux); From 355bf8b5538b4fe2f9f07b0d8fb2f4500c2f96c6 Mon Sep 17 00:00:00 2001 From: Jeff Epler Date: Mon, 26 Mar 2018 18:13:49 -0500 Subject: [PATCH 122/135] Conditionally compile out nonstandard array/struct typecodes .. defaulting to off for circuitpython-supported boards, on for others. .. fixing up the tests that fail when it is turned off, so that they skip instead of failing --- ports/atmel-samd/mpconfigport.h | 1 + ports/esp8266/mpconfigport.h | 1 + ports/nrf/mpconfigport.h | 1 + py/binary.c | 16 +++++++++++++++- py/mpconfig.h | 6 ++++++ py/objarray.c | 2 ++ shared-module/struct/__init__.c | 2 ++ tests/basics/array_micropython.py | 6 ++++++ tests/basics/struct_micropython.py | 6 ++++++ 9 files changed, 40 insertions(+), 1 deletion(-) diff --git a/ports/atmel-samd/mpconfigport.h b/ports/atmel-samd/mpconfigport.h index 1ce44ac8af..a5884b6ad9 100644 --- a/ports/atmel-samd/mpconfigport.h +++ b/ports/atmel-samd/mpconfigport.h @@ -46,6 +46,7 @@ #define MICROPY_PY_BUILTINS_SLICE (1) #define MICROPY_PY_BUILTINS_SLICE_ATTRS (1) #define MICROPY_PY_ARRAY_SLICE_ASSIGN (1) +#define MICROPY_NONSTANDARD_TYPECODES (0) #define MICROPY_PY_BUILTINS_PROPERTY (1) #define MICROPY_PY_BUILTINS_MIN_MAX (1) #define MICROPY_PY___FILE__ (1) diff --git a/ports/esp8266/mpconfigport.h b/ports/esp8266/mpconfigport.h index cdf06450c6..8caecf7594 100644 --- a/ports/esp8266/mpconfigport.h +++ b/ports/esp8266/mpconfigport.h @@ -49,6 +49,7 @@ #define MICROPY_PY_GC (1) #define MICROPY_PY_ARRAY (1) #define MICROPY_PY_ARRAY_SLICE_ASSIGN (1) +#define MICROPY_NONSTANDARD_TYPECODES (0) #define MICROPY_PY_COLLECTIONS (1) #define MICROPY_PY_COLLECTIONS_ORDEREDDICT (1) #define MICROPY_PY_MATH (0) diff --git a/ports/nrf/mpconfigport.h b/ports/nrf/mpconfigport.h index 053a3bbab2..e806c201f1 100644 --- a/ports/nrf/mpconfigport.h +++ b/ports/nrf/mpconfigport.h @@ -99,6 +99,7 @@ #define MICROPY_PY_ALL_SPECIAL_METHODS (0) #define MICROPY_PY_MICROPYTHON_MEM_INFO (1) #define MICROPY_PY_ARRAY_SLICE_ASSIGN (0) +#define MICROPY_NONSTANDARD_TYPECODES (0) #define MICROPY_PY_BUILTINS_SLICE_ATTRS (0) #define MICROPY_PY_SYS_EXIT (1) #define MICROPY_PY_SYS_MAXSIZE (1) diff --git a/py/binary.c b/py/binary.c index 62cb384f18..bb334ed3db 100644 --- a/py/binary.c +++ b/py/binary.c @@ -57,8 +57,10 @@ size_t mp_binary_get_size(char struct_type, char val_type, mp_uint_t *palign) { size = 4; break; case 'q': case 'Q': size = 8; break; +#if MICROPY_NONSTANDARD_TYPECODES case 'P': case 'O': case 'S': size = sizeof(void*); break; +#endif case 'f': size = sizeof(float); break; case 'd': @@ -89,9 +91,11 @@ size_t mp_binary_get_size(char struct_type, char val_type, mp_uint_t *palign) { case 'q': case 'Q': align = alignof(long long); size = sizeof(long long); break; +#if MICROPY_NONSTANDARD_TYPECODES case 'P': case 'O': case 'S': align = alignof(void*); size = sizeof(void*); break; +#endif case 'f': align = alignof(float); size = sizeof(float); break; @@ -148,12 +152,14 @@ mp_obj_t mp_binary_get_val_array(char typecode, void *p, mp_uint_t index) { case 'd': return mp_obj_new_float(((double*)p)[index]); #endif +#if MICROPY_NONSTANDARD_TYPECODES // Extension to CPython: array of objects case 'O': return ((mp_obj_t*)p)[index]; // Extension to CPython: array of pointers case 'P': return mp_obj_new_int((mp_int_t)(uintptr_t)((void**)p)[index]); +#endif } return MP_OBJ_NEW_SMALL_INT(val); } @@ -202,11 +208,13 @@ mp_obj_t mp_binary_get_val(char struct_type, char val_type, byte **ptr) { long long val = mp_binary_get_int(size, is_signed(val_type), (struct_type == '>'), p); - if (val_type == 'O') { + if (MICROPY_NONSTANDARD_TYPECODES && (val_type == 'O')) { return (mp_obj_t)(mp_uint_t)val; +#if MICROPY_NONSTANDARD_TYPECODES } else if (val_type == 'S') { const char *s_val = (const char*)(uintptr_t)(mp_uint_t)val; return mp_obj_new_str(s_val, strlen(s_val), false); +#endif #if MICROPY_PY_BUILTINS_FLOAT } else if (val_type == 'f') { union { uint32_t i; float f; } fpu = {val}; @@ -267,9 +275,11 @@ void mp_binary_set_val(char struct_type, char val_type, mp_obj_t val_in, byte ** mp_uint_t val; switch (val_type) { +#if MICROPY_NONSTANDARD_TYPECODES case 'O': val = (mp_uint_t)val_in; break; +#endif #if MICROPY_PY_BUILTINS_FLOAT case 'f': { union { uint32_t i; float f; } fp_sp; @@ -324,10 +334,12 @@ void mp_binary_set_val_array(char typecode, void *p, mp_uint_t index, mp_obj_t v ((double*)p)[index] = mp_obj_get_float(val_in); break; #endif +#if MICROPY_NONSTANDARD_TYPECODES // Extension to CPython: array of objects case 'O': ((mp_obj_t*)p)[index] = val_in; break; +#endif default: #if MICROPY_LONGINT_IMPL != MICROPY_LONGINT_IMPL_NONE if (MP_OBJ_IS_TYPE(val_in, &mp_type_int)) { @@ -384,9 +396,11 @@ void mp_binary_set_val_array_from_int(char typecode, void *p, mp_uint_t index, m ((double*)p)[index] = val; break; #endif +#if MICROPY_NONSTANDARD_TYPECODES // Extension to CPython: array of pointers case 'P': ((void**)p)[index] = (void*)(uintptr_t)val; break; +#endif } } diff --git a/py/mpconfig.h b/py/mpconfig.h index 252ab7f371..765ae1e8f0 100644 --- a/py/mpconfig.h +++ b/py/mpconfig.h @@ -888,6 +888,12 @@ typedef double mp_float_t; #define MICROPY_PY_ARRAY_SLICE_ASSIGN (0) #endif +// Whether to support nonstandard typecodes "O", "P" and "S" +// in array and struct modules. +#ifndef MICROPY_NONSTANDARD_TYPECODES +#define MICROPY_NONSTANDARD_TYPECODES (1) +#endif + // Whether to support attrtuple type (MicroPython extension) // It provides space-efficient tuples with attribute access #ifndef MICROPY_PY_ATTRTUPLE diff --git a/py/objarray.c b/py/objarray.c index eb053bd8a9..c4c547e19f 100644 --- a/py/objarray.c +++ b/py/objarray.c @@ -470,9 +470,11 @@ STATIC mp_obj_t array_subscr(mp_obj_t self_in, mp_obj_t index_in, mp_obj_t value } else { mp_seq_replace_slice_no_grow(dest_items, o->len, slice.start, slice.stop, src_items, src_len, item_sz); +#if MICROPY_NONSTANDARD_TYPECODES // Clear "freed" elements at the end of list // TODO: This is actually only needed for typecode=='O' mp_seq_clear(dest_items, o->len + len_adj, o->len, item_sz); +#endif // TODO: alloc policy after shrinking } o->len += len_adj; diff --git a/shared-module/struct/__init__.c b/shared-module/struct/__init__.c index e944f77387..eac41c9c31 100644 --- a/shared-module/struct/__init__.c +++ b/shared-module/struct/__init__.c @@ -33,9 +33,11 @@ #include "py/parsenum.h" void struct_validate_format(char fmt) { +#if MICROPY_NONSTANDARD_TYPECODES if( fmt == 'S' || fmt == 'O') { mp_raise_RuntimeError("'S' and 'O' are not supported format types"); } +#endif } char get_fmt_type(const char **fmt) { diff --git a/tests/basics/array_micropython.py b/tests/basics/array_micropython.py index e26ad7ae96..b92c5a9b93 100644 --- a/tests/basics/array_micropython.py +++ b/tests/basics/array_micropython.py @@ -5,6 +5,12 @@ except ImportError: print("SKIP") raise SystemExit +try: + array.array('O') +except ValueError: + print("SKIP") + raise SystemExit + # arrays of objects a = array.array('O') a.append(1) diff --git a/tests/basics/struct_micropython.py b/tests/basics/struct_micropython.py index f203a4666f..e721530714 100644 --- a/tests/basics/struct_micropython.py +++ b/tests/basics/struct_micropython.py @@ -9,6 +9,12 @@ except: print("SKIP") raise SystemExit +try: + struct.pack('O', None) +except ValueError: + print("SKIP") + raise SystemExit + class A(): pass From cebcec5e63d594dda93917ffbecfde6d6fe5c5ca Mon Sep 17 00:00:00 2001 From: Scott Shawcroft Date: Mon, 26 Mar 2018 16:32:16 -0700 Subject: [PATCH 123/135] Check for floating pins by pulling them low briefly before testing their values. --- ports/atmel-samd/common-hal/busio/I2C.c | 18 +++++++++++++++++- 1 file changed, 17 insertions(+), 1 deletion(-) diff --git a/ports/atmel-samd/common-hal/busio/I2C.c b/ports/atmel-samd/common-hal/busio/I2C.c index c5cd5d8b53..77676b5355 100644 --- a/ports/atmel-samd/common-hal/busio/I2C.c +++ b/ports/atmel-samd/common-hal/busio/I2C.c @@ -34,6 +34,7 @@ #include "peripherals.h" #include "pins.h" +#include "shared-bindings/microcontroller/__init__.h" // Number of times to try to send packet if failed. @@ -77,10 +78,21 @@ void common_hal_busio_i2c_construct(busio_i2c_obj_t *self, gpio_set_pin_function(scl->pin, GPIO_PIN_FUNCTION_OFF); gpio_set_pin_direction(sda->pin, GPIO_DIRECTION_IN); gpio_set_pin_direction(scl->pin, GPIO_DIRECTION_IN); + + gpio_set_pin_pull_mode(sda->pin, GPIO_PULL_DOWN); + gpio_set_pin_pull_mode(scl->pin, GPIO_PULL_DOWN); + + common_hal_mcu_delay_us(10); + gpio_set_pin_pull_mode(sda->pin, GPIO_PULL_OFF); gpio_set_pin_pull_mode(scl->pin, GPIO_PULL_OFF); + // We must pull up within 3us to achieve 400khz. + common_hal_mcu_delay_us(3); + if (!gpio_get_pin_level(sda->pin) || !gpio_get_pin_level(scl->pin)) { + reset_pin(sda->pin); + reset_pin(scl->pin); mp_raise_RuntimeError("SDA or SCL needs a pull up"); } gpio_set_pin_function(sda->pin, sda_pinmux); @@ -90,13 +102,17 @@ void common_hal_busio_i2c_construct(busio_i2c_obj_t *self, samd_peripherals_sercom_clock_init(sercom, sercom_index); if (i2c_m_sync_init(&self->i2c_desc, sercom) != ERR_NONE) { - mp_raise_OSError(MP_EIO); + reset_pin(sda->pin); + reset_pin(scl->pin); + mp_raise_OSError(MP_EIO); } // clkrate is always 0. baud_rate is in kHz. // Frequency must be set before the I2C device is enabled. if (i2c_m_sync_set_baudrate(&self->i2c_desc, 0, frequency / 1000) != ERR_NONE) { + reset_pin(sda->pin); + reset_pin(scl->pin); mp_raise_ValueError("Unsupported baudrate"); } From 047a4f59c5acc6ab70bab177b33f0cef2972e8a1 Mon Sep 17 00:00:00 2001 From: Jeff Epler Date: Sun, 25 Mar 2018 14:30:59 -0500 Subject: [PATCH 124/135] This test now passes, make it run regularly --- tests/{cpydiff => basics}/core_class_superproperty.py | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) rename tests/{cpydiff => basics}/core_class_superproperty.py (50%) diff --git a/tests/cpydiff/core_class_superproperty.py b/tests/basics/core_class_superproperty.py similarity index 50% rename from tests/cpydiff/core_class_superproperty.py rename to tests/basics/core_class_superproperty.py index 1ec210550e..69db10046a 100644 --- a/tests/cpydiff/core_class_superproperty.py +++ b/tests/basics/core_class_superproperty.py @@ -1,8 +1,5 @@ """ -categories: Core,Classes -description: Calling super() getter property in subclass will return a property object, not the value -cause: Unknown -workaround: Unknown +test that calling super() getter property in subclass will return the value """ class A: @property From f4563d11d1669d20a43bfd31dc893cf455dc49f2 Mon Sep 17 00:00:00 2001 From: Scott Shawcroft Date: Tue, 27 Mar 2018 14:25:14 -0700 Subject: [PATCH 125/135] Add four missing drivers --- docs/drivers.rst | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/docs/drivers.rst b/docs/drivers.rst index 523316b096..951967e09e 100644 --- a/docs/drivers.rst +++ b/docs/drivers.rst @@ -76,6 +76,7 @@ Multi-color led drivers. NeoPixel DotStar + WS2801 Displays ------------- @@ -111,7 +112,7 @@ Motion relating sensing including ``acceleration``, ``magnetic``, ``gyro``, and .. toctree:: BNO055 Accelerometer, Magnetometer, Gyroscope and Absolution Orientation - FXAS21002C Gyroscope + FXAS21002C Gyroscope FXOS8700 Accelerometer GPS Global Position LIS3DH Accelerometer @@ -154,6 +155,7 @@ These sensors detect light related attributes such as ``color``, ``light`` (unit .. toctree:: APDS9960 Proximity, Light, RGB, and Gesture + AS726x Color Spectrum Sensor TCS34725 Color Sensor TSL2561 Light Sensor TSL2591 High Dynamic Range Light Sensor @@ -191,6 +193,7 @@ These provide functionality similar to `analogio`, `digitalio`, `pulseio`, and ` ADS1x15 Analog-to-Digital Converter DS2413 OneWire GPIO Expander FocalTech Capacitive Touch + MCP230xx GPIO Expander MCP4725 Digital-to-Analog Converter PCA9685 16 x 12-bit PWM Driver TLC5947 24 x 12-bit PWM Driver From 968763aa1d4ee5ed597d6f32b19fef6cbbed5c5c Mon Sep 17 00:00:00 2001 From: Jeff Epler Date: Tue, 27 Mar 2018 21:28:18 -0500 Subject: [PATCH 126/135] factor out storage_object_from_path --- shared-module/storage/__init__.c | 18 +++++++----------- 1 file changed, 7 insertions(+), 11 deletions(-) diff --git a/shared-module/storage/__init__.c b/shared-module/storage/__init__.c index 97a049bac6..3e7b90384a 100644 --- a/shared-module/storage/__init__.c +++ b/shared-module/storage/__init__.c @@ -109,19 +109,15 @@ void common_hal_storage_umount_object(mp_obj_t vfs_obj) { mp_vfs_proxy_call(vfs, MP_QSTR_umount, 0, NULL); } -void common_hal_storage_umount_path(const char* mount_path) { - // remove vfs from the mount table - mp_obj_t *vfs_obj = NULL; +STATIC mp_obj_t storage_object_from_path(const char* mount_path) { for (mp_vfs_mount_t **vfsp = &MP_STATE_VM(vfs_mount_table); *vfsp != NULL; vfsp = &(*vfsp)->next) { if (strcmp(mount_path, (*vfsp)->str) == 0) { - vfs_obj = (*vfsp)->obj; - break; + return (*vfsp)->obj; } } - - if (vfs_obj == NULL) { - mp_raise_OSError(MP_EINVAL); - } - - common_hal_storage_umount_object(vfs_obj); + mp_raise_OSError(MP_EINVAL); +} + +void common_hal_storage_umount_path(const char* mount_path) { + common_hal_storage_umount_object(storage_object_from_path(mount_path)); } From c08f5a3a0071dd1940a09c6b5f0bdd8e4768c7f0 Mon Sep 17 00:00:00 2001 From: Jeff Epler Date: Tue, 27 Mar 2018 21:28:18 -0500 Subject: [PATCH 127/135] Add storage.getmount to retrieve the mount object associated with a path --- shared-bindings/storage/__init__.c | 10 ++++++++++ shared-bindings/storage/__init__.h | 1 + shared-module/storage/__init__.c | 4 ++++ 3 files changed, 15 insertions(+) diff --git a/shared-bindings/storage/__init__.c b/shared-bindings/storage/__init__.c index 6f6a30da6d..837017ef9e 100644 --- a/shared-bindings/storage/__init__.c +++ b/shared-bindings/storage/__init__.c @@ -122,12 +122,22 @@ mp_obj_t storage_remount(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_a } MP_DEFINE_CONST_FUN_OBJ_KW(storage_remount_obj, 1, storage_remount); +//| .. function:: getmount(mount_path) +//| +//| Retrieves the mount object associated with the mount path +//| +mp_obj_t storage_getmount(const mp_obj_t mnt_in) { + return common_hal_storage_getmount(mp_obj_str_get_str(mnt_in)); +} +MP_DEFINE_CONST_FUN_OBJ_1(storage_getmount_obj, storage_getmount); + STATIC const mp_rom_map_elem_t storage_module_globals_table[] = { { MP_ROM_QSTR(MP_QSTR___name__), MP_ROM_QSTR(MP_QSTR_storage) }, { MP_ROM_QSTR(MP_QSTR_mount), MP_ROM_PTR(&storage_mount_obj) }, { MP_ROM_QSTR(MP_QSTR_umount), MP_ROM_PTR(&storage_umount_obj) }, { MP_ROM_QSTR(MP_QSTR_remount), MP_ROM_PTR(&storage_remount_obj) }, + { MP_ROM_QSTR(MP_QSTR_getmount), MP_ROM_PTR(&storage_getmount_obj) }, //| .. class:: VfsFat(block_device) //| diff --git a/shared-bindings/storage/__init__.h b/shared-bindings/storage/__init__.h index 574b5ff8dd..76b9ae854f 100644 --- a/shared-bindings/storage/__init__.h +++ b/shared-bindings/storage/__init__.h @@ -34,5 +34,6 @@ void common_hal_storage_mount(mp_obj_t vfs_obj, const char* path, bool readonly) void common_hal_storage_umount_path(const char* path); void common_hal_storage_umount_object(mp_obj_t vfs_obj); void common_hal_storage_remount(const char* path, bool readonly); +mp_obj_t common_hal_storage_getmount(const char* path); #endif // MICROPY_INCLUDED_SHARED_BINDINGS_STORAGE___INIT___H diff --git a/shared-module/storage/__init__.c b/shared-module/storage/__init__.c index 3e7b90384a..5b0bbe01ec 100644 --- a/shared-module/storage/__init__.c +++ b/shared-module/storage/__init__.c @@ -121,3 +121,7 @@ STATIC mp_obj_t storage_object_from_path(const char* mount_path) { void common_hal_storage_umount_path(const char* mount_path) { common_hal_storage_umount_object(storage_object_from_path(mount_path)); } + +mp_obj_t common_hal_storage_getmount(const char *mount_path) { + return storage_object_from_path(mount_path); +} From fe7f405fc7708cdbe426e2f255b01a1a77e574d9 Mon Sep 17 00:00:00 2001 From: Jeff Epler Date: Tue, 27 Mar 2018 21:28:18 -0500 Subject: [PATCH 128/135] Add VfsFat.label property These allow accessing the filesystem label. For instance, in boot.py, you can set the label on the built-in storage with: storage.remount('/', False) storage.getmount('/').label = "NEWLABEL" storage.remount('/', True) Users with multiple CIRCUITPY boards may find it desirable to choose a different label for each board they own. --- extmod/vfs_fat.c | 34 +++++++++++++++++++++++++++++ ports/unix/mpconfigport_coverage.h | 1 + tests/extmod/vfs_fat_ramdisk.py | 2 ++ tests/extmod/vfs_fat_ramdisk.py.exp | 1 + 4 files changed, 38 insertions(+) diff --git a/extmod/vfs_fat.c b/extmod/vfs_fat.c index 22346bdf1d..66d3136ebb 100644 --- a/extmod/vfs_fat.c +++ b/extmod/vfs_fat.c @@ -33,6 +33,7 @@ #endif #include +#include "py/objproperty.h" #include "py/runtime.h" #include "py/mperrno.h" #include "lib/oofatfs/ff.h" @@ -317,6 +318,36 @@ STATIC mp_obj_t vfs_fat_umount(mp_obj_t self_in) { } STATIC MP_DEFINE_CONST_FUN_OBJ_1(fat_vfs_umount_obj, vfs_fat_umount); +#if MICROPY_FATFS_USE_LABEL +STATIC mp_obj_t vfs_fat_getlabel(mp_obj_t self_in) { + fs_user_mount_t *self = MP_OBJ_TO_PTR(self_in); + char working_buf[12]; + FRESULT res = f_getlabel(&self->fatfs, working_buf, NULL); + if (res != FR_OK) { + mp_raise_OSError(fresult_to_errno_table[res]); + } + return mp_obj_new_str(working_buf, strlen(working_buf), false); +} +STATIC MP_DEFINE_CONST_FUN_OBJ_1(fat_vfs_getlabel_obj, vfs_fat_getlabel); + +static mp_obj_t vfs_fat_setlabel(mp_obj_t self_in, mp_obj_t label_in) { + fs_user_mount_t *self = MP_OBJ_TO_PTR(self_in); + const char *label_str = mp_obj_str_get_str(label_in); + FRESULT res = f_setlabel(&self->fatfs, label_str); + if (res != FR_OK) { + mp_raise_OSError(fresult_to_errno_table[res]); + } + return mp_const_none; +} +STATIC MP_DEFINE_CONST_FUN_OBJ_2(fat_vfs_setlabel_obj, vfs_fat_setlabel); +STATIC const mp_obj_property_t fat_vfs_label_obj = { + .base.type = &mp_type_property, + .proxy = {(mp_obj_t)&fat_vfs_getlabel_obj, + (mp_obj_t)&fat_vfs_setlabel_obj, + (mp_obj_t)&mp_const_none_obj}, +}; +#endif + STATIC const mp_rom_map_elem_t fat_vfs_locals_dict_table[] = { { MP_ROM_QSTR(MP_QSTR_mkfs), MP_ROM_PTR(&fat_vfs_mkfs_obj) }, { MP_ROM_QSTR(MP_QSTR_open), MP_ROM_PTR(&fat_vfs_open_obj) }, @@ -331,6 +362,9 @@ STATIC const mp_rom_map_elem_t fat_vfs_locals_dict_table[] = { { MP_ROM_QSTR(MP_QSTR_statvfs), MP_ROM_PTR(&fat_vfs_statvfs_obj) }, { MP_ROM_QSTR(MP_QSTR_mount), MP_ROM_PTR(&vfs_fat_mount_obj) }, { MP_ROM_QSTR(MP_QSTR_umount), MP_ROM_PTR(&fat_vfs_umount_obj) }, +#if MICROPY_FATFS_USE_LABEL + { MP_ROM_QSTR(MP_QSTR_label), MP_ROM_PTR(&fat_vfs_label_obj) }, +#endif }; STATIC MP_DEFINE_CONST_DICT(fat_vfs_locals_dict, fat_vfs_locals_dict_table); diff --git a/ports/unix/mpconfigport_coverage.h b/ports/unix/mpconfigport_coverage.h index 367b4853af..86d95eb39b 100644 --- a/ports/unix/mpconfigport_coverage.h +++ b/ports/unix/mpconfigport_coverage.h @@ -43,4 +43,5 @@ #define MICROPY_PY_IO_BUFFEREDWRITER (1) #undef MICROPY_VFS_FAT #define MICROPY_VFS_FAT (1) +#define MICROPY_FATFS_USE_LABEL (1) #define MICROPY_PY_FRAMEBUF (1) diff --git a/tests/extmod/vfs_fat_ramdisk.py b/tests/extmod/vfs_fat_ramdisk.py index 801c697862..896641ab3b 100644 --- a/tests/extmod/vfs_fat_ramdisk.py +++ b/tests/extmod/vfs_fat_ramdisk.py @@ -54,6 +54,8 @@ print(b"hello!" not in bdev.data) vfs = uos.VfsFat(bdev) uos.mount(vfs, "/ramdisk") +vfs.label = 'label test' +print("label:", vfs.label) print("statvfs:", vfs.statvfs("/ramdisk")) print("getcwd:", vfs.getcwd()) diff --git a/tests/extmod/vfs_fat_ramdisk.py.exp b/tests/extmod/vfs_fat_ramdisk.py.exp index ccd0f7134c..a3c3470a94 100644 --- a/tests/extmod/vfs_fat_ramdisk.py.exp +++ b/tests/extmod/vfs_fat_ramdisk.py.exp @@ -1,5 +1,6 @@ True True +label: LABEL TEST statvfs: (512, 512, 16, 16, 16, 0, 0, 0, 0, 255) getcwd: / True From 9c47fd9c13b4d5a35d28c4c9eca8f1644cb882da Mon Sep 17 00:00:00 2001 From: Jeff Epler Date: Tue, 27 Mar 2018 21:28:19 -0500 Subject: [PATCH 129/135] Specifically give a better error message for setlabel on RO fs --- extmod/vfs_fat.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/extmod/vfs_fat.c b/extmod/vfs_fat.c index 66d3136ebb..81ca1e23dc 100644 --- a/extmod/vfs_fat.c +++ b/extmod/vfs_fat.c @@ -335,6 +335,9 @@ static mp_obj_t vfs_fat_setlabel(mp_obj_t self_in, mp_obj_t label_in) { const char *label_str = mp_obj_str_get_str(label_in); FRESULT res = f_setlabel(&self->fatfs, label_str); if (res != FR_OK) { + if(res == FR_WRITE_PROTECTED) { + mp_raise_msg(&mp_type_OSError, "Read-only filesystem"); + } mp_raise_OSError(fresult_to_errno_table[res]); } return mp_const_none; From 34f5498760452e30cb9b76e43f5ec65f36936376 Mon Sep 17 00:00:00 2001 From: Jeff Epler Date: Tue, 27 Mar 2018 21:28:19 -0500 Subject: [PATCH 130/135] Document storage.VfsFat more thoroughly --- shared-bindings/storage/__init__.c | 43 ++++++++++++++++++++++++++++++ 1 file changed, 43 insertions(+) diff --git a/shared-bindings/storage/__init__.c b/shared-bindings/storage/__init__.c index 837017ef9e..734cabcc1c 100644 --- a/shared-bindings/storage/__init__.c +++ b/shared-bindings/storage/__init__.c @@ -145,6 +145,49 @@ STATIC const mp_rom_map_elem_t storage_module_globals_table[] = { //| //| :param block_device: Block device the the filesystem lives on //| + //| .. attribute:: label + //| + //| The filesystem label, up to 11 case-insensitive bytes. Note that + //| this property can only be set when the device is writable by the + //| microcontroller. + //| + //| .. method:: mkfs + //| + //| Format the block device, deleting any data that may have been there + //| + //| .. method:: open(path, mode) + //| + //| Like builtin ``open()`` + //| + //| .. method:: ilistdir([path]) + //| + //| Return an iterator whose values describe files and folders within + //| ``path`` + //| + //| .. method:: mkdir(path) + //| + //| Like `os.mkdir` + //| + //| .. method:: rmdir(path) + //| + //| Like `os.rmdir` + //| + //| .. method:: stat(path) + //| + //| Like `os.stat` + //| + //| .. method:: statvfs(path) + //| + //| Like `os.statvfs` + //| + //| .. method:: mount(readonly, mkfs) + //| + //| Don't call this directly, call `storage.mount`. + //| + //| .. method:: umount + //| + //| Don't call this directly, call `storage.umount`. + //| { MP_ROM_QSTR(MP_QSTR_VfsFat), MP_ROM_PTR(&mp_fat_vfs_type) }, }; From abec199c19fdbd9705bd803cd9b8b2910c21bd3a Mon Sep 17 00:00:00 2001 From: Jeff Epler Date: Mon, 26 Mar 2018 07:31:13 -0500 Subject: [PATCH 131/135] Enable high-quality float hash This appears to have a relatively small impact on flash usage but fixes some pathological slow behavior putting floats in dicts or sets. Closes: #704 --- ports/atmel-samd/mpconfigport.h | 1 + ports/esp8266/mpconfigport.h | 1 + ports/nrf/mpconfigport.h | 1 + 3 files changed, 3 insertions(+) diff --git a/ports/atmel-samd/mpconfigport.h b/ports/atmel-samd/mpconfigport.h index a5884b6ad9..de8703943d 100644 --- a/ports/atmel-samd/mpconfigport.h +++ b/ports/atmel-samd/mpconfigport.h @@ -64,6 +64,7 @@ #define MICROPY_PY_SYS (1) #define MICROPY_PY_SYS_MAXSIZE (1) #define MICROPY_FLOAT_IMPL (MICROPY_FLOAT_IMPL_FLOAT) +#define MICROPY_FLOAT_HIGH_QUALITY_HASH (1) #define MICROPY_STREAMS_NON_BLOCK (1) // fatfs configuration used in ffconf.h diff --git a/ports/esp8266/mpconfigport.h b/ports/esp8266/mpconfigport.h index 8caecf7594..616e9875c1 100644 --- a/ports/esp8266/mpconfigport.h +++ b/ports/esp8266/mpconfigport.h @@ -91,6 +91,7 @@ #define MICROPY_CPYTHON_COMPAT (0) #define MICROPY_LONGINT_IMPL (MICROPY_LONGINT_IMPL_MPZ) #define MICROPY_FLOAT_IMPL (MICROPY_FLOAT_IMPL_FLOAT) +#define MICROPY_FLOAT_HIGH_QUALITY_HASH (1) #define MICROPY_ERROR_REPORTING (MICROPY_ERROR_REPORTING_NORMAL) #define MICROPY_WARNINGS (1) #define MICROPY_PY_STR_BYTES_CMP_WARN (1) diff --git a/ports/nrf/mpconfigport.h b/ports/nrf/mpconfigport.h index e806c201f1..45c82439b3 100644 --- a/ports/nrf/mpconfigport.h +++ b/ports/nrf/mpconfigport.h @@ -47,6 +47,7 @@ //CP UPDATE: See mpconfigport.h for LONGINT implementation #define MICROPY_LONGINT_IMPL (MICROPY_LONGINT_IMPL_MPZ) #define MICROPY_FLOAT_IMPL (MICROPY_FLOAT_IMPL_FLOAT) +#define MICROPY_FLOAT_HIGH_QUALITY_HASH (1) #define MICROPY_OPT_COMPUTED_GOTO (0) #define MICROPY_OPT_CACHE_MAP_LOOKUP_IN_BYTECODE (0) From 19b0b414e6091f75991be178f0ff2accd6e11124 Mon Sep 17 00:00:00 2001 From: Scott Shawcroft Date: Wed, 28 Mar 2018 13:49:14 -0700 Subject: [PATCH 132/135] Remove freetouch files that were accidentally checked in and readd the submodule. --- .gitmodules | 6 +- ports/atmel-samd/freetouch | 1 + .../freetouch/Adafruit_FreeTouch.cpp | 280 -------------- .../atmel-samd/freetouch/Adafruit_FreeTouch.h | 37 -- ports/atmel-samd/freetouch/README.md | 2 - ports/atmel-samd/freetouch/adafruit_ptc.c | 148 -------- ports/atmel-samd/freetouch/adafruit_ptc.h | 109 ------ .../examples/freetouch/freetouch.ino | 56 --- .../freetouch/samd21_ptc_component.h | 350 ------------------ 9 files changed, 4 insertions(+), 985 deletions(-) create mode 160000 ports/atmel-samd/freetouch delete mode 100644 ports/atmel-samd/freetouch/Adafruit_FreeTouch.cpp delete mode 100644 ports/atmel-samd/freetouch/Adafruit_FreeTouch.h delete mode 100644 ports/atmel-samd/freetouch/README.md delete mode 100644 ports/atmel-samd/freetouch/adafruit_ptc.c delete mode 100644 ports/atmel-samd/freetouch/adafruit_ptc.h delete mode 100644 ports/atmel-samd/freetouch/examples/freetouch/freetouch.ino delete mode 100644 ports/atmel-samd/freetouch/samd21_ptc_component.h diff --git a/.gitmodules b/.gitmodules index a7f31837a3..ec0b01e337 100644 --- a/.gitmodules +++ b/.gitmodules @@ -33,9 +33,6 @@ path = lib/stm32lib url = https://github.com/micropython/stm32lib branch = work-F4-1.13.1+F7-1.5.0+L4-1.3.0 -[submodule "freetouch2"] - path = ports/atmel-samd/freetouch - url = https://github.com/adafruit/Adafruit_FreeTouch.git [submodule "atmel-samd/asf4"] path = ports/atmel-samd/asf4 url = https://github.com/adafruit/asf4.git @@ -46,3 +43,6 @@ [submodule "lib/nrfutil"] path = lib/nrfutil url = https://github.com/adafruit/nRF52_nrfutil +[submodule "ports/atmel-samd/freetouch"] + path = ports/atmel-samd/freetouch + url = https://github.com/adafruit/Adafruit_FreeTouch.git diff --git a/ports/atmel-samd/freetouch b/ports/atmel-samd/freetouch new file mode 160000 index 0000000000..c3deba11eb --- /dev/null +++ b/ports/atmel-samd/freetouch @@ -0,0 +1 @@ +Subproject commit c3deba11eb4be397ec719cfbfba1abcaecda2c08 diff --git a/ports/atmel-samd/freetouch/Adafruit_FreeTouch.cpp b/ports/atmel-samd/freetouch/Adafruit_FreeTouch.cpp deleted file mode 100644 index 45cac38674..0000000000 --- a/ports/atmel-samd/freetouch/Adafruit_FreeTouch.cpp +++ /dev/null @@ -1,280 +0,0 @@ -/* - * FreeTouch, a QTouch-compatible library - tested on ATSAMD21 only! - * The MIT License (MIT) - * - * Copyright (c) 2017 Limor 'ladyada' Fried for Adafruit Industries - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ - -#include "Adafruit_FreeTouch.h" - -#include "adafruit_ptc.h" - -Adafruit_FreeTouch::Adafruit_FreeTouch(int p, oversample_t f, series_resistor_t r, freq_mode_t fh) { - adafruit_ptc_get_config_default(&config); - pin = p; - uint8_t port_offset = 0; - if (g_APinDescription[pin].ulPort == PORTB) { - port_offset += 32; - } - config.pin = port_offset + g_APinDescription[pin].ulPin; - config.yline = getYLine(); // determine the Y0-15 # - config.oversample = f; - config.seriesres = r; - config.freqhop = fh; -} - -bool Adafruit_FreeTouch::begin(void) { - if (config.yline == -1) { // not all pins have Y line - return false; - } - - /* Setup and enable generic clock source for PTC module. - struct system_gclk_chan_config gclk_chan_conf; - system_gclk_chan_get_config_defaults(&gclk_chan_conf); - */ - - uint8_t channel = PTC_GCLK_ID; - uint8_t source_generator = 1; - - // original line: system_gclk_chan_set_config(PTC_GCLK_ID, &gclk_chan_conf); - uint32_t new_clkctrl_config = (channel << GCLK_CLKCTRL_ID_Pos); // from gclk.c - - // original line: gclk_chan_conf.source_generator = GCLK_GENERATOR_1; - /* Select the desired generic clock generator */ - new_clkctrl_config |= source_generator << GCLK_CLKCTRL_GEN_Pos; // from gclk.c - - /* Disable generic clock channel */ - // original line: system_gclk_chan_disable(channel); - noInterrupts(); - - /* Select the requested generator channel */ - *((uint8_t*)&GCLK->CLKCTRL.reg) = channel; - - /* Sanity check WRTLOCK */ - //Assert(!GCLK->CLKCTRL.bit.WRTLOCK); - - /* Switch to known-working source so that the channel can be disabled */ - uint32_t prev_gen_id = GCLK->CLKCTRL.bit.GEN; - GCLK->CLKCTRL.bit.GEN = 0; - - /* Disable the generic clock */ - GCLK->CLKCTRL.reg &= ~GCLK_CLKCTRL_CLKEN; - while (GCLK->CLKCTRL.reg & GCLK_CLKCTRL_CLKEN) { - /* Wait for clock to become disabled */ - } - - /* Restore previous configured clock generator */ - GCLK->CLKCTRL.bit.GEN = prev_gen_id; - - //system_interrupt_leave_critical_section(); - interrupts(); - - /* Write the new configuration */ - GCLK->CLKCTRL.reg = new_clkctrl_config; - - // original line: system_gclk_chan_enable(PTC_GCLK_ID); - *((uint8_t*)&GCLK->CLKCTRL.reg) = channel; - GCLK->CLKCTRL.reg |= GCLK_CLKCTRL_CLKEN; /* Enable the generic clock */ - - - // original line: system_apb_clock_set_mask(SYSTEM_CLOCK_APB_APBC, PM_APBCMASK_PTC); - PM->APBCMASK.reg |= PM_APBCMASK_PTC; - - adafruit_ptc_init(PTC, &config); - - return true; -} - -uint16_t Adafruit_FreeTouch::measure(void) { - uint16_t m; - - m = measureRaw(); - if (m == -1) return -1; - - // normalize the signal - switch (config.oversample) { - case OVERSAMPLE_1: return m; - case OVERSAMPLE_2: return m/2; - case OVERSAMPLE_4: return m/4; - case OVERSAMPLE_8: return m/8; - case OVERSAMPLE_16: return m/16; - case OVERSAMPLE_32: return m/32; - case OVERSAMPLE_64: return m/64; - } - - return -1; // shouldn't reach here but fail if we do! -} - -uint16_t Adafruit_FreeTouch::measureRaw(void) { - adafruit_ptc_start_conversion(PTC, &config); - - while (!adafruit_ptc_is_conversion_finished(PTC)) { - yield(); - } - - return adafruit_ptc_get_conversion_result(PTC); -} - -/*********************************** low level config **/ - -int Adafruit_FreeTouch::getYLine(void) { - int p = g_APinDescription[pin].ulPin; - if (g_APinDescription[pin].ulPort == PORTA) { - if ((p >= 2) && (p <= 7)) { - return (p - 2); - } - } - if (g_APinDescription[pin].ulPort == PORTB) { - if ((p >= 0) && (p <= 9)) { - return (p + 6); - } - } - - // not valid - return -1; -} - -void Adafruit_FreeTouch::setCompCap(uint16_t cc) { - config.compcap = cc & 0x3FFF; -} - -void Adafruit_FreeTouch::setIntCap(uint8_t ic) { - config.intcap = ic & 0x3F; -} - -void Adafruit_FreeTouch::setOversampling(oversample_t lvl) { - config.oversample = lvl; // back it up for later -} - -void Adafruit_FreeTouch::setSeriesResistor(series_resistor_t res) { - config.seriesres = res; -} - -void Adafruit_FreeTouch::setFreqHopping(freq_mode_t fh, freq_hop_t hs) { - config.freqhop = fh; - config.hops = hs; -} - -/**************************** DEBUGGING ASSIST *************************/ -void Adafruit_FreeTouch::snapshotRegsAndPrint(uint32_t base, uint8_t numregs) { - volatile uint32_t addr = base; - uint8_t datas[255]; - - digitalWrite(LED_BUILTIN, HIGH); - for (uint8_t i=0; i -#include "adafruit_ptc.h" - -class Adafruit_FreeTouch { - public: - Adafruit_FreeTouch(int p = 0, oversample_t f = OVERSAMPLE_4, series_resistor_t r = RESISTOR_0, freq_mode_t fh = FREQ_MODE_NONE); - bool begin(void); - - uint16_t measure(void); - uint16_t measureRaw(void); - - private: - void ptcInitSettings(void); - void ptcConfigIOpin(void); - uint16_t startPtcAcquire(void); - - int getYLine(void); - void selectYLine(void); - void setOversampling(oversample_t lvl); - void setSeriesResistor(series_resistor_t res); - void setFreqHopping(freq_mode_t fh, freq_hop_t hops = FREQ_HOP_1); - void setCompCap(uint16_t cc); - void setIntCap(uint8_t ic); - - void snapshotRegsAndPrint(uint32_t base, uint8_t numregs); - void printHex(uint8_t h, boolean newline); - void printPTCregs(uint32_t base, uint8_t *regs, uint8_t num); - - private: - int pin; // arduino pin # - struct adafruit_ptc_config config; -}; - -#endif diff --git a/ports/atmel-samd/freetouch/README.md b/ports/atmel-samd/freetouch/README.md deleted file mode 100644 index 3b179a45c1..0000000000 --- a/ports/atmel-samd/freetouch/README.md +++ /dev/null @@ -1,2 +0,0 @@ -# Adafruit_FreeTouch -A QTouch-compatible library diff --git a/ports/atmel-samd/freetouch/adafruit_ptc.c b/ports/atmel-samd/freetouch/adafruit_ptc.c deleted file mode 100644 index f4369cf4a5..0000000000 --- a/ports/atmel-samd/freetouch/adafruit_ptc.c +++ /dev/null @@ -1,148 +0,0 @@ -/* - * FreeTouch, a QTouch-compatible library - tested on ATSAMD21 only! - * The MIT License (MIT) - * - * Copyright (c) 2017 Limor 'ladyada' Fried for Adafruit Industries - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ - -#include "adafruit_ptc.h" -#include "pinmux.h" - -static void sync_config(Ptc const* module_inst) { - while (module_inst->CONTROLB.bit.SYNCFLAG) ; -} - -void adafruit_ptc_get_config_default(struct adafruit_ptc_config *config) { - config->pin = 0xff; - config->yline = -1; - config->oversample = OVERSAMPLE_4; - config->seriesres = RESISTOR_0; - config->freqhop = FREQ_MODE_NONE; - config->compcap = 0x2000; - config->intcap = 0x3F; -} - -void adafruit_ptc_init(Ptc* module_inst, struct adafruit_ptc_config const* config) { - struct system_pinmux_config pinmux_config; - system_pinmux_get_config_defaults(&pinmux_config); - pinmux_config.mux_position = 0x1; - pinmux_config.input_pull = SYSTEM_PINMUX_PIN_PULL_NONE; - system_pinmux_pin_set_config(config->pin, &pinmux_config); - - sync_config(module_inst); - module_inst->CONTROLA.bit.ENABLE = 0; - sync_config(module_inst); - - module_inst->UNK4C04.reg &= 0xF7; //MEMORY[0x42004C04] &= 0xF7u; - module_inst->UNK4C04.reg &= 0xFB; //MEMORY[0x42004C04] &= 0xFBu; - module_inst->UNK4C04.reg &= 0xFC; //MEMORY[0x42004C04] &= 0xFCu; - sync_config(module_inst); - module_inst->FREQCONTROL.reg &= 0x9F; //MEMORY[0x42004C0C] &= 0x9Fu; - sync_config(module_inst); - module_inst->FREQCONTROL.reg &= 0xEF; //MEMORY[0x42004C0C] &= 0xEFu; - sync_config(module_inst); - module_inst->FREQCONTROL.bit.SAMPLEDELAY = 0; //MEMORY[0x42004C0C] &= 0xF0u; - module_inst->CONTROLC.bit.INIT = 1; //MEMORY[0x42004C05] |= 1u; - module_inst->CONTROLA.bit.RUNINSTANDBY = 1; //MEMORY[0x42004C00] |= 4u; - sync_config(module_inst); - module_inst->INTDISABLE.bit.WCO = 1; - sync_config(module_inst); - module_inst->INTDISABLE.bit.EOC = 1; - sync_config(module_inst); - - // enable the sensor, only done once per line - if (config->yline < 8) { - sync_config(module_inst); - module_inst->YENABLEL.reg |= 1 << config->yline; - sync_config(module_inst); - } else if (config->yline < 16) { - module_inst->YENABLEH.reg |= 1 << (config->yline - 8); - } - - sync_config(module_inst); - module_inst->CONTROLA.bit.ENABLE = 1; - sync_config(module_inst); -} - -void adafruit_ptc_start_conversion(Ptc* module_inst, struct adafruit_ptc_config const* config) { - module_inst->CONTROLA.bit.RUNINSTANDBY = 1; - sync_config(module_inst); - module_inst->CONTROLA.bit.ENABLE = 1; - sync_config(module_inst); - module_inst->INTDISABLE.bit.WCO = 1; - sync_config(module_inst); - module_inst->INTFLAGS.bit.WCO = 1; - sync_config(module_inst); - module_inst->INTFLAGS.bit.EOC = 1; - sync_config(module_inst); - - // set up pin! - sync_config(module_inst); - if (config->yline < 8) { - module_inst->YSELECTL.reg = 1 << config->yline; - } else { - module_inst->YSELECTL.reg = 0; - } - - if (config->yline > 7) { - module_inst->YSELECTH.reg = 1 << (config->yline - 8); - } else { - module_inst->YSELECTH.reg = 0; - } - - sync_config(module_inst); - // set up sense resistor - module_inst->SERRES.bit.RESISTOR = config->seriesres; - sync_config(module_inst); - // set up prescalar - module_inst->CONVCONTROL.bit.ADCACCUM = config->oversample; - sync_config(module_inst); - // set up freq hopping - if (config->freqhop == FREQ_MODE_NONE) { - module_inst->FREQCONTROL.bit.FREQSPREADEN = 0; - module_inst->FREQCONTROL.bit.SAMPLEDELAY = 0; - } else { - module_inst->FREQCONTROL.bit.FREQSPREADEN = 1; - module_inst->FREQCONTROL.bit.SAMPLEDELAY = config->hops; - } - // set up compensation cap + int (?) cap - sync_config(module_inst); - module_inst->COMPCAPL.bit.VALUE = config->compcap & 0xFF; - module_inst->COMPCAPH.bit.VALUE = (config->compcap>>8) & 0x3F; - sync_config(module_inst); - module_inst->INTCAP.bit.VALUE = config->intcap & 0x3F; - sync_config(module_inst); - - module_inst->BURSTMODE.reg = 0xA4; - sync_config(module_inst); - - module_inst->CONVCONTROL.bit.CONVERT = 1; - sync_config(module_inst); -} - -bool adafruit_ptc_is_conversion_finished(Ptc* module_inst) { - return module_inst->CONVCONTROL.bit.CONVERT == 0; -} - -uint16_t adafruit_ptc_get_conversion_result(Ptc* module_inst) { - sync_config(module_inst); - return module_inst->RESULT.reg; -} diff --git a/ports/atmel-samd/freetouch/adafruit_ptc.h b/ports/atmel-samd/freetouch/adafruit_ptc.h deleted file mode 100644 index 93bb16ef40..0000000000 --- a/ports/atmel-samd/freetouch/adafruit_ptc.h +++ /dev/null @@ -1,109 +0,0 @@ -/* - * FreeTouch, a QTouch-compatible library - tested on ATSAMD21 only! - * The MIT License (MIT) - * - * Copyright (c) 2017 Limor 'ladyada' Fried for Adafruit Industries - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ - -// This is similar to the drivers found in sam0/drivers but for the PTC. -#ifndef ADAFRUIT_FREETOUCH_ADAFRUIT_PTC_H -#define ADAFRUIT_FREETOUCH_ADAFRUIT_PTC_H - -#include - -#include "samd21_ptc_component.h" - -#ifdef __cplusplus -extern "C" { -#endif - -/* Touch library oversampling (filter) setting */ -typedef enum tag_oversample_level_t { - OVERSAMPLE_1, - OVERSAMPLE_2, - OVERSAMPLE_4, - OVERSAMPLE_8, - OVERSAMPLE_16, - OVERSAMPLE_32, - OVERSAMPLE_64 -} -oversample_t; - -/* Touch library series resistor setting */ -typedef enum tag_series_resistor_t { - RESISTOR_0, - RESISTOR_20K, - RESISTOR_50K, - RESISTOR_100K, -} -series_resistor_t; - -typedef enum tag_freq_mode_t { - FREQ_MODE_NONE, - FREQ_MODE_HOP, - FREQ_MODE_SPREAD, - FREQ_MODE_SPREAD_MEDIAN -} -freq_mode_t; - -typedef enum tag_freq_hop_t { - FREQ_HOP_1, - FREQ_HOP_2, - FREQ_HOP_3, - FREQ_HOP_4, - FREQ_HOP_5, - FREQ_HOP_6, - FREQ_HOP_7, - FREQ_HOP_8, - FREQ_HOP_9, - FREQ_HOP_10, - FREQ_HOP_11, - FREQ_HOP_12, - FREQ_HOP_13, - FREQ_HOP_14, - FREQ_HOP_15, - FREQ_HOP_16 -} -freq_hop_t; - -struct adafruit_ptc_config { - uint8_t pin; // ASF pin # - int8_t yline; // the Y select line (see datasheet) - oversample_t oversample; - series_resistor_t seriesres; - freq_mode_t freqhop; - freq_hop_t hops; - uint16_t compcap; - uint8_t intcap; -}; - -void adafruit_ptc_get_config_default(struct adafruit_ptc_config *config); -void adafruit_ptc_init(Ptc* module_inst, struct adafruit_ptc_config const* config); -void adafruit_ptc_start_conversion(Ptc* module_inst, struct adafruit_ptc_config const* config); - -bool adafruit_ptc_is_conversion_finished(Ptc* module_inst); -uint16_t adafruit_ptc_get_conversion_result(Ptc* module_inst); - -#ifdef __cplusplus -} -#endif - -#endif // ADAFRUIT_FREETOUCH_ADAFRUIT_PTC_H diff --git a/ports/atmel-samd/freetouch/examples/freetouch/freetouch.ino b/ports/atmel-samd/freetouch/examples/freetouch/freetouch.ino deleted file mode 100644 index d89642c2e5..0000000000 --- a/ports/atmel-samd/freetouch/examples/freetouch/freetouch.ino +++ /dev/null @@ -1,56 +0,0 @@ -#include "Adafruit_FreeTouch.h" - -Adafruit_FreeTouch qt_1 = Adafruit_FreeTouch(A0, OVERSAMPLE_4, RESISTOR_50K, FREQ_MODE_NONE); -Adafruit_FreeTouch qt_2 = Adafruit_FreeTouch(A1, OVERSAMPLE_4, RESISTOR_50K, FREQ_MODE_NONE); -Adafruit_FreeTouch qt_3 = Adafruit_FreeTouch(A2, OVERSAMPLE_4, RESISTOR_50K, FREQ_MODE_NONE); -Adafruit_FreeTouch qt_4 = Adafruit_FreeTouch(A3, OVERSAMPLE_4, RESISTOR_50K, FREQ_MODE_NONE); - -void setup() { - Serial.begin(115200); - - while (!Serial); - Serial.println("FreeTouch test"); - // initialize digital pin LED_BUILTIN as an output. - pinMode(LED_BUILTIN, OUTPUT); - - if (! qt_1.begin()) - Serial.println("Failed to begin qt on pin A0"); - if (! qt_2.begin()) - Serial.println("Failed to begin qt on pin A1"); - if (! qt_3.begin()) - Serial.println("Failed to begin qt on pin A2"); - if (! qt_4.begin()) - Serial.println("Failed to begin qt on pin A3"); - -} - - - -void loop() { - int counter, result = 0; - - // DIY - Serial.println("\n*************************************"); - - counter = millis(); - result = qt_1.measure(); - Serial.print("QT 1: "); Serial.print(result); - Serial.print(" ("); Serial.print(millis() - counter); Serial.println(" ms)"); - - counter = millis(); - result = qt_2.measure(); - Serial.print("QT 2: "); Serial.print(result); - Serial.print(" ("); Serial.print(millis() - counter); Serial.println(" ms)"); - - counter = millis(); - result = qt_3.measure(); - Serial.print("QT 3: "); Serial.print(result); - Serial.print(" ("); Serial.print(millis() - counter); Serial.println(" ms)"); - - counter = millis(); - result = qt_4.measure(); - Serial.print("QT 4: "); Serial.print(result); - Serial.print(" ("); Serial.print(millis() - counter); Serial.println(" ms)"); - - delay(200); -} \ No newline at end of file diff --git a/ports/atmel-samd/freetouch/samd21_ptc_component.h b/ports/atmel-samd/freetouch/samd21_ptc_component.h deleted file mode 100644 index 0af3236d38..0000000000 --- a/ports/atmel-samd/freetouch/samd21_ptc_component.h +++ /dev/null @@ -1,350 +0,0 @@ -/* - * FreeTouch, a QTouch-compatible library - tested on ATSAMD21 only! - * The MIT License (MIT) - * - * Copyright (c) 2017 Limor 'ladyada' Fried for Adafruit Industries - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ - -// This is similar to the component definitions found in -// sam0/utils/cmsis/samd21/include/component but for the PTC. -#ifndef ADAFRUIT_FREETOUCH_PTC_COMPONENT_H -#define ADAFRUIT_FREETOUCH_PTC_COMPONENT_H - -#include "compiler.h" - -#undef ENABLE - -/*************** CONTROL A register ***************/ -#define PTC_REG_CONTROLA 0x42004C00 -#define PTC_BIT_ENABLE 0x02 -#define PTC_BIT_RUNINSTBY 0x04 - - -typedef union { - struct { - uint8_t SWRESET:1; - uint8_t ENABLE:1; - uint8_t RUNINSTANDBY:1; - uint8_t __pad0__:5; - } bit; - uint8_t reg; -} PTC_REG_CONTROLA_Type; - -/*************** CONTROL B register ***************/ - -#define PTC_REG_CONTROLB 0x42004C01 -#define PTC_BIT_SYNCFLAG 0x80 - -typedef union { - struct { - uint8_t __pad0__:7; - uint8_t SYNCFLAG:1; - } bit; - uint8_t reg; -} PTC_REG_CONTROLB_Type; - -/*************** UNK4C04 register ***************/ - -#define PTC_REG_UNK4C04 0x42004C04 - -typedef union { - uint8_t reg; -} PTC_REG_UNK4C04_Type; - - -/*************** CONTROL C register ***************/ - -#define PTC_REG_CONTROLC 0x42004C05 -#define PTC_BIT_INIT 0x01 - -typedef union { - struct { - uint8_t INIT:1; - uint8_t __pad0__:7; - } bit; - uint8_t reg; -} PTC_REG_CONTROLC_Type; - - - -/*************** INT registers ***************/ - -typedef union { - struct { - uint8_t EOC:1; - uint8_t WCO:1; - uint8_t __pad0__:6; - } bit; - uint8_t reg; -} PTC_REG_INT_Type; - - -#define PTC_REG_INTDISABLE 0x42004C08 -#define PTC_REG_INTENABLE 0x42004C09 -#define PTC_BIT_EOCINTEN 0x01 -#define PTC_BIT_WCOINTEN 0x02 - -#define PTC_REG_INTFLAGS 0x42004C0A -#define PTC_BIT_EOCINTFLAG 0x01 -#define PTC_BIT_WCOINTFLAG 0x02 - - -/*************** FREQ CONTROL reg ***************/ - -typedef union { - struct { - uint8_t SAMPLEDELAY:4; - uint8_t FREQSPREADEN:1; - uint8_t __pad0__:3; - } bit; - uint8_t reg; -} PTC_REG_FREQCONTROL_Type; - -#define PTC_REG_FREQCONTROL 0x42004C0C -#define PTC_BIT_FREQSPREADEN 0x10 -#define PTC_REG_SAMPLEDELAY_MASK 0x0F - -/*************** CONVERT CONTROL reg ***************/ - -typedef union { - struct { - uint8_t ADCACCUM:3; - uint8_t __pad0__:4; - uint8_t CONVERT:1; - } bit; - uint8_t reg; -} __attribute__ ((packed)) PTC_REG_CONVCONTROL_Type; - - -#define PTC_REG_CONVCONTROL 0x42004C0D -#define PTC_BIT_CONVSTARTED 0x80 -#define PTC_REG_ADCACC_MASK 0x07 - - -/*************** Y SELECT L+H reg ***************/ - -typedef union { - struct { - uint8_t Y0:1; - uint8_t Y1:1; - uint8_t Y2:1; - uint8_t Y3:1; - uint8_t Y4:1; - uint8_t Y5:1; - uint8_t Y6:1; - uint8_t Y7:1; - } bit; - uint8_t reg; -} __attribute__ ((packed)) PTC_REG_YSELECTL_Type; - -typedef union { - struct { - uint8_t Y8:1; - uint8_t Y9:1; - uint8_t Y10:1; - uint8_t Y11:1; - uint8_t Y12:1; - uint8_t Y13:1; - uint8_t Y14:1; - uint8_t Y15:1; - } bit; - uint8_t reg; -} __attribute__ ((packed)) PTC_REG_YSELECTH_Type; - -#define PTC_REG_YSELECT_L 0x42004C10 -#define PTC_REG_YSELECT_H 0x42004C11 - -#define PTC_REG_YENABLE_L 0x42004C14 -#define PTC_REG_YENABLE_H 0x42004C15 - - -/*************** X SELECT L+H reg ***************/ - -typedef union { - struct { - uint8_t X0:1; - uint8_t X1:1; - uint8_t X2:1; - uint8_t X3:1; - uint8_t X4:1; - uint8_t X5:1; - uint8_t X6:1; - uint8_t X7:1; - } bit; - uint8_t reg; -} __attribute__ ((packed)) PTC_REG_XSELECTL_Type; - -typedef union { - struct { - uint8_t X8:1; - uint8_t X9:1; - uint8_t X10:1; - uint8_t X11:1; - uint8_t X12:1; - uint8_t X13:1; - uint8_t X14:1; - uint8_t X15:1; - } bit; - uint8_t reg; -} __attribute__ ((packed)) PTC_REG_XSELECTH_Type; - - -#define PTC_REG_XSELECT_L 0x42004C12 -#define PTC_REG_XSELECT_H 0x42004C13 - -#define PTC_REG_XENABLE_L 0x42004C16 -#define PTC_REG_XENABLE_H 0x42004C17 - -/*************** Compensation Cap reg ***************/ - -typedef union { - struct { - uint8_t VALUE:8; - } bit; - uint8_t reg; -} __attribute__ ((packed)) PTC_REG_COMPCAPL_Type; - -typedef union { - struct { - uint8_t VALUE:6; - uint8_t __pad0__:2; - } bit; - uint8_t reg; -} __attribute__ ((packed)) PTC_REG_COMPCAPH_Type; - -#define PTC_REG_COMPCAPL 0x42004C18 -#define PTC_REG_COMPCAPH 0x42004C19 - -/*************** Int Cap reg ***************/ - -typedef union { - struct { - uint8_t VALUE:6; - uint8_t __pad0__:2; - } bit; - uint8_t reg; -} __attribute__ ((packed)) PTC_REG_INTCAP_Type; - - -#define PTC_REG_INTCAP 0x42004C1A - -/*************** Series resistor reg ***************/ - -typedef union { - struct { - uint8_t RESISTOR:2; - uint8_t __pad0__:6; - } bit; - uint8_t reg; -} __attribute__ ((packed)) PTC_REG_SERRES_Type; - -#define PTC_REG_SERIESRES 0x42004C1B - -/*************** conversion result reg ***************/ - -typedef union { - struct { - uint8_t LOWBYTE; - uint8_t HIGHBYTE; - } byte; - uint16_t reg; -} __attribute__ ((packed)) PTC_REG_CONVRESULT_Type; - -#define PTC_REG_CONVRESULT_L 0x42004C1C -#define PTC_REG_CONVRESULT_H 0x42004C1D - -/*************** burst mode reg ***************/ - -typedef union { - struct { - uint8_t __pad0__:2; - uint8_t CTSLOWPOWER:1; - uint8_t __pad1__:1; - uint8_t BURSTMODE:4; - } bit; - uint8_t reg; -} __attribute__ ((packed)) PTC_REG_BURSTMODE_Type; - - -#define PTC_REG_BURSTMODE 0x42004C20 -#define PTC_REG_BURSTMODE_MASK 0xF0 -#define PTC_BIT_CTSLOWPOWER 0x04 - -/*************** etc unused reg ***************/ - -#define PTC_REG_XYENABLE 0x42004C16 -#define PTC_BIT_XYENABLE 0x02 - -#define PTC_REG_WCO_MODE 0x42004C21 -#define PTC_REG_WCO_MODE_MASK 0x07 - -#define PTC_SET_WCO_THRESHHOLD_A_L 0x42004C24 -#define PTC_SET_WCO_THRESHHOLD_A_H 0x42004C25 -#define PTC_SET_WCO_THRESHHOLD_B_L 0x42004C26 -#define PTC_SET_WCO_THRESHHOLD_B_H 0x42004C27 - -typedef struct { - __IO PTC_REG_CONTROLA_Type CONTROLA; // 0x42004C00 - __IO PTC_REG_CONTROLB_Type CONTROLB; // 0x42004C01 - uint8_t __pad4c02__; // 0x42004C02 unknown - uint8_t __pad4c03__; // 0x42004C03 unknown - __IO PTC_REG_UNK4C04_Type UNK4C04; // 0x42004C04 unknown - __IO PTC_REG_CONTROLC_Type CONTROLC; // 0x42004C05 - uint8_t __pad4c06__; // 0x42004C06 unknown - uint8_t __pad4c07__; // 0x42004C07 unknown - __IO PTC_REG_INT_Type INTDISABLE; // 0x42004C08 - __IO PTC_REG_INT_Type INTENABLE; // 0x42004C09 - __IO PTC_REG_INT_Type INTFLAGS; // 0x42004C0A - uint8_t __pad4c0b__; // 0x42004C0B unknown - __IO PTC_REG_FREQCONTROL_Type FREQCONTROL; //0x42004C0C - __IO PTC_REG_CONVCONTROL_Type CONVCONTROL; // 0x42004C0D - uint8_t __pad4c0e__; // 0x42004C0E unknown - uint8_t __pad4c0f__; // 0x42004C0F unknown - __IO PTC_REG_YSELECTL_Type YSELECTL; // 0x42004C10 - __IO PTC_REG_YSELECTL_Type YSELECTH; // 0x42004C11 - __IO PTC_REG_XSELECTL_Type XSELECTL; // 0x42004C12 - __IO PTC_REG_XSELECTL_Type XSELECTH; // 0x42004C13 - __IO PTC_REG_YSELECTL_Type YENABLEL; // 0x42004C14 - __IO PTC_REG_YSELECTL_Type YENABLEH; // 0x42004C15 - __IO PTC_REG_XSELECTL_Type XENABLEL; // 0x42004C16 - __IO PTC_REG_XSELECTL_Type XENABLEH; // 0x42004C17 - - __IO PTC_REG_COMPCAPL_Type COMPCAPL; // 0x42004C18 - __IO PTC_REG_COMPCAPH_Type COMPCAPH; // 0x42004C19 - __IO PTC_REG_INTCAP_Type INTCAP; // 0x42004C1A - __IO PTC_REG_SERRES_Type SERRES; // 0x42004C1B - - __IO PTC_REG_CONVRESULT_Type RESULT; // 0x42004C1C + 0x42004C1D - uint8_t __pad4c1e__; // 0x42004C1E unknown - uint8_t __pad4c1f__; // 0x42004C1F unknown - __IO PTC_REG_BURSTMODE_Type BURSTMODE; // 0x42004C20 -} Ptc; - -#define PTC (( Ptc *)0x42004C00U) - -#define PTC_REG_INTDISABLE 0x42004C08 -#define PTC_REG_INTENABLE 0x42004C09 -#define PTC_BIT_EOCINTEN 0x01 -#define PTC_BIT_WCOINTEN 0x02 - -#define PTC_REG_INTFLAGS 0x42004C0A - -#endif // ADAFRUIT_FREETOUCH_PTC_COMPONENT_H From a55988a547011c04978a1661325062397ef74110 Mon Sep 17 00:00:00 2001 From: Jeff Epler Date: Sun, 25 Mar 2018 16:01:06 -0500 Subject: [PATCH 133/135] Fix assertion failure in mpz_divmod_inpl .. turning this from an assertion failure into an exception: pow(1,1,0) --- py/objint_mpz.c | 4 ++++ tests/basics/builtin_pow3.py | 5 +++++ 2 files changed, 9 insertions(+) diff --git a/py/objint_mpz.c b/py/objint_mpz.c index 7b5cb0b9d4..808fae6e41 100644 --- a/py/objint_mpz.c +++ b/py/objint_mpz.c @@ -343,6 +343,10 @@ mp_obj_t mp_obj_int_pow3(mp_obj_t base, mp_obj_t exponent, mp_obj_t modulus) { mpz_t *rhs = mp_mpz_for_int(exponent, &r_temp); mpz_t *mod = mp_mpz_for_int(modulus, &m_temp); + if (mpz_is_zero(mod)) { + mp_raise_msg(&mp_type_ValueError, "pow() 3rd argument cannot be 0"); + } + mpz_pow3_inpl(&(res_p->mpz), lhs, rhs, mod); if (lhs == &l_temp) { mpz_deinit(lhs); } diff --git a/tests/basics/builtin_pow3.py b/tests/basics/builtin_pow3.py index 69b57e5484..293a5acc9a 100644 --- a/tests/basics/builtin_pow3.py +++ b/tests/basics/builtin_pow3.py @@ -22,3 +22,8 @@ try: print(pow(4, 5, "z")) except TypeError: print("TypeError expected") + +try: + print(pow(4, 5, 0)) +except ValueError: + print("ValueError expected") From 6da8d7c46583387aa32d5c153b3c5b7d9e1afccd Mon Sep 17 00:00:00 2001 From: Jeff Epler Date: Sun, 25 Mar 2018 16:05:32 -0500 Subject: [PATCH 134/135] Fix assertion failures in mp_obj_new_type Fixes the following assertion failures when the arguments to type() were not of valid types: micropython: ../../py/objtype.c:984: mp_obj_new_type: Assertion `MP_OBJ_IS_TYPE(bases_tuple, &mp_type_tuple)' failed. micropython: ../../py/objtype.c:994: mp_obj_new_type: Assertion `MP_OBJ_IS_TYPE(items[i], &mp_type_type)' failed. e.g., when making calls like type("", (), 3) type("", 3, {}) --- py/objtype.c | 14 +++++++++++--- tests/basics/types3.py | 20 ++++++++++++++++++++ 2 files changed, 31 insertions(+), 3 deletions(-) create mode 100644 tests/basics/types3.py diff --git a/py/objtype.c b/py/objtype.c index 7262892bd8..3fa25eb774 100644 --- a/py/objtype.c +++ b/py/objtype.c @@ -981,8 +981,14 @@ const mp_obj_type_t mp_type_type = { }; mp_obj_t mp_obj_new_type(qstr name, mp_obj_t bases_tuple, mp_obj_t locals_dict) { - assert(MP_OBJ_IS_TYPE(bases_tuple, &mp_type_tuple)); // MicroPython restriction, for now - assert(MP_OBJ_IS_TYPE(locals_dict, &mp_type_dict)); // MicroPython restriction, for now + if(!MP_OBJ_IS_TYPE(bases_tuple, &mp_type_tuple)) { + // MicroPython restriction, for now + mp_raise_TypeError("type() argument 2 must be tuple"); + } + if(!MP_OBJ_IS_TYPE(locals_dict, &mp_type_dict)) { + // MicroPython restriction, for now + mp_raise_TypeError("type() argument 3 must be dict"); + } // TODO might need to make a copy of locals_dict; at least that's how CPython does it @@ -991,7 +997,9 @@ mp_obj_t mp_obj_new_type(qstr name, mp_obj_t bases_tuple, mp_obj_t locals_dict) mp_obj_t *items; mp_obj_tuple_get(bases_tuple, &len, &items); for (size_t i = 0; i < len; i++) { - assert(MP_OBJ_IS_TYPE(items[i], &mp_type_type)); + if(!MP_OBJ_IS_TYPE(items[i], &mp_type_type)) { + mp_raise_TypeError("type is not an acceptable base type"); + } mp_obj_type_t *t = MP_OBJ_TO_PTR(items[i]); // TODO: Verify with CPy, tested on function type if (t->make_new == NULL) { diff --git a/tests/basics/types3.py b/tests/basics/types3.py new file mode 100644 index 0000000000..71f7906923 --- /dev/null +++ b/tests/basics/types3.py @@ -0,0 +1,20 @@ +try: + type('abc', None, None) +except TypeError: + print(True) +else: + print(False) + +try: + type('abc', (), None) +except TypeError: + print(True) +else: + print(False) + +try: + type('abc', (1,), {}) +except TypeError: + print(True) +else: + print(False) From ff06a455995322978dbd9ad9291154ebbdf0abb5 Mon Sep 17 00:00:00 2001 From: Jeff Epler Date: Sun, 25 Mar 2018 16:13:49 -0500 Subject: [PATCH 135/135] Fix assertion failures in super_attr micropython: ../../py/objtype.c:1100: super_attr: Assertion `MP_OBJ_IS_TYPE(self->type, &mp_type_type)' failed. e.g., when making calls like super(1, 1).x --- py/objtype.c | 3 +++ tests/basics/class_super.py | 7 +++++++ 2 files changed, 10 insertions(+) diff --git a/py/objtype.c b/py/objtype.c index 3fa25eb774..5b70e8e489 100644 --- a/py/objtype.c +++ b/py/objtype.c @@ -1085,6 +1085,9 @@ STATIC mp_obj_t super_make_new(const mp_obj_type_t *type_in, size_t n_args, size // 0 arguments are turned into 2 in the compiler // 1 argument is not yet implemented mp_arg_check_num(n_args, n_kw, 2, 2, false); + if(!MP_OBJ_IS_TYPE(args[0], &mp_type_type)) { + mp_raise_TypeError("first argument to super() must be type"); + } mp_obj_super_t *o = m_new_obj(mp_obj_super_t); *o = (mp_obj_super_t){{type_in}, args[0], args[1]}; return MP_OBJ_FROM_PTR(o); diff --git a/tests/basics/class_super.py b/tests/basics/class_super.py index 1338ef4523..5a18017ac6 100644 --- a/tests/basics/class_super.py +++ b/tests/basics/class_super.py @@ -34,3 +34,10 @@ class B(A): print(super().bar) # accessing attribute after super() return super().foo().count(2) # calling a subsequent method print(B().foo()) + +try: + super(1, 1).x +except TypeError: + print(True) +else: + print(False)