Merge remote-tracking branch 'upstream/master'
This commit is contained in:
commit
20a3b4c0cd
101 changed files with 8203 additions and 1133 deletions
22
extras/bmp180/LICENSE
Normal file
22
extras/bmp180/LICENSE
Normal file
|
|
@ -0,0 +1,22 @@
|
|||
The MIT License (MIT)
|
||||
|
||||
Copyright (c) 2015 Frank Bargstedt
|
||||
|
||||
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.
|
||||
|
||||
56
extras/bmp180/README.md
Normal file
56
extras/bmp180/README.md
Normal file
|
|
@ -0,0 +1,56 @@
|
|||
# Driver for BMP085/BMP180 digital pressure sensor
|
||||
|
||||
This driver is written for usage with the ESP8266 and FreeRTOS ([esp-open-rtos](https://github.com/SuperHouse/esp-open-rtos) and [esp-open-rtos-driver-i2c](https://github.com/kanflo/esp-open-rtos-driver-i2c)).
|
||||
|
||||
### Usage
|
||||
|
||||
Before using the BMP180 module, the function `bmp180_init(SCL_PIN, SDA_PIN)` needs to be called to setup the I2C interface and do validation if the BMP180/BMP085 is accessible.
|
||||
|
||||
If the setup is sucessfully and a measurement is triggered, the result of the measurement is provided to the user as an event send via the `qQueue` provided with `bmp180_trigger_*measurement(pQueue);`
|
||||
|
||||
#### Example
|
||||
|
||||
```
|
||||
#define SCL_PIN GPIO_ID_PIN(0)
|
||||
#define SDA_PIN GPIO_ID_PIN(2)
|
||||
...
|
||||
|
||||
if (!bmp180_init(SCL_PIN, SDA_PIN)) {
|
||||
// An error occured, while dong the init (E.g device not found etc.)
|
||||
}
|
||||
|
||||
// Trigger a measurement
|
||||
bmp180_trigger_measurement(pQueue);
|
||||
|
||||
```
|
||||
|
||||
#### Change queue event
|
||||
|
||||
Per default the event send to the user via the provided queue is of the type `bmp180_result_t`. As this might not always be desired, a way is provided so that the user can provide a function, which creates and sends the event via the provided queue.
|
||||
|
||||
As all data aqquired from the BMP180/BMP085 is provided to the `bmp180_informUser` function, it is also possible to calculate new informations (E.g altitude etc.)
|
||||
|
||||
##### Example
|
||||
|
||||
```
|
||||
// Own BMP180 User Inform Implementation
|
||||
bool my_informUser(const xQueueHandle* resultQueue, uint8_t cmd, bmp180_temp_t temperature, bmp180_press_t pressure) {
|
||||
my_event_t ev;
|
||||
|
||||
ev.event_type = MY_EVT_BMP180;
|
||||
ev.bmp180_data.cmd = cmd;
|
||||
ev.bmp180_data.temperature = temperature;
|
||||
ev.bmp180_data.pressure = pressure;
|
||||
|
||||
return (xQueueSend(*resultQueue, &ev, 0) == pdTRUE);
|
||||
}
|
||||
|
||||
...
|
||||
|
||||
// Use our user inform implementation
|
||||
// needs to be set before first measurement is triggered
|
||||
bmp180_informUser = my_informUser;
|
||||
|
||||
|
||||
```
|
||||
|
||||
351
extras/bmp180/bmp180.c
Normal file
351
extras/bmp180/bmp180.c
Normal file
|
|
@ -0,0 +1,351 @@
|
|||
#include "bmp180.h"
|
||||
|
||||
#include "FreeRTOS.h"
|
||||
#include "queue.h"
|
||||
#include "task.h"
|
||||
|
||||
#include "espressif/esp_common.h"
|
||||
#include "espressif/sdk_private.h"
|
||||
|
||||
#include "i2c/i2c.h"
|
||||
|
||||
#define BMP180_RX_QUEUE_SIZE 10
|
||||
#define BMP180_TASK_PRIORITY 9
|
||||
|
||||
#define BMP180_DEVICE_ADDRESS 0x77
|
||||
|
||||
#define BMP180_VERSION_REG 0xD0
|
||||
#define BMP180_CONTROL_REG 0xF4
|
||||
#define BMP180_RESET_REG 0xE0
|
||||
#define BMP180_OUT_MSB_REG 0xF6
|
||||
#define BMP180_OUT_LSB_REG 0xF7
|
||||
#define BMP180_OUT_XLSB_REG 0xF8
|
||||
|
||||
#define BMP180_CALIBRATION_REG 0xAA
|
||||
|
||||
//
|
||||
// Values for BMP180_CONTROL_REG
|
||||
//
|
||||
#define BMP180_MEASURE_TEMP 0x2E
|
||||
#define BMP180_MEASURE_PRESS_OSS0 0x34
|
||||
#define BMP180_MEASURE_PRESS_OSS1 0x74
|
||||
#define BMP180_MEASURE_PRESS_OSS2 0xB4
|
||||
#define BMP180_MEASURE_PRESS_OSS3 0xF4
|
||||
|
||||
#define BMP180_DEFAULT_CONV_TIME 5000
|
||||
|
||||
//
|
||||
// CHIP ID stored in BMP180_VERSION_REG
|
||||
//
|
||||
#define BMP180_CHIP_ID 0x55
|
||||
|
||||
//
|
||||
// Reset value for BMP180_RESET_REG
|
||||
//
|
||||
#define BMP180_RESET_VALUE 0xB6
|
||||
|
||||
|
||||
// BMP180_Event_Command
|
||||
typedef struct
|
||||
{
|
||||
uint8_t cmd;
|
||||
const xQueueHandle* resultQueue;
|
||||
} bmp180_command_t;
|
||||
|
||||
// Just works due to the fact that xQueueHandle is a "void *"
|
||||
static xQueueHandle bmp180_rx_queue = NULL;
|
||||
static xTaskHandle bmp180_task_handle = NULL;
|
||||
|
||||
// Calibration constants
|
||||
static int16_t AC1;
|
||||
static int16_t AC2;
|
||||
static int16_t AC3;
|
||||
static uint16_t AC4;
|
||||
static uint16_t AC5;
|
||||
static uint16_t AC6;
|
||||
|
||||
static int16_t B1;
|
||||
static int16_t B2;
|
||||
|
||||
static int16_t MB;
|
||||
static int16_t MC;
|
||||
static int16_t MD;
|
||||
|
||||
//
|
||||
// Forward declarations
|
||||
//
|
||||
static void bmp180_meassure(const bmp180_command_t* command);
|
||||
static bool bmp180_informUser_Impl(const xQueueHandle* resultQueue, uint8_t cmd, bmp180_temp_t temperature, bmp180_press_t pressure);
|
||||
|
||||
// Set default implementation .. User gets result as bmp180_result_t event
|
||||
bool (*bmp180_informUser)(const xQueueHandle* resultQueue, uint8_t cmd, bmp180_temp_t temperature, bmp180_press_t pressure) = bmp180_informUser_Impl;
|
||||
|
||||
// I2C Driver Task
|
||||
static void bmp180_driver_task(void *pvParameters)
|
||||
{
|
||||
// Data to be received from user
|
||||
bmp180_command_t current_command;
|
||||
|
||||
#ifdef BMP180_DEBUG
|
||||
// Wait for commands from the outside
|
||||
printf("%s: Started Task\n", __FUNCTION__);
|
||||
#endif
|
||||
|
||||
while(1)
|
||||
{
|
||||
// Wait for user to insert commands
|
||||
if (xQueueReceive(bmp180_rx_queue, ¤t_command, portMAX_DELAY) == pdTRUE)
|
||||
{
|
||||
#ifdef BMP180_DEBUG
|
||||
printf("%s: Received user command %d 0x%p\n", __FUNCTION__, current_command.cmd, current_command.resultQueue);
|
||||
#endif
|
||||
// use user provided queue
|
||||
if (current_command.resultQueue != NULL)
|
||||
{
|
||||
// Work on it ...
|
||||
bmp180_meassure(¤t_command);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static uint8_t bmp180_readRegister8(uint8_t reg)
|
||||
{
|
||||
uint8_t r = 0;
|
||||
|
||||
if (!i2c_slave_read(BMP180_DEVICE_ADDRESS, reg, &r, 1))
|
||||
{
|
||||
r = 0;
|
||||
}
|
||||
return r;
|
||||
}
|
||||
|
||||
|
||||
static int16_t bmp180_readRegister16(uint8_t reg)
|
||||
{
|
||||
uint8_t d[] = { 0, 0 };
|
||||
int16_t r = 0;
|
||||
|
||||
if (i2c_slave_read(BMP180_DEVICE_ADDRESS, reg, d, 2))
|
||||
{
|
||||
r = ((int16_t)d[0]<<8) | (d[1]);
|
||||
}
|
||||
return r;
|
||||
}
|
||||
|
||||
static void bmp180_start_Messurement(uint8_t cmd)
|
||||
{
|
||||
uint8_t d[] = { BMP180_CONTROL_REG, cmd };
|
||||
|
||||
i2c_slave_write(BMP180_DEVICE_ADDRESS, d, 2);
|
||||
}
|
||||
|
||||
static int16_t bmp180_getUncompensatedMessurement(uint8_t cmd)
|
||||
{
|
||||
// Write Start Code into reg 0xF4 (Currently without oversampling ...)
|
||||
bmp180_start_Messurement((cmd==BMP180_TEMPERATURE)?BMP180_MEASURE_TEMP:BMP180_MEASURE_PRESS_OSS0);
|
||||
|
||||
// Wait 5ms Datasheet states 4.5ms
|
||||
sdk_os_delay_us(BMP180_DEFAULT_CONV_TIME);
|
||||
|
||||
return (int16_t)bmp180_readRegister16(BMP180_OUT_MSB_REG);
|
||||
}
|
||||
|
||||
static void bmp180_fillInternalConstants(void)
|
||||
{
|
||||
AC1 = bmp180_readRegister16(BMP180_CALIBRATION_REG+0);
|
||||
AC2 = bmp180_readRegister16(BMP180_CALIBRATION_REG+2);
|
||||
AC3 = bmp180_readRegister16(BMP180_CALIBRATION_REG+4);
|
||||
AC4 = bmp180_readRegister16(BMP180_CALIBRATION_REG+6);
|
||||
AC5 = bmp180_readRegister16(BMP180_CALIBRATION_REG+8);
|
||||
AC6 = bmp180_readRegister16(BMP180_CALIBRATION_REG+10);
|
||||
|
||||
B1 = bmp180_readRegister16(BMP180_CALIBRATION_REG+12);
|
||||
B2 = bmp180_readRegister16(BMP180_CALIBRATION_REG+14);
|
||||
|
||||
MB = bmp180_readRegister16(BMP180_CALIBRATION_REG+16);
|
||||
MC = bmp180_readRegister16(BMP180_CALIBRATION_REG+18);
|
||||
MD = bmp180_readRegister16(BMP180_CALIBRATION_REG+20);
|
||||
|
||||
#ifdef BMP180_DEBUG
|
||||
printf("%s: AC1:=%d AC2:=%d AC3:=%d AC4:=%u AC5:=%u AC6:=%u \n", __FUNCTION__, AC1, AC2, AC3, AC4, AC5, AC6);
|
||||
printf("%s: B1:=%d B2:=%d\n", __FUNCTION__, B1, B2);
|
||||
printf("%s: MB:=%d MC:=%d MD:=%d\n", __FUNCTION__, MB, MC, MD);
|
||||
#endif
|
||||
}
|
||||
|
||||
static bool bmp180_create_communication_queues()
|
||||
{
|
||||
// Just create them once
|
||||
if (bmp180_rx_queue==NULL)
|
||||
{
|
||||
bmp180_rx_queue = xQueueCreate(BMP180_RX_QUEUE_SIZE, sizeof(bmp180_result_t));
|
||||
}
|
||||
|
||||
return (bmp180_rx_queue!=NULL);
|
||||
}
|
||||
|
||||
static bool bmp180_is_avaialble()
|
||||
{
|
||||
return (bmp180_readRegister8(BMP180_VERSION_REG)==BMP180_CHIP_ID);
|
||||
}
|
||||
|
||||
static bool bmp180_createTask()
|
||||
{
|
||||
// We already have a task
|
||||
portBASE_TYPE x = pdPASS;
|
||||
|
||||
if (bmp180_task_handle==NULL)
|
||||
{
|
||||
x = xTaskCreate(bmp180_driver_task, (signed char *)"bmp180_driver_task", 256, NULL, BMP180_TASK_PRIORITY, &bmp180_task_handle);
|
||||
}
|
||||
return (x==pdPASS);
|
||||
}
|
||||
|
||||
static void bmp180_meassure(const bmp180_command_t* command)
|
||||
{
|
||||
int32_t T, P;
|
||||
|
||||
// Init result to 0
|
||||
T = P = 0;
|
||||
|
||||
if (command->resultQueue != NULL)
|
||||
{
|
||||
int32_t UT, X1, X2, B5;
|
||||
|
||||
//
|
||||
// Temperature is always needed ... Also required for pressure only
|
||||
//
|
||||
// Calculation taken from BMP180 Datasheet
|
||||
UT = (int32_t)bmp180_getUncompensatedMessurement(BMP180_TEMPERATURE);
|
||||
|
||||
X1 = (UT - (int32_t)AC6) * ((int32_t)AC5) >> 15;
|
||||
X2 = ((int32_t)MC << 11) / (X1 + (int32_t)MD);
|
||||
B5 = X1 + X2;
|
||||
|
||||
T = (B5 + 8) >> 4;
|
||||
|
||||
#ifdef BMP180_DEBUG
|
||||
printf("%s: T:= %ld.%d\n", __FUNCTION__, T/10, abs(T%10));
|
||||
#endif
|
||||
|
||||
// Do we also need pressure?
|
||||
if (command->cmd & BMP180_PRESSURE)
|
||||
{
|
||||
int32_t X3, B3, B6;
|
||||
uint32_t B4, B7, UP;
|
||||
|
||||
UP = ((uint32_t)bmp180_getUncompensatedMessurement(BMP180_PRESSURE) & 0xFFFF);
|
||||
|
||||
// Calculation taken from BMP180 Datasheet
|
||||
B6 = B5 - 4000;
|
||||
X1 = ((int32_t)B2 * ((B6 * B6) >> 12)) >> 11;
|
||||
X2 = ((int32_t)AC2 * B6) >> 11;
|
||||
X3 = X1 + X2;
|
||||
|
||||
B3 = (((int32_t)AC1 * 4 + X3) + 2) >> 2;
|
||||
X1 = ((int32_t)AC3 * B6) >> 13;
|
||||
X2 = ((int32_t)B1 * ((B6 * B6) >> 12)) >> 16;
|
||||
X3 = ((X1 + X2) + 2) >> 2;
|
||||
B4 = ((uint32_t)AC4 * (uint32_t)(X3 + 32768)) >> 15;
|
||||
B7 = (UP - B3) * (uint32_t)(50000UL);
|
||||
|
||||
if (B7 < 0x80000000)
|
||||
{
|
||||
P = (B7 * 2) / B4;
|
||||
}
|
||||
else
|
||||
{
|
||||
P = (B7 / B4) * 2;
|
||||
}
|
||||
|
||||
X1 = (P >> 8) * (P >> 8);
|
||||
X1 = (X1 * 3038) >> 16;
|
||||
X2 = (-7357 * P) >> 16;
|
||||
P = P + ((X1 + X2 + (int32_t)3791) >> 4);
|
||||
|
||||
#ifdef BMP180_DEBUG
|
||||
printf("%s: P:= %ld\n", __FUNCTION__, P);
|
||||
#endif
|
||||
}
|
||||
|
||||
// Inform the user ...
|
||||
if (!bmp180_informUser(command->resultQueue, command->cmd, ((bmp180_temp_t)T)/10.0, (bmp180_press_t)P))
|
||||
{
|
||||
// Failed to send info to user
|
||||
printf("%s: Unable to inform user bmp180_informUser returned \"false\"\n", __FUNCTION__);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Default user inform implementation
|
||||
static bool bmp180_informUser_Impl(const xQueueHandle* resultQueue, uint8_t cmd, bmp180_temp_t temperature, bmp180_press_t pressure)
|
||||
{
|
||||
bmp180_result_t result;
|
||||
|
||||
result.cmd = cmd;
|
||||
result.temperature = temperature;
|
||||
result.pressure = pressure;
|
||||
|
||||
return (xQueueSend(*resultQueue, &result, 0) == pdTRUE);
|
||||
}
|
||||
|
||||
// Just init all needed queues
|
||||
bool bmp180_init(uint8_t scl, uint8_t sda)
|
||||
{
|
||||
// 1. Create required queues
|
||||
bool result = false;
|
||||
|
||||
if (bmp180_create_communication_queues())
|
||||
{
|
||||
// 2. Init i2c driver
|
||||
i2c_init(scl, sda);
|
||||
|
||||
// 3. Check for bmp180 ...
|
||||
if (bmp180_is_avaialble())
|
||||
{
|
||||
// 4. Init all internal constants ...
|
||||
bmp180_fillInternalConstants();
|
||||
|
||||
// 5. Start driver task
|
||||
if (bmp180_createTask())
|
||||
{
|
||||
// We are finished
|
||||
result = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
void bmp180_trigger_measurement(const xQueueHandle* resultQueue)
|
||||
{
|
||||
bmp180_command_t c;
|
||||
|
||||
c.cmd = BMP180_PRESSURE + BMP180_TEMPERATURE;
|
||||
c.resultQueue = resultQueue;
|
||||
|
||||
xQueueSend(bmp180_rx_queue, &c, 0);
|
||||
}
|
||||
|
||||
|
||||
void bmp180_trigger_pressure_measurement(const xQueueHandle* resultQueue)
|
||||
{
|
||||
bmp180_command_t c;
|
||||
|
||||
c.cmd = BMP180_PRESSURE;
|
||||
c.resultQueue = resultQueue;
|
||||
|
||||
xQueueSend(bmp180_rx_queue, &c, 0);
|
||||
}
|
||||
|
||||
void bmp180_trigger_temperature_measurement(const xQueueHandle* resultQueue)
|
||||
{
|
||||
bmp180_command_t c;
|
||||
|
||||
c.cmd = BMP180_TEMPERATURE;
|
||||
c.resultQueue = resultQueue;
|
||||
|
||||
xQueueSend(bmp180_rx_queue, &c, 0);
|
||||
}
|
||||
55
extras/bmp180/bmp180.h
Normal file
55
extras/bmp180/bmp180.h
Normal file
|
|
@ -0,0 +1,55 @@
|
|||
/*
|
||||
* bmp180.h
|
||||
*
|
||||
* Created on: 23.08.2015
|
||||
* Author: fbargste
|
||||
*/
|
||||
|
||||
#ifndef DRIVER_BMP180_H_
|
||||
#define DRIVER_BMP180_H_
|
||||
|
||||
#include "stdint.h"
|
||||
#include "stdbool.h"
|
||||
|
||||
#include "FreeRTOS.h"
|
||||
#include "queue.h"
|
||||
|
||||
// Uncomment to enable debug output
|
||||
//#define BMP180_DEBUG
|
||||
|
||||
#define BMP180_TEMPERATURE (1<<0)
|
||||
#define BMP180_PRESSURE (1<<1)
|
||||
|
||||
//
|
||||
// Create bmp180_types
|
||||
//
|
||||
|
||||
// temperature in °C
|
||||
typedef float bmp180_temp_t;
|
||||
// pressure in mPa (To get hPa divide by 100)
|
||||
typedef uint32_t bmp180_press_t;
|
||||
|
||||
// BMP180_Event_Result
|
||||
typedef struct
|
||||
{
|
||||
uint8_t cmd;
|
||||
bmp180_temp_t temperature;
|
||||
bmp180_press_t pressure;
|
||||
} bmp180_result_t;
|
||||
|
||||
// Init bmp180 driver ...
|
||||
bool bmp180_init(uint8_t scl, uint8_t sda);
|
||||
|
||||
// Trigger a "complete" measurement (temperature and pressure will be valid when given to "bmp180_informUser)
|
||||
void bmp180_trigger_measurement(const xQueueHandle* resultQueue);
|
||||
|
||||
// Trigger a "temperature only" measurement (only temperature will be valid when given to "bmp180_informUser)
|
||||
void bmp180_trigger_temperature_measurement(const xQueueHandle* resultQueue);
|
||||
|
||||
// Trigger a "pressure only" measurement (only pressure will be valid when given to "bmp180_informUser)
|
||||
void bmp180_trigger_pressure_measurement(const xQueueHandle* resultQueue);
|
||||
|
||||
// Give the user the chance to create it's own handler
|
||||
extern bool (*bmp180_informUser)(const xQueueHandle* resultQueue, uint8_t cmd, bmp180_temp_t temperature, bmp180_press_t pressure);
|
||||
|
||||
#endif /* DRIVER_BMP180_H_ */
|
||||
9
extras/bmp180/component.mk
Normal file
9
extras/bmp180/component.mk
Normal file
|
|
@ -0,0 +1,9 @@
|
|||
# Component makefile for extras/bmp180
|
||||
|
||||
# expected anyone using bmp driver includes it as 'bmp180/bmp180.h'
|
||||
INC_DIRS += $(bmp180_ROOT)..
|
||||
|
||||
# args for passing into compile rule generation
|
||||
bmp180_SRC_DIR = $(bmp180_ROOT)
|
||||
|
||||
$(eval $(call component_compile_rules,bmp180))
|
||||
8
extras/cpp_support/component.mk
Normal file
8
extras/cpp_support/component.mk
Normal file
|
|
@ -0,0 +1,8 @@
|
|||
# Component makefile for extras/cpp_support
|
||||
INC_DIRS += $(ROOT)extras/cpp_support/include
|
||||
|
||||
# args for passing into compile rule generation
|
||||
# extras/mqtt-client_INC_DIR = $(ROOT)extras/mqtt-client
|
||||
# extras/mqtt-client_SRC_DIR = $(ROOT)extras/mqtt-client
|
||||
|
||||
# $(eval $(call component_compile_rules,extras/mqtt-client))
|
||||
102
extras/cpp_support/include/countdown.hpp
Normal file
102
extras/cpp_support/include/countdown.hpp
Normal file
|
|
@ -0,0 +1,102 @@
|
|||
/*
|
||||
* The MIT License (MIT)
|
||||
*
|
||||
* ESP8266 FreeRTOS Firmware
|
||||
* Copyright (c) 2015 Michael Jacobsen (github.com/mikejac)
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
* https://github.com/SuperHouse/esp-open-rtos
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef ESP_OPEN_RTOS_TIMER_HPP
|
||||
#define ESP_OPEN_RTOS_TIMER_HPP
|
||||
|
||||
#include "FreeRTOS.h"
|
||||
#include "task.h"
|
||||
|
||||
namespace esp_open_rtos {
|
||||
namespace timer {
|
||||
|
||||
#define __millis() (xTaskGetTickCount() * portTICK_RATE_MS)
|
||||
|
||||
/******************************************************************************************************************
|
||||
* countdown_t
|
||||
*
|
||||
*/
|
||||
class countdown_t
|
||||
{
|
||||
public:
|
||||
/**
|
||||
*
|
||||
*/
|
||||
countdown_t()
|
||||
{
|
||||
interval_end_ms = 0L;
|
||||
}
|
||||
/**
|
||||
*
|
||||
* @param ms
|
||||
*/
|
||||
countdown_t(int ms)
|
||||
{
|
||||
countdown_ms(ms);
|
||||
}
|
||||
/**
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
bool expired()
|
||||
{
|
||||
return (interval_end_ms > 0L) && (__millis() >= interval_end_ms);
|
||||
}
|
||||
/**
|
||||
*
|
||||
* @param ms
|
||||
*/
|
||||
void countdown_ms(unsigned long ms)
|
||||
{
|
||||
interval_end_ms = __millis() + ms;
|
||||
}
|
||||
/**
|
||||
*
|
||||
* @param seconds
|
||||
*/
|
||||
void countdown(int seconds)
|
||||
{
|
||||
countdown_ms((unsigned long)seconds * 1000L);
|
||||
}
|
||||
/**
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
int left_ms()
|
||||
{
|
||||
return interval_end_ms - __millis();
|
||||
}
|
||||
|
||||
private:
|
||||
portTickType interval_end_ms;
|
||||
};
|
||||
|
||||
} // namespace timer {
|
||||
} // namespace esp_open_rtos {
|
||||
|
||||
#endif
|
||||
113
extras/cpp_support/include/mutex.hpp
Normal file
113
extras/cpp_support/include/mutex.hpp
Normal file
|
|
@ -0,0 +1,113 @@
|
|||
/*
|
||||
* The MIT License (MIT)
|
||||
*
|
||||
* ESP8266 FreeRTOS Firmware
|
||||
* Copyright (c) 2015 Michael Jacobsen (github.com/mikejac)
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
* https://github.com/SuperHouse/esp-open-rtos
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef ESP_OPEN_RTOS_MUTEX_HPP
|
||||
#define ESP_OPEN_RTOS_MUTEX_HPP
|
||||
|
||||
#include "semphr.h"
|
||||
|
||||
namespace esp_open_rtos {
|
||||
namespace thread {
|
||||
|
||||
/******************************************************************************************************************
|
||||
* class mutex_t
|
||||
*
|
||||
*/
|
||||
class mutex_t
|
||||
{
|
||||
public:
|
||||
/**
|
||||
*
|
||||
*/
|
||||
inline mutex_t()
|
||||
{
|
||||
mutex = 0;
|
||||
}
|
||||
/**
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
inline int mutex_create()
|
||||
{
|
||||
mutex = xSemaphoreCreateMutex();
|
||||
|
||||
if(mutex == NULL) {
|
||||
return -1;
|
||||
}
|
||||
else {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
/**
|
||||
*
|
||||
*/
|
||||
inline void mutex_destroy()
|
||||
{
|
||||
vQueueDelete(mutex);
|
||||
mutex = 0;
|
||||
}
|
||||
/**
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
inline int lock()
|
||||
{
|
||||
return (xSemaphoreTake(mutex, portMAX_DELAY) == pdTRUE) ? 0 : -1;
|
||||
}
|
||||
/**
|
||||
*
|
||||
* @param ms
|
||||
* @return
|
||||
*/
|
||||
inline int try_lock(unsigned long ms)
|
||||
{
|
||||
return (xSemaphoreTake(mutex, ms / portTICK_RATE_MS) == pdTRUE) ? 0 : -1;
|
||||
}
|
||||
/**
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
inline int unlock()
|
||||
{
|
||||
return (xSemaphoreGive(mutex) == pdTRUE) ? 0 : -1;
|
||||
}
|
||||
|
||||
private:
|
||||
xSemaphoreHandle mutex;
|
||||
|
||||
// Disable copy construction and assignment.
|
||||
mutex_t (const mutex_t&);
|
||||
const mutex_t &operator = (const mutex_t&);
|
||||
};
|
||||
|
||||
} //namespace thread {
|
||||
} //namespace esp_open_rtos {
|
||||
|
||||
|
||||
#endif /* ESP_OPEN_RTOS_MUTEX_HPP */
|
||||
|
||||
124
extras/cpp_support/include/queue.hpp
Normal file
124
extras/cpp_support/include/queue.hpp
Normal file
|
|
@ -0,0 +1,124 @@
|
|||
/*
|
||||
* The MIT License (MIT)
|
||||
*
|
||||
* ESP8266 FreeRTOS Firmware
|
||||
* Copyright (c) 2015 Michael Jacobsen (github.com/mikejac)
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
* https://github.com/SuperHouse/esp-open-rtos
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef ESP_OPEN_RTOS_QUEUE_HPP
|
||||
#define ESP_OPEN_RTOS_QUEUE_HPP
|
||||
|
||||
#include "FreeRTOS.h"
|
||||
#include "queue.h"
|
||||
|
||||
namespace esp_open_rtos {
|
||||
namespace thread {
|
||||
|
||||
/******************************************************************************************************************
|
||||
* class queue_t
|
||||
*
|
||||
*/
|
||||
template<class Data>
|
||||
class queue_t
|
||||
{
|
||||
public:
|
||||
/**
|
||||
*
|
||||
*/
|
||||
inline queue_t()
|
||||
{
|
||||
queue = 0;
|
||||
}
|
||||
/**
|
||||
*
|
||||
* @param uxQueueLength
|
||||
* @param uxItemSize
|
||||
* @return
|
||||
*/
|
||||
inline int queue_create(unsigned portBASE_TYPE uxQueueLength)
|
||||
{
|
||||
queue = xQueueCreate(uxQueueLength, sizeof(Data));
|
||||
|
||||
if(queue == NULL) {
|
||||
return -1;
|
||||
}
|
||||
else {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
/**
|
||||
*
|
||||
*/
|
||||
inline void queue_destroy()
|
||||
{
|
||||
vQueueDelete(queue);
|
||||
queue = 0;
|
||||
}
|
||||
/**
|
||||
*
|
||||
* @param data
|
||||
* @param ms
|
||||
* @return
|
||||
*/
|
||||
inline int post(const Data& data, unsigned long ms = 0)
|
||||
{
|
||||
return (xQueueSend(queue, &data, ms / portTICK_RATE_MS) == pdTRUE) ? 0 : -1;
|
||||
}
|
||||
/**
|
||||
*
|
||||
* @param data
|
||||
* @param ms
|
||||
* @return
|
||||
*/
|
||||
inline int receive(Data& data, unsigned long ms = 0)
|
||||
{
|
||||
return (xQueueReceive(queue, &data, ms / portTICK_RATE_MS) == pdTRUE) ? 0 : -1;
|
||||
}
|
||||
/**
|
||||
*
|
||||
* @param other
|
||||
* @return
|
||||
*/
|
||||
const queue_t &operator = (const queue_t& other)
|
||||
{
|
||||
if(this != &other) { // protect against invalid self-assignment
|
||||
queue = other.queue;
|
||||
}
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
private:
|
||||
xQueueHandle queue;
|
||||
|
||||
// Disable copy construction.
|
||||
queue_t (const queue_t&);
|
||||
};
|
||||
|
||||
} //namespace thread {
|
||||
} //namespace esp_open_rtos {
|
||||
|
||||
|
||||
#endif /* ESP_OPEN_RTOS_QUEUE_HPP */
|
||||
|
||||
106
extras/cpp_support/include/task.hpp
Normal file
106
extras/cpp_support/include/task.hpp
Normal file
|
|
@ -0,0 +1,106 @@
|
|||
/*
|
||||
* The MIT License (MIT)
|
||||
*
|
||||
* ESP8266 FreeRTOS Firmware
|
||||
* Copyright (c) 2015 Michael Jacobsen (github.com/mikejac)
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
* https://github.com/SuperHouse/esp-open-rtos
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef ESP_OPEN_RTOS_TASK_HPP
|
||||
#define ESP_OPEN_RTOS_TASK_HPP
|
||||
|
||||
#include "FreeRTOS.h"
|
||||
#include "task.h"
|
||||
|
||||
namespace esp_open_rtos {
|
||||
namespace thread {
|
||||
|
||||
/******************************************************************************************************************
|
||||
* task_t
|
||||
*
|
||||
*/
|
||||
class task_t
|
||||
{
|
||||
public:
|
||||
/**
|
||||
*
|
||||
*/
|
||||
task_t()
|
||||
{}
|
||||
/**
|
||||
*
|
||||
* @param pcName
|
||||
* @param usStackDepth
|
||||
* @param uxPriority
|
||||
* @return
|
||||
*/
|
||||
int task_create(const char* const pcName, unsigned short usStackDepth = 256, unsigned portBASE_TYPE uxPriority = 2)
|
||||
{
|
||||
return xTaskCreate(task_t::_task, (signed char *)pcName, usStackDepth, this, uxPriority, NULL);
|
||||
}
|
||||
|
||||
protected:
|
||||
/**
|
||||
*
|
||||
* @param ms
|
||||
*/
|
||||
void sleep(unsigned long ms)
|
||||
{
|
||||
vTaskDelay(ms / portTICK_RATE_MS);
|
||||
}
|
||||
/**
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
inline unsigned long millis()
|
||||
{
|
||||
return xTaskGetTickCount() * portTICK_RATE_MS;
|
||||
}
|
||||
|
||||
private:
|
||||
/**
|
||||
*
|
||||
*/
|
||||
virtual void task() = 0;
|
||||
/**
|
||||
*
|
||||
* @param pvParameters
|
||||
*/
|
||||
static void _task(void* pvParameters)
|
||||
{
|
||||
if(pvParameters != 0) {
|
||||
((task_t*)(pvParameters))->task();
|
||||
}
|
||||
}
|
||||
|
||||
// no copy and no = operator
|
||||
task_t(const task_t&);
|
||||
task_t &operator=(const task_t&);
|
||||
};
|
||||
|
||||
} //namespace thread {
|
||||
} //namespace esp_open_rtos {
|
||||
|
||||
|
||||
#endif /* ESP_OPEN_RTOS_TASK_HPP */
|
||||
|
||||
22
extras/i2c/LICENSE
Normal file
22
extras/i2c/LICENSE
Normal file
|
|
@ -0,0 +1,22 @@
|
|||
The MIT License (MIT)
|
||||
|
||||
Copyright (c) 2015 Johan Kanflo
|
||||
|
||||
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.
|
||||
|
||||
40
extras/i2c/README.md
Normal file
40
extras/i2c/README.md
Normal file
|
|
@ -0,0 +1,40 @@
|
|||
# Yet another I2C driver for the ESP8266
|
||||
|
||||
This time a driver for the excellent esp-open-rtos. This is a bit banging I2C driver based on the Wikipedia pesudo C code [1].
|
||||
|
||||
### Adding to your project
|
||||
|
||||
Add the driver to your project as a submodule rather than cloning it:
|
||||
|
||||
````
|
||||
% git submodule add https://github.com/kanflo/esp-open-rtos-driver-i2c.git i2c
|
||||
````
|
||||
The esp-open-rtos makefile-fu will make sure the driver is built.
|
||||
|
||||
### Usage
|
||||
|
||||
|
||||
````
|
||||
#include <i2c.h>
|
||||
|
||||
#define SCL_PIN (0)
|
||||
#define SDA_PIN (2)
|
||||
|
||||
uint8_t slave_addr = 0x20;
|
||||
uint8_t reg_addr = 0x1f;
|
||||
uint8_t reg_data;
|
||||
uint8_t data[] = {reg_addr, 0xc8};
|
||||
|
||||
i2c_init(SCL_PIN, SDA_PIN);
|
||||
|
||||
// Write data to slave
|
||||
bool success = i2c_slave_write(slave_addr, data, sizeof(data));
|
||||
|
||||
// Issue write to slave, sending reg_addr, followed by reading 1 byte
|
||||
success = i2c_slave_read(slave_addr, ®_addr, reg_data, 1);
|
||||
|
||||
````
|
||||
|
||||
The driver is released under the MIT license.
|
||||
|
||||
[1] https://en.wikipedia.org/wiki/I²C#Example_of_bit-banging_the_I.C2.B2C_Master_protocol
|
||||
10
extras/i2c/component.mk
Normal file
10
extras/i2c/component.mk
Normal file
|
|
@ -0,0 +1,10 @@
|
|||
# Component makefile for extras/i2c
|
||||
|
||||
# expected anyone using i2c driver includes it as 'i2c/i2c.h'
|
||||
INC_DIRS += $(i2c_ROOT)..
|
||||
|
||||
# args for passing into compile rule generation
|
||||
i2c_INC_DIR =
|
||||
i2c_SRC_DIR = $(i2c_ROOT)
|
||||
|
||||
$(eval $(call component_compile_rules,i2c))
|
||||
229
extras/i2c/i2c.c
Normal file
229
extras/i2c/i2c.c
Normal file
|
|
@ -0,0 +1,229 @@
|
|||
/*
|
||||
* The MIT License (MIT)
|
||||
*
|
||||
* Copyright (c) 2015 Johan Kanflo (github.com/kanflo)
|
||||
*
|
||||
* 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 <esp8266.h>
|
||||
#include <espressif/esp_misc.h> // sdk_os_delay_us
|
||||
#include "i2c.h"
|
||||
|
||||
|
||||
// I2C driver for ESP8266 written for use with esp-open-rtos
|
||||
// Based on https://en.wikipedia.org/wiki/I²C#Example_of_bit-banging_the_I.C2.B2C_Master_protocol
|
||||
|
||||
// With calling overhead, we end up at ~100kbit/s
|
||||
#define CLK_HALF_PERIOD_US (1)
|
||||
|
||||
#define CLK_STRETCH (10)
|
||||
|
||||
static bool started;
|
||||
static uint8_t g_scl_pin;
|
||||
static uint8_t g_sda_pin;
|
||||
|
||||
void i2c_init(uint8_t scl_pin, uint8_t sda_pin)
|
||||
{
|
||||
started = false;
|
||||
g_scl_pin = scl_pin;
|
||||
g_sda_pin = sda_pin;
|
||||
}
|
||||
|
||||
static void i2c_delay(void)
|
||||
{
|
||||
sdk_os_delay_us(CLK_HALF_PERIOD_US);
|
||||
}
|
||||
|
||||
// Set SCL as input and return current level of line, 0 or 1
|
||||
static bool read_scl(void)
|
||||
{
|
||||
gpio_enable(g_scl_pin, GPIO_INPUT);
|
||||
return gpio_read(g_scl_pin); // Clock high, valid ACK
|
||||
}
|
||||
|
||||
// Set SDA as input and return current level of line, 0 or 1
|
||||
static bool read_sda(void)
|
||||
{
|
||||
gpio_enable(g_sda_pin, GPIO_INPUT);
|
||||
// TODO: Without this delay we get arbitration lost in i2c_stop
|
||||
i2c_delay();
|
||||
return gpio_read(g_sda_pin); // Clock high, valid ACK
|
||||
}
|
||||
|
||||
// Actively drive SCL signal low
|
||||
static void clear_scl(void)
|
||||
{
|
||||
gpio_enable(g_scl_pin, GPIO_OUTPUT);
|
||||
gpio_write(g_scl_pin, 0);
|
||||
}
|
||||
|
||||
// Actively drive SDA signal low
|
||||
static void clear_sda(void)
|
||||
{
|
||||
gpio_enable(g_sda_pin, GPIO_OUTPUT);
|
||||
gpio_write(g_sda_pin, 0);
|
||||
}
|
||||
|
||||
// Output start condition
|
||||
void i2c_start(void)
|
||||
{
|
||||
uint32_t clk_stretch = CLK_STRETCH;
|
||||
if (started) { // if started, do a restart cond
|
||||
// Set SDA to 1
|
||||
(void) read_sda();
|
||||
i2c_delay();
|
||||
while (read_scl() == 0 && clk_stretch--) ;
|
||||
// Repeated start setup time, minimum 4.7us
|
||||
i2c_delay();
|
||||
}
|
||||
if (read_sda() == 0) {
|
||||
printf("I2C: arbitration lost in i2c_start\n");
|
||||
}
|
||||
// SCL is high, set SDA from 1 to 0.
|
||||
clear_sda();
|
||||
i2c_delay();
|
||||
clear_scl();
|
||||
started = true;
|
||||
}
|
||||
|
||||
// Output stop condition
|
||||
void i2c_stop(void)
|
||||
{
|
||||
uint32_t clk_stretch = CLK_STRETCH;
|
||||
// Set SDA to 0
|
||||
clear_sda();
|
||||
i2c_delay();
|
||||
// Clock stretching
|
||||
while (read_scl() == 0 && clk_stretch--) ;
|
||||
// Stop bit setup time, minimum 4us
|
||||
i2c_delay();
|
||||
// SCL is high, set SDA from 0 to 1
|
||||
if (read_sda() == 0) {
|
||||
printf("I2C: arbitration lost in i2c_stop\n");
|
||||
}
|
||||
i2c_delay();
|
||||
started = false;
|
||||
}
|
||||
|
||||
// Write a bit to I2C bus
|
||||
static void i2c_write_bit(bool bit)
|
||||
{
|
||||
uint32_t clk_stretch = CLK_STRETCH;
|
||||
if (bit) {
|
||||
(void) read_sda();
|
||||
} else {
|
||||
clear_sda();
|
||||
}
|
||||
i2c_delay();
|
||||
// Clock stretching
|
||||
while (read_scl() == 0 && clk_stretch--) ;
|
||||
// SCL is high, now data is valid
|
||||
// If SDA is high, check that nobody else is driving SDA
|
||||
if (bit && read_sda() == 0) {
|
||||
printf("I2C: arbitration lost in i2c_write_bit\n");
|
||||
}
|
||||
i2c_delay();
|
||||
clear_scl();
|
||||
}
|
||||
|
||||
// Read a bit from I2C bus
|
||||
static bool i2c_read_bit(void)
|
||||
{
|
||||
uint32_t clk_stretch = CLK_STRETCH;
|
||||
bool bit;
|
||||
// Let the slave drive data
|
||||
(void) read_sda();
|
||||
i2c_delay();
|
||||
// Clock stretching
|
||||
while (read_scl() == 0 && clk_stretch--) ;
|
||||
// SCL is high, now data is valid
|
||||
bit = read_sda();
|
||||
i2c_delay();
|
||||
clear_scl();
|
||||
return bit;
|
||||
}
|
||||
|
||||
bool i2c_write(uint8_t byte)
|
||||
{
|
||||
bool nack;
|
||||
uint8_t bit;
|
||||
for (bit = 0; bit < 8; bit++) {
|
||||
i2c_write_bit((byte & 0x80) != 0);
|
||||
byte <<= 1;
|
||||
}
|
||||
nack = i2c_read_bit();
|
||||
return !nack;
|
||||
}
|
||||
|
||||
uint8_t i2c_read(bool ack)
|
||||
{
|
||||
uint8_t byte = 0;
|
||||
uint8_t bit;
|
||||
for (bit = 0; bit < 8; bit++) {
|
||||
byte = (byte << 1) | i2c_read_bit();
|
||||
}
|
||||
i2c_write_bit(ack);
|
||||
return byte;
|
||||
}
|
||||
|
||||
bool i2c_slave_write(uint8_t slave_addr, uint8_t *data, uint8_t len)
|
||||
{
|
||||
bool success = false;
|
||||
do {
|
||||
i2c_start();
|
||||
if (!i2c_write(slave_addr << 1))
|
||||
break;
|
||||
while (len--) {
|
||||
if (!i2c_write(*data++))
|
||||
break;
|
||||
}
|
||||
i2c_stop();
|
||||
success = true;
|
||||
} while(0);
|
||||
return success;
|
||||
}
|
||||
|
||||
bool i2c_slave_read(uint8_t slave_addr, uint8_t data, uint8_t *buf, uint32_t len)
|
||||
{
|
||||
bool success = false;
|
||||
do {
|
||||
i2c_start();
|
||||
if (!i2c_write(slave_addr << 1)) {
|
||||
break;
|
||||
}
|
||||
i2c_write(data);
|
||||
i2c_stop();
|
||||
i2c_start();
|
||||
if (!i2c_write(slave_addr << 1 | 1)) { // Slave address + read
|
||||
break;
|
||||
}
|
||||
while(len) {
|
||||
*buf = i2c_read(len == 1);
|
||||
buf++;
|
||||
len--;
|
||||
}
|
||||
success = true;
|
||||
} while(0);
|
||||
i2c_stop();
|
||||
if (!success) {
|
||||
printf("I2C: write error\n");
|
||||
}
|
||||
return success;
|
||||
}
|
||||
51
extras/i2c/i2c.h
Normal file
51
extras/i2c/i2c.h
Normal file
|
|
@ -0,0 +1,51 @@
|
|||
/*
|
||||
* The MIT License (MIT)
|
||||
*
|
||||
* Copyright (c) 2015 Johan Kanflo (github.com/kanflo)
|
||||
*
|
||||
* 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 __I2C_H__
|
||||
#define __I2C_H__
|
||||
#endif
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stdbool.h>
|
||||
|
||||
// Init bitbanging I2C driver on given pins
|
||||
void i2c_init(uint8_t scl_pin, uint8_t sda_pin);
|
||||
|
||||
// Write a byte to I2C bus. Return true if slave acked.
|
||||
bool i2c_write(uint8_t byte);
|
||||
|
||||
// Read a byte from I2C bus. Return true if slave acked.
|
||||
uint8_t i2c_read(bool ack);
|
||||
|
||||
// Write 'len' bytes from 'buf' to slave. Return true if slave acked.
|
||||
bool i2c_slave_write(uint8_t slave_addr, uint8_t *buf, uint8_t len);
|
||||
|
||||
// Issue a read operation and send 'data', followed by reading 'len' bytes
|
||||
// from slave into 'buf'. Return true if slave acked.
|
||||
bool i2c_slave_read(uint8_t slave_addr, uint8_t data, uint8_t *buf, uint32_t len);
|
||||
|
||||
// Send start and stop conditions. Only needed when implementing protocols for
|
||||
// devices where the i2c_slave_[read|write] functions above are of no use.
|
||||
void i2c_start(void);
|
||||
void i2c_stop(void);
|
||||
56
extras/mbedtls/component.mk
Normal file
56
extras/mbedtls/component.mk
Normal file
|
|
@ -0,0 +1,56 @@
|
|||
# Component makefile for mbedtls
|
||||
|
||||
# mbedtls by default builds into 3 libraries not one. We just use one for now (doesn't make a huge difference when static linking)
|
||||
|
||||
# Config:
|
||||
# We supply our own hand tweaked mbedtls/config.h in our 'include' dir, the rest of upstream mbedtls is not changed.
|
||||
|
||||
MBEDTLS_DIR = $(mbedtls_ROOT)mbedtls/
|
||||
INC_DIRS += $(mbedtls_ROOT)include $(MBEDTLS_DIR)include
|
||||
|
||||
# these OBJS_xxx variables are copied directly from mbedtls/mbedtls/Makefile,
|
||||
# minus a few values (noted in comments)
|
||||
#
|
||||
# If updating to a future mbedtls version you can just copy these in.
|
||||
OBJS_CRYPTO= aes.o aesni.o arc4.o \
|
||||
asn1parse.o asn1write.o base64.o \
|
||||
bignum.o blowfish.o camellia.o \
|
||||
ccm.o cipher.o cipher_wrap.o \
|
||||
ctr_drbg.o des.o dhm.o \
|
||||
ecdh.o ecdsa.o ecp.o \
|
||||
ecp_curves.o entropy.o entropy_poll.o \
|
||||
error.o gcm.o havege.o \
|
||||
hmac_drbg.o md.o md2.o \
|
||||
md4.o md5.o md_wrap.o \
|
||||
memory_buffer_alloc.o oid.o \
|
||||
padlock.o pem.o pk.o \
|
||||
pk_wrap.o pkcs12.o pkcs5.o \
|
||||
pkparse.o pkwrite.o platform.o \
|
||||
ripemd160.o rsa.o sha1.o \
|
||||
sha256.o sha512.o threading.o \
|
||||
timing.o version.o \
|
||||
version_features.o xtea.o
|
||||
# minus net.o
|
||||
|
||||
OBJS_X509= certs.o pkcs11.o x509.o \
|
||||
x509_create.o x509_crl.o x509_crt.o \
|
||||
x509_csr.o x509write_crt.o x509write_csr.o
|
||||
|
||||
OBJS_TLS= debug.o ssl_cache.o \
|
||||
ssl_ciphersuites.o ssl_cli.o \
|
||||
ssl_cookie.o ssl_srv.o ssl_ticket.o \
|
||||
ssl_tls.o
|
||||
|
||||
# args for passing into compile rule generation
|
||||
mbedtls_INC_DIR =
|
||||
mbedtls_SRC_DIR = $(mbedtls_ROOT)
|
||||
mbedtls_EXTRA_SRC_FILES = $(patsubst %.o,$(MBEDTLS_DIR)library/%.c,$(OBJS_CRYPTO) $(OBJS_X509) $(OBJS_TLS))
|
||||
|
||||
# depending on cipher configuration, some mbedTLS variables are unused
|
||||
mbedtls_CFLAGS = -Wno-error=unused-but-set-variable -Wno-error=unused-variable $(CFLAGS)
|
||||
|
||||
$(eval $(call component_compile_rules,mbedtls))
|
||||
|
||||
# Helpful error if git submodule not initialised
|
||||
$(MBEDTLS_DIR):
|
||||
$(error "mbedtls git submodule not installed. Please run 'git submodule update --init'")
|
||||
22
extras/mbedtls/hardware_entropy.c
Normal file
22
extras/mbedtls/hardware_entropy.c
Normal file
|
|
@ -0,0 +1,22 @@
|
|||
/* ESP8266 "Hardware RNG" (validity still being confirmed) support for ESP8266
|
||||
*
|
||||
* Based on research done by @foogod.
|
||||
*
|
||||
* Please don't rely on this too much as an entropy source, quite yet...
|
||||
*
|
||||
* Part of esp-open-rtos
|
||||
* Copyright (C) 2015 Angus Gratton
|
||||
* BSD Licensed as described in the file LICENSE
|
||||
*/
|
||||
#include <mbedtls/entropy_poll.h>
|
||||
#include <esp/hwrand.h>
|
||||
|
||||
int mbedtls_hardware_poll( void *data,
|
||||
unsigned char *output, size_t len, size_t *olen )
|
||||
{
|
||||
(void)(data);
|
||||
hwrand_fill(output, len);
|
||||
if(olen)
|
||||
*olen = len;
|
||||
return 0;
|
||||
}
|
||||
2446
extras/mbedtls/include/mbedtls/config.h
Normal file
2446
extras/mbedtls/include/mbedtls/config.h
Normal file
File diff suppressed because it is too large
Load diff
1
extras/mbedtls/mbedtls
Submodule
1
extras/mbedtls/mbedtls
Submodule
|
|
@ -0,0 +1 @@
|
|||
Subproject commit 0a0c22e0efcf2f8f71d7e16712f80b8f77326f72
|
||||
510
extras/mbedtls/net_lwip.c
Normal file
510
extras/mbedtls/net_lwip.c
Normal file
|
|
@ -0,0 +1,510 @@
|
|||
/*
|
||||
* TCP/IP or UDP/IP networking functions
|
||||
* modified for LWIP support on ESP8266
|
||||
*
|
||||
* Copyright (C) 2006-2015, ARM Limited, All Rights Reserved
|
||||
* Additions Copyright (C) 2015 Angus Gratton
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License"); you may
|
||||
* not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
* This file is part of mbed TLS (https://tls.mbed.org)
|
||||
*/
|
||||
|
||||
#if !defined(MBEDTLS_CONFIG_FILE)
|
||||
#include "mbedtls/config.h"
|
||||
#else
|
||||
#include MBEDTLS_CONFIG_FILE
|
||||
#endif
|
||||
|
||||
#if defined(MBEDTLS_NET_C)
|
||||
|
||||
#include "mbedtls/net.h"
|
||||
|
||||
#include <string.h>
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <sys/socket.h>
|
||||
#include <sys/time.h>
|
||||
#include <unistd.h>
|
||||
#include <netdb.h>
|
||||
#include <errno.h>
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
|
||||
#include <time.h>
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
/*
|
||||
* Prepare for using the sockets interface
|
||||
*/
|
||||
static int net_prepare( void )
|
||||
{
|
||||
#if ( defined(_WIN32) || defined(_WIN32_WCE) ) && !defined(EFIX64) && \
|
||||
!defined(EFI32)
|
||||
WSADATA wsaData;
|
||||
|
||||
if( wsa_init_done == 0 )
|
||||
{
|
||||
if( WSAStartup( MAKEWORD(2,0), &wsaData ) != 0 )
|
||||
return( MBEDTLS_ERR_NET_SOCKET_FAILED );
|
||||
|
||||
wsa_init_done = 1;
|
||||
}
|
||||
#else
|
||||
#endif
|
||||
return( 0 );
|
||||
}
|
||||
|
||||
/*
|
||||
* Initialize a context
|
||||
*/
|
||||
void mbedtls_net_init( mbedtls_net_context *ctx )
|
||||
{
|
||||
ctx->fd = -1;
|
||||
}
|
||||
|
||||
/*
|
||||
* Initiate a TCP connection with host:port and the given protocol
|
||||
*/
|
||||
int mbedtls_net_connect( mbedtls_net_context *ctx, const char *host, const char *port, int proto )
|
||||
{
|
||||
int ret;
|
||||
struct addrinfo hints, *addr_list, *cur;
|
||||
|
||||
if( ( ret = net_prepare() ) != 0 )
|
||||
return( ret );
|
||||
|
||||
/* Do name resolution with both IPv6 and IPv4 */
|
||||
memset( &hints, 0, sizeof( hints ) );
|
||||
hints.ai_family = AF_UNSPEC;
|
||||
hints.ai_socktype = proto == MBEDTLS_NET_PROTO_UDP ? SOCK_DGRAM : SOCK_STREAM;
|
||||
hints.ai_protocol = proto == MBEDTLS_NET_PROTO_UDP ? IPPROTO_UDP : IPPROTO_TCP;
|
||||
|
||||
if( getaddrinfo( host, port, &hints, &addr_list ) != 0 )
|
||||
return( MBEDTLS_ERR_NET_UNKNOWN_HOST );
|
||||
|
||||
/* Try the sockaddrs until a connection succeeds */
|
||||
ret = MBEDTLS_ERR_NET_UNKNOWN_HOST;
|
||||
for( cur = addr_list; cur != NULL; cur = cur->ai_next )
|
||||
{
|
||||
ctx->fd = (int) socket( cur->ai_family, cur->ai_socktype,
|
||||
cur->ai_protocol );
|
||||
if( ctx->fd < 0 )
|
||||
{
|
||||
ret = MBEDTLS_ERR_NET_SOCKET_FAILED;
|
||||
continue;
|
||||
}
|
||||
|
||||
if( connect( ctx->fd, cur->ai_addr, cur->ai_addrlen ) == 0 )
|
||||
{
|
||||
ret = 0;
|
||||
break;
|
||||
}
|
||||
|
||||
close( ctx->fd );
|
||||
ret = MBEDTLS_ERR_NET_CONNECT_FAILED;
|
||||
}
|
||||
|
||||
freeaddrinfo( addr_list );
|
||||
|
||||
return( ret );
|
||||
}
|
||||
|
||||
/*
|
||||
* Create a listening socket on bind_ip:port
|
||||
*/
|
||||
int mbedtls_net_bind( mbedtls_net_context *ctx, const char *bind_ip, const char *port, int proto )
|
||||
{
|
||||
int n, ret;
|
||||
struct addrinfo hints, *addr_list, *cur;
|
||||
|
||||
if( ( ret = net_prepare() ) != 0 )
|
||||
return( ret );
|
||||
|
||||
/* Bind to IPv6 and/or IPv4, but only in the desired protocol */
|
||||
memset( &hints, 0, sizeof( hints ) );
|
||||
hints.ai_family = AF_UNSPEC;
|
||||
hints.ai_socktype = proto == MBEDTLS_NET_PROTO_UDP ? SOCK_DGRAM : SOCK_STREAM;
|
||||
hints.ai_protocol = proto == MBEDTLS_NET_PROTO_UDP ? IPPROTO_UDP : IPPROTO_TCP;
|
||||
|
||||
if( getaddrinfo( bind_ip, port, &hints, &addr_list ) != 0 )
|
||||
return( MBEDTLS_ERR_NET_UNKNOWN_HOST );
|
||||
|
||||
/* Try the sockaddrs until a binding succeeds */
|
||||
ret = MBEDTLS_ERR_NET_UNKNOWN_HOST;
|
||||
for( cur = addr_list; cur != NULL; cur = cur->ai_next )
|
||||
{
|
||||
ctx->fd = (int) socket( cur->ai_family, cur->ai_socktype,
|
||||
cur->ai_protocol );
|
||||
if( ctx->fd < 0 )
|
||||
{
|
||||
ret = MBEDTLS_ERR_NET_SOCKET_FAILED;
|
||||
continue;
|
||||
}
|
||||
|
||||
n = 1;
|
||||
if( setsockopt( ctx->fd, SOL_SOCKET, SO_REUSEADDR,
|
||||
(const char *) &n, sizeof( n ) ) != 0 )
|
||||
{
|
||||
close( ctx->fd );
|
||||
ret = MBEDTLS_ERR_NET_SOCKET_FAILED;
|
||||
continue;
|
||||
}
|
||||
|
||||
if( bind( ctx->fd, cur->ai_addr, cur->ai_addrlen ) != 0 )
|
||||
{
|
||||
close( ctx->fd );
|
||||
ret = MBEDTLS_ERR_NET_BIND_FAILED;
|
||||
continue;
|
||||
}
|
||||
|
||||
/* Listen only makes sense for TCP */
|
||||
if( proto == MBEDTLS_NET_PROTO_TCP )
|
||||
{
|
||||
if( listen( ctx->fd, MBEDTLS_NET_LISTEN_BACKLOG ) != 0 )
|
||||
{
|
||||
close( ctx->fd );
|
||||
ret = MBEDTLS_ERR_NET_LISTEN_FAILED;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
/* I we ever get there, it's a success */
|
||||
ret = 0;
|
||||
break;
|
||||
}
|
||||
|
||||
freeaddrinfo( addr_list );
|
||||
|
||||
return( ret );
|
||||
|
||||
}
|
||||
|
||||
#if ( defined(_WIN32) || defined(_WIN32_WCE) ) && !defined(EFIX64) && \
|
||||
!defined(EFI32)
|
||||
/*
|
||||
* Check if the requested operation would be blocking on a non-blocking socket
|
||||
* and thus 'failed' with a negative return value.
|
||||
*/
|
||||
static int net_would_block( const mbedtls_net_context *ctx )
|
||||
{
|
||||
((void) ctx);
|
||||
return( WSAGetLastError() == WSAEWOULDBLOCK );
|
||||
}
|
||||
#else
|
||||
/*
|
||||
* Check if the requested operation would be blocking on a non-blocking socket
|
||||
* and thus 'failed' with a negative return value.
|
||||
*
|
||||
* Note: on a blocking socket this function always returns 0!
|
||||
*/
|
||||
static int net_would_block( const mbedtls_net_context *ctx )
|
||||
{
|
||||
/*
|
||||
* Never return 'WOULD BLOCK' on a non-blocking socket
|
||||
*/
|
||||
if( ( fcntl( ctx->fd, F_GETFL, 0) & O_NONBLOCK ) != O_NONBLOCK )
|
||||
return( 0 );
|
||||
|
||||
switch( errno )
|
||||
{
|
||||
#if defined EAGAIN
|
||||
case EAGAIN:
|
||||
#endif
|
||||
#if defined EWOULDBLOCK && EWOULDBLOCK != EAGAIN
|
||||
case EWOULDBLOCK:
|
||||
#endif
|
||||
return( 1 );
|
||||
}
|
||||
return( 0 );
|
||||
}
|
||||
#endif /* ( _WIN32 || _WIN32_WCE ) && !EFIX64 && !EFI32 */
|
||||
|
||||
/*
|
||||
* Accept a connection from a remote client
|
||||
*/
|
||||
int mbedtls_net_accept( mbedtls_net_context *bind_ctx,
|
||||
mbedtls_net_context *client_ctx,
|
||||
void *client_ip, size_t buf_size, size_t *ip_len )
|
||||
{
|
||||
int ret;
|
||||
int type;
|
||||
|
||||
struct sockaddr_in client_addr;
|
||||
|
||||
socklen_t n = (socklen_t) sizeof( client_addr );
|
||||
socklen_t type_len = (socklen_t) sizeof( type );
|
||||
|
||||
/* Is this a TCP or UDP socket? */
|
||||
if( getsockopt( bind_ctx->fd, SOL_SOCKET, SO_TYPE,
|
||||
(void *) &type, (socklen_t *) &type_len ) != 0 ||
|
||||
( type != SOCK_STREAM && type != SOCK_DGRAM ) )
|
||||
{
|
||||
return( MBEDTLS_ERR_NET_ACCEPT_FAILED );
|
||||
}
|
||||
|
||||
if( type == SOCK_STREAM )
|
||||
{
|
||||
/* TCP: actual accept() */
|
||||
ret = client_ctx->fd = (int) accept( bind_ctx->fd,
|
||||
(struct sockaddr *) &client_addr, &n );
|
||||
}
|
||||
else
|
||||
{
|
||||
/* UDP: wait for a message, but keep it in the queue */
|
||||
char buf[1] = { 0 };
|
||||
|
||||
ret = recvfrom( bind_ctx->fd, buf, sizeof( buf ), MSG_PEEK,
|
||||
(struct sockaddr *) &client_addr, &n );
|
||||
|
||||
#if defined(_WIN32)
|
||||
if( ret == SOCKET_ERROR &&
|
||||
WSAGetLastError() == WSAEMSGSIZE )
|
||||
{
|
||||
/* We know buf is too small, thanks, just peeking here */
|
||||
ret = 0;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
if( ret < 0 )
|
||||
{
|
||||
if( net_would_block( bind_ctx ) != 0 )
|
||||
return( MBEDTLS_ERR_SSL_WANT_READ );
|
||||
|
||||
return( MBEDTLS_ERR_NET_ACCEPT_FAILED );
|
||||
}
|
||||
|
||||
/* UDP: hijack the listening socket to communicate with the client,
|
||||
* then bind a new socket to accept new connections */
|
||||
if( type != SOCK_STREAM )
|
||||
{
|
||||
struct sockaddr_in local_addr;
|
||||
int one = 1;
|
||||
|
||||
if( connect( bind_ctx->fd, (struct sockaddr *) &client_addr, n ) != 0 )
|
||||
return( MBEDTLS_ERR_NET_ACCEPT_FAILED );
|
||||
|
||||
client_ctx->fd = bind_ctx->fd;
|
||||
bind_ctx->fd = -1; /* In case we exit early */
|
||||
|
||||
n = sizeof( struct sockaddr_in );
|
||||
if( getsockname( client_ctx->fd,
|
||||
(struct sockaddr *) &local_addr, &n ) != 0 ||
|
||||
( bind_ctx->fd = (int) socket( AF_INET,
|
||||
SOCK_DGRAM, IPPROTO_UDP ) ) < 0 ||
|
||||
setsockopt( bind_ctx->fd, SOL_SOCKET, SO_REUSEADDR,
|
||||
(const char *) &one, sizeof( one ) ) != 0 )
|
||||
{
|
||||
return( MBEDTLS_ERR_NET_SOCKET_FAILED );
|
||||
}
|
||||
|
||||
if( bind( bind_ctx->fd, (struct sockaddr *) &local_addr, n ) != 0 )
|
||||
{
|
||||
return( MBEDTLS_ERR_NET_BIND_FAILED );
|
||||
}
|
||||
}
|
||||
|
||||
if( client_ip != NULL )
|
||||
{
|
||||
struct sockaddr_in *addr4 = (struct sockaddr_in *) &client_addr;
|
||||
*ip_len = sizeof( addr4->sin_addr.s_addr );
|
||||
|
||||
if( buf_size < *ip_len )
|
||||
return( MBEDTLS_ERR_NET_BUFFER_TOO_SMALL );
|
||||
|
||||
memcpy( client_ip, &addr4->sin_addr.s_addr, *ip_len );
|
||||
}
|
||||
|
||||
return( 0 );
|
||||
}
|
||||
|
||||
/*
|
||||
* Set the socket blocking or non-blocking
|
||||
*/
|
||||
int mbedtls_net_set_block( mbedtls_net_context *ctx )
|
||||
{
|
||||
#if ( defined(_WIN32) || defined(_WIN32_WCE) ) && !defined(EFIX64) && \
|
||||
!defined(EFI32)
|
||||
u_long n = 0;
|
||||
return( ioctlsocket( ctx->fd, FIONBIO, &n ) );
|
||||
#else
|
||||
return( fcntl( ctx->fd, F_SETFL, fcntl( ctx->fd, F_GETFL, 0 ) & ~O_NONBLOCK ) );
|
||||
#endif
|
||||
}
|
||||
|
||||
int mbedtls_net_set_nonblock( mbedtls_net_context *ctx )
|
||||
{
|
||||
#if ( defined(_WIN32) || defined(_WIN32_WCE) ) && !defined(EFIX64) && \
|
||||
!defined(EFI32)
|
||||
u_long n = 1;
|
||||
return( ioctlsocket( ctx->fd, FIONBIO, &n ) );
|
||||
#else
|
||||
return( fcntl( ctx->fd, F_SETFL, fcntl( ctx->fd, F_GETFL, 0 ) | O_NONBLOCK ) );
|
||||
#endif
|
||||
}
|
||||
|
||||
/*
|
||||
* Portable usleep helper
|
||||
*/
|
||||
void mbedtls_net_usleep( unsigned long usec )
|
||||
{
|
||||
#if defined(_WIN32)
|
||||
Sleep( ( usec + 999 ) / 1000 );
|
||||
#else
|
||||
struct timeval tv;
|
||||
tv.tv_sec = usec / 1000000;
|
||||
#if defined(__unix__) || defined(__unix) || \
|
||||
( defined(__APPLE__) && defined(__MACH__) )
|
||||
tv.tv_usec = (suseconds_t) usec % 1000000;
|
||||
#else
|
||||
tv.tv_usec = usec % 1000000;
|
||||
#endif
|
||||
select( 0, NULL, NULL, NULL, &tv );
|
||||
#endif
|
||||
}
|
||||
|
||||
/*
|
||||
* Read at most 'len' characters
|
||||
*/
|
||||
int mbedtls_net_recv( void *ctx, unsigned char *buf, size_t len )
|
||||
{
|
||||
int ret;
|
||||
int fd = ((mbedtls_net_context *) ctx)->fd;
|
||||
|
||||
if( fd < 0 )
|
||||
return( MBEDTLS_ERR_NET_INVALID_CONTEXT );
|
||||
|
||||
ret = (int) read( fd, buf, len );
|
||||
|
||||
if( ret < 0 )
|
||||
{
|
||||
if( net_would_block( ctx ) != 0 )
|
||||
return( MBEDTLS_ERR_SSL_WANT_READ );
|
||||
|
||||
#if ( defined(_WIN32) || defined(_WIN32_WCE) ) && !defined(EFIX64) && \
|
||||
!defined(EFI32)
|
||||
if( WSAGetLastError() == WSAECONNRESET )
|
||||
return( MBEDTLS_ERR_NET_CONN_RESET );
|
||||
#else
|
||||
if( errno == EPIPE || errno == ECONNRESET )
|
||||
return( MBEDTLS_ERR_NET_CONN_RESET );
|
||||
|
||||
if( errno == EINTR )
|
||||
return( MBEDTLS_ERR_SSL_WANT_READ );
|
||||
#endif
|
||||
|
||||
return( MBEDTLS_ERR_NET_RECV_FAILED );
|
||||
}
|
||||
|
||||
return( ret );
|
||||
}
|
||||
|
||||
/*
|
||||
* Read at most 'len' characters, blocking for at most 'timeout' ms
|
||||
*/
|
||||
int mbedtls_net_recv_timeout( void *ctx, unsigned char *buf, size_t len,
|
||||
uint32_t timeout )
|
||||
{
|
||||
int ret;
|
||||
struct timeval tv;
|
||||
fd_set read_fds;
|
||||
int fd = ((mbedtls_net_context *) ctx)->fd;
|
||||
|
||||
if( fd < 0 )
|
||||
return( MBEDTLS_ERR_NET_INVALID_CONTEXT );
|
||||
|
||||
FD_ZERO( &read_fds );
|
||||
FD_SET( fd, &read_fds );
|
||||
|
||||
tv.tv_sec = timeout / 1000;
|
||||
tv.tv_usec = ( timeout % 1000 ) * 1000;
|
||||
|
||||
ret = select( fd + 1, &read_fds, NULL, NULL, timeout == 0 ? NULL : &tv );
|
||||
|
||||
/* Zero fds ready means we timed out */
|
||||
if( ret == 0 )
|
||||
return( MBEDTLS_ERR_SSL_TIMEOUT );
|
||||
|
||||
if( ret < 0 )
|
||||
{
|
||||
#if ( defined(_WIN32) || defined(_WIN32_WCE) ) && !defined(EFIX64) && \
|
||||
!defined(EFI32)
|
||||
if( WSAGetLastError() == WSAEINTR )
|
||||
return( MBEDTLS_ERR_SSL_WANT_READ );
|
||||
#else
|
||||
if( errno == EINTR )
|
||||
return( MBEDTLS_ERR_SSL_WANT_READ );
|
||||
#endif
|
||||
|
||||
return( MBEDTLS_ERR_NET_RECV_FAILED );
|
||||
}
|
||||
|
||||
/* This call will not block */
|
||||
return( mbedtls_net_recv( ctx, buf, len ) );
|
||||
}
|
||||
|
||||
/*
|
||||
* Write at most 'len' characters
|
||||
*/
|
||||
int mbedtls_net_send( void *ctx, const unsigned char *buf, size_t len )
|
||||
{
|
||||
int ret;
|
||||
int fd = ((mbedtls_net_context *) ctx)->fd;
|
||||
|
||||
if( fd < 0 )
|
||||
return( MBEDTLS_ERR_NET_INVALID_CONTEXT );
|
||||
|
||||
ret = (int) write( fd, buf, len );
|
||||
|
||||
if( ret < 0 )
|
||||
{
|
||||
if( net_would_block( ctx ) != 0 )
|
||||
return( MBEDTLS_ERR_SSL_WANT_WRITE );
|
||||
|
||||
#if ( defined(_WIN32) || defined(_WIN32_WCE) ) && !defined(EFIX64) && \
|
||||
!defined(EFI32)
|
||||
if( WSAGetLastError() == WSAECONNRESET )
|
||||
return( MBEDTLS_ERR_NET_CONN_RESET );
|
||||
#else
|
||||
if( errno == EPIPE || errno == ECONNRESET )
|
||||
return( MBEDTLS_ERR_NET_CONN_RESET );
|
||||
|
||||
if( errno == EINTR )
|
||||
return( MBEDTLS_ERR_SSL_WANT_WRITE );
|
||||
#endif
|
||||
|
||||
return( MBEDTLS_ERR_NET_SEND_FAILED );
|
||||
}
|
||||
|
||||
return( ret );
|
||||
}
|
||||
|
||||
/*
|
||||
* Gracefully close the connection
|
||||
*/
|
||||
void mbedtls_net_free( mbedtls_net_context *ctx )
|
||||
{
|
||||
if( ctx->fd == -1 )
|
||||
return;
|
||||
|
||||
shutdown( ctx->fd, 2 );
|
||||
close( ctx->fd );
|
||||
|
||||
ctx->fd = -1;
|
||||
}
|
||||
|
||||
#endif /* MBEDTLS_NET_C */
|
||||
|
|
@ -1,9 +1,9 @@
|
|||
# Component makefile for extras/rboot-ota
|
||||
|
||||
INC_DIRS += $(ROOT)extras/rboot-ota
|
||||
INC_DIRS += $(rboot-ota_ROOT)
|
||||
|
||||
# args for passing into compile rule generation
|
||||
extras/rboot-ota_INC_DIR = $(ROOT)extras/rboot-ota
|
||||
extras/rboot-ota_SRC_DIR = $(ROOT)extras/rboot-ota
|
||||
rboot-ota_SRC_DIR = $(rboot-ota_ROOT)
|
||||
|
||||
$(eval $(call component_compile_rules,rboot-ota))
|
||||
|
||||
$(eval $(call component_compile_rules,extras/rboot-ota))
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue