/************************************************************************ * Initialize Environment use * * We are still running from ROM, so data use is limited */ int env_init (void) { DECLARE_GLOBAL_DATA_PTR; #ifdef CONFIG_AMIGAONEG3SE enable_nvram(); #endif #if defined(CFG_NVRAM_ACCESS_ROUTINE) ulong crc; uchar data[ENV_SIZE]; nvram_read (&crc, CFG_ENV_ADDR, sizeof(ulong)); nvram_read (data, CFG_ENV_ADDR+sizeof(ulong), ENV_SIZE); if (crc32(0, data, ENV_SIZE) == crc) { gd->env_addr = (ulong)CFG_ENV_ADDR + sizeof(long); #else if (crc32(0, env_ptr->data, ENV_SIZE) == env_ptr->crc) { gd->env_addr = (ulong)&(env_ptr->data); #endif gd->env_valid = 1; } else { gd->env_addr = (ulong)&default_environment[0]; gd->env_valid = 0; } #ifdef CONFIG_AMIGAONEG3SE disable_nvram(); #endif return (0); }
INT32 platform_load_nvram_data(PINT8 filename, PINT8 buf, INT32 len) { /* int ret; */ BT_INFO_FUNC("platform_load_nvram_data ++ BDADDR\n"); return nvram_read(filename, buf, len, 0); }
int platform_load_nvram_data( char * filename, char * buf, int len) { //int ret; printk("[wifi] platform_load_nvram_data ++\n"); return nvram_read( filename, buf, len, 0); }
int platform_load_nvram_data( char * filename, char * buf, int len) { //int ret; BT_INFO_FUNC("platform_load_nvram_data ++ BDADDR\n"); return nvram_read( filename, buf, len, 0); }
/** * Dump 256 bytes of NVRAM. */ static void dump_nvram(WINDOW *win, int row, int col) { int i, x = 0, y = 0; /* Print vertical and horizontal index numbers. */ for (i = 0; i < 16; i++) { mvwprintw(win, ((i < 8) ? 4 : 5) + i, 1, "%2.2X ", i * 0x10); mvwprintw(win, 2, 4 + (i * 3), "%2.2X ", i); } /* Print vertical and horizontal line. */ for (i = 0; i < 18; i++) mvwaddch(win, 3 + i, 3, ACS_VLINE); for (i = 0; i < 48; i++) mvwaddch(win, 3, 3 + i, (i == 0) ? ACS_ULCORNER : ACS_HLINE); /* Dump NVRAM contents. */ for (i = 1; i < 257; i++) { mvwprintw(win, row + y, col + x, "%02x ", nvram_read(i - 1)); x += 3; if (i % 16 == 0) { y++; /* Start a newline after 16 bytes. */ x = 0; } if (i % 128 == 0) { y++; /* Add an empty line after 128 bytes. */ x = 0; } } }
void env_relocate_spec (void) { #if defined(CFG_NVRAM_ACCESS_ROUTINE) nvram_read(env_ptr, CFG_ENV_ADDR, CFG_ENV_SIZE); #else memcpy (env_ptr, (void*)CFG_ENV_ADDR, CFG_ENV_SIZE); #endif }
uchar env_get_char_spec(int index) { uchar c; nvram_read(&c, CONFIG_ENV_ADDR + index, 1); return c; }
/** * @brief Calibrate magnetometer * * This function measures the magnetometer output if 3 different device * orientations, calculates average offset values, and stores these offsets * in non-volatile memory. The offsets will later be used during normal * measurements, to compensate for fixed magnetic effects. * * This routine must be called 3 times total, with the "step" parameter * indicating what stage of the calibration is being performed. This * multi-step mechanism allows the application to prompt for physical * placement of the sensor device before this routine is called. * * @param sensor Address of an initialized sensor device descriptor. * @param calib_type The address of a vector storing sensor axis data. * @param step The calibration stage number [1,3]. * @param info Unimplemented (ignored) parameter. * @return bool true if the call succeeds, else false is returned. */ static bool ak8975_calibrate(sensor_t *sensor, sensor_calibration_t calib_type, int step, void *info) { sensor_hal_t *const hal = sensor->hal; static vector3_t step_data [3]; /* Validate the supported calibration types and step number. */ if ((calib_type != MANUAL_CALIBRATE) || ((step < 1) || (step > 3))) { return false; } /* Read sensor data and test for data overflow. */ vector3_t *const ptr_step_data = &step_data[ step - 1 ]; if ((!ak8975_get_data(hal, AK8975_SINGLE_MODE, ptr_step_data)) || ak8975_check_overflow(ptr_step_data)) { return false; } switch (step) { /* There's nothing to do on the first two passes. */ case 1: case 2: break; /* Calculate & update the calibrated offsets on the final pass. */ case 3: calibrated_offsets.x = (step_data[0].x + step_data[1].x) / 2; calibrated_offsets.y = (step_data[0].y + step_data[1].y) / 2; calibrated_offsets.z = (step_data[1].z + step_data[2].z) / 2; /* Write the calibration data then read it back and confirm it * was written correctly */ nvram_write(0, &calibrated_offsets, sizeof(calibrated_offsets)); vector3_t read_back; nvram_read(0, &read_back, sizeof(vector3_t)); if (memcmp(&calibrated_offsets, &read_back, sizeof(vector3_t))) { sensor->err = SENSOR_ERR_IO; return false; } break; /* Any other step number is invalid */ default: sensor->err = SENSOR_ERR_PARAMS; return false; } return true; }
void env_relocate_spec(void) { char buf[CONFIG_ENV_SIZE]; #if defined(CONFIG_SYS_NVRAM_ACCESS_ROUTINE) nvram_read(buf, CONFIG_ENV_ADDR, CONFIG_ENV_SIZE); #else memcpy(buf, (void*)CONFIG_ENV_ADDR, CONFIG_ENV_SIZE); #endif env_import(buf, 1); }
bool platformNvramRead16( void * prAdapter,unsigned char ucWordOffset, unsigned short * pu2Data ) { if( pu2Data == NULL ) return false; if( nvram_read( WIFI_NVRAM_FILE_NAME, (char *)pu2Data, sizeof(unsigned short), ucWordOffset*sizeof(unsigned short)) != sizeof(unsigned short) ) return false; else return true; }
bool customDataRead8( void * prAdapter,unsigned char ucByteOffset, unsigned char * pucData ) { if( pucData == NULL ) return false; if( nvram_read( WIFI_NVRAM_CUSTOM_NAME, (char *)pucData, sizeof(unsigned char), ucByteOffset*sizeof(unsigned char)) != sizeof(unsigned char) ) return false; else return true; }
/** * @brief Calibrate proximity sensor detection thresholds * * This function measures the proximity sensor output in 3 different steps, * one for each channel in the device. This function should be called when * a sample object has been placed at the desired distance from the device * to define the threshold for near-proximity detection. The measured * proximity sensor value for each channel is stored in non-volatile memory. * These thresholds will later be used to set the threshold during the * device initialization sequence. * * This routine must be called 3 times total, with the "step" parameter * indicating what stage of the calibration is being performed (i.e. which * channel of the proximity sensor). This multi-step mechanism allows * the application to prompt for physical placement of the object to be * detected before this routine is called. * * @param sensor Address of an initialized sensor device descriptor. * @param calib_type The address of a vector storing sensor axis data. * @param step The calibration stage number [1,3]. * @param info Unimplemented (ignored) parameter. * @return bool true if the call succeeds, else false is returned. */ static bool sfh7770_calibrate(sensor_t *sensor, sensor_calibration_t calib_type, int step, void *info) { sensor_hal_t *const hal = sensor->hal; static uint8_t prox_data[3]; uint8_t read_data[3]; /* Validate the specified calibration type */ if (calib_type != MANUAL_CALIBRATE) { sensor->err = SENSOR_ERR_PARAMS; return false; } /* Read proximity sensor for individual channel based on step number. */ switch (step) { case 1: prox_data[0] = sensor_bus_get(hal, SFH7770_PS_DATA_LED1); break; case 2: prox_data[1] = sensor_bus_get(hal, SFH7770_PS_DATA_LED2); break; case 3: prox_data[2] = sensor_bus_get(hal, SFH7770_PS_DATA_LED3); /* Write data */ nvram_write((SFH7770_NVRAM_OFFSET), prox_data, sizeof(prox_data)); /* Read back data and confirm it was written correctly */ nvram_read(SFH7770_NVRAM_OFFSET, read_data, sizeof(read_data)); if (memcmp(prox_data, read_data, sizeof(prox_data))) { sensor->err = SENSOR_ERR_IO; return false; } /* Apply stored proximity thresholds from nvram */ sensor_bus_write(hal, (SFH7770_PS_THR_LED1), read_data, sizeof(read_data)); break; /* Any other step number is invalid */ default: sensor->err = SENSOR_ERR_PARAMS; return false; } return true; }
uchar env_get_char_spec(int index) { #ifdef CONFIG_SYS_NVRAM_ACCESS_ROUTINE uchar c; nvram_read(&c, CONFIG_ENV_ADDR+index, 1); return c; #else return *((uchar *)(gd->env_addr + index)); #endif }
static void i386_detect_memory(void) { size_t npages_extmem; // Use CMOS calls to measure available base & extended memory. // (CMOS calls return results in kilobytes.) npages_basemem = (nvram_read(NVRAM_BASELO) * 1024) / PGSIZE; npages_extmem = (nvram_read(NVRAM_EXTLO) * 1024) / PGSIZE; // Calculate the number of physical pages available in both base // and extended memory. if (npages_extmem) npages = (EXTPHYSMEM / PGSIZE) + npages_extmem; else npages = npages_basemem; cprintf("Physical memory: %uK available, base = %uK, extended = %uK\n", npages * PGSIZE / 1024, npages_basemem * PGSIZE / 1024, npages_extmem * PGSIZE / 1024); }
void env_relocate_spec(void) { char *buf; #if defined(CONFIG_SYS_NVRAM_ACCESS_ROUTINE) buf = env_buf; nvram_read(buf, CONFIG_ENV_ADDR, CONFIG_ENV_SIZE); #else buf = (void *)CONFIG_ENV_ADDR; #endif env_import(buf, 1); }
/* * Initialize Environment use * * We are still running from ROM, so data use is limited */ int env_init(void) { #if defined(CONFIG_SYS_NVRAM_ACCESS_ROUTINE) ulong crc; uchar data[ENV_SIZE]; nvram_read(&crc, CONFIG_ENV_ADDR, sizeof(ulong)); nvram_read(data, CONFIG_ENV_ADDR+sizeof(ulong), ENV_SIZE); if (crc32(0, data, ENV_SIZE) == crc) { gd->env_addr = (ulong)CONFIG_ENV_ADDR + sizeof(long); #else if (crc32(0, env_ptr->data, ENV_SIZE) == env_ptr->crc) { gd->env_addr = (ulong)&(env_ptr->data); #endif gd->env_valid = 1; } else { gd->env_addr = (ulong)&default_environment[0]; gd->env_valid = 0; } return (0); }
static void i386_detect_memory(void) { unsigned baseval, extval, extabove16mval; // Use CMOS calls to measure available base & total memory. // This code is BIOS-specific; it works on QEMU, but not necessarily // on all hardware. For something more robust, see, e.g., Linux's // arch/x86/boot/memory.c. // NVRAM_BASE and EXT return results in KB. EXTABOVE16M returns // (total memory - 16MB) / 64KB. baseval = nvram_read(NVRAM_BASELO); extval = nvram_read(NVRAM_EXTLO); extabove16mval = nvram_read(NVRAM_EXTABOVE16M_LO); // Double-checks. if (baseval != 640) panic("Physical memory detection error: base != 640K"); if (extabove16mval != 0 && extval != 65535) { cprintf("Physical memory detection warning: BIOS mismatch\n"); extabove16mval = 0; } // Set npages based on read values. npages_basemem = baseval * 1024 / PGSIZE; if (extabove16mval != 0) npages = (extabove16mval + (16<<20)/65536) * (65536 / PGSIZE); else if (extval != 0) npages = (extval * 1024 + EXTPHYSMEM) / PGSIZE; else npages = npages_basemem; cprintf("Physical memory: %uK available\n", npages * PGSIZE / 1024); // We can't use more than 256MB. if (npages > -KERNBASE / PGSIZE) { npages = -KERNBASE / PGSIZE; cprintf("(restricting to %uK)\n", npages * PGSIZE / 1024); } }
uchar env_get_char_spec (int index) { #ifdef CFG_NVRAM_ACCESS_ROUTINE uchar c; nvram_read(&c, CFG_ENV_ADDR+index, 1); return c; #else DECLARE_GLOBAL_DATA_PTR; return *((uchar *)(gd->env_addr + index)); #endif }
int main(void) { uint32_t pos, len; board_init(); nvram_init(); LED_On(LED0); printk("Writing firmware data to flash\n"); pos = 0; while (pos < fw_len) { if (fw_len - pos > SECTOR_SIZE) len = SECTOR_SIZE; else len = fw_len - pos; nvram_write(pos, fw_buf + pos, len); pos += len; } LED_Off(LED0); printk("Verifying firmware data\n"); pos = 0; while (pos < fw_len) { static uint8_t page_buf[SECTOR_SIZE]; uint32_t i; if (fw_len - pos > SECTOR_SIZE) len = SECTOR_SIZE; else len = fw_len - pos; nvram_read(pos, page_buf, len); for (i = 0; i < len; i++) if (*(page_buf + i) != *(fw_buf + pos + i)) { printk("Verify failed at byte %d, 0x%02x != 0x%02x\n", pos + i, *(page_buf + i), *(fw_buf + pos + i)); return 0; } pos += len; } LED_On(LED0); printk("Firmware successfully stored in flash!\n"); return 0; }
/* offs buf length -- status actlen */ static int rc_nvram_fetch( ulong args[], ulong ret[] ) { /* printm("RTAS nvram-fetch %04lx %08lX %ld\n", args[0], args[1], args[2] ); */ ret[1] = nvram_read( args[0], (char*)args[1], args[2] ); ret[0] = 0; if( ret[1] != args[2] ){ printm("---> nvram_read parameter error\n"); ret[0] = -3; /* parameter error */ } /* printm("RTAS nvram-fetch %08lX [len=%d] %02X\n", args[0], args[2], *(char*)args[1] ); */ return 0; }
void fw_download_cb(void* ctx, uint8_t** buf, uint32_t* len) { /* remember accross different calls */ static uint8_t* fw_buf = NULL; static uint32_t offset = 0; /* when firmware download is completed, this function will be invoked * on additional time with the input value of len set to 0. we can free * the firmware buffer at this time since it's no longer needed. */ if (*len == 0) { if (fw_buf) free(fw_buf); return; } /* first call? then initialize flash and allocate a buffer to hold * firmware data. */ if (fw_buf == NULL) { fw_buf = malloc(BUF_SIZE); if (fw_buf == NULL) { printk("could not allocate firmware buffer\n"); *len = 0; return; } } /* decide how much to read. we know *len bytes remains, but we only have * room for SECTOR_SIEZ bytes in our buffer (fw_buf) */ uint32_t fw_len = *len > BUF_SIZE ? BUF_SIZE : *len; /* read data and update output parameters */ nvram_read(offset, fw_buf, fw_len); *buf = fw_buf; *len = fw_len; /* we need to know where to start reading upon next call */ offset += fw_len; }
/*----------------------------------------------------------------------------*/ BOOLEAN kalCfgDataRead16( IN P_GLUE_INFO_T prGlueInfo, IN UINT_32 u4Offset, OUT PUINT_16 pu2Data ) { if(pu2Data == NULL) { return FALSE; } if(nvram_read(WIFI_NVRAM_FILE_NAME, (char *)pu2Data, sizeof(unsigned short), u4Offset) != sizeof(unsigned short)) { return FALSE; } else { return TRUE; } }
/** * Get the current time and date from the RTC * * @param time A pointer to a broken-down time structure */ void rtc_read_clock(struct tm *time) { memset(time, 0, sizeof(*time)); while(nvram_updating()); time->tm_mon = bcd2dec(nvram_read(NVRAM_RTC_MONTH)) - 1; time->tm_sec = bcd2dec(nvram_read(NVRAM_RTC_SECONDS)); time->tm_min = bcd2dec(nvram_read(NVRAM_RTC_MINUTES)); time->tm_mday = bcd2dec(nvram_read(NVRAM_RTC_DAY)); time->tm_hour = bcd2dec(nvram_read(NVRAM_RTC_HOURS)); /* Instead of finding the century register, we just make an assumption that if the year value is less then 80, then it is 2000+ */ time->tm_year = bcd2dec(nvram_read(NVRAM_RTC_YEAR)); if (time->tm_year < 80) time->tm_year += 100; }
/** * @brief Honeywell HMC5883L magnetometer driver initialization. * * This is the main initialization function for the HMC5883L device. * * @param sensor Address of a sensor device descriptor. * @param resvd Reserved value. * @return bool true if the call succeeds, else false is returned. */ bool hmc5883l_init(sensor_t *sensor, int resvd) { bool status = false; sensor_hal_t *const hal = sensor->hal; sensor_data_t data; if (hmc5883l_device_id(hal, &data) && (HMC5883L_DEV_ID == data.device.id)) { /* Set the driver function table and capabilities pointer. */ static const sensor_device_t hmc5883l_device = { .func.read = hmc5883l_read, .func.ioctl = hmc5883l_ioctl, .func.selftest = hmc5883l_selftest, .func.calibrate = hmc5883l_calibrate, .caps.feature = SENSOR_CAPS_3_AXIS | SENSOR_CAPS_SELFTEST, .caps.vendor = SENSOR_VENDOR_HONEYWELL, .caps.units = SENSOR_UNITS_tesla, .caps.scale = SENSOR_SCALE_micro, .caps.name = "HMC5883L triaxial compass/magnetometer" }; sensor->drv = &hmc5883l_device; /* Enable sensor in continuous measurement mode */ sensor_bus_put(hal, HMC5883L_MODE_REG, MODE_CONTIN); /* Set the driver (device) default range, bandwidth, and * resolution. */ sensor_bus_put(hal, HMC5883L_CONFIG_REG_A, (DATA_RATE_15HZ | MEAS_MODE_NORM)); hal->range = range_table[index_130uT].range_units; hal->bandwidth = band_table[index_15hz].bandwidth_Hz; hal->resolution = HMC5883L_DATA_RESOLUTION; hmc5883l_set_range(hal, index_130uT); hmc5883l_set_bandwidth(hal, index_15hz); /* Initialize calibration data (offsets & sensitivity) from * NVRAM. */ nvram_read(0, &cal_data, sizeof(cal_data)); /* Clear all calibration values if any are invalid. */ #if defined(MATH_FIXED_POINT) if ((cal_data.x == -1) || (cal_data.y == -1) || (cal_data.z == -1)) { #else if (isnan(cal_data.offsets.x) || isnan(cal_data.offsets.y) || isnan(cal_data.offsets.z)) { #endif memset(&cal_data, 0x00, sizeof(cal_data)); } status = (STATUS_OK == hal->bus.status); } return status; } /** * @brief Read magnetometer device ID * * This function reads the magnetometer hardware identification registers * and returns these values to the addresses specified in the function * parameters. * * @param hal Address of an initialized sensor hardware descriptor. * @param data Address of sensor_data_t structure to return values. * @return bool true if the call succeeds, else false is returned. */ static bool hmc5883l_device_id(sensor_hal_t *hal, sensor_data_t *data) { uint32_t id_reg = 0; size_t const id_len = 3; size_t const count = sensor_bus_read (hal, HMC5883L_ID_REG_A, &id_reg, id_len); data->device.id = cpu_to_be32(id_reg) >> 8; data->device.version = 0; return (count == id_len); } /** * @brief Read magnetometer vector data. * * This function obtains magnetometer data for all three axes of the Honeywell * device. The data is read from six device registers using a multi-byte * bus transfer. The 13-bit raw results are then assembled from the two * register values for each axis, including extending the sign bit, to * form a signed 16-bit value. * * @param hal Address of an initialized sensor hardware descriptor. * @param data The address of a vector storing sensor axis data. * @return bool true if the call succeeds, else false is returned. */ static bool hmc5883l_get_data(sensor_hal_t *hal, vector3_t *data) { int16_t axis_data[3]; /* input data values: X,Y,Z */ /* Ensure that single-measurement mode is set and that bit MR7 is * cleared. Bit MR7 is set internally after each single-measurement * operation. */ sensor_bus_put(hal, HMC5883L_MODE_REG, MODE_SINGLE); do { /* Wait for the data ready signal. * * Instead of polling DRDY, as is done below, the device can be * placed in continuous measurement mode and this signal can be * configured to trigger an asynchronous interrupt. */ } while (gpio_pin_is_low(hal->mcu_sigint /* DRDY input */)); /* Get measurement data (consecutive big endian byte pairs: x, y, z). */ hmc588l_axis_t input[3]; size_t const count = sensor_bus_read (hal, HMC5883L_MAG_X_HI, (uint8_t *)input, sizeof(input)); if (count != sizeof(input)) { return false; } /* Note: Device data register order = x, z, y !! */ axis_data[0] = ((int16_t)((input[0].msb << 8) + input[0].lsb)); axis_data[2] = ((int16_t)((input[1].msb << 8) + input[1].lsb)); axis_data[1] = ((int16_t)((input[2].msb << 8) + input[2].lsb)); if ((axis_data[0] == DATA_OUTPUT_OVERFLOW) || (axis_data[1] == DATA_OUTPUT_OVERFLOW) || (axis_data[2] == DATA_OUTPUT_OVERFLOW)) { return false; } /* * Convert signed integer values to a real data type for calculations. * Use device orientation configuration to assign axes. */ const sensor_orient_t *const orient = &(hal->orientation); data->x = orient->x.sign * axis_data[orient->x.axis]; data->y = orient->y.sign * axis_data[orient->y.axis]; data->z = orient->z.sign * axis_data[orient->z.axis]; return true; }
/** * @brief Calibrate magnetometer * * This function measures the magnetometer output if 3 different device * orientations, calculates average offset values, and stores these offsets * in non-volatile memory. The offsets will later be used during normal * measurements, to compensate for fixed magnetic effects. * * This routine must be called 3 times total, with the "step" parameter * indicating what stage of the calibration is being performed. This * multi-step mechanism allows the application to prompt for physical * placement of the sensor device before this routine is called. * * @param sensor Address of an initialized sensor descriptor. * @param data The address of a vector storing sensor axis data. * @param step The calibration stage number (1 to 3). * @param info Unimplemented (ignored) parameter. * @return bool true if the call succeeds, else false is returned. */ bool hmc5883l_calibrate(sensor_t *sensor, sensor_calibration_t calib_type, int step, void *info) { static vector3_t step_data[3]; /* sensor readings during calibration */ vector3_t dummy_data; /* data from first sensor read (ignored) */ vector3_t read_back; /* data read back from nvram to validate */ sensor_data_t test_data; /* readings during self test */ int test_code; /* self-test code & result */ sensor_hal_t *const hal = sensor->hal; /* Validate the supported calibration types and step number. */ if ((calib_type != MANUAL_CALIBRATE) || ((step < 1) || (step > 3))) { return false; } /* During first pass, use self-test to determine sensitivity scaling */ if (step == 1) { /* Run internal self test with known bias field */ test_code = SENSOR_TEST_BIAS_POS; if ((hmc5883l_selftest(sensor, &test_code, &test_data) == false) || (test_code != SENSOR_TEST_ERR_NONE)) { return false; } /* Calculate & store sensitivity adjustment values */ cal_data.sensitivity.x = ((scalar_t)HMC5883L_TEST_X_NORM / test_data.axis.x); cal_data.sensitivity.z = ((scalar_t)HMC5883L_TEST_Z_NORM / test_data.axis.z); cal_data.sensitivity.y = ((scalar_t)HMC5883L_TEST_Y_NORM / test_data.axis.y); nvram_write(CAL_SENSITIVITY_ADDR, &cal_data.sensitivity, sizeof(cal_data.sensitivity)); /* Read back data and confirm it was written correctly */ nvram_read(CAL_SENSITIVITY_ADDR, &read_back, sizeof(vector3_t)); if (memcmp(&cal_data.sensitivity, &read_back, sizeof(vector3_t))) { sensor->err = SENSOR_ERR_IO; return false; } } /* Read sensor data and test for data overflow. * Note: Sensor must be read twice - the first reading may * contain stale data from previous orientation. */ if (hmc5883l_get_data(hal, &dummy_data) != true) { return false; } delay_ms(READ_DELAY_MSEC); if (hmc5883l_get_data(hal, &(step_data [step - 1])) != true) { return false; } /* Apply sensitivity scaling factors */ hmc5883l_apply_sensitivity(&(step_data [step - 1])); switch (step) { /* There's nothing more to do on the first two passes. */ case 1: case 2: break; /* Calculate & store the offsets on the final pass. */ case 3: cal_data.offsets.x = (step_data[0].x + step_data[1].x) / 2; cal_data.offsets.y = (step_data[0].y + step_data[1].y) / 2; cal_data.offsets.z = (step_data[1].z + step_data[2].z) / 2; nvram_write(CAL_OFFSETS_ADDR, &cal_data.offsets, sizeof(cal_data.offsets)); /* Read back data and confirm it was written correctly */ nvram_read(0, &read_back, sizeof(vector3_t)); if (memcmp(&cal_data.offsets, &read_back, sizeof(vector3_t))) { sensor->err = SENSOR_ERR_IO; return false; } break; default: return false; /* bad step value */ } return true; }
unsigned nvram_read16(unsigned r) { return nvram_read(r) | (nvram_read(r + 1) << 8); }
/** * @brief Osram SFH7770 light & proximity sensor driver initialization. * * This is the main initialization function for the SFH7770 device. * * @param sensor Address of a sensor device descriptor. * @param resvd Reserved value. * @return bool true if the call succeeds, else false is returned. */ bool sfh7770_init(sensor_t *sensor, int resvd) { bool status = false; sensor_hal_t *const hal = sensor->hal; /* Proximity threshold values from NVRAM */ struct { uint8_t ps_thr_led1; uint8_t ps_thr_led2; uint8_t ps_thr_led3; } prox_thresholds; /* Read and check part ID register */ uint8_t part_id = sensor_bus_get(hal, SFH7770_PART_ID); if (part_id == (SFH7770_PART_ID_VAL | SFH7770_PART_REV_VAL)) { /* Set the driver function table and capabilities pointer. */ static const sensor_device_t sfh7770_device = { .func.read = sfh7770_read, .func.ioctl = sfh7770_ioctl, .func.calibrate = sfh7770_calibrate, .func.event = sfh7770_event, #if 0 .caps.feature = XXX #endif .caps.vendor = SENSOR_VENDOR_OSRAM, .caps.units = SENSOR_UNITS_lux, .caps.scale = SENSOR_SCALE_one, .caps.name = "SFH7770 Ambient Light & Proximity Sensor" }; sensor->drv = &sfh7770_device; hal->resolution = SFH7770_DATA_RESOLUTION; /* Set the device burst read starting register address. */ hal->burst_addr = SFH7770_ALS_DATA_LSB; /* Reset device during first init call */ if (!sfh7770_initialized) { sensor_bus_put(hal, SFH7770_ALS_CONTROL, ALS_CONTROL_SW_RESET); } /* Init light sensor functions if specified */ if (sensor->type & SENSOR_TYPE_LIGHT) { /* Set light sensor mode & interval */ sensor_bus_put(hal, SFH7770_ALS_CONTROL, ALS_MODE_FREE_RUNNING); sensor_bus_put(hal, SFH7770_ALS_INTERVAL, ALS_INTERVAL_500MS); } /* Init proximity sensor functions if specified */ if (sensor->type & SENSOR_TYPE_PROXIMITY) { /* Set proximity sensor mode & interval */ sensor_bus_put(hal, SFH7770_PS_CONTROL, PS_MODE_FREE_RUNNING); sensor_bus_put(hal, SFH7770_PS_INTERVAL, PS_INTERVAL_100MS); /* Specify which LEDs are active */ uint8_t const active_leds = LED_ACTIVE_ALL; /* XXX one of: */ /* XXX LED_ACTIVE_1 - LED1 only (default) */ /* XXX LED_ACTIVE_1_2 - LED1 & LED2 */ /* XXX LED_ACTIVE_1_3 - LED1 & LED3 */ /* XXX LED_ACTIVE_ALL - all LEDs */ /* Set LED current levels */ uint8_t const led1_curr = I_LED_50MA; /* LED1 current */ uint8_t const led2_curr = I_LED_50MA; /* LED2 current */ uint8_t const led3_curr = I_LED_50MA; /* LED3 current */ sensor_bus_put(hal, SFH7770_I_LED_1_2, (active_leds | (led2_curr << I_LED2_SHIFT) | led1_curr)); sensor_bus_put(hal, SFH7770_I_LED_3, led3_curr); /* Apply stored proximity thresholds from nvram */ nvram_read(SFH7770_NVRAM_OFFSET, &prox_thresholds, sizeof(prox_thresholds)); sensor_bus_write(hal, (SFH7770_PS_THR_LED1), &prox_thresholds, sizeof(prox_thresholds)); } if (!sfh7770_initialized) { /* Set interrupt output polarity & mode(active-low, * latched). */ sensor_bus_put(hal, SFH7770_INT_SET, 0); /* Set up interrupt handler */ if (STATUS_OK == hal->bus.status) { sensor_irq_connect(hal->mcu_sigint, sfh7770_isr, hal); } } sfh7770_initialized = true; status = true; } return status; } /** * @brief Osram SFH7770 driver interrupt service routine. * * This is the common interrupt service routine for all enabled SFH7770 * interrupt events. Three different types of interrupts can be programmed: * high light level, low light level, and near proximity. All share the * same interrupt pin and therefore the same ISR entry. * * @param arg The address of the driver sensor_hal_t descriptor. * @return Nothing. */ static void sfh7770_isr(volatile void *arg) { sensor_hal_t *const hal = (sensor_hal_t *)arg; struct { /* Interrupt register data */ uint8_t als_data_lsb; /* light meas data - least signif byte */ uint8_t als_data_msb; /* light meas data - most signif byte */ uint8_t als_ps_status; /* light & prox sensor status */ uint8_t ps_data_led1; /* proximity meas data - LED 1 */ uint8_t ps_data_led2; /* proximity meas data - LED 2 */ uint8_t ps_data_led3; /* proximity meas data - LED 3 */ uint8_t int_set; /* interrupt status */ } regs; /* Do not wait for a busy bus when reading data. */ hal->bus.no_wait = true; sensor_bus_read(hal, hal->burst_addr, (uint8_t *)®s, sizeof(regs)); hal->bus.no_wait = false; if (STATUS_OK == hal->bus.status) { static sensor_event_data_t event_data = {.data.scaled = true}; event_data.data.timestamp = sensor_timestamp(); event_data.event = SENSOR_EVENT_UNKNOWN; /* * Determine the interrupt source then combine measurement * register values into a single 16-bit measurement value. */ uint8_t const int_source = (regs.int_set & INT_SOURCE_MASK); uint16_t const light_level = ((regs.als_data_msb << 8) | regs.als_data_lsb); switch (int_source) { case INT_SOURCE_ALS: /* Determine if low or high light interrupt */ if (light_level >= high_light_threshold) { event_data.event = SENSOR_EVENT_HIGH_LIGHT; event_data.data.light.value = light_level; (event_cb[2].handler)(&event_data, event_cb[2].arg); } else if (light_level <= low_light_threshold) { event_data.event = SENSOR_EVENT_LOW_LIGHT; event_data.data.light.value = light_level; (event_cb[1].handler)(&event_data, event_cb[1].arg); } return; case INT_SOURCE_LED1: case INT_SOURCE_LED2: case INT_SOURCE_LED3: event_data.event = SENSOR_EVENT_NEAR_PROXIMITY; if (int_source == INT_SOURCE_LED1) { event_data.channel = 1; } else if (int_source == INT_SOURCE_LED2) { event_data.channel = 2; } else { /* INT_SOURCE_LED3 */ event_data.channel = 3; } /* Use internal device threshold status to * determine scaled values. */ event_data.data.proximity.value[0] = (regs.als_ps_status & PS_LED1_THRESH) ? PROXIMITY_NEAR : PROXIMITY_NONE; event_data.data.proximity.value[1] = (regs.als_ps_status & PS_LED2_THRESH) ? PROXIMITY_NEAR : PROXIMITY_NONE; event_data.data.proximity.value[2] = (regs.als_ps_status & PS_LED3_THRESH) ? PROXIMITY_NEAR : PROXIMITY_NONE; (event_cb[0].handler)(&event_data, event_cb[0].arg); } } } /** * @brief Read SFH7770 device ID and revision numbers. * * This function reads the sensor hardware identification registers * and returns these values in the specified data structure. * * @param hal Address of an initialized sensor hardware descriptor. * @param data Address of sensor_data_t structure to return values. * @return bool true if the call succeeds, else false is returned. */ static bool sfh7770_device_id(sensor_hal_t *hal, sensor_data_t *data) { uint8_t const part_id = sensor_bus_get(hal, SFH7770_PART_ID); data->device.id = (uint32_t)(part_id & PART_ID_MASK) >> PART_ID_SHIFT; data->device.version = (uint32_t)(part_id & PART_REV_MASK); return true; }
int nvram_updating(void) { return (nvram_read(NVRAM_RTC_FREQ_SELECT) & NVRAM_RTC_UIP) ? 1 : 0; }
static uint8_t NVRAM_get_byte(Nvram *nvram, uint32_t addr) { return nvram_read(nvram, addr); }
int env_load(void) { int size; unsigned char *buffer; unsigned char *ptr; unsigned char *envval; unsigned int reclen; unsigned int rectype; int offset; int flg; int retval = -1; char valuestr[256]; /* * If in 'safe mode', don't read the environment the first time. */ if (cfe_startflags & CFE_INIT_SAFE) { cfe_startflags &= ~CFE_INIT_SAFE; return 0; } flg = nvram_open(); if (flg < 0) return flg; size = nvram_getsize(); buffer = KMALLOC(size,0); if (buffer == NULL) return CFE_ERR_NOMEM; ptr = buffer; offset = 0; /* Read the record type and length */ if (nvram_read(ptr,offset,1) != 1) { retval = CFE_ERR_IOERR; goto error; } while ((*ptr != ENV_TLV_TYPE_END) && (size > 1)) { /* Adjust pointer for TLV type */ rectype = *(ptr); offset++; size--; /* * Read the length. It can be either 1 or 2 bytes * depending on the code */ if (rectype & ENV_LENGTH_8BITS) { /* Read the record type and length - 8 bits */ if (nvram_read(ptr,offset,1) != 1) { retval = CFE_ERR_IOERR; goto error; } reclen = *(ptr); size--; offset++; } else { /* Read the record type and length - 16 bits, MSB first */ if (nvram_read(ptr,offset,2) != 2) { retval = CFE_ERR_IOERR; goto error; } reclen = (((unsigned int) *(ptr)) << 8) + (unsigned int) *(ptr+1); size -= 2; offset += 2; } if (reclen > size) break; /* should not happen, bad NVRAM */ switch (rectype) { case ENV_TLV_TYPE_ENV: /* Read the TLV data */ if (nvram_read(ptr,offset,reclen) != reclen) goto error; flg = *ptr++; envval = (unsigned char *) strnchr(ptr,'=',(reclen-1)); if (envval) { *envval++ = '\0'; memcpy(valuestr,envval,(reclen-1)-(envval-ptr)); valuestr[(reclen-1)-(envval-ptr)] = '\0'; env_setenv(ptr,valuestr,flg); } break; default: /* Unknown TLV type, skip it. */ break; } /* * Advance to next TLV */ size -= (int)reclen; offset += reclen; /* Read the next record type */ ptr = buffer; if (nvram_read(ptr,offset,1) != 1) goto error; } retval = 0; /* success! */ error: KFREE(buffer); nvram_close(); return retval; }