Merge branch 'master' into rng

Added haltest

Conflicts:
	os/hal/hal.mk
	os/hal/include/hal_community.h
	os/hal/src/hal_community.c
This commit is contained in:
Stephane D'Alu 2016-02-21 17:03:19 +01:00
commit e9a1a01f90
93 changed files with 26717 additions and 24 deletions

View File

@ -1,5 +1,6 @@
/*
Copyright (C) 2015 Fabio Utzig
2016 Stéphane D'Alu / Bruno Remond
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
@ -17,6 +18,14 @@
#include "hal.h"
#if HAL_USE_PAL || defined(__DOXYGEN__)
/* RAM Banks
* (Values are defined in Nordic gcc_startup_nrf51.s)
*/
#define NRF_POWER_RAMON_ADDRESS 0x40000524
#define NRF_POWER_RAMONB_ADDRESS 0x40000554
#define NRF_POWER_RAMONx_RAMxON_ONMODE_Msk 0x3
/**
* @brief PAL setup.
* @details Digital I/O ports static configuration as defined in @p board.h.
@ -68,6 +77,9 @@ const PALConfig pal_default_config =
*/
void __early_init(void)
{
/* Make sure ALL RAM banks are powered on */
*(uint32_t *)NRF_POWER_RAMON_ADDRESS |= NRF_POWER_RAMONx_RAMxON_ONMODE_Msk;
*(uint32_t *)NRF_POWER_RAMONB_ADDRESS |= NRF_POWER_RAMONx_RAMxON_ONMODE_Msk;
}
/**

View File

@ -22,7 +22,8 @@
#define BOARD_NAME "nRF51 DK"
/* Board oscillators-related settings. */
#define XTAL_VALUE 16000000
#define NRF51_XTAL_VALUE 16000000
#define NRF51_LFCLK_SOURCE 1
/* GPIO pins. */
#define BTN1 17

View File

@ -3,3 +3,9 @@ BOARDSRC = ${CHIBIOS_CONTRIB}/os/hal/boards/NRF51-DK/board.c
# Required include directories
BOARDINC = ${CHIBIOS_CONTRIB}/os/hal/boards/NRF51-DK
# Flash
JLINK_DEVICE = nrf51422
JLINK_PRE_FLASH = w4 4001e504 1
JLINK_ERASE_ALL = w4 4001e504 2\nw4 4001e50c 1\nsleep 100

View File

@ -22,7 +22,7 @@
#define BOARD_NAME "WvShare BLE400"
/* Board oscillators-related settings. */
#define XTAL_VALUE 16000000
#define NRF51_XTAL_VALUE 16000000
/* GPIO pins. */
#define KEY1 16

View File

@ -5,6 +5,17 @@ HALSRC += ${CHIBIOS_CONTRIB}/os/hal/src/hal_community.c \
${CHIBIOS_CONTRIB}/os/hal/src/onewire.c \
${CHIBIOS_CONTRIB}/os/hal/src/eicu.c \
${CHIBIOS_CONTRIB}/os/hal/src/crc.c \
${CHIBIOS_CONTRIB}/os/hal/src/rng.c
${CHIBIOS_CONTRIB}/os/hal/src/rng.c \
${CHIBIOS_CONTRIB}/os/hal/src/usbh.c \
${CHIBIOS_CONTRIB}/os/hal/src/usbh/usbh_debug.c \
${CHIBIOS_CONTRIB}/os/hal/src/usbh/usbh_desciter.c \
${CHIBIOS_CONTRIB}/os/hal/src/usbh/usbh_hub.c \
${CHIBIOS_CONTRIB}/os/hal/src/usbh/usbh_msd.c \
${CHIBIOS_CONTRIB}/os/hal/src/usbh/usbh_ftdi.c \
${CHIBIOS_CONTRIB}/os/hal/src/usbh/usbh_uvc.c \
${CHIBIOS_CONTRIB}/os/hal/src/ee24xx.c \
${CHIBIOS_CONTRIB}/os/hal/src/ee25xx.c \
${CHIBIOS_CONTRIB}/os/hal/src/eeprom.c \
${CHIBIOS_CONTRIB}/os/hal/src/timcap.c \
HALINC += ${CHIBIOS_CONTRIB}/os/hal/include

64
os/hal/include/ee24xx.h Normal file
View File

@ -0,0 +1,64 @@
/*
Copyright 2012 Uladzimir Pylinski aka barthess.
You may use this work without restrictions, as long as this notice is included.
The work is provided "as is" without warranty of any kind, neither express nor implied.
*/
#ifndef EE24XX_H
#define EE24XX_H
#include "hal.h"
#if defined(HAL_USE_EEPROM) && HAL_USE_EEPROM && EEPROM_USE_EE24XX
#define EEPROM_DEV_24XX 24
/**
* @extends EepromFileConfig
*/
typedef struct {
_eeprom_file_config_data
/**
* Driver connected to IC.
*/
I2CDriver *i2cp;
/**
* Address of IC on I2C bus.
*/
i2caddr_t addr;
/**
* Pointer to write buffer. The safest size is (pagesize + 2)
*/
uint8_t *write_buf;
} I2CEepromFileConfig;
/**
* @brief @p I2CEepromFileStream specific data.
*/
#define _eeprom_file_stream_data_i2c \
_eeprom_file_stream_data
/**
* @extends EepromFileStream
*
* @brief EEPROM file stream driver class for I2C device.
*/
typedef struct {
const struct EepromFileStreamVMT *vmt;
_eeprom_file_stream_data_i2c
/* Overwritten parent data member. */
const I2CEepromFileConfig *cfg;
} I2CEepromFileStream;
/**
* Open I2C EEPROM IC as file and return pointer to the file stream object
* @note Fucntion allways successfully open file. All checking makes
* in read/write functions.
*/
#define I2CEepromFileOpen(efs, eepcfg, eepdev) \
EepromFileOpen((EepromFileStream *)efs, (EepromFileConfig *)eepcfg, eepdev);
#endif /* #if defined(EEPROM_USE_EE24XX) && EEPROM_USE_EE24XX */
#endif // EE24XX_H

63
os/hal/include/ee25xx.h Normal file
View File

@ -0,0 +1,63 @@
/*
Copyright 2012 Uladzimir Pylinski aka barthess.
You may use this work without restrictions, as long as this notice is included.
The work is provided "as is" without warranty of any kind, neither express nor implied.
*/
#ifndef EE25XX_H
#define EE25XX_H
#include "hal.h"
#if defined(HAL_USE_EEPROM) && HAL_USE_EEPROM && EEPROM_USE_EE25XX
#define EEPROM_DEV_25XX 25
/**
* @extends EepromFileConfig
*/
typedef struct {
_eeprom_file_config_data
/**
* Driver connected to IC.
*/
SPIDriver *spip;
/**
* Config associated with SPI driver.
*/
const SPIConfig *spicfg;
} SPIEepromFileConfig;
/**
* @brief @p SPIEepromFileStream specific data.
*/
#define _eeprom_file_stream_data_spi \
_eeprom_file_stream_data
/**
* @extends EepromFileStream
*
* @brief EEPROM file stream driver class for SPI device.
*/
typedef struct {
const struct EepromFileStreamVMT *vmt;
_eeprom_file_stream_data_spi
/* Overwritten parent data member. */
const SPIEepromFileConfig *cfg;
} SPIEepromFileStream;
/**
* Open SPI EEPROM IC as file and return pointer to the file stream object
* @note Fucntion allways successfully open file. All checking makes
* in read/write functions.
*/
EepromFileStream *SPIEepromFileOpen(SPIEepromFileStream *efs,
const SPIEepromFileConfig *eepcfg,
const EepromDevice *eepdev);
#define SPIEepromFileOpen(efs, eepcfg, eepdev) \
EepromFileOpen((EepromFileStream *)efs, (EepromFileConfig *)eepcfg, eepdev);
#endif /* #if defined(EEPROM_USE_EE25XX) && EEPROM_USE_EE25XX */
#endif // EE25XX_H

147
os/hal/include/eeprom.h Normal file
View File

@ -0,0 +1,147 @@
/*
Copyright (c) 2013 Timon Wong
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.
*/
/*
Copyright 2012 Uladzimir Pylinski aka barthess.
You may use this work without restrictions, as long as this notice is included.
The work is provided "as is" without warranty of any kind, neither express nor implied.
*/
#ifndef __EEPROM_H__
#define __EEPROM_H__
#include "ch.h"
#include "hal.h"
#ifndef HAL_USE_EEPROM
#define HAL_USE_EEPROM FALSE
#endif
#ifndef EEPROM_USE_EE25XX
#define EEPROM_USE_EE25XX FALSE
#endif
#ifndef EEPROM_USE_EE24XX
#define EEPROM_USE_EE24XX FALSE
#endif
#if HAL_USE_EEPROM
#if EEPROM_USE_EE25XX && EEPROM_USE_EE24XX
#define EEPROM_TABLE_SIZE 2
#elif EEPROM_USE_EE25XX || EEPROM_USE_EE24XX
#define EEPROM_TABLE_SIZE 1
#else
#error "No EEPROM device selected!"
#endif
#if EEPROM_USE_EE25XX && !HAL_USE_SPI
#error "25xx enabled but SPI driver is disabled!"
#endif
#if EEPROM_USE_EE24XX && !HAL_USE_I2C
#error "24xx enabled but I2C driver is disabled!"
#endif
#define _eeprom_file_config_data \
/* Lower barrier of file in EEPROM memory array. */ \
uint32_t barrier_low; \
/* Higher barrier of file in EEPROM memory array. */ \
uint32_t barrier_hi; \
/* Size of memory array in bytes. */ \
uint32_t size; \
/* Size of single page in bytes. */ \
uint16_t pagesize; \
/* Time needed by IC for single byte/page writing. */ \
systime_t write_time;
typedef uint32_t fileoffset_t;
typedef struct {
_eeprom_file_config_data
} EepromFileConfig;
/**
* @brief @p EepromFileStream specific data.
*/
#define _eeprom_file_stream_data \
_base_sequential_stream_data \
uint32_t errors; \
uint32_t position; \
/**
* @extends BaseFileStreamVMT
*
* @brief @p EepromFileStream virtual methods table.
*/
struct EepromFileStreamVMT {
_file_stream_methods
};
/**
* @extends BaseFileStream
*
* @brief EEPROM file stream driver class.
* @details This class extends @p BaseFileStream by adding some fields.
*/
typedef struct {
/** @brief Virtual Methods Table.*/
const struct EepromFileStreamVMT *vmt;
_eeprom_file_stream_data
/** pointer to config object, must be overwritten by all derived classes.*/
const EepromFileConfig *cfg;
} EepromFileStream;
/**
* @brief Low level device descriptor.
*/
typedef struct {
const uint8_t id;
const struct EepromFileStreamVMT *efsvmt;
} EepromDevice;
const EepromDevice *EepromFindDevice(uint8_t id);
EepromFileStream *EepromFileOpen(EepromFileStream *efs,
const EepromFileConfig *eepcfg,
const EepromDevice *eepdev);
uint8_t EepromReadByte(EepromFileStream *efs);
uint16_t EepromReadHalfword(EepromFileStream *efs);
uint32_t EepromReadWord(EepromFileStream *efs);
size_t EepromWriteByte(EepromFileStream *efs, uint8_t data);
size_t EepromWriteHalfword(EepromFileStream *efs, uint16_t data);
size_t EepromWriteWord(EepromFileStream *efs, uint32_t data);
msg_t eepfs_getsize(void *ip);
msg_t eepfs_getposition(void *ip);
msg_t eepfs_lseek(void *ip, fileoffset_t offset);
msg_t eepfs_close(void *ip);
msg_t eepfs_geterror(void *ip);
msg_t eepfs_put(void *ip, uint8_t b);
msg_t eepfs_get(void *ip);
#include "ee24xx.h"
#include "ee25xx.h"
#endif /* #if defined(HAL_USE_EEPROM) && HAL_USE_EEPROM */
#endif /* __EEPROM_H__ */

View File

@ -33,10 +33,13 @@
#include "nand.h"
#include "eicu.h"
#include "rng.h"
#include "usbh.h"
#include "timcap.h"
/* Complex drivers.*/
#include "onewire.h"
#include "crc.h"
#include "eeprom.h"
/*===========================================================================*/
/* Driver constants. */

210
os/hal/include/timcap.h Normal file
View File

@ -0,0 +1,210 @@
/*
ChibiOS/RT - Copyright (C) 2006,2007,2008,2009,2010,
2011,2012,2013 Giovanni Di Sirio.
This file is part of ChibiOS/RT.
ChibiOS/RT is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 3 of the License, or
(at your option) any later version.
ChibiOS/RT is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
/**
* @file timcap.h
* @brief TIMCAP Driver macros and structures.
*
* @addtogroup TIMCAP
* @{
*/
#ifndef _TIMCAP_H_
#define _TIMCAP_H_
#include "ch.h"
#include "hal.h"
#ifndef HAL_USE_TIMCAP
#define HAL_USE_TIMCAP FALSE
#endif
#if HAL_USE_TIMCAP || defined(__DOXYGEN__)
/*===========================================================================*/
/* Driver constants. */
/*===========================================================================*/
/*===========================================================================*/
/* Driver pre-compile time settings. */
/*===========================================================================*/
/*===========================================================================*/
/* Derived constants and error checks. */
/*===========================================================================*/
/*===========================================================================*/
/* Driver data structures and types. */
/*===========================================================================*/
/**
* @brief Driver state machine possible states.
*/
typedef enum {
TIMCAP_UNINIT = 0, /**< Not initialized. */
TIMCAP_STOP = 1, /**< Stopped. */
TIMCAP_READY = 2, /**< Ready. */
TIMCAP_WAITING = 3, /**< Waiting first edge. */
TIMCAP_ACTIVE = 4, /**< Active cycle phase. */
TIMCAP_IDLE = 5, /**< Idle cycle phase. */
} timcapstate_t;
/**
* @brief Type of a structure representing an TIMCAP driver.
*/
typedef struct TIMCAPDriver TIMCAPDriver;
/**
* @brief TIMCAP notification callback type.
*
* @param[in] timcapp pointer to a @p TIMCAPDriver object
*/
typedef void (*timcapcallback_t)(TIMCAPDriver *timcapp);
#include "timcap_lld.h"
/*===========================================================================*/
/* Driver macros. */
/*===========================================================================*/
/**
* @name Macro Functions
* @{
*/
/**
* @brief Enables the input capture.
*
* @param[in] timcapp pointer to the @p TIMCAPDriver object
*
* @iclass
*/
#define timcapEnableI(timcapp) timcap_lld_enable(timcapp)
/**
* @brief Disables the input capture.
*
* @param[in] timcapp pointer to the @p TIMCAPDriver object
*
* @iclass
*/
#define timcapDisableI(timcapp) timcap_lld_disable(timcapp)
/** @} */
/**
* @name Low Level driver helper macros
* @{
*/
/**
* @brief Common ISR code, TIMCAP channel 1 event.
*
* @param[in] timcapp pointer to the @p TIMCAPDriver object
*
* @notapi
*/
#define _timcap_isr_invoke_channel1_cb(timcapp) { \
timcapstate_t previous_state = (timcapp)->state; \
(timcapp)->state = TIMCAP_ACTIVE; \
if (previous_state != TIMCAP_WAITING) \
(timcapp)->config->capture_cb_array[0](timcapp); \
}
/**
* @brief Common ISR code, TIMCAP channel 2 event.
*
* @param[in] timcapp pointer to the @p TIMCAPDriver object
*
* @notapi
*/
#define _timcap_isr_invoke_channel2_cb(timcapp) { \
timcapstate_t previous_state = (timcapp)->state; \
(timcapp)->state = TIMCAP_ACTIVE; \
if (previous_state != TIMCAP_WAITING) \
(timcapp)->config->capture_cb_array[1](timcapp); \
}
/**
* @brief Common ISR code, TIMCAP channel 3 event.
*
* @param[in] timcapp pointer to the @p TIMCAPDriver object
*
* @notapi
*/
#define _timcap_isr_invoke_channel3_cb(timcapp) { \
timcapstate_t previous_state = (timcapp)->state; \
(timcapp)->state = TIMCAP_ACTIVE; \
if (previous_state != TIMCAP_WAITING) \
(timcapp)->config->capture_cb_array[2](timcapp); \
}
/**
* @brief Common ISR code, TIMCAP channel 4 event.
*
* @param[in] timcapp pointer to the @p TIMCAPDriver object
*
* @notapi
*/
#define _timcap_isr_invoke_channel4_cb(timcapp) { \
timcapstate_t previous_state = (timcapp)->state; \
(timcapp)->state = TIMCAP_ACTIVE; \
if (previous_state != TIMCAP_WAITING) \
(timcapp)->config->capture_cb_array[3](timcapp); \
}
/**
* @brief Common ISR code, TIMCAP timer overflow event.
*
* @param[in] timcapp pointer to the @p TIMCAPDriver object
*
* @notapi
*/
#define _timcap_isr_invoke_overflow_cb(timcapp) { \
(timcapp)->config->overflow_cb(timcapp); \
}
/** @} */
/*===========================================================================*/
/* External declarations. */
/*===========================================================================*/
#ifdef __cplusplus
extern "C" {
#endif
void timcapInit(void);
void timcapObjectInit(TIMCAPDriver *timcapp);
void timcapStart(TIMCAPDriver *timcapp, const TIMCAPConfig *config);
void timcapStop(TIMCAPDriver *timcapp);
void timcapEnable(TIMCAPDriver *timcapp);
void timcapDisable(TIMCAPDriver *timcapp);
#ifdef __cplusplus
}
#endif
#endif /* HAL_USE_TIMCAP */
#endif /* _TIMCAP_H_ */
/** @} */

439
os/hal/include/usbh.h Normal file
View File

@ -0,0 +1,439 @@
/*
ChibiOS - Copyright (C) 2006..2015 Giovanni Di Sirio
Copyright (C) 2015 Diego Ismirlian, TISA, (dismirlian (at) google's mail)
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.
*/
#ifndef USBH_H_
#define USBH_H_
#include "hal.h"
#ifndef HAL_USE_USBH
#define HAL_USE_USBH FALSE
#endif
#ifndef HAL_USBH_USE_FTDI
#define HAL_USBH_USE_FTDI FALSE
#endif
#ifndef HAL_USBH_USE_HUB
#define HAL_USBH_USE_HUB FALSE
#endif
#ifndef HAL_USBH_USE_MSD
#define HAL_USBH_USE_MSD FALSE
#endif
#ifndef HAL_USBH_USE_UVC
#define HAL_USBH_USE_UVC FALSE
#endif
#if HAL_USE_USBH
#include "osal.h"
#include "usbh/list.h"
#include "usbh/defs.h"
/* TODO:
*
* - Integrate VBUS power switching functionality to the API.
*
*/
/*===========================================================================*/
/* Derived constants and error checks. */
/*===========================================================================*/
#if !HAL_USBH_USE_HUB
#define USBH_MAX_ADDRESSES 1
#else
#define USBH_MAX_ADDRESSES (HAL_USBHHUB_MAX_PORTS + 1)
#endif
enum usbh_status {
USBH_STATUS_STOPPED = 0,
USBH_STATUS_STARTED,
USBH_STATUS_SUSPENDED,
};
enum usbh_devstatus {
USBH_DEVSTATUS_DISCONNECTED = 0,
USBH_DEVSTATUS_ATTACHED,
USBH_DEVSTATUS_CONNECTED,
USBH_DEVSTATUS_DEFAULT,
USBH_DEVSTATUS_ADDRESS,
USBH_DEVSTATUS_CONFIGURED,
};
enum usbh_devspeed {
USBH_DEVSPEED_LOW = 0,
USBH_DEVSPEED_FULL,
USBH_DEVSPEED_HIGH,
};
enum usbh_epdir {
USBH_EPDIR_IN = 0x80,
USBH_EPDIR_OUT = 0
};
enum usbh_eptype {
USBH_EPTYPE_CTRL = 0,
USBH_EPTYPE_ISO = 1,
USBH_EPTYPE_BULK = 2,
USBH_EPTYPE_INT = 3,
};
enum usbh_epstatus {
USBH_EPSTATUS_UNINITIALIZED = 0,
USBH_EPSTATUS_CLOSED,
USBH_EPSTATUS_OPEN,
USBH_EPSTATUS_HALTED,
};
enum usbh_urbstatus {
USBH_URBSTATUS_UNINITIALIZED = 0,
USBH_URBSTATUS_INITIALIZED,
USBH_URBSTATUS_PENDING,
// USBH_URBSTATUS_QUEUED,
USBH_URBSTATUS_ERROR,
USBH_URBSTATUS_TIMEOUT,
USBH_URBSTATUS_CANCELLED,
USBH_URBSTATUS_STALL,
USBH_URBSTATUS_DISCONNECTED,
// USBH_URBSTATUS_EPCLOSED,
USBH_URBSTATUS_OK,
};
/*===========================================================================*/
/* Driver data structures and types. */
/*===========================================================================*/
/* forward declarations */
typedef struct USBHDriver USBHDriver;
typedef struct usbh_port usbh_port_t;
typedef struct usbh_device usbh_device_t;
typedef struct usbh_ep usbh_ep_t;
typedef struct usbh_urb usbh_urb_t;
typedef struct usbh_baseclassdriver usbh_baseclassdriver_t;
typedef struct usbh_classdriverinfo usbh_classdriverinfo_t;
#if HAL_USBH_USE_HUB
typedef struct USBHHubDriver USBHHubDriver;
#endif
/* typedefs */
typedef enum usbh_status usbh_status_t;
typedef enum usbh_devspeed usbh_devspeed_t;
typedef enum usbh_devstatus usbh_devstatus_t;
typedef enum usbh_epdir usbh_epdir_t;
typedef enum usbh_eptype usbh_eptype_t;
typedef enum usbh_epstatus usbh_epstatus_t;
typedef enum usbh_urbstatus usbh_urbstatus_t;
typedef uint16_t usbh_portstatus_t;
typedef uint16_t usbh_portcstatus_t;
typedef void (*usbh_completion_cb)(usbh_urb_t *);
/* include the low level driver; the required definitions are above */
#include "usbh_lld.h"
#define USBH_DEFINE_BUFFER(type, name) USBH_LLD_DEFINE_BUFFER(type, name)
struct usbh_urb {
usbh_ep_t *ep;
void *userData;
usbh_completion_cb callback;
const void *setup_buff;
void *buff;
uint32_t requestedLength;
uint32_t actualLength;
usbh_urbstatus_t status;
thread_reference_t waitingThread;
thread_reference_t abortingThread;
/* Low level part */
_usbh_urb_ll_data
};
struct usbh_ep {
usbh_device_t *device;
usbh_ep_t *next;
usbh_epstatus_t status;
uint8_t address;
bool in;
usbh_eptype_t type;
uint16_t wMaxPacketSize;
uint8_t bInterval;
/* debug */
const char *name;
/* Low-level part */
_usbh_ep_ll_data
};
struct usbh_device {
USBHDriver *host; /* shortcut to host */
usbh_ep_t ctrl;
usbh_ep_t *endpoints;
usbh_baseclassdriver_t *drivers;
uint16_t langID0;
usbh_devstatus_t status;
usbh_devspeed_t speed;
USBH_DEFINE_BUFFER(usbh_device_descriptor_t, devDesc);
unsigned char align_bytes[2];
USBH_DEFINE_BUFFER(usbh_config_descriptor_t, basicConfigDesc);
uint8_t *fullConfigurationDescriptor;
uint8_t keepFullCfgDesc;
uint8_t address;
uint8_t bConfiguration;
/* Low level part */
_usbh_device_ll_data
};
struct usbh_port {
#if HAL_USBH_USE_HUB
USBHHubDriver *hub;
#endif
usbh_portstatus_t status;
usbh_portcstatus_t c_status;
usbh_port_t *next;
uint8_t number;
usbh_device_t device;
/* Low level part */
_usbh_port_ll_data
};
struct USBHDriver {
usbh_status_t status;
uint8_t address_bitmap[(USBH_MAX_ADDRESSES + 7) / 8];
usbh_port_t rootport;
#if HAL_USBH_USE_HUB
struct list_head hubs;
#endif
/* Low level part */
_usbhdriver_ll_data
#if USBH_DEBUG_ENABLE
/* debug */
uint8_t dbg_buff[USBH_DEBUG_BUFFER];
THD_WORKING_AREA(waDebug, 512);
input_queue_t iq;
#endif
};
/*===========================================================================*/
/* External declarations. */
/*===========================================================================*/
#if STM32_USBH_USE_OTG1
extern USBHDriver USBHD1;
#endif
#if STM32_USBH_USE_OTG2
extern USBHDriver USBHD2;
#endif
/*===========================================================================*/
/* Main driver API. */
/*===========================================================================*/
#ifdef __cplusplus
extern "C" {
#endif
/* Main functions */
void usbhObjectInit(USBHDriver *usbh);
void usbhInit(void);
void usbhStart(USBHDriver *usbh);
void usbhStop(USBHDriver *usbh);
void usbhSuspend(USBHDriver *usbh);
void usbhResume(USBHDriver *usbh);
/* Device-related */
#if USBH_DEBUG_ENABLE && USBH_DEBUG_ENABLE_INFO
void usbhDevicePrintInfo(usbh_device_t *dev);
void usbhDevicePrintConfiguration(const uint8_t *descriptor, uint16_t rem);
#else
# define usbhDevicePrintInfo(dev) do {} while(0)
# define usbhDevicePrintConfiguration(descriptor, rem) do {} while(0)
#endif
bool usbhDeviceReadString(usbh_device_t *dev, char *dest, uint8_t size,
uint8_t index, uint16_t langID);
static inline usbh_port_t *usbhDeviceGetPort(usbh_device_t *dev) {
return container_of(dev, usbh_port_t, device);
}
/* Synchronous API */
usbh_urbstatus_t usbhBulkTransfer(usbh_ep_t *ep,
void *data,
uint32_t len,
uint32_t *actual_len,
systime_t timeout);
usbh_urbstatus_t usbhControlRequest(usbh_device_t *dev,
uint8_t bmRequestType,
uint8_t bRequest,
uint16_t wValue,
uint16_t wIndex,
uint16_t wLength,
uint8_t *buff);
usbh_urbstatus_t usbhControlRequestExtended(usbh_device_t *dev,
const usbh_control_request_t *req,
uint8_t *buff,
uint32_t *actual_len,
systime_t timeout);
/* Standard request helpers */
bool usbhStdReqGetDeviceDescriptor(usbh_device_t *dev,
uint16_t wLength,
uint8_t *buf);
bool usbhStdReqGetConfigurationDescriptor(usbh_device_t *dev,
uint8_t index,
uint16_t wLength,
uint8_t *buf);
bool usbhStdReqGetStringDescriptor(usbh_device_t *dev,
uint8_t index,
uint16_t langID,
uint16_t wLength,
uint8_t *buf);
bool usbhStdReqSetInterface(usbh_device_t *dev,
uint8_t bInterfaceNumber,
uint8_t bAlternateSetting);
bool usbhStdReqGetInterface(usbh_device_t *dev,
uint8_t bInterfaceNumber,
uint8_t *bAlternateSetting);
/* Endpoint/pipe management */
void usbhEPObjectInit(usbh_ep_t *ep, usbh_device_t *dev, const usbh_endpoint_descriptor_t *desc);
static inline void usbhEPOpen(usbh_ep_t *ep) {
osalDbgCheck(ep != 0);
osalSysLock();
osalDbgAssert(ep->status == USBH_EPSTATUS_CLOSED, "invalid state");
usbh_lld_ep_open(ep);
ep->next = ep->device->endpoints;
ep->device->endpoints = ep;
osalSysUnlock();
}
static inline void usbhEPCloseS(usbh_ep_t *ep) {
osalDbgCheck(ep != 0);
osalDbgCheckClassS();
osalDbgAssert(ep->status != USBH_EPSTATUS_UNINITIALIZED, "invalid state");
if (ep->status == USBH_EPSTATUS_CLOSED) {
osalOsRescheduleS();
return;
}
usbh_lld_ep_close(ep);
}
static inline void usbhEPClose(usbh_ep_t *ep) {
osalSysLock();
usbhEPCloseS(ep);
osalSysUnlock();
}
static inline void usbhEPResetI(usbh_ep_t *ep) {
osalDbgCheckClassI();
osalDbgCheck(ep != NULL);
usbh_lld_epreset(ep);
}
static inline bool usbhEPIsPeriodic(usbh_ep_t *ep) {
osalDbgCheck(ep != NULL);
return (ep->type & 1) != 0;
}
static inline bool usbhURBIsBusy(usbh_urb_t *urb) {
osalDbgCheck(urb != NULL);
return (urb->status == USBH_URBSTATUS_PENDING);
}
static inline void usbhEPSetName(usbh_ep_t *ep, const char *name) {
ep->name = name;
}
/* URB management */
void usbhURBObjectInit(usbh_urb_t *urb, usbh_ep_t *ep, usbh_completion_cb callback,
void *user, void *buff, uint32_t len);
void usbhURBObjectResetI(usbh_urb_t *urb);
void usbhURBSubmitI(usbh_urb_t *urb);
bool usbhURBCancelI(usbh_urb_t *urb);
msg_t usbhURBSubmitAndWaitS(usbh_urb_t *urb, systime_t timeout);
void usbhURBCancelAndWaitS(usbh_urb_t *urb);
msg_t usbhURBWaitTimeoutS(usbh_urb_t *urb, systime_t timeout);
/* Main loop */
void usbhMainLoop(USBHDriver *usbh);
#ifdef __cplusplus
}
#endif
/*===========================================================================*/
/* Class driver definitions and API. */
/*===========================================================================*/
typedef struct usbh_classdriver_vmt usbh_classdriver_vmt_t;
struct usbh_classdriver_vmt {
usbh_baseclassdriver_t *(*load)(usbh_device_t *dev, const uint8_t *descriptor, uint16_t rem);
void (*unload)(usbh_baseclassdriver_t *drv);
};
struct usbh_classdriverinfo {
int16_t class;
int16_t subclass;
int16_t protocol;
const char *name;
const usbh_classdriver_vmt_t *vmt;
};
#define _usbh_base_classdriver_data \
const usbh_classdriverinfo_t *info; \
usbh_device_t *dev; \
usbh_baseclassdriver_t *next;
struct usbh_baseclassdriver {
_usbh_base_classdriver_data
};
/*===========================================================================*/
/* Helper functions. */
/*===========================================================================*/
#include <usbh/desciter.h> /* descriptor iterators */
#include <usbh/debug.h> /* debug */
#endif
#endif /* USBH_H_ */

View File

@ -0,0 +1,44 @@
/*
ChibiOS - Copyright (C) 2006..2015 Giovanni Di Sirio
Copyright (C) 2015 Diego Ismirlian, TISA, (dismirlian (at) google's mail)
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.
*/
#ifndef USBH_DEBUG_H_
#define USBH_DEBUG_H_
#include "usbh.h"
#if HAL_USE_USBH
//TODO: Debug is only for USBHD1, make it generic.
#if USBH_DEBUG_ENABLE
void usbDbgPrintf(const char *fmt, ...);
void usbDbgPuts(const char *s);
void usbDbgInit(USBHDriver *host);
void usbDbgReset(void);
void usbDbgSystemHalted(void);
#else
#define usbDbgPrintf(fmt, ...) do {} while(0)
#define usbDbgPuts(s) do {} while(0)
#define usbDbgInit(host) do {} while(0)
#define usbDbgReset() do {} while(0)
#define usbDbgSystemHalted() do {} while(0)
#endif
#endif
#endif /* USBH_DEBUG_H_ */

160
os/hal/include/usbh/defs.h Normal file
View File

@ -0,0 +1,160 @@
/*
ChibiOS - Copyright (C) 2006..2015 Giovanni Di Sirio
Copyright (C) 2015 Diego Ismirlian, TISA, (dismirlian (at) google's mail)
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.
*/
#ifndef USBH_DEFS_H_
#define USBH_DEFS_H_
#include "hal.h"
#if HAL_USE_USBH
#include "osal.h"
#ifdef __IAR_SYSTEMS_ICC__
#define PACKED_STRUCT typedef PACKED_VAR struct
#else
#define PACKED_STRUCT typedef struct PACKED_VAR
#endif
PACKED_STRUCT {
uint8_t bLength;
uint8_t bDescriptorType;
uint16_t bcdUSB;
uint8_t bDeviceClass;
uint8_t bDeviceSubClass;
uint8_t bDeviceProtocol;
uint8_t bMaxPacketSize0;
uint16_t idVendor;
uint16_t idProduct;
uint16_t bcdDevice;
uint8_t iManufacturer;
uint8_t iProduct;
uint8_t iSerialNumber;
uint8_t bNumConfigurations;
} usbh_device_descriptor_t;
#define USBH_DT_DEVICE 0x01
#define USBH_DT_DEVICE_SIZE 18
PACKED_STRUCT {
uint8_t bLength;
uint8_t bDescriptorType;
uint16_t wTotalLength;
uint8_t bNumInterfaces;
uint8_t bConfigurationValue;
uint8_t iConfiguration;
uint8_t bmAttributes;
uint8_t bMaxPower;
} usbh_config_descriptor_t;
#define USBH_DT_CONFIG 0x02
#define USBH_DT_CONFIG_SIZE 9
PACKED_STRUCT {
uint8_t bLength;
uint8_t bDescriptorType;
uint16_t wData[1];
} usbh_string_descriptor_t;
#define USBH_DT_STRING 0x03
#define USBH_DT_STRING_SIZE 2
PACKED_STRUCT {
uint8_t bLength;
uint8_t bDescriptorType;
uint8_t bInterfaceNumber;
uint8_t bAlternateSetting;
uint8_t bNumEndpoints;
uint8_t bInterfaceClass;
uint8_t bInterfaceSubClass;
uint8_t bInterfaceProtocol;
uint8_t iInterface;
} usbh_interface_descriptor_t;
#define USBH_DT_INTERFACE 0x04
#define USBH_DT_INTERFACE_SIZE 9
PACKED_STRUCT {
uint8_t bLength;
uint8_t bDescriptorType;
uint8_t bEndpointAddress;
uint8_t bmAttributes;
uint16_t wMaxPacketSize;
uint8_t bInterval;
} usbh_endpoint_descriptor_t;
#define USBH_DT_ENDPOINT 0x05
#define USBH_DT_ENDPOINT_SIZE 7
PACKED_STRUCT {
uint8_t bLength;
uint8_t bDescriptorType;
uint8_t bFirstInterface;
uint8_t bInterfaceCount;
uint8_t bFunctionClass;
uint8_t bFunctionSubClass;
uint8_t bFunctionProtocol;
uint8_t iFunction;
} usbh_ia_descriptor_t;
#define USBH_DT_INTERFACE_ASSOCIATION 0x0b
#define USBH_DT_INTERFACE_ASSOCIATION_SIZE 8
PACKED_STRUCT {
uint8_t bDescLength;
uint8_t bDescriptorType;
uint8_t bNbrPorts;
uint16_t wHubCharacteristics;
uint8_t bPwrOn2PwrGood;
uint8_t bHubContrCurrent;
uint32_t DeviceRemovable;
} usbh_hub_descriptor_t;
#define USBH_DT_HUB 0x29
#define USBH_DT_HUB_SIZE (7 + 4)
PACKED_STRUCT {
uint8_t bmRequestType;
uint8_t bRequest;
uint16_t wValue;
uint16_t wIndex;
uint16_t wLength;
} usbh_control_request_t;
#define USBH_REQ_GET_STATUS 0x00
#define USBH_REQ_CLEAR_FEATURE 0x01
#define USBH_REQ_SET_FEATURE 0x03
#define USBH_REQ_SET_ADDRESS 0x05
#define USBH_REQ_GET_DESCRIPTOR 0x06
#define USBH_REQ_SET_DESCRIPTOR 0x07
#define USBH_REQ_GET_CONFIGURATION 0x08
#define USBH_REQ_SET_CONFIGURATION 0x09
#define USBH_REQ_GET_INTERFACE 0x0A
#define USBH_REQ_SET_INTERFACE 0x0B
#define USBH_REQ_SYNCH_FRAME 0x0C
#define USBH_REQTYPE_IN 0x80
#define USBH_REQTYPE_OUT 0x00
#define USBH_REQTYPE_STANDARD 0x00
#define USBH_REQTYPE_CLASS 0x20
#define USBH_REQTYPE_VENDOR 0x40
#define USBH_REQTYPE_DEVICE 0x00
#define USBH_REQTYPE_INTERFACE 0x01
#define USBH_REQTYPE_ENDPOINT 0x02
#define USBH_REQTYPE_OTHER 0x03
#endif
#endif /* USBH_DEFS_H_ */

View File

@ -0,0 +1,63 @@
/*
ChibiOS - Copyright (C) 2006..2015 Giovanni Di Sirio
Copyright (C) 2015 Diego Ismirlian, TISA, (dismirlian (at) google's mail)
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.
*/
#ifndef USBH_DESCITER_H_
#define USBH_DESCITER_H_
#include "hal.h"
#if HAL_USE_USBH
#include "usbh/defs.h"
/* DESCRIPTOR PARSING */
#define _generic_iterator_fields \
const uint8_t *curr; \
uint16_t rem; \
bool valid;
typedef struct {
_generic_iterator_fields
} generic_iterator_t;
typedef struct {
_generic_iterator_fields
const usbh_ia_descriptor_t *iad;
} if_iterator_t;
void cfg_iter_init(generic_iterator_t *icfg, const uint8_t *buff, uint16_t rem);
void if_iter_init(if_iterator_t *iif, const generic_iterator_t *icfg);
void ep_iter_init(generic_iterator_t *iep, const if_iterator_t *iif);
void cs_iter_init(generic_iterator_t *ics, const generic_iterator_t *iter);
void if_iter_next(if_iterator_t *iif);
void ep_iter_next(generic_iterator_t *iep);
void cs_iter_next(generic_iterator_t *ics);
static inline const usbh_config_descriptor_t *cfg_get(generic_iterator_t *icfg) {
return (const usbh_config_descriptor_t *)icfg->curr;
}
static inline const usbh_interface_descriptor_t *if_get(if_iterator_t *iif) {
return (const usbh_interface_descriptor_t *)iif->curr;
}
static inline const usbh_endpoint_descriptor_t *ep_get(generic_iterator_t *iep) {
return (const usbh_endpoint_descriptor_t *)iep->curr;
}
#endif
#endif /* USBH_DESCITER_H_ */

View File

@ -0,0 +1,154 @@
/*
ChibiOS - Copyright (C) 2006..2015 Giovanni Di Sirio
Copyright (C) 2015 Diego Ismirlian, TISA, (dismirlian (at) google's mail)
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.
*/
#ifndef USBH_FTDI_H_
#define USBH_FTDI_H_
#include "usbh.h"
#if HAL_USE_USBH && HAL_USBH_USE_FTDI
/*===========================================================================*/
/* Driver pre-compile time settings. */
/*===========================================================================*/
/*===========================================================================*/
/* Derived constants and error checks. */
/*===========================================================================*/
#define USBHFTDI_FRAMING_DATABITS_7 (0x7 << 0)
#define USBHFTDI_FRAMING_DATABITS_8 (0x8 << 0)
#define USBHFTDI_FRAMING_PARITY_NONE (0x0 << 8)
#define USBHFTDI_FRAMING_PARITY_NONE (0x0 << 8)
#define USBHFTDI_FRAMING_PARITY_ODD (0x1 << 8)
#define USBHFTDI_FRAMING_PARITY_EVEN (0x2 << 8)
#define USBHFTDI_FRAMING_PARITY_MARK (0x3 << 8)
#define USBHFTDI_FRAMING_PARITY_SPACE (0x4 << 8)
#define USBHFTDI_FRAMING_STOP_BITS_1 (0x0 << 11)
#define USBHFTDI_FRAMING_STOP_BITS_15 (0x1 << 11)
#define USBHFTDI_FRAMING_STOP_BITS_2 (0x2 << 11)
#define USBHFTDI_HANDSHAKE_NONE (0x0)
#define USBHFTDI_HANDSHAKE_RTS_CTS (0x1)
#define USBHFTDI_HANDSHAKE_DTR_DSR (0x2)
#define USBHFTDI_HANDSHAKE_XON_XOFF (0x4)
/*===========================================================================*/
/* Driver data structures and types. */
/*===========================================================================*/
typedef struct {
uint32_t speed;
uint16_t framing;
uint8_t handshake;
uint8_t xon_character;
uint8_t xoff_character;
} USBHFTDIPortConfig;
typedef enum {
USBHFTDI_TYPE_A,
USBHFTDI_TYPE_B,
USBHFTDI_TYPE_H,
} usbhftdi_type_t;
typedef enum {
USBHFTDIP_STATE_UNINIT = 0,
USBHFTDIP_STATE_STOP = 1,
USBHFTDIP_STATE_ACTIVE = 2,
USBHFTDIP_STATE_READY = 3
} usbhftdip_state_t;
#define _ftdi_port_driver_methods \
_base_asynchronous_channel_methods
struct FTDIPortDriverVMT {
_ftdi_port_driver_methods
};
typedef struct USBHFTDIPortDriver USBHFTDIPortDriver;
typedef struct USBHFTDIDriver USBHFTDIDriver;
struct USBHFTDIPortDriver {
/* inherited from abstract asyncrhonous channel driver */
const struct FTDIPortDriverVMT *vmt;
_base_asynchronous_channel_data
USBHFTDIDriver *ftdip;
usbhftdip_state_t state;
usbh_ep_t epin;
usbh_urb_t iq_urb;
threads_queue_t iq_waiting;
uint32_t iq_counter;
USBH_DEFINE_BUFFER(uint8_t, iq_buff[64]);
uint8_t *iq_ptr;
usbh_ep_t epout;
usbh_urb_t oq_urb;
threads_queue_t oq_waiting;
uint32_t oq_counter;
USBH_DEFINE_BUFFER(uint8_t, oq_buff[64]);
uint8_t *oq_ptr;
virtual_timer_t vt;
uint8_t ifnum;
USBHFTDIPortDriver *next;
};
typedef struct USBHFTDIDriver {
/* inherited from abstract class driver */
_usbh_base_classdriver_data
usbhftdi_type_t type;
USBHFTDIPortDriver *ports;
mutex_t mtx;
} USBHFTDIDriver;
/*===========================================================================*/
/* Driver macros. */
/*===========================================================================*/
/*===========================================================================*/
/* External declarations. */
/*===========================================================================*/
extern USBHFTDIDriver USBHFTDID[HAL_USBHFTDI_MAX_INSTANCES];
extern USBHFTDIPortDriver FTDIPD[HAL_USBHFTDI_MAX_PORTS];
#ifdef __cplusplus
extern "C" {
#endif
/* FTDI device driver */
void usbhftdiObjectInit(USBHFTDIDriver *ftdip);
/* FTDI port driver */
void usbhftdipObjectInit(USBHFTDIPortDriver *ftdipp);
void usbhftdipStart(USBHFTDIPortDriver *ftdipp, const USBHFTDIPortConfig *config);
void usbhftdipStop(USBHFTDIPortDriver *ftdipp);
#ifdef __cplusplus
}
#endif
#endif
#endif /* USBH_FTDI_H_ */

View File

@ -0,0 +1,138 @@
/*
ChibiOS - Copyright (C) 2006..2015 Giovanni Di Sirio
Copyright (C) 2015 Diego Ismirlian, TISA, (dismirlian (at) google's mail)
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.
*/
#ifndef USBH_HUB_H_
#define USBH_HUB_H_
#include "usbh.h"
#if HAL_USE_USBH
#if HAL_USBH_USE_HUB
typedef struct USBHHubDriver {
/* inherited from abstract class driver */
_usbh_base_classdriver_data
struct list_head node;
usbh_ep_t epint;
usbh_urb_t urb;
USBH_DEFINE_BUFFER(uint8_t, scbuff[4]);
volatile uint32_t statuschange;
uint16_t status;
uint16_t c_status;
usbh_port_t *ports;
USBH_DEFINE_BUFFER(usbh_hub_descriptor_t, hubDesc);
/* Low level part */
_usbh_hub_ll_data
} USBHHubDriver;
extern USBHHubDriver USBHHUBD[HAL_USBHHUB_MAX_INSTANCES];
usbh_urbstatus_t usbhhubControlRequest(USBHDriver *host, USBHHubDriver *hub,
uint8_t bmRequestType,
uint8_t bRequest,
uint16_t wValue,
uint16_t wIndex,
uint16_t wLength,
uint8_t *buf);
static inline usbh_urbstatus_t usbhhubClearFeaturePort(usbh_port_t *port, uint8_t feature) {
return usbhhubControlRequest(port->device.host, port->hub,
USBH_REQTYPE_OUT | USBH_REQTYPE_CLASS | USBH_REQTYPE_OTHER,
USBH_REQ_CLEAR_FEATURE,
feature,
port->number,
0,
0);
}
static inline usbh_urbstatus_t usbhhubClearFeatureHub(USBHDriver *host, USBHHubDriver *hub, uint8_t feature) {
return usbhhubControlRequest(host, hub,
USBH_REQTYPE_OUT | USBH_REQTYPE_CLASS | USBH_REQTYPE_DEVICE,
USBH_REQ_CLEAR_FEATURE,
feature,
0,
0,
0);
}
static inline usbh_urbstatus_t usbhhubSetFeaturePort(usbh_port_t *port, uint8_t feature) {
return usbhhubControlRequest(port->device.host, port->hub,
USBH_REQTYPE_OUT | USBH_REQTYPE_CLASS | USBH_REQTYPE_OTHER,
USBH_REQ_SET_FEATURE,
feature,
port->number,
0,
0);
}
void usbhhubObjectInit(USBHHubDriver *hubdp);
#else
static inline usbh_urbstatus_t usbhhubControlRequest(USBHDriver *host,
uint8_t bmRequestType,
uint8_t bRequest,
uint16_t wValue,
uint16_t wIndex,
uint16_t wLength,
uint8_t *buf) {
return usbh_lld_root_hub_request(host, bmRequestType, bRequest, wValue, wIndex, wLength, buf);
}
static inline usbh_urbstatus_t usbhhubClearFeaturePort(usbh_port_t *port, uint8_t feature) {
return usbhhubControlRequest(port->device.host,
USBH_REQTYPE_OUT | USBH_REQTYPE_CLASS | USBH_REQTYPE_OTHER,
USBH_REQ_CLEAR_FEATURE,
feature,
port->number,
0,
0);
}
static inline usbh_urbstatus_t usbhhubClearFeatureHub(USBHDriver *host, uint8_t feature) {
return usbhhubControlRequest(host,
USBH_REQTYPE_OUT | USBH_REQTYPE_CLASS | USBH_REQTYPE_DEVICE,
USBH_REQ_CLEAR_FEATURE,
feature,
0,
0,
0);
}
static inline usbh_urbstatus_t usbhhubSetFeaturePort(usbh_port_t *port, uint8_t feature) {
return usbhhubControlRequest(port->device.host,
USBH_REQTYPE_OUT | USBH_REQTYPE_CLASS | USBH_REQTYPE_OTHER,
USBH_REQ_SET_FEATURE,
feature,
port->number,
0,
0);
}
#endif
#endif
#endif /* USBH_HUB_H_ */

View File

@ -0,0 +1,125 @@
/*
ChibiOS - Copyright (C) 2006..2015 Giovanni Di Sirio
Copyright (C) 2015 Diego Ismirlian, TISA, (dismirlian (at) google's mail)
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.
*/
#ifndef USBH_MSD_H_
#define USBH_MSD_H_
#include "usbh.h"
#if HAL_USE_USBH && HAL_USBH_USE_MSD
/* TODO:
*
* - Implement of conditional compilation of multiple-luns per instance.
* - Implement error checking and recovery when commands fail.
*
*/
/*===========================================================================*/
/* Driver pre-compile time settings. */
/*===========================================================================*/
/*===========================================================================*/
/* Derived constants and error checks. */
/*===========================================================================*/
/*===========================================================================*/
/* Driver data structures and types. */
/*===========================================================================*/
#define _usbhmsd_driver_methods \
_base_block_device_methods
struct USBHMassStorageDriverVMT {
_usbhmsd_driver_methods
};
typedef struct USBHMassStorageLUNDriver USBHMassStorageLUNDriver;
typedef struct USBHMassStorageDriver USBHMassStorageDriver;
struct USBHMassStorageLUNDriver {
/* inherited from abstract block driver */
const struct USBHMassStorageDriverVMT *vmt;
_base_block_device_data
BlockDeviceInfo info;
USBHMassStorageDriver *msdp;
USBHMassStorageLUNDriver *next;
};
typedef struct USBHMassStorageDriver {
/* inherited from abstract class driver */
_usbh_base_classdriver_data
/* for LUN request serialization, can be removed
* if the driver is configured to support only one LUN
* per USBHMassStorageDriver instance */
mutex_t mtx;
usbh_ep_t epin;
usbh_ep_t epout;
uint8_t ifnum;
uint8_t max_lun;
uint32_t tag;
USBHMassStorageLUNDriver *luns;
} USBHMassStorageDriver;
/*===========================================================================*/
/* Driver macros. */
/*===========================================================================*/
/*===========================================================================*/
/* External declarations. */
/*===========================================================================*/
extern USBHMassStorageLUNDriver MSBLKD[HAL_USBHMSD_MAX_LUNS];
extern USBHMassStorageDriver USBHMSD[HAL_USBHMSD_MAX_INSTANCES];
#ifdef __cplusplus
extern "C" {
#endif
/* Mass Storage Driver */
void usbhmsdObjectInit(USBHMassStorageDriver *msdp);
/* Mass Storage LUN Driver (block driver) */
void usbhmsdLUNObjectInit(USBHMassStorageLUNDriver *lunp);
void usbhmsdLUNStart(USBHMassStorageLUNDriver *lunp);
void usbhmsdLUNStop(USBHMassStorageLUNDriver *lunp);
bool usbhmsdLUNConnect(USBHMassStorageLUNDriver *lunp);
bool usbhmsdLUNDisconnect(USBHMassStorageLUNDriver *lunp);
bool usbhmsdLUNRead(USBHMassStorageLUNDriver *lunp, uint32_t startblk,
uint8_t *buffer, uint32_t n);
bool usbhmsdLUNWrite(USBHMassStorageLUNDriver *lunp, uint32_t startblk,
const uint8_t *buffer, uint32_t n);
bool usbhmsdLUNSync(USBHMassStorageLUNDriver *lunp);
bool usbhmsdLUNGetInfo(USBHMassStorageLUNDriver *lunp, BlockDeviceInfo *bdip);
bool usbhmsdLUNIsInserted(USBHMassStorageLUNDriver *lunp);
bool usbhmsdLUNIsProtected(USBHMassStorageLUNDriver *lunp);
#ifdef __cplusplus
}
#endif
#endif
#endif /* USBH_MSD_H_ */

View File

@ -0,0 +1,148 @@
/*
ChibiOS - Copyright (C) 2006..2015 Giovanni Di Sirio
Copyright (C) 2015 Diego Ismirlian, TISA, (dismirlian (at) google's mail)
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.
*/
#ifndef USBH_INTERNAL_H_
#define USBH_INTERNAL_H_
#include "usbh.h"
#if HAL_USE_USBH
/*===========================================================================*/
/* These declarations are not part of the public API. */
/*===========================================================================*/
#if HAL_USBH_USE_FTDI
extern const usbh_classdriverinfo_t usbhftdiClassDriverInfo;
#endif
#if HAL_USBH_USE_MSD
extern const usbh_classdriverinfo_t usbhmsdClassDriverInfo;
#endif
#if HAL_USBH_USE_UVC
extern const usbh_classdriverinfo_t usbhuvcClassDriverInfo;
#endif
#if HAL_USBH_USE_HUB
extern const usbh_classdriverinfo_t usbhhubClassDriverInfo;
void _usbhub_port_object_init(usbh_port_t *port, USBHDriver *usbh,
USBHHubDriver *hub, uint8_t number);
#else
void _usbhub_port_object_init(usbh_port_t *port, USBHDriver *usbh, uint8_t number);
#endif
void _usbh_port_disconnected(usbh_port_t *port);
void _usbh_urb_completeI(usbh_urb_t *urb, usbh_urbstatus_t status);
bool _usbh_urb_abortI(usbh_urb_t *urb, usbh_urbstatus_t status);
void _usbh_urb_abort_and_waitS(usbh_urb_t *urb, usbh_urbstatus_t status);
#define USBH_CLASSIN(type, req, value, index) \
(USBH_REQTYPE_IN | type | USBH_REQTYPE_CLASS), \
req, \
value, \
index
#define USBH_CLASSOUT(type, req, value, index) \
(USBH_REQTYPE_OUT | type | USBH_REQTYPE_CLASS), \
req, \
value, \
index
#define USBH_STANDARDIN(type, req, value, index) \
(USBH_REQTYPE_IN | type | USBH_REQTYPE_STANDARD), \
req, \
value, \
index
#define USBH_STANDARDOUT(type, req, value, index) \
(USBH_REQTYPE_OUT | type | USBH_REQTYPE_STANDARD), \
req, \
value, \
index
#define USBH_PID_DATA0 0
#define USBH_PID_DATA2 1
#define USBH_PID_DATA1 2
#define USBH_PID_MDATA 3
#define USBH_PID_SETUP 3
/* GetBusState and SetHubDescriptor are optional, omitted */
#define ClearHubFeature (((USBH_REQTYPE_OUT | USBH_REQTYPE_CLASS | USBH_REQTYPE_DEVICE) << 8) \
| USBH_REQ_CLEAR_FEATURE)
#define SetHubFeature (((USBH_REQTYPE_OUT | USBH_REQTYPE_CLASS | USBH_REQTYPE_DEVICE) << 8) \
| USBH_REQ_SET_FEATURE)
#define ClearPortFeature (((USBH_REQTYPE_OUT | USBH_REQTYPE_CLASS | USBH_REQTYPE_OTHER) << 8) \
| USBH_REQ_CLEAR_FEATURE)
#define SetPortFeature (((USBH_REQTYPE_OUT | USBH_REQTYPE_CLASS | USBH_REQTYPE_OTHER) << 8) \
| USBH_REQ_SET_FEATURE)
#define GetHubDescriptor (((USBH_REQTYPE_IN | USBH_REQTYPE_CLASS | USBH_REQTYPE_DEVICE) << 8) \
| USBH_REQ_GET_DESCRIPTOR)
#define GetHubStatus (((USBH_REQTYPE_IN | USBH_REQTYPE_CLASS | USBH_REQTYPE_DEVICE) << 8) \
| USBH_REQ_GET_STATUS)
#define GetPortStatus (((USBH_REQTYPE_IN | USBH_REQTYPE_CLASS | USBH_REQTYPE_OTHER) << 8) \
| USBH_REQ_GET_STATUS)
#define USBH_PORTSTATUS_CONNECTION 0x0001
#define USBH_PORTSTATUS_ENABLE 0x0002
#define USBH_PORTSTATUS_SUSPEND 0x0004
#define USBH_PORTSTATUS_OVERCURRENT 0x0008
#define USBH_PORTSTATUS_RESET 0x0010
/* bits 5 to 7 are reserved */
#define USBH_PORTSTATUS_POWER 0x0100
#define USBH_PORTSTATUS_LOW_SPEED 0x0200
#define USBH_PORTSTATUS_HIGH_SPEED 0x0400
#define USBH_PORTSTATUS_TEST 0x0800
#define USBH_PORTSTATUS_INDICATOR 0x1000
/* bits 13 to 15 are reserved */
#define USBH_PORTSTATUS_C_CONNECTION 0x0001
#define USBH_PORTSTATUS_C_ENABLE 0x0002
#define USBH_PORTSTATUS_C_SUSPEND 0x0004
#define USBH_PORTSTATUS_C_OVERCURRENT 0x0008
#define USBH_PORTSTATUS_C_RESET 0x0010
#define USBH_HUBSTATUS_C_HUB_LOCAL_POWER 0x0001
#define USBH_HUBSTATUS_C_HUB_OVER_CURRENT 0x0002
/*
* Port feature numbers
* See USB 2.0 spec Table 11-17
*/
#define USBH_HUB_FEAT_C_HUB_LOCAL_POWER 0
#define USBH_HUB_FEAT_C_HUB_OVER_CURRENT 1
#define USBH_PORT_FEAT_CONNECTION 0
#define USBH_PORT_FEAT_ENABLE 1
#define USBH_PORT_FEAT_SUSPEND 2
#define USBH_PORT_FEAT_OVERCURRENT 3
#define USBH_PORT_FEAT_RESET 4
#define USBH_PORT_FEAT_POWER 8
#define USBH_PORT_FEAT_LOWSPEED 9
#define USBH_PORT_FEAT_C_CONNECTION 16
#define USBH_PORT_FEAT_C_ENABLE 17
#define USBH_PORT_FEAT_C_SUSPEND 18
#define USBH_PORT_FEAT_C_OVERCURRENT 19
#define USBH_PORT_FEAT_C_RESET 20
#define USBH_PORT_FEAT_TEST 21
#define USBH_PORT_FEAT_INDICATOR 22
#define sizeof_array(x) (sizeof(x)/sizeof(*(x)))
#endif
#endif /* USBH_INTERNAL_H_ */

598
os/hal/include/usbh/list.h Normal file
View File

@ -0,0 +1,598 @@
#ifndef USBH_LIST_H_
#define USBH_LIST_H_
/* TODO: re-write this file; stolen from linux */
#ifndef offsetof
#define offsetof(TYPE, MEMBER) ((size_t) &((TYPE *)0)->MEMBER)
#endif
#define container_of(ptr, type, member) ((type *)(void *)((char *)(ptr) - offsetof(type, member)))
#ifndef container_of
#define container_of(ptr, type, member) ({ \
const typeof(((type *)0)->member) * __mptr = (ptr); \
(type *)((char *)__mptr - offsetof(type, member)); })
#endif
/*
* Simple doubly linked list implementation.
*
* Some of the internal functions ("__xxx") are useful when
* manipulating whole lists rather than single entries, as
* sometimes we already know the next/prev entries and we can
* generate better code by using them directly rather than
* using the generic single-entry routines.
*/
struct list_head {
struct list_head *next, *prev;
};
#define LIST_HEAD_INIT(name) { &(name), &(name) }
#define LIST_HEAD(name) \
struct list_head name = LIST_HEAD_INIT(name)
static inline void INIT_LIST_HEAD(struct list_head *list)
{
list->next = list;
list->prev = list;
}
/*
* Insert a new entry between two known consecutive entries.
*
* This is only for internal list manipulation where we know
* the prev/next entries already!
*/
#ifndef CONFIG_DEBUG_LIST
static inline void __list_add(struct list_head *new,
struct list_head *prev,
struct list_head *next)
{
next->prev = new;
new->next = next;
new->prev = prev;
prev->next = new;
}
#else
extern void __list_add(struct list_head *new,
struct list_head *prev,
struct list_head *next);
#endif
/**
* list_add - add a new entry
* @new: new entry to be added
* @head: list head to add it after
*
* Insert a new entry after the specified head.
* This is good for implementing stacks.
*/
static inline void list_add(struct list_head *new, struct list_head *head)
{
__list_add(new, head, head->next);
}
/**
* list_add_tail - add a new entry
* @new: new entry to be added
* @head: list head to add it before
*
* Insert a new entry before the specified head.
* This is useful for implementing queues.
*/
static inline void list_add_tail(struct list_head *new, struct list_head *head)
{
__list_add(new, head->prev, head);
}
/*
* Delete a list entry by making the prev/next entries
* point to each other.
*
* This is only for internal list manipulation where we know
* the prev/next entries already!
*/
static inline void __list_del(struct list_head * prev, struct list_head * next)
{
next->prev = prev;
prev->next = next;
}
/**
* list_del - deletes entry from list.
* @entry: the element to delete from the list.
* Note: list_empty() on entry does not return true after this, the entry is
* in an undefined state.
*/
#ifndef CONFIG_DEBUG_LIST
static inline void __list_del_entry(struct list_head *entry)
{
__list_del(entry->prev, entry->next);
}
static inline void list_del(struct list_head *entry)
{
__list_del(entry->prev, entry->next);
// entry->next = LIST_POISON1;
// entry->prev = LIST_POISON2;
}
#else
extern void __list_del_entry(struct list_head *entry);
extern void list_del(struct list_head *entry);
#endif
/**
* list_replace - replace old entry by new one
* @old : the element to be replaced
* @new : the new element to insert
*
* If @old was empty, it will be overwritten.
*/
static inline void list_replace(struct list_head *old,
struct list_head *new)
{
new->next = old->next;
new->next->prev = new;
new->prev = old->prev;
new->prev->next = new;
}
static inline void list_replace_init(struct list_head *old,
struct list_head *new)
{
list_replace(old, new);
INIT_LIST_HEAD(old);
}
/**
* list_del_init - deletes entry from list and reinitialize it.
* @entry: the element to delete from the list.
*/
static inline void list_del_init(struct list_head *entry)
{
__list_del_entry(entry);
INIT_LIST_HEAD(entry);
}
/**
* list_move - delete from one list and add as another's head
* @list: the entry to move
* @head: the head that will precede our entry
*/
static inline void list_move(struct list_head *list, struct list_head *head)
{
__list_del_entry(list);
list_add(list, head);
}
/**
* list_move_tail - delete from one list and add as another's tail
* @list: the entry to move
* @head: the head that will follow our entry
*/
static inline void list_move_tail(struct list_head *list,
struct list_head *head)
{
__list_del_entry(list);
list_add_tail(list, head);
}
/**
* list_is_last - tests whether @list is the last entry in list @head
* @list: the entry to test
* @head: the head of the list
*/
static inline int list_is_last(const struct list_head *list,
const struct list_head *head)
{
return list->next == head;
}
/**
* list_empty - tests whether a list is empty
* @head: the list to test.
*/
static inline int list_empty(const struct list_head *head)
{
return head->next == head;
}
/**
* list_empty_careful - tests whether a list is empty and not being modified
* @head: the list to test
*
* Description:
* tests whether a list is empty _and_ checks that no other CPU might be
* in the process of modifying either member (next or prev)
*
* NOTE: using list_empty_careful() without synchronization
* can only be safe if the only activity that can happen
* to the list entry is list_del_init(). Eg. it cannot be used
* if another CPU could re-list_add() it.
*/
static inline int list_empty_careful(const struct list_head *head)
{
struct list_head *next = head->next;
return (next == head) && (next == head->prev);
}
/**
* list_rotate_left - rotate the list to the left
* @head: the head of the list
*/
static inline void list_rotate_left(struct list_head *head)
{
struct list_head *first;
if (!list_empty(head)) {
first = head->next;
list_move_tail(first, head);
}
}
/**
* list_is_singular - tests whether a list has just one entry.
* @head: the list to test.
*/
static inline int list_is_singular(const struct list_head *head)
{
return !list_empty(head) && (head->next == head->prev);
}
static inline void __list_cut_position(struct list_head *list,
struct list_head *head, struct list_head *entry)
{
struct list_head *new_first = entry->next;
list->next = head->next;
list->next->prev = list;
list->prev = entry;
entry->next = list;
head->next = new_first;
new_first->prev = head;
}
/**
* list_cut_position - cut a list into two
* @list: a new list to add all removed entries
* @head: a list with entries
* @entry: an entry within head, could be the head itself
* and if so we won't cut the list
*
* This helper moves the initial part of @head, up to and
* including @entry, from @head to @list. You should
* pass on @entry an element you know is on @head. @list
* should be an empty list or a list you do not care about
* losing its data.
*
*/
static inline void list_cut_position(struct list_head *list,
struct list_head *head, struct list_head *entry)
{
if (list_empty(head))
return;
if (list_is_singular(head) &&
(head->next != entry && head != entry))
return;
if (entry == head)
INIT_LIST_HEAD(list);
else
__list_cut_position(list, head, entry);
}
static inline void __list_splice(const struct list_head *list,
struct list_head *prev,
struct list_head *next)
{
struct list_head *first = list->next;
struct list_head *last = list->prev;
first->prev = prev;
prev->next = first;
last->next = next;
next->prev = last;
}
/**
* list_splice - join two lists, this is designed for stacks
* @list: the new list to add.
* @head: the place to add it in the first list.
*/
static inline void list_splice(const struct list_head *list,
struct list_head *head)
{
if (!list_empty(list))
__list_splice(list, head, head->next);
}
/**
* list_splice_tail - join two lists, each list being a queue
* @list: the new list to add.
* @head: the place to add it in the first list.
*/
static inline void list_splice_tail(struct list_head *list,
struct list_head *head)
{
if (!list_empty(list))
__list_splice(list, head->prev, head);
}
/**
* list_splice_init - join two lists and reinitialise the emptied list.
* @list: the new list to add.
* @head: the place to add it in the first list.
*
* The list at @list is reinitialised
*/
static inline void list_splice_init(struct list_head *list,
struct list_head *head)
{
if (!list_empty(list)) {
__list_splice(list, head, head->next);
INIT_LIST_HEAD(list);
}
}
/**
* list_splice_tail_init - join two lists and reinitialise the emptied list
* @list: the new list to add.
* @head: the place to add it in the first list.
*
* Each of the lists is a queue.
* The list at @list is reinitialised
*/
static inline void list_splice_tail_init(struct list_head *list,
struct list_head *head)
{
if (!list_empty(list)) {
__list_splice(list, head->prev, head);
INIT_LIST_HEAD(list);
}
}
/**
* list_entry - get the struct for this entry
* @ptr: the &struct list_head pointer.
* @type: the type of the struct this is embedded in.
* @member: the name of the list_head within the struct.
*/
#define list_entry(ptr, type, member) \
container_of(ptr, type, member)
/**
* list_first_entry - get the first element from a list
* @ptr: the list head to take the element from.
* @type: the type of the struct this is embedded in.
* @member: the name of the list_head within the struct.
*
* Note, that list is expected to be not empty.
*/
#define list_first_entry(ptr, type, member) \
list_entry((ptr)->next, type, member)
/**
* list_last_entry - get the last element from a list
* @ptr: the list head to take the element from.
* @type: the type of the struct this is embedded in.
* @member: the name of the list_head within the struct.
*
* Note, that list is expected to be not empty.
*/
#define list_last_entry(ptr, type, member) \
list_entry((ptr)->prev, type, member)
/**
* list_first_entry_or_null - get the first element from a list
* @ptr: the list head to take the element from.
* @type: the type of the struct this is embedded in.
* @member: the name of the list_head within the struct.
*
* Note that if the list is empty, it returns NULL.
*/
#define list_first_entry_or_null(ptr, type, member) \
(!list_empty(ptr) ? list_first_entry(ptr, type, member) : NULL)
/**
* list_next_entry - get the next element in list
* @pos: the type * to cursor
* @member: the name of the list_head within the struct.
*/
#define list_next_entry(pos, type, member) \
list_entry((pos)->member.next, type, member)
/**
* list_prev_entry - get the prev element in list
* @pos: the type * to cursor
* @member: the name of the list_head within the struct.
*/
#define list_prev_entry(pos, type, member) \
list_entry((pos)->member.prev, type, member)
/**
* list_for_each - iterate over a list
* @pos: the &struct list_head to use as a loop cursor.
* @head: the head for your list.
*/
#define list_for_each(pos, head) \
for (pos = (head)->next; pos != (head); pos = pos->next)
/**
* list_for_each_prev - iterate over a list backwards
* @pos: the &struct list_head to use as a loop cursor.
* @head: the head for your list.
*/
#define list_for_each_prev(pos, head) \
for (pos = (head)->prev; pos != (head); pos = pos->prev)
/**
* list_for_each_safe - iterate over a list safe against removal of list entry
* @pos: the &struct list_head to use as a loop cursor.
* @n: another &struct list_head to use as temporary storage
* @head: the head for your list.
*/
#define list_for_each_safe(pos, n, head) \
for (pos = (head)->next, n = pos->next; pos != (head); \
pos = n, n = pos->next)
/**
* list_for_each_prev_safe - iterate over a list backwards safe against removal of list entry
* @pos: the &struct list_head to use as a loop cursor.
* @n: another &struct list_head to use as temporary storage
* @head: the head for your list.
*/
#define list_for_each_prev_safe(pos, n, head) \
for (pos = (head)->prev, n = pos->prev; \
pos != (head); \
pos = n, n = pos->prev)
/**
* list_for_each_entry - iterate over list of given type
* @pos: the type * to use as a loop cursor.
* @head: the head for your list.
* @member: the name of the list_head within the struct.
*/
#define list_for_each_entry(pos, type, head, member) \
for (pos = list_first_entry(head, type, member); \
&pos->member != (head); \
pos = list_next_entry(pos, type, member))
/**
* list_for_each_entry_reverse - iterate backwards over list of given type.
* @pos: the type * to use as a loop cursor.
* @head: the head for your list.
* @member: the name of the list_head within the struct.
*/
#define list_for_each_entry_reverse(pos, type, head, member) \
for (pos = list_last_entry(head, type, member); \
&pos->member != (head); \
pos = list_prev_entry(pos, type, member))
/**
* list_prepare_entry - prepare a pos entry for use in list_for_each_entry_continue()
* @pos: the type * to use as a start point
* @head: the head of the list
* @member: the name of the list_head within the struct.
*
* Prepares a pos entry for use as a start point in list_for_each_entry_continue().
*/
#define list_prepare_entry(pos, type, head, member) \
((pos) ? : list_entry(head, type, member))
/**
* list_for_each_entry_continue - continue iteration over list of given type
* @pos: the type * to use as a loop cursor.
* @head: the head for your list.
* @member: the name of the list_head within the struct.
*
* Continue to iterate over list of given type, continuing after
* the current position.
*/
#define list_for_each_entry_continue(pos, type, head, member) \
for (pos = list_next_entry(pos, type, member); \
&pos->member != (head); \
pos = list_next_entry(pos, type, member))
/**
* list_for_each_entry_continue_reverse - iterate backwards from the given point
* @pos: the type * to use as a loop cursor.
* @head: the head for your list.
* @member: the name of the list_head within the struct.
*
* Start to iterate over list of given type backwards, continuing after
* the current position.
*/
#define list_for_each_entry_continue_reverse(pos, type, head, member) \
for (pos = list_prev_entry(pos, type, member); \
&pos->member != (head); \
pos = list_prev_entry(pos, type, member))
/**
* list_for_each_entry_from - iterate over list of given type from the current point
* @pos: the type * to use as a loop cursor.
* @head: the head for your list.
* @member: the name of the list_head within the struct.
*
* Iterate over list of given type, continuing from current position.
*/
#define list_for_each_entry_from(pos, type, head, member) \
for (; &pos->member != (head); \
pos = list_next_entry(pos, type, member))
/**
* list_for_each_entry_safe - iterate over list of given type safe against removal of list entry
* @pos: the type * to use as a loop cursor.
* @n: another type * to use as temporary storage
* @head: the head for your list.
* @member: the name of the list_head within the struct.
*/
#define list_for_each_entry_safe(pos, type, n, head, member) \
for (pos = list_first_entry(head, type, member), \
n = list_next_entry(pos, type, member); \
&pos->member != (head); \
pos = n, n = list_next_entry(n, type, member))
/**
* list_for_each_entry_safe_continue - continue list iteration safe against removal
* @pos: the type * to use as a loop cursor.
* @n: another type * to use as temporary storage
* @head: the head for your list.
* @member: the name of the list_head within the struct.
*
* Iterate over list of given type, continuing after current point,
* safe against removal of list entry.
*/
#define list_for_each_entry_safe_continue(pos, type, n, head, member) \
for (pos = list_next_entry(pos, type, member), \
n = list_next_entry(pos, type, member); \
&pos->member != (head); \
pos = n, n = list_next_entry(n, type, member))
/**
* list_for_each_entry_safe_from - iterate over list from current point safe against removal
* @pos: the type * to use as a loop cursor.
* @n: another type * to use as temporary storage
* @head: the head for your list.
* @member: the name of the list_head within the struct.
*
* Iterate over list of given type from current point, safe against
* removal of list entry.
*/
#define list_for_each_entry_safe_from(pos, type, n, head, member) \
for (n = list_next_entry(pos, type, member); \
&pos->member != (head); \
pos = n, n = list_next_entry(n, type, member))
/**
* list_for_each_entry_safe_reverse - iterate backwards over list safe against removal
* @pos: the type * to use as a loop cursor.
* @n: another type * to use as temporary storage
* @head: the head for your list.
* @member: the name of the list_head within the struct.
*
* Iterate backwards over list of given type, safe against removal
* of list entry.
*/
#define list_for_each_entry_safe_reverse(pos, type, n, head, member) \
for (pos = list_last_entry(head, type, member), \
n = list_prev_entry(pos, type, member); \
&pos->member != (head); \
pos = n, n = list_prev_entry(n, type, member))
/**
* list_safe_reset_next - reset a stale list_for_each_entry_safe loop
* @pos: the loop cursor used in the list_for_each_entry_safe loop
* @n: temporary storage used in list_for_each_entry_safe
* @member: the name of the list_head within the struct.
*
* list_safe_reset_next is not safe to use in general if the list may be
* modified concurrently (eg. the lock is dropped in the loop body). An
* exception to this is if the cursor element (pos) is pinned in the list,
* and list_safe_reset_next is called after re-taking the lock and before
* completing the current iteration of the loop body.
*/
#define list_safe_reset_next(pos, type, n, member) \
n = list_next_entry(pos, type, member)
#endif /* USBH_LIST_H_ */

View File

@ -94,7 +94,7 @@
#if !NRF51_GPT_USE_TIMER0 && !NRF51_GPT_USE_TIMER1 && \
!NRF51_GPT_USE_TIMER2
#error "GPT driver activated but no TIM peripheral assigned"
#error "GPT driver activated but no TIMER peripheral assigned"
#endif
#if 0

View File

@ -55,6 +55,29 @@
*/
void hal_lld_init(void)
{
/* High frequency clock initialisation
* (If NRF51_XTAL_VALUE is not defined assume its an RC oscillator)
*/
NRF_CLOCK->TASKS_HFCLKSTOP = 1;
#if defined(NRF51_XTAL_VALUE)
#if NRF51_XTAL_VALUE == 16000000
NRF_CLOCK->XTALFREQ = 0xFF;
#elif NRF51_XTAL_VALUE == 32000000
NRF_CLOCK->XTALFREQ = 0x00;
#endif
#endif
/* Low frequency clock initialisation
* Clock is only started if st driver requires it
*/
NRF_CLOCK->TASKS_LFCLKSTOP = 1;
NRF_CLOCK->LFCLKSRC = NRF51_LFCLK_SOURCE;
#if (OSAL_ST_MODE != OSAL_ST_MODE_NONE) && \
(NRF51_SYSTEM_TICKS == NRF51_SYSTEM_TICKS_AS_RTC)
NRF_CLOCK->TASKS_LFCLKSTART = 1;
#endif
}
/**

View File

@ -39,14 +39,36 @@
* @}
*/
/**
* @brief Frequency valuefor the Low Frequency Clock
*/
#define NRF51_LFCLK_FREQUENCY 32768
/*===========================================================================*/
/* Driver pre-compile time settings. */
/*===========================================================================*/
/**
* @brief Select source of Low Frequency Clock (LFCLK)
* @details Possible values for source are:
* 0 : RC oscillator
* 1 : External cristal
* 2 : Synthetized clock from High Frequency Clock (HFCLK)
* When cristal is not available it's preferable to use the
* internal RC oscillator that synthezing the clock.
*/
#if !defined(NRF51_LFCLK_SOURCE) || defined(__DOXYGEN__)
#define NRF51_LFCLK_SOURCE 0
#endif
/*===========================================================================*/
/* Derived constants and error checks. */
/*===========================================================================*/
#if (NRF51_LFCLK_SOURCE < 0) || (NRF51_LFCLK_SOURCE > 2)
#error "Possible value for NRF51_LFCLK_SOURCE are 0=RC, 1=XTAL, 2=Synth"
#endif
/*===========================================================================*/
/* Driver data structures and types. */
/*===========================================================================*/

View File

@ -1,5 +1,5 @@
ifeq ($(USE_SMART_BUILD),yes)
HALCONF := $(strip $(shell cat halconf.h | egrep -e "define"))
HALCONF := $(strip $(shell cat halconf.h halconf_community.h | egrep -e "define"))
# List of all the NRF51x platform files.
PLATFORMSRC = ${CHIBIOS}/os/hal/ports/common/ARMCMx/nvic.c \

View File

@ -1,5 +1,6 @@
/*
ChibiOS - Copyright (C) 2015 Fabio Utzig
2016 Stephane D'Alu
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
@ -51,9 +52,55 @@
/*===========================================================================*/
#if (OSAL_ST_MODE == OSAL_ST_MODE_PERIODIC) || defined(__DOXYGEN__)
#if NRF51_ST_USE_RTC0 == TRUE
/**
* @brief System Timer vector.
* @details This interrupt is used for system tick in periodic mode.
* @brief System Timer vector (RTC0)
* @details This interrupt is used for system tick in periodic mode
* if selected with NRF51_ST_USE_RTC0
*
* @isr
*/
OSAL_IRQ_HANDLER(Vector6C) {
OSAL_IRQ_PROLOGUE();
NRF_RTC0->EVENTS_TICK = 0;
osalSysLockFromISR();
osalOsTimerHandlerI();
osalSysUnlockFromISR();
OSAL_IRQ_EPILOGUE();
}
#endif
#if NRF51_ST_USE_RTC1 == TRUE
/**
* @brief System Timer vector (RTC1)
* @details This interrupt is used for system tick in periodic mode
* if selected with NRF51_ST_USE_RTC1
*
* @isr
*/
OSAL_IRQ_HANDLER(Vector84) {
OSAL_IRQ_PROLOGUE();
NRF_RTC1->EVENTS_TICK = 0;
osalSysLockFromISR();
osalOsTimerHandlerI();
osalSysUnlockFromISR();
OSAL_IRQ_EPILOGUE();
}
#endif
#if NRF51_ST_USE_TIMER0 == TRUE
/**
* @brief System Timer vector. (TIMER0)
* @details This interrupt is used for system tick in periodic mode
* if selected with NRF51_ST_USE_TIMER0
*
* @isr
*/
@ -71,8 +118,73 @@ OSAL_IRQ_HANDLER(Vector60) {
OSAL_IRQ_EPILOGUE();
}
#endif
#endif /* OSAL_ST_MODE == OSAL_ST_MODE_PERIODIC */
#if (OSAL_ST_MODE == OSAL_ST_MODE_FREERUNNING) || defined(__DOXYGEN__)
#if NRF51_ST_USE_RTC0 == TRUE
/**
* @brief System Timer vector (RTC0)
* @details This interrupt is used for freerunning mode (tick-less)
* if selected with NRF51_ST_USE_RTC0
*
* @isr
*/
OSAL_IRQ_HANDLER(Vector6C) {
OSAL_IRQ_PROLOGUE();
if (NRF_RTC0->EVENTS_COMPARE[0]) {
NRF_RTC0->EVENTS_COMPARE[0] = 0;
osalSysLockFromISR();
osalOsTimerHandlerI();
osalSysUnlockFromISR();
}
#if OSAL_ST_RESOLUTION == 16
if (NRF_RTC0->EVENTS_COMPARE[1]) {
NRF_RTC0->EVENTS_COMPARE[1] = 0;
NRF_RTC0->TASKS_CLEAR = 1;
}
#endif
OSAL_IRQ_EPILOGUE();
}
#endif
#if NRF51_ST_USE_RTC1 == TRUE
/**
* @brief System Timer vector (RTC1)
* @details This interrupt is used for freerunning mode (tick-less)
* if selected with NRF51_ST_USE_RTC1
*
* @isr
*/
OSAL_IRQ_HANDLER(Vector84) {
OSAL_IRQ_PROLOGUE();
if (NRF_RTC1->EVENTS_COMPARE[0]) {
NRF_RTC1->EVENTS_COMPARE[0] = 0;
osalSysLockFromISR();
osalOsTimerHandlerI();
osalSysUnlockFromISR();
}
#if OSAL_ST_RESOLUTION == 16
if (NRF_RTC1->EVENTS_COMPARE[1]) {
NRF_RTC1->EVENTS_COMPARE[1] = 0;
NRF_RTC1->TASKS_CLEAR = 1;
}
#endif
OSAL_IRQ_EPILOGUE();
}
#endif
#endif /* OSAL_ST_MODE == OSAL_ST_MODE_FREERUNNING */
/*===========================================================================*/
/* Driver exported functions. */
/*===========================================================================*/
@ -83,8 +195,75 @@ OSAL_IRQ_HANDLER(Vector60) {
* @notapi
*/
void st_lld_init(void) {
#if OSAL_ST_MODE == OSAL_ST_MODE_FREERUNNING
#if NRF51_ST_USE_RTC0 == TRUE
/* Using RTC with prescaler */
NRF_RTC0->TASKS_STOP = 1;
NRF_RTC0->PRESCALER = (NRF51_LFCLK_FREQUENCY / OSAL_ST_FREQUENCY) - 1;
NRF_RTC0->EVTENCLR = RTC_EVTENSET_COMPARE0_Msk;
NRF_RTC0->EVENTS_COMPARE[0] = 0;
NRF_RTC0->INTENSET = RTC_INTENSET_COMPARE0_Msk;
#if OSAL_ST_RESOLUTION == 16
NRF_RTC0->CC[1] = 0x10000; /* 2^16 */
NRF_RTC0->EVENTS_COMPARE[1] = 0;
NRF_RTC0->EVTENSET = RTC_EVTENSET_COMPARE0_Msk;
NRF_RTC0->INTENSET = RTC_INTENSET_COMPARE1_Msk;
#endif
NRF_RTC0->TASKS_CLEAR = 1;
/* Start timer */
nvicEnableVector(RTC0_IRQn, NRF51_ST_PRIORITY);
NRF_RTC0->TASKS_START = 1;
#endif /* NRF51_ST_USE_RTC0 == TRUE */
#if NRF51_ST_USE_RTC1 == TRUE
/* Using RTC with prescaler */
NRF_RTC1->TASKS_STOP = 1;
NRF_RTC1->PRESCALER = (NRF51_LFCLK_FREQUENCY / OSAL_ST_FREQUENCY) - 1;
NRF_RTC1->EVTENCLR = RTC_EVTENSET_COMPARE0_Msk;
NRF_RTC1->EVENTS_COMPARE[0] = 0;
NRF_RTC1->INTENSET = RTC_INTENSET_COMPARE0_Msk;
#if OSAL_ST_RESOLUTION == 16
NRF_RTC1->CC[1] = 0x10000; /* 2^16 */
NRF_RTC1->EVENTS_COMPARE[1] = 0;
NRF_RTC1->EVTENSET = RTC_EVTENSET_COMPARE0_Msk;
NRF_RTC1->INTENSET = RTC_INTENSET_COMPARE1_Msk;
#endif
NRF_RTC1->TASKS_CLEAR = 1;
/* Start timer */
nvicEnableVector(RTC1_IRQn, NRF51_ST_PRIORITY);
NRF_RTC1->TASKS_START = 1;
#endif /* NRF51_ST_USE_RTC1 == TRUE */
#endif /* OSAL_ST_MODE == OSAL_ST_MODE_FREERUNNING */
#if OSAL_ST_MODE == OSAL_ST_MODE_PERIODIC
#if NRF51_ST_USE_RTC0 == TRUE
/* Using RTC with prescaler */
NRF_RTC0->TASKS_STOP = 1;
NRF_RTC0->PRESCALER = (NRF51_LFCLK_FREQUENCY / OSAL_ST_FREQUENCY) - 1;
NRF_RTC0->INTENSET = RTC_INTENSET_TICK_Msk;
/* Start timer */
nvicEnableVector(RTC0_IRQn, NRF51_ST_PRIORITY);
NRF_RTC0->TASKS_START = 1;
#endif /* NRF51_ST_USE_RTC0 == TRUE */
#if NRF51_ST_USE_RTC1 == TRUE
/* Using RTC with prescaler */
NRF_RTC1->TASKS_STOP = 1;
NRF_RTC1->PRESCALER = (NRF51_LFCLK_FREQUENCY / OSAL_ST_FREQUENCY) - 1;
NRF_RTC1->INTENSET = RTC_INTENSET_TICK_Msk;
/* Start timer */
nvicEnableVector(RTC1_IRQn, NRF51_ST_PRIORITY);
NRF_RTC1->TASKS_START = 1;
#endif /* NRF51_ST_USE_RTC1 == TRUE */
#if NRF51_ST_USE_TIMER0 == TRUE
NRF_TIMER0->TASKS_CLEAR = 1;
/*
@ -102,12 +281,12 @@ void st_lld_init(void) {
NRF_TIMER0->SHORTS = 1;
NRF_TIMER0->INTENSET = 0x10000;
nvicEnableVector(TIMER0_IRQn, 8);
/* Start timer */
nvicEnableVector(TIMER0_IRQn, NRF51_ST_PRIORITY);
NRF_TIMER0->TASKS_START = 1;
#endif
#endif /* NRF51_ST_USE_TIMER0 == TRUE */
#endif /* OSAL_ST_MODE == OSAL_ST_MODE_PERIODIC */
}
#endif /* OSAL_ST_MODE != OSAL_ST_MODE_NONE */

View File

@ -27,6 +27,8 @@
#ifndef _ST_LLD_H_
#define _ST_LLD_H_
#include "halconf.h"
/*===========================================================================*/
/* Driver constants. */
/*===========================================================================*/
@ -35,10 +37,92 @@
/* Driver pre-compile time settings. */
/*===========================================================================*/
/**
* @brief Use RTC0 to generates system ticks
*/
#if !defined(NRF51_ST_USE_RTC0) || defined(__DOXYGEN__)
#if !defined(SOFTDEVICE_PRESENT)
#define NRF51_ST_USE_RTC0 TRUE
#else
#define NRF51_ST_USE_RTC0 FALSE
#endif
#endif
/**
* @brief Use RTC1 to generates system ticks
*/
#if !defined(NRF51_ST_USE_RTC1) || defined(__DOXYGEN__)
#if !defined(SOFTDEVICE_PRESENT)
#define NRF51_ST_USE_RTC1 FALSE
#else
#define NRF51_ST_USE_RTC1 TRUE
#endif
#endif
/**
* @brief Use TIMER0 to generates system ticks
*/
#if !defined(NRF51_ST_USE_TIMER0) || defined(__DOXYGEN__)
#define NRF51_ST_USE_TIMER0 FALSE
#endif
/**
* @brief ST interrupt priority level setting.
*/
#if !defined(NRF51_ST_PRIORITY) || defined(__DOXYGEN__)
#if !defined(SOFTDEVICE_PRESENT)
#define NRF51_ST_PRIORITY 8
#else
#define NRF51_ST_PRIORITY 1
#endif
#endif
/*===========================================================================*/
/* Derived constants and error checks. */
/*===========================================================================*/
#if OSAL_ST_MODE != OSAL_ST_MODE_NONE
#if (NRF51_ST_USE_TIMER0 == TRUE) && (NRF51_GPT_USE_TIMER0 == TRUE)
#error "TIMER0 already used by GPT driver"
#endif
#if (NRF51_ST_USE_RTC0 == FALSE) && \
(NRF51_ST_USE_RTC1 == FALSE) && \
(NRF51_ST_USE_TIMER0 == FALSE)
#error "One clock source is needed, enable one (RTC0, RTC1, or TIMER0)"
#endif
#if ((NRF51_ST_USE_RTC0 == TRUE ? 1 : 0) + \
(NRF51_ST_USE_RTC1 == TRUE ? 1 : 0) + \
(NRF51_ST_USE_TIMER0 == TRUE ? 1 : 0)) > 1
#error "Only one clock source can be used (RTC0, RTC1, or TIMER0)"
#endif
#if defined(SOFTDEVICE_PRESENT)
#if NRF51_ST_USE_RTC0 == TRUE
#error "RTC0 cannot be used for system ticks when SOFTDEVICE present"
#endif
#if NRF51_ST_USE_TIMER0 == TRUE
#error "TIMER0 cannot be used for system ticks when SOFTDEVICE present"
#endif
#if NRF51_ST_PRIORITY != 1
#error "ST priority must be 1 when SOFTDEVICE present"
#endif
#endif /* defined(SOFTDEVICE_PRESENT) */
#endif /* OSAL_ST_MODE != OSAL_ST_MODE_NONE */
#if OSAL_ST_MODE == OSAL_ST_MODE_FREERUNNING
#if defined(CH_CFG_ST_TIMEDELTA) && (CH_CFG_ST_TIMEDELTA < 5)
#error "CH_CFG_ST_TIMEDELTA is too low"
#endif
#if NRF51_ST_USE_TIMER0 == TRUE
#error "Freeruning (tick-less) mode not supported with TIMER, use RTC"
#endif
#endif /* OSAL_ST_MODE == OSAL_ST_MODE_FREERUNNING */
/*===========================================================================*/
/* Driver data structures and types. */
/*===========================================================================*/
@ -71,8 +155,12 @@ extern "C" {
* @notapi
*/
static inline systime_t st_lld_get_counter(void) {
return (systime_t)0;
#if NRF51_ST_USE_RTC0 == TRUE
return (systime_t)NRF_RTC0->COUNTER;
#endif
#if NRF51_ST_USE_RTC1 == TRUE
return (systime_t)NRF_RTC1->COUNTER;
#endif
}
/**
@ -85,8 +173,16 @@ static inline systime_t st_lld_get_counter(void) {
* @notapi
*/
static inline void st_lld_start_alarm(systime_t abstime) {
(void)abstime;
#if NRF51_ST_USE_RTC0 == TRUE
NRF_RTC0->CC[0] = abstime;
NRF_RTC0->EVENTS_COMPARE[0] = 0;
NRF_RTC0->EVTENSET = RTC_EVTENSET_COMPARE0_Msk;
#endif
#if NRF51_ST_USE_RTC1 == TRUE
NRF_RTC1->CC[0] = abstime;
NRF_RTC1->EVENTS_COMPARE[0] = 0;
NRF_RTC1->EVTENSET = RTC_EVTENSET_COMPARE0_Msk;
#endif
}
/**
@ -95,7 +191,14 @@ static inline void st_lld_start_alarm(systime_t abstime) {
* @notapi
*/
static inline void st_lld_stop_alarm(void) {
#if NRF51_ST_USE_RTC0 == TRUE
NRF_RTC0->EVTENCLR = RTC_EVTENCLR_COMPARE0_Msk;
NRF_RTC0->EVENTS_COMPARE[0] = 0;
#endif
#if NRF51_ST_USE_RTC1 == TRUE
NRF_RTC1->EVTENCLR = RTC_EVTENCLR_COMPARE0_Msk;
NRF_RTC1->EVENTS_COMPARE[0] = 0;
#endif
}
/**
@ -106,8 +209,12 @@ static inline void st_lld_stop_alarm(void) {
* @notapi
*/
static inline void st_lld_set_alarm(systime_t abstime) {
(void)abstime;
#if NRF51_ST_USE_RTC0 == TRUE
NRF_RTC0->CC[0] = abstime;
#endif
#if NRF51_ST_USE_RTC1 == TRUE
NRF_RTC1->CC[0] = abstime;
#endif
}
/**
@ -118,8 +225,12 @@ static inline void st_lld_set_alarm(systime_t abstime) {
* @notapi
*/
static inline systime_t st_lld_get_alarm(void) {
return (systime_t)0;
#if NRF51_ST_USE_RTC0 == TRUE
return (systime_t)NRF_RTC0->CC[0];
#endif
#if NRF51_ST_USE_RTC1 == TRUE
return (systime_t)NRF_RTC1->CC[0];
#endif
}
/**
@ -132,8 +243,12 @@ static inline systime_t st_lld_get_alarm(void) {
* @notapi
*/
static inline bool st_lld_is_alarm_active(void) {
return false;
#if NRF51_ST_USE_RTC0 == TRUE
return NRF_RTC0->EVTEN & RTC_EVTEN_COMPARE0_Msk;
#endif
#if NRF51_ST_USE_RTC1 == TRUE
return NRF_RTC1->EVTEN & RTC_EVTEN_COMPARE0_Msk;
#endif
}
#endif /* _ST_LLD_H_ */

View File

@ -0,0 +1,818 @@
/*
ChibiOS/RT - Copyright (C) 2006-2013 Giovanni Di Sirio
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 was derived from the ICU subsystem code, modified to achieve
timing measurements on 2 and/or 4 channel STM32 timers by Dave Camarillo.
*/
/*
Concepts and parts of this file have been contributed by Fabio Utzig and
Xo Wang.
*/
/**
* @file STM32/timcap_lld.c
* @brief STM32 TIMCAP subsystem low level driver header.
*
* @addtogroup TIMCAP
* @{
*/
#include "ch.h"
#include "hal.h"
#if HAL_USE_TIMCAP || defined(__DOXYGEN__)
#include "stm32_tim.h"
#include "timcap.h"
/*===========================================================================*/
/* Driver local definitions. */
/*===========================================================================*/
/*===========================================================================*/
/* Driver exported variables. */
/*===========================================================================*/
/**
* @brief TIMCAPD1 driver identifier.
* @note The driver TIMCAPD1 allocates the complex timer TIM1 when enabled.
*/
#if STM32_TIMCAP_USE_TIM1 || defined(__DOXYGEN__)
TIMCAPDriver TIMCAPD1;
#endif
/**
* @brief TIMCAPD2 driver identifier.
* @note The driver TIMCAPD1 allocates the timer TIM2 when enabled.
*/
#if STM32_TIMCAP_USE_TIM2 || defined(__DOXYGEN__)
TIMCAPDriver TIMCAPD2;
#endif
/**
* @brief TIMCAPD3 driver identifier.
* @note The driver TIMCAPD1 allocates the timer TIM3 when enabled.
*/
#if STM32_TIMCAP_USE_TIM3 || defined(__DOXYGEN__)
TIMCAPDriver TIMCAPD3;
#endif
/**
* @brief TIMCAPD4 driver identifier.
* @note The driver TIMCAPD4 allocates the timer TIM4 when enabled.
*/
#if STM32_TIMCAP_USE_TIM4 || defined(__DOXYGEN__)
TIMCAPDriver TIMCAPD4;
#endif
/**
* @brief TIMCAPD5 driver identifier.
* @note The driver TIMCAPD5 allocates the timer TIM5 when enabled.
*/
#if STM32_TIMCAP_USE_TIM5 || defined(__DOXYGEN__)
TIMCAPDriver TIMCAPD5;
#endif
/**
* @brief TIMCAPD8 driver identifier.
* @note The driver TIMCAPD8 allocates the timer TIM8 when enabled.
*/
#if STM32_TIMCAP_USE_TIM8 || defined(__DOXYGEN__)
TIMCAPDriver TIMCAPD8;
#endif
/**
* @brief TIMCAPD9 driver identifier.
* @note The driver TIMCAPD9 allocates the timer TIM9 when enabled.
*/
#if STM32_TIMCAP_USE_TIM9 || defined(__DOXYGEN__)
TIMCAPDriver TIMCAPD9;
#endif
/*===========================================================================*/
/* Driver local variables and types. */
/*===========================================================================*/
/*===========================================================================*/
/* Driver local functions. */
/*===========================================================================*/
/**
* @brief Returns the maximum channel number for the respective TIMCAP driver.
* Note: different timer perepherials on the STM32 have between 1 and 4
* CCR registers.
*
* @param[in] timcapp pointer to the @p TIMCAPDriver object
*/
static timcapchannel_t timcap_get_max_timer_channel(const TIMCAPDriver *timcapp) {
//Choose a sane default value
#if STM32_TIMCAP_USE_TIM1 || defined(__DOXYGEN__)
if( timcapp == &TIMCAPD1 ) {
return(TIMCAP_CHANNEL_4);
}
#endif
#if STM32_TIMCAP_USE_TIM2 || defined(__DOXYGEN__)
if( timcapp == &TIMCAPD2 ) {
return(TIMCAP_CHANNEL_4);
}
#endif
#if STM32_TIMCAP_USE_TIM3 || defined(__DOXYGEN__)
if( timcapp == &TIMCAPD3 ) {
return(TIMCAP_CHANNEL_4);
}
#endif
#if STM32_TIMCAP_USE_TIM4 || defined(__DOXYGEN__)
if( timcapp == &TIMCAPD4 ) {
return(TIMCAP_CHANNEL_4);
}
#endif
#if STM32_TIMCAP_USE_TIM5 || defined(__DOXYGEN__)
if( timcapp == &TIMCAPD5 ) {
return(TIMCAP_CHANNEL_4);
}
#endif
#if STM32_TIMCAP_USE_TIM8 || defined(__DOXYGEN__)
if( timcapp == &TIMCAPD8 ) {
return(TIMCAP_CHANNEL_4);
}
#endif
#if STM32_TIMCAP_USE_TIM9 || defined(__DOXYGEN__)
if( timcapp == &TIMCAPD9 ) {
return(TIMCAP_CHANNEL_2);
}
#endif
/*Return a conservative default value.*/
return(TIMCAP_CHANNEL_1);
}
/**
* @brief Returns the maximum value for the ARR register of a given timer.
*
* @param[in] timcapp pointer to the @p TIMCAPDriver object
*/
static uint32_t timcap_get_max_arr(const TIMCAPDriver *timcapp) {
//Choose a sane default value
#if STM32_TIMCAP_USE_TIM1 || defined(__DOXYGEN__)
if( timcapp == &TIMCAPD1 ) {
return(UINT16_MAX);
}
#endif
#if STM32_TIMCAP_USE_TIM2 || defined(__DOXYGEN__)
if( timcapp == &TIMCAPD2 ) {
return(UINT32_MAX);
}
#endif
#if STM32_TIMCAP_USE_TIM3 || defined(__DOXYGEN__)
if( timcapp == &TIMCAPD3 ) {
return(UINT16_MAX);
}
#endif
#if STM32_TIMCAP_USE_TIM4 || defined(__DOXYGEN__)
if( timcapp == &TIMCAPD4 ) {
return(UINT16_MAX);
}
#endif
#if STM32_TIMCAP_USE_TIM5 || defined(__DOXYGEN__)
if( timcapp == &TIMCAPD5 ) {
return(UINT32_MAX);
}
#endif
#if STM32_TIMCAP_USE_TIM8 || defined(__DOXYGEN__)
if( timcapp == &TIMCAPD8 ) {
return(UINT16_MAX);
}
#endif
#if STM32_TIMCAP_USE_TIM9 || defined(__DOXYGEN__)
if( timcapp == &TIMCAPD9 ) {
return(UINT16_MAX);
}
#endif
/*Return a conservative default value.*/
return(UINT16_MAX);
}
/**
* @brief Shared IRQ handler.
*
* @param[in] timcapp pointer to the @p TIMCAPDriver object
*/
static void timcap_lld_serve_interrupt(TIMCAPDriver *timcapp) {
uint16_t sr;
sr = timcapp->tim->SR;
sr &= timcapp->tim->DIER & STM32_TIM_DIER_IRQ_MASK;
timcapp->tim->SR = ~sr;
if ((sr & STM32_TIM_SR_CC1IF) != 0 && timcapp->config->capture_cb_array[TIMCAP_CHANNEL_1] != NULL )
_timcap_isr_invoke_channel1_cb(timcapp);
if ((sr & STM32_TIM_SR_CC2IF) != 0 && timcapp->config->capture_cb_array[TIMCAP_CHANNEL_2] != NULL )
_timcap_isr_invoke_channel2_cb(timcapp);
if ((sr & STM32_TIM_SR_CC3IF) != 0 && timcapp->config->capture_cb_array[TIMCAP_CHANNEL_3] != NULL )
_timcap_isr_invoke_channel3_cb(timcapp);
if ((sr & STM32_TIM_SR_CC4IF) != 0 && timcapp->config->capture_cb_array[TIMCAP_CHANNEL_4] != NULL )
_timcap_isr_invoke_channel4_cb(timcapp);
if ((sr & STM32_TIM_SR_UIF) != 0 && timcapp->config->overflow_cb != NULL)
_timcap_isr_invoke_overflow_cb(timcapp);
}
/*===========================================================================*/
/* Driver interrupt handlers. */
/*===========================================================================*/
#if STM32_TIMCAP_USE_TIM1
#if !defined(STM32_TIM1_UP_HANDLER)
#error "STM32_TIM1_UP_HANDLER not defined"
#endif
/**
* @brief TIM1 compare interrupt handler.
* @note It is assumed that the various sources are only activated if the
* associated callback pointer is not equal to @p NULL in order to not
* perform an extra check in a potentially critical interrupt handler.
*
* @isr
*/
CH_IRQ_HANDLER(STM32_TIM1_UP_HANDLER) {
CH_IRQ_PROLOGUE();
timcap_lld_serve_interrupt(&TIMCAPD1);
CH_IRQ_EPILOGUE();
}
#if !defined(STM32_TIM1_CC_HANDLER)
#error "STM32_TIM1_CC_HANDLER not defined"
#endif
/**
* @brief TIM1 compare interrupt handler.
* @note It is assumed that the various sources are only activated if the
* associated callback pointer is not equal to @p NULL in order to not
* perform an extra check in a potentially critical interrupt handler.
*
* @isr
*/
CH_IRQ_HANDLER(STM32_TIM1_CC_HANDLER) {
CH_IRQ_PROLOGUE();
timcap_lld_serve_interrupt(&TIMCAPD1);
CH_IRQ_EPILOGUE();
}
#endif /* STM32_TIMCAP_USE_TIM1 */
#if STM32_TIMCAP_USE_TIM2
#if !defined(STM32_TIM2_HANDLER)
#error "STM32_TIM2_HANDLER not defined"
#endif
/**
* @brief TIM2 interrupt handler.
* @note It is assumed that the various sources are only activated if the
* associated callback pointer is not equal to @p NULL in order to not
* perform an extra check in a potentially critical interrupt handler.
*
* @isr
*/
CH_IRQ_HANDLER(STM32_TIM2_HANDLER) {
CH_IRQ_PROLOGUE();
timcap_lld_serve_interrupt(&TIMCAPD2);
CH_IRQ_EPILOGUE();
}
#endif /* STM32_TIMCAP_USE_TIM2 */
#if STM32_TIMCAP_USE_TIM3
#if !defined(STM32_TIM3_HANDLER)
#error "STM32_TIM3_HANDLER not defined"
#endif
/**
* @brief TIM3 interrupt handler.
* @note It is assumed that the various sources are only activated if the
* associated callback pointer is not equal to @p NULL in order to not
* perform an extra check in a potentially critical interrupt handler.
*
* @isr
*/
CH_IRQ_HANDLER(STM32_TIM3_HANDLER) {
CH_IRQ_PROLOGUE();
timcap_lld_serve_interrupt(&TIMCAPD3);
CH_IRQ_EPILOGUE();
}
#endif /* STM32_TIMCAP_USE_TIM3 */
#if STM32_TIMCAP_USE_TIM4
#if !defined(STM32_TIM4_HANDLER)
#error "STM32_TIM4_HANDLER not defined"
#endif
/**
* @brief TIM4 interrupt handler.
* @note It is assumed that the various sources are only activated if the
* associated callback pointer is not equal to @p NULL in order to not
* perform an extra check in a potentially critical interrupt handler.
*
* @isr
*/
CH_IRQ_HANDLER(STM32_TIM4_HANDLER) {
CH_IRQ_PROLOGUE();
timcap_lld_serve_interrupt(&TIMCAPD4);
CH_IRQ_EPILOGUE();
}
#endif /* STM32_TIMCAP_USE_TIM4 */
#if STM32_TIMCAP_USE_TIM5
#if !defined(STM32_TIM5_HANDLER)
#error "STM32_TIM5_HANDLER not defined"
#endif
/**
* @brief TIM5 interrupt handler.
* @note It is assumed that the various sources are only activated if the
* associated callback pointer is not equal to @p NULL in order to not
* perform an extra check in a potentially critical interrupt handler.
*
* @isr
*/
CH_IRQ_HANDLER(STM32_TIM5_HANDLER) {
CH_IRQ_PROLOGUE();
timcap_lld_serve_interrupt(&TIMCAPD5);
CH_IRQ_EPILOGUE();
}
#endif /* STM32_TIMCAP_USE_TIM5 */
#if STM32_TIMCAP_USE_TIM8
#if !defined(STM32_TIM8_UP_HANDLER)
#error "STM32_TIM8_UP_HANDLER not defined"
#endif
/**
* @brief TIM8 compare interrupt handler.
* @note It is assumed that the various sources are only activated if the
* associated callback pointer is not equal to @p NULL in order to not
* perform an extra check in a potentially critical interrupt handler.
*
* @isr
*/
CH_IRQ_HANDLER(STM32_TIM8_UP_HANDLER) {
CH_IRQ_PROLOGUE();
timcap_lld_serve_interrupt(&TIMCAPD8);
CH_IRQ_EPILOGUE();
}
#if !defined(STM32_TIM8_CC_HANDLER)
#error "STM32_TIM8_CC_HANDLER not defined"
#endif
/**
* @brief TIM8 compare interrupt handler.
* @note It is assumed that the various sources are only activated if the
* associated callback pointer is not equal to @p NULL in order to not
* perform an extra check in a potentially critical interrupt handler.
*
* @isr
*/
CH_IRQ_HANDLER(STM32_TIM8_CC_HANDLER) {
CH_IRQ_PROLOGUE();
timcap_lld_serve_interrupt(&TIMCAPD8);
CH_IRQ_EPILOGUE();
}
#endif /* STM32_TIMCAP_USE_TIM8 */
#if STM32_TIMCAP_USE_TIM9
#if !defined(STM32_TIM9_HANDLER)
#error "STM32_TIM9_HANDLER not defined"
#endif
/**
* @brief TIM9 interrupt handler.
* @note It is assumed that the various sources are only activated if the
* associated callback pointer is not equal to @p NULL in order to not
* perform an extra check in a potentially critical interrupt handler.
*
* @isr
*/
CH_IRQ_HANDLER(STM32_TIM9_HANDLER) {
CH_IRQ_PROLOGUE();
timcap_lld_serve_interrupt(&TIMCAPD9);
CH_IRQ_EPILOGUE();
}
#endif /* STM32_TIMCAP_USE_TIM9 */
/*===========================================================================*/
/* Driver exported functions. */
/*===========================================================================*/
/**
* @brief Low level TIMCAP driver initialization.
*
* @notapi
*/
void timcap_lld_init(void) {
#if STM32_TIMCAP_USE_TIM1
/* Driver initialization.*/
timcapObjectInit(&TIMCAPD1);
TIMCAPD1.tim = STM32_TIM1;
#endif
#if STM32_TIMCAP_USE_TIM2
/* Driver initialization.*/
timcapObjectInit(&TIMCAPD2);
TIMCAPD2.tim = STM32_TIM2;
#endif
#if STM32_TIMCAP_USE_TIM3
/* Driver initialization.*/
timcapObjectInit(&TIMCAPD3);
TIMCAPD3.tim = STM32_TIM3;
#endif
#if STM32_TIMCAP_USE_TIM4
/* Driver initialization.*/
timcapObjectInit(&TIMCAPD4);
TIMCAPD4.tim = STM32_TIM4;
#endif
#if STM32_TIMCAP_USE_TIM5
/* Driver initialization.*/
timcapObjectInit(&TIMCAPD5);
TIMCAPD5.tim = STM32_TIM5;
#endif
#if STM32_TIMCAP_USE_TIM8
/* Driver initialization.*/
timcapObjectInit(&TIMCAPD8);
TIMCAPD8.tim = STM32_TIM8;
#endif
#if STM32_TIMCAP_USE_TIM9
/* Driver initialization.*/
timcapObjectInit(&TIMCAPD9);
TIMCAPD9.tim = STM32_TIM9;
#endif
}
/**
* @brief Configures and activates the TIMCAP peripheral.
*
* @param[in] timcapp pointer to the @p TIMCAPDriver object
*
* @notapi
*/
void timcap_lld_start(TIMCAPDriver *timcapp) {
uint32_t psc;
const timcapchannel_t tim_max_channel = timcap_get_max_timer_channel(timcapp);
if (timcapp->state == TIMCAP_STOP) {
/* Clock activation and timer reset.*/
#if STM32_TIMCAP_USE_TIM1
if (&TIMCAPD1 == timcapp) {
rccEnableTIM1(FALSE);
rccResetTIM1();
nvicEnableVector(STM32_TIM1_UP_NUMBER, STM32_TIMCAP_TIM1_IRQ_PRIORITY);
nvicEnableVector(STM32_TIM1_CC_NUMBER, STM32_TIMCAP_TIM1_IRQ_PRIORITY);
#if defined(STM32_TIM1CLK)
timcapp->clock = STM32_TIM1CLK;
#else
timcapp->clock = STM32_TIMCLK2;
#endif
}
#endif
#if STM32_TIMCAP_USE_TIM2
if (&TIMCAPD2 == timcapp) {
rccEnableTIM2(FALSE);
rccResetTIM2();
nvicEnableVector(STM32_TIM2_NUMBER, STM32_TIMCAP_TIM2_IRQ_PRIORITY);
timcapp->clock = STM32_TIMCLK1;
}
#endif
#if STM32_TIMCAP_USE_TIM3
if (&TIMCAPD3 == timcapp) {
rccEnableTIM3(FALSE);
rccResetTIM3();
nvicEnableVector(STM32_TIM3_NUMBER, STM32_TIMCAP_TIM3_IRQ_PRIORITY);
timcapp->clock = STM32_TIMCLK1;
}
#endif
#if STM32_TIMCAP_USE_TIM4
if (&TIMCAPD4 == timcapp) {
rccEnableTIM4(FALSE);
rccResetTIM4();
nvicEnableVector(STM32_TIM4_NUMBER, STM32_TIMCAP_TIM4_IRQ_PRIORITY);
timcapp->clock = STM32_TIMCLK1;
}
#endif
#if STM32_TIMCAP_USE_TIM5
if (&TIMCAPD5 == timcapp) {
rccEnableTIM5(FALSE);
rccResetTIM5();
nvicEnableVector(STM32_TIM5_NUMBER, STM32_TIMCAP_TIM5_IRQ_PRIORITY);
timcapp->clock = STM32_TIMCLK1;
}
#endif
#if STM32_TIMCAP_USE_TIM8
if (&TIMCAPD8 == timcapp) {
rccEnableTIM8(FALSE);
rccResetTIM8();
nvicEnableVector(STM32_TIM8_UP_NUMBER, STM32_TIMCAP_TIM8_IRQ_PRIORITY);
nvicEnableVector(STM32_TIM8_CC_NUMBER, STM32_TIMCAP_TIM8_IRQ_PRIORITY);
#if defined(STM32_TIM8CLK)
timcapp->clock = STM32_TIM8CLK;
#else
timcapp->clock = STM32_TIMCLK2;
#endif
}
#endif
#if STM32_TIMCAP_USE_TIM9
if (&TIMCAPD9 == timcapp) {
rccEnableTIM9(FALSE);
rccResetTIM9();
nvicEnableVector(STM32_TIM9_NUMBER, STM32_TIMCAP_TIM9_IRQ_PRIORITY);
timcapp->clock = STM32_TIMCLK1;
}
#endif
}
else {
/* Driver re-configuration scenario, it must be stopped first.*/
timcapp->tim->CR1 = 0; /* Timer disabled. */
timcapp->tim->DIER = timcapp->config->dier &/* DMA-related DIER settings. */
~STM32_TIM_DIER_IRQ_MASK;
timcapp->tim->SR = 0; /* Clear eventual pending IRQs. */
timcapp->tim->CCR[0] = 0; /* Comparator 1 disabled. */
timcapp->tim->CCR[1] = 0; /* Comparator 2 disabled. */
if( tim_max_channel >= TIMCAP_CHANNEL_3 )
timcapp->tim->CCR[2] = 0; /* Comparator 3 disabled. */
if( tim_max_channel >= TIMCAP_CHANNEL_4 )
timcapp->tim->CCR[3] = 0; /* Comparator 4 disabled. */
timcapp->tim->CNT = 0; /* Counter reset to zero. */
}
/* Timer configuration.*/
psc = (timcapp->clock / timcapp->config->frequency) - 1;
osalDbgAssert((psc <= 0xFFFF) &&
((psc + 1) * timcapp->config->frequency) == timcapp->clock,
"invalid frequency");
timcapp->tim->PSC = (uint16_t)psc;
timcapp->tim->ARR = timcap_get_max_arr(timcapp);
timcapp->tim->CCMR1 = 0;
timcapp->tim->CCMR2 = 0;
timcapp->tim->CCER = 0;
timcapchannel_t chan = TIMCAP_CHANNEL_1;
/*go through each non-NULL callback channel and enable the capture register on rising/falling edge*/
for( chan = TIMCAP_CHANNEL_1; chan <= tim_max_channel; chan++ ) {
if( timcapp->config->capture_cb_array[chan] == NULL ) {
continue;
}
switch (chan) {
case TIMCAP_CHANNEL_1:
/*CCMR1_CC1S = 01 = CH1 Input on TI1.*/
timcapp->tim->CCMR1 |= STM32_TIM_CCMR1_CC1S(1);
break;
case TIMCAP_CHANNEL_2:
/*CCMR1_CC2S = 10 = CH2 Input on TI1.*/
timcapp->tim->CCMR1 |= STM32_TIM_CCMR1_CC2S(1);
break;
case TIMCAP_CHANNEL_3:
timcapp->tim->CCMR2 |= STM32_TIM_CCMR2_CC3S(1);
break;
case TIMCAP_CHANNEL_4:
timcapp->tim->CCMR2 |= STM32_TIM_CCMR2_CC4S(1);
break;
}
/* The CCER settings depend on the selected trigger mode.
TIMCAP_INPUT_DISABLED: Input not used.
TIMCAP_INPUT_ACTIVE_HIGH: Active on rising edge, idle on falling edge.
TIMCAP_INPUT_ACTIVE_LOW: Active on falling edge, idle on rising edge.*/
if (timcapp->config->modes[chan] == TIMCAP_INPUT_ACTIVE_HIGH) {
switch (chan) {
case TIMCAP_CHANNEL_1:
timcapp->tim->CCER |= STM32_TIM_CCER_CC1E;
break;
case TIMCAP_CHANNEL_2:
timcapp->tim->CCER |= STM32_TIM_CCER_CC2E;
break;
case TIMCAP_CHANNEL_3:
timcapp->tim->CCER |= STM32_TIM_CCER_CC3E;
break;
case TIMCAP_CHANNEL_4:
timcapp->tim->CCER |= STM32_TIM_CCER_CC4E;
break;
}
}
else if (timcapp->config->modes[chan] == TIMCAP_INPUT_ACTIVE_LOW) {
switch (chan) {
case TIMCAP_CHANNEL_1:
timcapp->tim->CCER |= STM32_TIM_CCER_CC1E | STM32_TIM_CCER_CC1P;
break;
case TIMCAP_CHANNEL_2:
timcapp->tim->CCER |= STM32_TIM_CCER_CC2E | STM32_TIM_CCER_CC2P;
break;
case TIMCAP_CHANNEL_3:
timcapp->tim->CCER |= STM32_TIM_CCER_CC3E | STM32_TIM_CCER_CC3P;
break;
case TIMCAP_CHANNEL_4:
timcapp->tim->CCER |= STM32_TIM_CCER_CC4E | STM32_TIM_CCER_CC4P;
break;
}
}
else {
switch (chan) {
case TIMCAP_CHANNEL_1:
timcapp->tim->CCER &= ~STM32_TIM_CCER_CC1E;
break;
case TIMCAP_CHANNEL_2:
timcapp->tim->CCER &= ~STM32_TIM_CCER_CC2E;
break;
case TIMCAP_CHANNEL_3:
timcapp->tim->CCER &= ~STM32_TIM_CCER_CC3E;
break;
case TIMCAP_CHANNEL_4:
timcapp->tim->CCER &= ~STM32_TIM_CCER_CC4E;
break;
}
}
/* Direct pointers to the capture registers in order to make reading
data faster from within callbacks.*/
timcapp->ccr_p[chan] = &timcapp->tim->CCR[chan];
}
/* SMCR_TS = 101, input is TI1FP1.*/
timcapp->tim->SMCR = STM32_TIM_SMCR_TS(5);
}
/**
* @brief Deactivates the TIMCAP peripheral.
*
* @param[in] timcapp pointer to the @p TIMCAPDriver object
*
* @notapi
*/
void timcap_lld_stop(TIMCAPDriver *timcapp) {
if (timcapp->state == TIMCAP_READY) {
/* Clock deactivation.*/
timcapp->tim->CR1 = 0; /* Timer disabled. */
timcapp->tim->DIER = 0; /* All IRQs disabled. */
timcapp->tim->SR = 0; /* Clear eventual pending IRQs. */
#if STM32_TIMCAP_USE_TIM1
if (&TIMCAPD1 == timcapp) {
nvicDisableVector(STM32_TIM1_UP_NUMBER);
nvicDisableVector(STM32_TIM1_CC_NUMBER);
rccDisableTIM1(FALSE);
}
#endif
#if STM32_TIMCAP_USE_TIM2
if (&TIMCAPD2 == timcapp) {
nvicDisableVector(STM32_TIM2_NUMBER);
rccDisableTIM2(FALSE);
}
#endif
#if STM32_TIMCAP_USE_TIM3
if (&TIMCAPD3 == timcapp) {
nvicDisableVector(STM32_TIM3_NUMBER);
rccDisableTIM3(FALSE);
}
#endif
#if STM32_TIMCAP_USE_TIM4
if (&TIMCAPD4 == timcapp) {
nvicDisableVector(STM32_TIM4_NUMBER);
rccDisableTIM4(FALSE);
}
#endif
#if STM32_TIMCAP_USE_TIM5
if (&TIMCAPD5 == timcapp) {
nvicDisableVector(STM32_TIM5_NUMBER);
rccDisableTIM5(FALSE);
}
#endif
#if STM32_TIMCAP_USE_TIM8
if (&TIMCAPD8 == timcapp) {
nvicDisableVector(STM32_TIM8_UP_NUMBER);
nvicDisableVector(STM32_TIM8_CC_NUMBER);
rccDisableTIM8(FALSE);
}
#endif
#if STM32_TIMCAP_USE_TIM9
if (&TIMCAPD9 == timcapp) {
nvicDisableVector(STM32_TIM9_NUMBER);
rccDisableTIM9(FALSE);
}
#endif
}
}
/**
* @brief Enables the input capture.
*
* @param[in] timcapp pointer to the @p TIMCAPDriver object
*
* @notapi
*/
void timcap_lld_enable(TIMCAPDriver *timcapp) {
timcapp->tim->EGR |= STM32_TIM_EGR_UG;
timcapp->tim->SR = 0; /* Clear pending IRQs (if any). */
timcapchannel_t chan = TIMCAP_CHANNEL_1;
const timcapchannel_t tim_max_channel = timcap_get_max_timer_channel(timcapp);
for( chan = TIMCAP_CHANNEL_1; chan <= tim_max_channel; chan++ ) {
if( timcapp->config->capture_cb_array[chan] != NULL
&& timcapp->config->modes[chan] != TIMCAP_INPUT_DISABLED ) {
switch (chan) {
case TIMCAP_CHANNEL_1:
timcapp->tim->DIER |= STM32_TIM_DIER_CC1IE;
break;
case TIMCAP_CHANNEL_2:
timcapp->tim->DIER |= STM32_TIM_DIER_CC2IE;
break;
case TIMCAP_CHANNEL_3:
timcapp->tim->DIER |= STM32_TIM_DIER_CC3IE;
break;
case TIMCAP_CHANNEL_4:
timcapp->tim->DIER |= STM32_TIM_DIER_CC4IE;
break;
}
}
}
if (timcapp->config->overflow_cb != NULL)
timcapp->tim->DIER |= STM32_TIM_DIER_UIE;
timcapp->tim->CR1 = STM32_TIM_CR1_URS | STM32_TIM_CR1_CEN | timcapp->config->cr1;
}
/**
* @brief Disables the input capture.
*
* @param[in] timcapp pointer to the @p TIMCAPDriver object
*
* @notapi
*/
void timcap_lld_disable(TIMCAPDriver *timcapp) {
timcapp->tim->CR1 = 0; /* Initially stopped. */
timcapp->tim->SR = 0; /* Clear pending IRQs (if any). */
/* All interrupts disabled.*/
timcapp->tim->DIER &= ~STM32_TIM_DIER_IRQ_MASK;
}
#endif /* HAL_USE_TIMCAP */
/** @} */

View File

@ -0,0 +1,390 @@
/*
ChibiOS/RT - Copyright (C) 2006-2013 Giovanni Di Sirio
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.
*/
/**
* @file STM32/timcap_lld.h
* @brief STM32 TIMCAP subsystem low level driver header.
*
* @addtogroup TIMCAP
* @{
*/
#ifndef _TIMCAP_LLD_H_
#define _TIMCAP_LLD_H_
#include "ch.h"
#include "hal.h"
#include "stm32_tim.h"
#if HAL_USE_TIMCAP || defined(__DOXYGEN__)
/*===========================================================================*/
/* Driver constants. */
/*===========================================================================*/
/*===========================================================================*/
/* Driver pre-compile time settings. */
/*===========================================================================*/
/**
* @name Configuration options
* @{
*/
/**
* @brief TIMCAPD1 driver enable switch.
* @details If set to @p TRUE the support for TIMCAPD1 is included.
* @note The default is @p TRUE.
*/
#if !defined(STM32_TIMCAP_USE_TIM1) || defined(__DOXYGEN__)
#define STM32_TIMCAP_USE_TIM1 FALSE
#endif
/**
* @brief TIMCAPD2 driver enable switch.
* @details If set to @p TRUE the support for TIMCAPD2 is included.
* @note The default is @p TRUE.
*/
#if !defined(STM32_TIMCAP_USE_TIM2) || defined(__DOXYGEN__)
#define STM32_TIMCAP_USE_TIM2 FALSE
#endif
/**
* @brief TIMCAPD3 driver enable switch.
* @details If set to @p TRUE the support for TIMCAPD3 is included.
* @note The default is @p TRUE.
*/
#if !defined(STM32_TIMCAP_USE_TIM3) || defined(__DOXYGEN__)
#define STM32_TIMCAP_USE_TIM3 FALSE
#endif
/**
* @brief TIMCAPD4 driver enable switch.
* @details If set to @p TRUE the support for TIMCAPD4 is included.
* @note The default is @p TRUE.
*/
#if !defined(STM32_TIMCAP_USE_TIM4) || defined(__DOXYGEN__)
#define STM32_TIMCAP_USE_TIM4 FALSE
#endif
/**
* @brief TIMCAPD5 driver enable switch.
* @details If set to @p TRUE the support for TIMCAPD5 is included.
* @note The default is @p TRUE.
*/
#if !defined(STM32_TIMCAP_USE_TIM5) || defined(__DOXYGEN__)
#define STM32_TIMCAP_USE_TIM5 FALSE
#endif
/**
* @brief TIMCAPD8 driver enable switch.
* @details If set to @p TRUE the support for TIMCAPD8 is included.
* @note The default is @p TRUE.
*/
#if !defined(STM32_TIMCAP_USE_TIM8) || defined(__DOXYGEN__)
#define STM32_TIMCAP_USE_TIM8 FALSE
#endif
/**
* @brief TIMCAPD9 driver enable switch.
* @details If set to @p TRUE the support for TIMCAPD9 is included.
* @note The default is @p TRUE.
*/
#if !defined(STM32_TIMCAP_USE_TIM9) || defined(__DOXYGEN__)
#define STM32_TIMCAP_USE_TIM9 FALSE
#endif
/**
* @brief TIMCAPD1 interrupt priority level setting.
*/
#if !defined(STM32_TIMCAP_TIM1_IRQ_PRIORITY) || defined(__DOXYGEN__)
#define STM32_TIMCAP_TIM1_IRQ_PRIORITY 7
#endif
/**
* @brief TIMCAPD2 interrupt priority level setting.
*/
#if !defined(STM32_TIMCAP_TIM2_IRQ_PRIORITY) || defined(__DOXYGEN__)
#define STM32_TIMCAP_TIM2_IRQ_PRIORITY 7
#endif
/**
* @brief TIMCAPD3 interrupt priority level setting.
*/
#if !defined(STM32_TIMCAP_TIM3_IRQ_PRIORITY) || defined(__DOXYGEN__)
#define STM32_TIMCAP_TIM3_IRQ_PRIORITY 7
#endif
/**
* @brief TIMCAPD4 interrupt priority level setting.
*/
#if !defined(STM32_TIMCAP_TIM4_IRQ_PRIORITY) || defined(__DOXYGEN__)
#define STM32_TIMCAP_TIM4_IRQ_PRIORITY 7
#endif
/**
* @brief TIMCAPD5 interrupt priority level setting.
*/
#if !defined(STM32_TIMCAP_TIM5_IRQ_PRIORITY) || defined(__DOXYGEN__)
#define STM32_TIMCAP_TIM5_IRQ_PRIORITY 7
#endif
/**
* @brief TIMCAPD8 interrupt priority level setting.
*/
#if !defined(STM32_TIMCAP_TIM8_IRQ_PRIORITY) || defined(__DOXYGEN__)
#define STM32_TIMCAP_TIM8_IRQ_PRIORITY 7
#endif
/**
* @brief TIMCAPD9 interrupt priority level setting.
*/
#if !defined(STM32_TIMCAP_TIM9_IRQ_PRIORITY) || defined(__DOXYGEN__)
#define STM32_TIMCAP_TIM9_IRQ_PRIORITY 7
#endif
/** @} */
/*===========================================================================*/
/* Derived constants and error checks. */
/*===========================================================================*/
#if STM32_TIMCAP_USE_TIM1 && !STM32_HAS_TIM1
#error "TIM1 not present in the selected device"
#endif
#if STM32_TIMCAP_USE_TIM2 && !STM32_HAS_TIM2
#error "TIM2 not present in the selected device"
#endif
#if STM32_TIMCAP_USE_TIM3 && !STM32_HAS_TIM3
#error "TIM3 not present in the selected device"
#endif
#if STM32_TIMCAP_USE_TIM4 && !STM32_HAS_TIM4
#error "TIM4 not present in the selected device"
#endif
#if STM32_TIMCAP_USE_TIM5 && !STM32_HAS_TIM5
#error "TIM5 not present in the selected device"
#endif
#if STM32_TIMCAP_USE_TIM8 && !STM32_HAS_TIM8
#error "TIM8 not present in the selected device"
#endif
#if STM32_TIMCAP_USE_TIM9 && !STM32_HAS_TIM9
#error "TIM9 not present in the selected device"
#endif
#if !STM32_TIMCAP_USE_TIM1 && !STM32_TIMCAP_USE_TIM2 && \
!STM32_TIMCAP_USE_TIM3 && !STM32_TIMCAP_USE_TIM4 && \
!STM32_TIMCAP_USE_TIM5 && !STM32_TIMCAP_USE_TIM8 && \
!STM32_TIMCAP_USE_TIM9
#error "TIMCAP driver activated but no TIM peripheral assigned"
#endif
#if STM32_TIMCAP_USE_TIM1 && \
!OSAL_IRQ_IS_VALID_PRIORITY(STM32_TIMCAP_TIM1_IRQ_PRIORITY)
#error "Invalid IRQ priority assigned to TIM1"
#endif
#if STM32_TIMCAP_USE_TIM2 && \
!OSAL_IRQ_IS_VALID_PRIORITY(STM32_TIMCAP_TIM2_IRQ_PRIORITY)
#error "Invalid IRQ priority assigned to TIM2"
#endif
#if STM32_TIMCAP_USE_TIM3 && \
!OSAL_IRQ_IS_VALID_PRIORITY(STM32_TIMCAP_TIM3_IRQ_PRIORITY)
#error "Invalid IRQ priority assigned to TIM3"
#endif
#if STM32_TIMCAP_USE_TIM4 && \
!OSAL_IRQ_IS_VALID_PRIORITY(STM32_TIMCAP_TIM4_IRQ_PRIORITY)
#error "Invalid IRQ priority assigned to TIM4"
#endif
#if STM32_TIMCAP_USE_TIM5 && \
!OSAL_IRQ_IS_VALID_PRIORITY(STM32_TIMCAP_TIM5_IRQ_PRIORITY)
#error "Invalid IRQ priority assigned to TIM5"
#endif
#if STM32_TIMCAP_USE_TIM8 && \
!OSAL_IRQ_IS_VALID_PRIORITY(STM32_TIMCAP_TIM8_IRQ_PRIORITY)
#error "Invalid IRQ priority assigned to TIM8"
#endif
#if STM32_TIMCAP_USE_TIM9 && \
!OSAL_IRQ_IS_VALID_PRIORITY(STM32_TIMCAP_TIM9_IRQ_PRIORITY)
#error "Invalid IRQ priority assigned to TIM9"
#endif
/*===========================================================================*/
/* Driver data structures and types. */
/*===========================================================================*/
/**
* @brief TIMCAP driver mode.
*/
typedef enum {
TIMCAP_INPUT_DISABLED = 0,
TIMCAP_INPUT_ACTIVE_HIGH = 1, /**< Trigger on rising edge. */
TIMCAP_INPUT_ACTIVE_LOW = 2, /**< Trigger on falling edge. */
} timcapmode_t;
/**
* @brief TIMCAP frequency type.
*/
typedef uint32_t timcapfreq_t;
/**
* @brief TIMCAP channel type.
*/
typedef enum {
TIMCAP_CHANNEL_1 = 0, /**< Use TIMxCH1. */
TIMCAP_CHANNEL_2 = 1, /**< Use TIMxCH2. */
TIMCAP_CHANNEL_3 = 2, /**< Use TIMxCH3. */
TIMCAP_CHANNEL_4 = 3, /**< Use TIMxCH4. */
} timcapchannel_t;
/**
* @brief Driver configuration structure.
* @note It could be empty on some architectures.
*/
typedef struct {
/**
* @brief Driver mode.
*/
timcapmode_t modes[4];
/**
* @brief Timer clock in Hz.
* @note The low level can use assertions in order to catch invalid
* frequency specifications.
*/
timcapfreq_t frequency;
/**
* @brief Callback when a capture occurs
*/
timcapcallback_t capture_cb_array[4];
/**
* @brief Callback for timer overflow.
*/
timcapcallback_t overflow_cb;
/* End of the mandatory fields.*/
/**
* @brief TIM DIER register initialization data.
* @note The value of this field should normally be equal to zero.
* @note Only the DMA-related bits can be specified in this field.
*/
uint32_t dier;
/**
* @brief TIM CR1 register initialization data.
* @note The value of this field should normally be equal to zero.
*/
uint32_t cr1;
} TIMCAPConfig;
/**
* @brief Structure representing an TIMCAP driver.
*/
struct TIMCAPDriver {
/**
* @brief Driver state.
*/
timcapstate_t state;
/**
* @brief Current configuration data.
*/
const TIMCAPConfig *config;
#if defined(TIMCAP_DRIVER_EXT_FIELDS)
TIMCAP_DRIVER_EXT_FIELDS
#endif
/* End of the mandatory fields.*/
/**
* @brief Timer base clock.
*/
uint32_t clock;
/**
* @brief Pointer to the TIMx registers block.
*/
stm32_tim_t *tim;
/**
* @brief CCR register used for capture.
*/
volatile uint32_t *ccr_p[4];
};
/*===========================================================================*/
/* Driver macros. */
/*===========================================================================*/
//FIXME document this
#define timcap_lld_get_ccr(timcapp, channel) (*((timcapp)->ccr_p[channel]) + 1)
/*===========================================================================*/
/* External declarations. */
/*===========================================================================*/
#if STM32_TIMCAP_USE_TIM1 && !defined(__DOXYGEN__)
extern TIMCAPDriver TIMCAPD1;
#endif
#if STM32_TIMCAP_USE_TIM2 && !defined(__DOXYGEN__)
extern TIMCAPDriver TIMCAPD2;
#endif
#if STM32_TIMCAP_USE_TIM3 && !defined(__DOXYGEN__)
extern TIMCAPDriver TIMCAPD3;
#endif
#if STM32_TIMCAP_USE_TIM4 && !defined(__DOXYGEN__)
extern TIMCAPDriver TIMCAPD4;
#endif
#if STM32_TIMCAP_USE_TIM5 && !defined(__DOXYGEN__)
extern TIMCAPDriver TIMCAPD5;
#endif
#if STM32_TIMCAP_USE_TIM8 && !defined(__DOXYGEN__)
extern TIMCAPDriver TIMCAPD8;
#endif
#if STM32_TIMCAP_USE_TIM9 && !defined(__DOXYGEN__)
extern TIMCAPDriver TIMCAPD9;
#endif
#ifdef __cplusplus
extern "C" {
#endif
void timcap_lld_init(void);
void timcap_lld_start(TIMCAPDriver *timcapp);
void timcap_lld_stop(TIMCAPDriver *timcapp);
void timcap_lld_enable(TIMCAPDriver *timcapp);
void timcap_lld_disable(TIMCAPDriver *timcapp);
#ifdef __cplusplus
}
#endif
#endif /* HAL_USE_TIMCAP */
#endif /* _TIMCAP_LLD_H_ */
/** @} */

View File

@ -0,0 +1,929 @@
/*
ChibiOS - Copyright (C) 2006..2015 Giovanni Di Sirio
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.
*/
/**
* @file stm32_otg.h
* @brief STM32 OTG registers layout header.
*
* @addtogroup USB
* @{
*/
#ifndef _STM32_OTG_H_
#define _STM32_OTG_H_
/**
* @brief Number of the implemented endpoints in OTG_FS.
* @details This value does not include the endpoint 0 that is always present.
*/
#define STM32_OTG1_ENDOPOINTS_NUMBER 3
/**
* @brief Number of the implemented endpoints in OTG_HS.
* @details This value does not include the endpoint 0 that is always present.
*/
#define STM32_OTG2_ENDOPOINTS_NUMBER 5
/**
* @brief OTG_FS FIFO memory size in words.
*/
#define STM32_OTG1_FIFO_MEM_SIZE 320
/**
* @brief OTG_HS FIFO memory size in words.
*/
#define STM32_OTG2_FIFO_MEM_SIZE 1024
/**
* @brief Host channel registers group.
*/
typedef struct {
volatile uint32_t HCCHAR; /**< @brief Host channel characteristics
register. */
volatile uint32_t resvd8;
volatile uint32_t HCINT; /**< @brief Host channel interrupt register.*/
volatile uint32_t HCINTMSK; /**< @brief Host channel interrupt mask
register. */
volatile uint32_t HCTSIZ; /**< @brief Host channel transfer size
register. */
volatile uint32_t resvd14;
volatile uint32_t resvd18;
volatile uint32_t resvd1c;
} stm32_otg_host_chn_t;
/**
* @brief Device input endpoint registers group.
*/
typedef struct {
volatile uint32_t DIEPCTL; /**< @brief Device control IN endpoint
control register. */
volatile uint32_t resvd4;
volatile uint32_t DIEPINT; /**< @brief Device IN endpoint interrupt
register. */
volatile uint32_t resvdC;
volatile uint32_t DIEPTSIZ; /**< @brief Device IN endpoint transfer size
register. */
volatile uint32_t resvd14;
volatile uint32_t DTXFSTS; /**< @brief Device IN endpoint transmit FIFO
status register. */
volatile uint32_t resvd1C;
} stm32_otg_in_ep_t;
/**
* @brief Device output endpoint registers group.
*/
typedef struct {
volatile uint32_t DOEPCTL; /**< @brief Device control OUT endpoint
control register. */
volatile uint32_t resvd4;
volatile uint32_t DOEPINT; /**< @brief Device OUT endpoint interrupt
register. */
volatile uint32_t resvdC;
volatile uint32_t DOEPTSIZ; /**< @brief Device OUT endpoint transfer
size register. */
volatile uint32_t resvd14;
volatile uint32_t resvd18;
volatile uint32_t resvd1C;
} stm32_otg_out_ep_t;
/**
* @brief USB registers memory map.
*/
typedef struct {
volatile uint32_t GOTGCTL; /**< @brief OTG control and status register.*/
volatile uint32_t GOTGINT; /**< @brief OTG interrupt register. */
volatile uint32_t GAHBCFG; /**< @brief AHB configuration register. */
volatile uint32_t GUSBCFG; /**< @brief USB configuration register. */
volatile uint32_t GRSTCTL; /**< @brief Reset register size. */
volatile uint32_t GINTSTS; /**< @brief Interrupt register. */
volatile uint32_t GINTMSK; /**< @brief Interrupt mask register. */
volatile uint32_t GRXSTSR; /**< @brief Receive status debug read
register. */
volatile uint32_t GRXSTSP; /**< @brief Receive status read/pop
register. */
volatile uint32_t GRXFSIZ; /**< @brief Receive FIFO size register. */
volatile uint32_t DIEPTXF0; /**< @brief Endpoint 0 transmit FIFO size
register. */
volatile uint32_t HNPTXSTS; /**< @brief Non-periodic transmit FIFO/queue
status register. */
volatile uint32_t resvd30;
volatile uint32_t resvd34;
volatile uint32_t GCCFG; /**< @brief General core configuration. */
volatile uint32_t CID; /**< @brief Core ID register. */
volatile uint32_t resvd58[48];
volatile uint32_t HPTXFSIZ; /**< @brief Host periodic transmit FIFO size
register. */
volatile uint32_t DIEPTXF[15];/**< @brief Device IN endpoint transmit FIFO
size registers. */
volatile uint32_t resvd140[176];
volatile uint32_t HCFG; /**< @brief Host configuration register. */
volatile uint32_t HFIR; /**< @brief Host frame interval register. */
volatile uint32_t HFNUM; /**< @brief Host frame number/frame time
Remaining register. */
volatile uint32_t resvd40C;
volatile uint32_t HPTXSTS; /**< @brief Host periodic transmit FIFO/queue
status register. */
volatile uint32_t HAINT; /**< @brief Host all channels interrupt
register. */
volatile uint32_t HAINTMSK; /**< @brief Host all channels interrupt mask
register. */
volatile uint32_t resvd41C[9];
volatile uint32_t HPRT; /**< @brief Host port control and status
register. */
volatile uint32_t resvd444[47];
stm32_otg_host_chn_t hc[16]; /**< @brief Host channels array. */
volatile uint32_t resvd700[64];
volatile uint32_t DCFG; /**< @brief Device configuration register. */
volatile uint32_t DCTL; /**< @brief Device control register. */
volatile uint32_t DSTS; /**< @brief Device status register. */
volatile uint32_t resvd80C;
volatile uint32_t DIEPMSK; /**< @brief Device IN endpoint common
interrupt mask register. */
volatile uint32_t DOEPMSK; /**< @brief Device OUT endpoint common
interrupt mask register. */
volatile uint32_t DAINT; /**< @brief Device all endpoints interrupt
register. */
volatile uint32_t DAINTMSK; /**< @brief Device all endpoints interrupt
mask register. */
volatile uint32_t resvd820;
volatile uint32_t resvd824;
volatile uint32_t DVBUSDIS; /**< @brief Device VBUS discharge time
register. */
volatile uint32_t DVBUSPULSE; /**< @brief Device VBUS pulsing time
register. */
volatile uint32_t resvd830;
volatile uint32_t DIEPEMPMSK; /**< @brief Device IN endpoint FIFO empty
interrupt mask register. */
volatile uint32_t resvd838;
volatile uint32_t resvd83C;
volatile uint32_t resvd840[16];
volatile uint32_t resvd880[16];
volatile uint32_t resvd8C0[16];
stm32_otg_in_ep_t ie[16]; /**< @brief Input endpoints. */
stm32_otg_out_ep_t oe[16]; /**< @brief Output endpoints. */
volatile uint32_t resvdD00[64];
volatile uint32_t PCGCCTL; /**< @brief Power and clock gating control
register. */
volatile uint32_t resvdE04[127];
volatile uint32_t FIFO[16][1024];
} stm32_otg_t;
/**
* @name GOTGCTL register bit definitions
* @{
*/
#define GOTGCTL_BSVLD (1U<<19) /**< B-Session Valid. */
#define GOTGCTL_ASVLD (1U<<18) /**< A-Session Valid. */
#define GOTGCTL_DBCT (1U<<17) /**< Long/Short debounce time. */
#define GOTGCTL_CIDSTS (1U<<16) /**< Connector ID status. */
#define GOTGCTL_EHEN (1U<<12)
#define GOTGCTL_DHNPEN (1U<<11) /**< Device HNP enabled. */
#define GOTGCTL_HSHNPEN (1U<<10) /**< Host Set HNP enable. */
#define GOTGCTL_HNPRQ (1U<<9) /**< HNP request. */
#define GOTGCTL_HNGSCS (1U<<8) /**< Host negotiation success. */
#define GOTGCTL_BVALOVAL (1U<<7)
#define GOTGCTL_BVALOEN (1U<<6)
#define GOTGCTL_AVALOVAL (1U<<5)
#define GOTGCTL_AVALOEN (1U<<4)
#define GOTGCTL_VBVALOVAL (1U<<3)
#define GOTGCTL_VBVALOEN (1U<<2)
#define GOTGCTL_SRQ (1U<<1) /**< Session request. */
#define GOTGCTL_SRQSCS (1U<<0) /**< Session request success. */
/** @} */
/**
* @name GOTGINT register bit definitions
* @{
*/
#define GOTGINT_DBCDNE (1U<<19) /**< Debounce done. */
#define GOTGINT_ADTOCHG (1U<<18) /**< A-Device timeout change. */
#define GOTGINT_HNGDET (1U<<17) /**< Host negotiation detected. */
#define GOTGINT_HNSSCHG (1U<<9) /**< Host negotiation success
status change. */
#define GOTGINT_SRSSCHG (1U<<8) /**< Session request success
status change. */
#define GOTGINT_SEDET (1U<<2) /**< Session end detected. */
/** @} */
/**
* @name GAHBCFG register bit definitions
* @{
*/
#define GAHBCFG_PTXFELVL (1U<<8) /**< Periodic TxFIFO empty
level. */
#define GAHBCFG_TXFELVL (1U<<7) /**< Non-periodic TxFIFO empty
level. */
#define GAHBCFG_DMAEN (1U<<5) /**< DMA enable (HS only). */
#define GAHBCFG_HBSTLEN_MASK (15U<<1) /**< Burst length/type mask (HS
only). */
#define GAHBCFG_HBSTLEN(n) ((n)<<1) /**< Burst length/type (HS
only). */
#define GAHBCFG_GINTMSK (1U<<0) /**< Global interrupt mask. */
/** @} */
/**
* @name GUSBCFG register bit definitions
* @{
*/
#define GUSBCFG_CTXPKT (1U<<31) /**< Corrupt Tx packet. */
#define GUSBCFG_FDMOD (1U<<30) /**< Force Device Mode. */
#define GUSBCFG_FHMOD (1U<<29) /**< Force Host Mode. */
#define GUSBCFG_TRDT_MASK (15U<<10) /**< USB Turnaround time field
mask. */
#define GUSBCFG_TRDT(n) ((n)<<10) /**< USB Turnaround time field
value. */
#define GUSBCFG_HNPCAP (1U<<9) /**< HNP-Capable. */
#define GUSBCFG_SRPCAP (1U<<8) /**< SRP-Capable. */
#define GUSBCFG_PHYSEL (1U<<6) /**< USB 2.0 High-Speed PHY or
USB 1.1 Full-Speed serial
transceiver Select. */
#define GUSBCFG_TOCAL_MASK (7U<<0) /**< HS/FS timeout calibration
field mask. */
#define GUSBCFG_TOCAL(n) ((n)<<0) /**< HS/FS timeout calibration
field value. */
/** @} */
/**
* @name GRSTCTL register bit definitions
* @{
*/
#define GRSTCTL_AHBIDL (1U<<31) /**< AHB Master Idle. */
#define GRSTCTL_TXFNUM_MASK (31U<<6) /**< TxFIFO number field mask. */
#define GRSTCTL_TXFNUM(n) ((n)<<6) /**< TxFIFO number field value. */
#define GRSTCTL_TXFFLSH (1U<<5) /**< TxFIFO flush. */
#define GRSTCTL_RXFFLSH (1U<<4) /**< RxFIFO flush. */
#define GRSTCTL_FCRST (1U<<2) /**< Host frame counter reset. */
#define GRSTCTL_HSRST (1U<<1) /**< HClk soft reset. */
#define GRSTCTL_CSRST (1U<<0) /**< Core soft reset. */
/** @} */
/**
* @name GINTSTS register bit definitions
* @{
*/
#define GINTSTS_WKUPINT (1U<<31) /**< Resume/Remote wakeup
detected interrupt. */
#define GINTSTS_SRQINT (1U<<30) /**< Session request/New session
detected interrupt. */
#define GINTSTS_DISCINT (1U<<29) /**< Disconnect detected
interrupt. */
#define GINTSTS_CIDSCHG (1U<<28) /**< Connector ID status change.*/
#define GINTSTS_PTXFE (1U<<26) /**< Periodic TxFIFO empty. */
#define GINTSTS_HCINT (1U<<25) /**< Host channels interrupt. */
#define GINTSTS_HPRTINT (1U<<24) /**< Host port interrupt. */
#define GINTSTS_IPXFR (1U<<21) /**< Incomplete periodic
transfer. */
#define GINTSTS_IISOOXFR (1U<<21) /**< Incomplete isochronous OUT
transfer. */
#define GINTSTS_IISOIXFR (1U<<20) /**< Incomplete isochronous IN
transfer. */
#define GINTSTS_OEPINT (1U<<19) /**< OUT endpoints interrupt. */
#define GINTSTS_IEPINT (1U<<18) /**< IN endpoints interrupt. */
#define GINTSTS_EOPF (1U<<15) /**< End of periodic frame
interrupt. */
#define GINTSTS_ISOODRP (1U<<14) /**< Isochronous OUT packet
dropped interrupt. */
#define GINTSTS_ENUMDNE (1U<<13) /**< Enumeration done. */
#define GINTSTS_USBRST (1U<<12) /**< USB reset. */
#define GINTSTS_USBSUSP (1U<<11) /**< USB suspend. */
#define GINTSTS_ESUSP (1U<<10) /**< Early suspend. */
#define GINTSTS_GONAKEFF (1U<<7) /**< Global OUT NAK effective. */
#define GINTSTS_GINAKEFF (1U<<6) /**< Global IN non-periodic NAK
effective. */
#define GINTSTS_NPTXFE (1U<<5) /**< Non-periodic TxFIFO empty. */
#define GINTSTS_RXFLVL (1U<<4) /**< RxFIFO non-empty. */
#define GINTSTS_SOF (1U<<3) /**< Start of frame. */
#define GINTSTS_OTGINT (1U<<2) /**< OTG interrupt. */
#define GINTSTS_MMIS (1U<<1) /**< Mode Mismatch interrupt. */
#define GINTSTS_CMOD (1U<<0) /**< Current mode of operation. */
/** @} */
/**
* @name GINTMSK register bit definitions
* @{
*/
#define GINTMSK_WKUM (1U<<31) /**< Resume/remote wakeup
detected interrupt mask. */
#define GINTMSK_SRQM (1U<<30) /**< Session request/New session
detected interrupt mask. */
#define GINTMSK_DISCM (1U<<29) /**< Disconnect detected
interrupt mask. */
#define GINTMSK_CIDSCHGM (1U<<28) /**< Connector ID status change
mask. */
#define GINTMSK_PTXFEM (1U<<26) /**< Periodic TxFIFO empty mask.*/
#define GINTMSK_HCM (1U<<25) /**< Host channels interrupt
mask. */
#define GINTMSK_HPRTM (1U<<24) /**< Host port interrupt mask. */
#define GINTMSK_IPXFRM (1U<<21) /**< Incomplete periodic
transfer mask. */
#define GINTMSK_IISOOXFRM (1U<<21) /**< Incomplete isochronous OUT
transfer mask. */
#define GINTMSK_IISOIXFRM (1U<<20) /**< Incomplete isochronous IN
transfer mask. */
#define GINTMSK_OEPM (1U<<19) /**< OUT endpoints interrupt
mask. */
#define GINTMSK_IEPM (1U<<18) /**< IN endpoints interrupt
mask. */
#define GINTMSK_EOPFM (1U<<15) /**< End of periodic frame
interrupt mask. */
#define GINTMSK_ISOODRPM (1U<<14) /**< Isochronous OUT packet
dropped interrupt mask. */
#define GINTMSK_ENUMDNEM (1U<<13) /**< Enumeration done mask. */
#define GINTMSK_USBRSTM (1U<<12) /**< USB reset mask. */
#define GINTMSK_USBSUSPM (1U<<11) /**< USB suspend mask. */
#define GINTMSK_ESUSPM (1U<<10) /**< Early suspend mask. */
#define GINTMSK_GONAKEFFM (1U<<7) /**< Global OUT NAK effective
mask. */
#define GINTMSK_GINAKEFFM (1U<<6) /**< Global non-periodic IN NAK
effective mask. */
#define GINTMSK_NPTXFEM (1U<<5) /**< Non-periodic TxFIFO empty
mask. */
#define GINTMSK_RXFLVLM (1U<<4) /**< Receive FIFO non-empty
mask. */
#define GINTMSK_SOFM (1U<<3) /**< Start of (micro)frame mask.*/
#define GINTMSK_OTGM (1U<<2) /**< OTG interrupt mask. */
#define GINTMSK_MMISM (1U<<1) /**< Mode Mismatch interrupt
mask. */
/** @} */
/**
* @name GRXSTSR register bit definitions
* @{
*/
#define GRXSTSR_PKTSTS_MASK (15U<<17) /**< Packet status mask. */
#define GRXSTSR_PKTSTS(n) ((n)<<17) /**< Packet status value. */
#define GRXSTSR_OUT_GLOBAL_NAK GRXSTSR_PKTSTS(1)
#define GRXSTSR_OUT_DATA GRXSTSR_PKTSTS(2)
#define GRXSTSR_OUT_COMP GRXSTSR_PKTSTS(3)
#define GRXSTSR_SETUP_COMP GRXSTSR_PKTSTS(4)
#define GRXSTSR_SETUP_DATA GRXSTSR_PKTSTS(6)
#define GRXSTSR_DPID_MASK (3U<<15) /**< Data PID mask. */
#define GRXSTSR_DPID(n) ((n)<<15) /**< Data PID value. */
#define GRXSTSR_BCNT_MASK (0x7FF<<4) /**< Byte count mask. */
#define GRXSTSR_BCNT(n) ((n)<<4) /**< Byte count value. */
#define GRXSTSR_CHNUM_MASK (15U<<0) /**< Channel number mask. */
#define GRXSTSR_CHNUM(n) ((n)<<0) /**< Channel number value. */
#define GRXSTSR_EPNUM_MASK (15U<<0) /**< Endpoint number mask. */
#define GRXSTSR_EPNUM(n) ((n)<<0) /**< Endpoint number value. */
/** @} */
/**
* @name GRXSTSP register bit definitions
* @{
*/
#define GRXSTSP_PKTSTS_MASK (15<<17) /**< Packet status mask. */
#define GRXSTSP_PKTSTS(n) ((n)<<17) /**< Packet status value. */
#define GRXSTSP_OUT_GLOBAL_NAK GRXSTSP_PKTSTS(1)
#define GRXSTSP_OUT_DATA GRXSTSP_PKTSTS(2)
#define GRXSTSP_OUT_COMP GRXSTSP_PKTSTS(3)
#define GRXSTSP_SETUP_COMP GRXSTSP_PKTSTS(4)
#define GRXSTSP_SETUP_DATA GRXSTSP_PKTSTS(6)
#define GRXSTSP_DPID_MASK (3U<<15) /**< Data PID mask. */
#define GRXSTSP_DPID(n) ((n)<<15) /**< Data PID value. */
#define GRXSTSP_BCNT_MASK (0x7FF<<4) /**< Byte count mask. */
#define GRXSTSP_BCNT_OFF 4 /**< Byte count offset. */
#define GRXSTSP_BCNT(n) ((n)<<4) /**< Byte count value. */
#define GRXSTSP_CHNUM_MASK (15U<<0) /**< Channel number mask. */
#define GRXSTSP_CHNUM(n) ((n)<<0) /**< Channel number value. */
#define GRXSTSP_EPNUM_MASK (15U<<0) /**< Endpoint number mask. */
#define GRXSTSP_EPNUM_OFF 0 /**< Endpoint number offset. */
#define GRXSTSP_EPNUM(n) ((n)<<0) /**< Endpoint number value. */
/** @} */
/**
* @name GRXFSIZ register bit definitions
* @{
*/
#define GRXFSIZ_RXFD_MASK (0xFFFF<<0) /**< RxFIFO depth mask. */
#define GRXFSIZ_RXFD(n) ((n)<<0) /**< RxFIFO depth value. */
/** @} */
/**
* @name DIEPTXFx register bit definitions
* @{
*/
#define DIEPTXF_INEPTXFD_MASK (0xFFFFU<<16)/**< IN endpoint TxFIFO depth
mask. */
#define DIEPTXF_INEPTXFD(n) ((n)<<16) /**< IN endpoint TxFIFO depth
value. */
#define DIEPTXF_INEPTXSA_MASK (0xFFFF<<0) /**< IN endpoint FIFOx transmit
RAM start address mask. */
#define DIEPTXF_INEPTXSA(n) ((n)<<0) /**< IN endpoint FIFOx transmit
RAM start address value. */
/** @} */
/**
* @name GCCFG register bit definitions
* @{
*/
#define GCCFG_NOVBUSSENS (1U<<21) /**< VBUS sensing disable. */
#define GCCFG_SOFOUTEN (1U<<20) /**< SOF output enable. */
#define GCCFG_VBUSBSEN (1U<<19) /**< Enable the VBUS sensing "B"
device. */
#define GCCFG_VBUSASEN (1U<<18) /**< Enable the VBUS sensing "A"
device. */
#define GCCFG_PWRDWN (1U<<16) /**< Power down. */
/** @} */
/**
* @name HPTXFSIZ register bit definitions
* @{
*/
#define HPTXFSIZ_PTXFD_MASK (0xFFFFU<<16)/**< Host periodic TxFIFO
depth mask. */
#define HPTXFSIZ_PTXFD(n) ((n)<<16) /**< Host periodic TxFIFO
depth value. */
#define HPTXFSIZ_PTXSA_MASK (0xFFFFU<<0)/**< Host periodic TxFIFO
Start address mask. */
#define HPTXFSIZ_PTXSA(n) ((n)<<0) /**< Host periodic TxFIFO
start address value. */
/** @} */
/**
* @name HCFG register bit definitions
* @{
*/
#define HCFG_FSLSS (1U<<2) /**< FS- and LS-only support. */
#define HCFG_FSLSPCS_MASK (3U<<0) /**< FS/LS PHY clock select
mask. */
#define HCFG_FSLSPCS_48 (1U<<0) /**< PHY clock is running at
48 MHz. */
#define HCFG_FSLSPCS_6 (2U<<0) /**< PHY clock is running at
6 MHz. */
/** @} */
/**
* @name HFIR register bit definitions
* @{
*/
#define HFIR_FRIVL_MASK (0xFFFFU<<0)/**< Frame interval mask. */
#define HFIR_FRIVL(n) ((n)<<0) /**< Frame interval value. */
/** @} */
/**
* @name HFNUM register bit definitions
* @{
*/
#define HFNUM_FTREM_MASK (0xFFFFU<<16)/**< Frame time Remaining mask.*/
#define HFNUM_FTREM(n) ((n)<<16) /**< Frame time Remaining value.*/
#define HFNUM_FRNUM_MASK (0xFFFFU<<0)/**< Frame number mask. */
#define HFNUM_FRNUM(n) ((n)<<0) /**< Frame number value. */
/** @} */
/**
* @name HPTXSTS register bit definitions
* @{
*/
#define HPTXSTS_PTXQTOP_MASK (0xFFU<<24) /**< Top of the periodic
transmit request queue
mask. */
#define HPTXSTS_PTXQTOP(n) ((n)<<24) /**< Top of the periodic
transmit request queue
value. */
#define HPTXSTS_PTXQSAV_MASK (0xFF<<16) /**< Periodic transmit request
queue Space Available
mask. */
#define HPTXSTS_PTXQSAV(n) ((n)<<16) /**< Periodic transmit request
queue Space Available
value. */
#define HPTXSTS_PTXFSAVL_MASK (0xFFFF<<0) /**< Periodic transmit Data
FIFO Space Available
mask. */
#define HPTXSTS_PTXFSAVL(n) ((n)<<0) /**< Periodic transmit Data
FIFO Space Available
value. */
/** @} */
/**
* @name HAINT register bit definitions
* @{
*/
#define HAINT_HAINT_MASK (0xFFFFU<<0)/**< Channel interrupts mask. */
#define HAINT_HAINT(n) ((n)<<0) /**< Channel interrupts value. */
/** @} */
/**
* @name HAINTMSK register bit definitions
* @{
*/
#define HAINTMSK_HAINTM_MASK (0xFFFFU<<0)/**< Channel interrupt mask
mask. */
#define HAINTMSK_HAINTM(n) ((n)<<0) /**< Channel interrupt mask
value. */
/** @} */
/**
* @name HPRT register bit definitions
* @{
*/
#define HPRT_PSPD_MASK (3U<<17) /**< Port speed mask. */
#define HPRT_PSPD_FS (1U<<17) /**< Full speed value. */
#define HPRT_PSPD_LS (2U<<17) /**< Low speed value. */
#define HPRT_PTCTL_MASK (15<<13) /**< Port Test control mask. */
#define HPRT_PTCTL(n) ((n)<<13) /**< Port Test control value. */
#define HPRT_PPWR (1U<<12) /**< Port power. */
#define HPRT_PLSTS_MASK (3U<<11) /**< Port Line status mask. */
#define HPRT_PLSTS_DM (1U<<11) /**< Logic level of D-. */
#define HPRT_PLSTS_DP (1U<<10) /**< Logic level of D+. */
#define HPRT_PRST (1U<<8) /**< Port reset. */
#define HPRT_PSUSP (1U<<7) /**< Port suspend. */
#define HPRT_PRES (1U<<6) /**< Port Resume. */
#define HPRT_POCCHNG (1U<<5) /**< Port overcurrent change. */
#define HPRT_POCA (1U<<4) /**< Port overcurrent active. */
#define HPRT_PENCHNG (1U<<3) /**< Port enable/disable change.*/
#define HPRT_PENA (1U<<2) /**< Port enable. */
#define HPRT_PCDET (1U<<1) /**< Port Connect detected. */
#define HPRT_PCSTS (1U<<0) /**< Port connect status. */
/** @} */
/**
* @name HCCHAR register bit definitions
* @{
*/
#define HCCHAR_CHENA (1U<<31) /**< Channel enable. */
#define HCCHAR_CHDIS (1U<<30) /**< Channel Disable. */
#define HCCHAR_ODDFRM (1U<<29) /**< Odd frame. */
#define HCCHAR_DAD_MASK (0x7FU<<22) /**< Device Address mask. */
#define HCCHAR_DAD(n) ((n)<<22) /**< Device Address value. */
#define HCCHAR_MCNT_MASK (3U<<20) /**< Multicount mask. */
#define HCCHAR_MCNT(n) ((n)<<20) /**< Multicount value. */
#define HCCHAR_EPTYP_MASK (3U<<18) /**< Endpoint type mask. */
#define HCCHAR_EPTYP(n) ((n)<<18) /**< Endpoint type value. */
#define HCCHAR_EPTYP_CTL (0U<<18) /**< Control endpoint value. */
#define HCCHAR_EPTYP_ISO (1U<<18) /**< Isochronous endpoint value.*/
#define HCCHAR_EPTYP_BULK (2U<<18) /**< Bulk endpoint value. */
#define HCCHAR_EPTYP_INTR (3U<<18) /**< Interrupt endpoint value. */
#define HCCHAR_LSDEV (1U<<17) /**< Low-Speed device. */
#define HCCHAR_EPDIR (1U<<15) /**< Endpoint direction. */
#define HCCHAR_EPNUM_MASK (15U<<11) /**< Endpoint number mask. */
#define HCCHAR_EPNUM(n) ((n)<<11) /**< Endpoint number value. */
#define HCCHAR_MPS_MASK (0x7FFU<<0) /**< Maximum packet size mask. */
#define HCCHAR_MPS(n) ((n)<<0) /**< Maximum packet size value. */
/** @} */
/**
* @name HCINT register bit definitions
* @{
*/
#define HCINT_DTERR (1U<<10) /**< Data toggle error. */
#define HCINT_FRMOR (1U<<9) /**< Frame overrun. */
#define HCINT_BBERR (1U<<8) /**< Babble error. */
#define HCINT_TRERR (1U<<7) /**< Transaction Error. */
#define HCINT_ACK (1U<<5) /**< ACK response
received/transmitted
interrupt. */
#define HCINT_NAK (1U<<4) /**< NAK response received
interrupt. */
#define HCINT_STALL (1U<<3) /**< STALL response received
interrupt. */
#define HCINT_CHH (1U<<1) /**< Channel halted. */
#define HCINT_XFRC (1U<<0) /**< Transfer completed. */
/** @} */
/**
* @name HCINTMSK register bit definitions
* @{
*/
#define HCINTMSK_DTERRM (1U<<10) /**< Data toggle error mask. */
#define HCINTMSK_FRMORM (1U<<9) /**< Frame overrun mask. */
#define HCINTMSK_BBERRM (1U<<8) /**< Babble error mask. */
#define HCINTMSK_TRERRM (1U<<7) /**< Transaction error mask. */
#define HCINTMSK_NYET (1U<<6) /**< NYET response received
interrupt mask. */
#define HCINTMSK_ACKM (1U<<5) /**< ACK Response
received/transmitted
interrupt mask. */
#define HCINTMSK_NAKM (1U<<4) /**< NAK response received
interrupt mask. */
#define HCINTMSK_STALLM (1U<<3) /**< STALL response received
interrupt mask. */
#define HCINTMSK_AHBERRM (1U<<2)
#define HCINTMSK_CHHM (1U<<1) /**< Channel halted mask. */
#define HCINTMSK_XFRCM (1U<<0) /**< Transfer completed mask. */
/** @} */
/**
* @name HCTSIZ register bit definitions
* @{
*/
#define HCTSIZ_DPID_MASK (3U<<29) /**< PID mask. */
#define HCTSIZ_DPID_DATA0 (0U<<29) /**< DATA0. */
#define HCTSIZ_DPID_DATA2 (1U<<29) /**< DATA2. */
#define HCTSIZ_DPID_DATA1 (2U<<29) /**< DATA1. */
#define HCTSIZ_DPID_MDATA (3U<<29) /**< MDATA. */
#define HCTSIZ_DPID_SETUP (3U<<29) /**< SETUP. */
#define HCTSIZ_PKTCNT_MASK (0x3FFU<<19)/**< Packet count mask. */
#define HCTSIZ_PKTCNT(n) ((n)<<19) /**< Packet count value. */
#define HCTSIZ_XFRSIZ_MASK (0x7FFFF<<0)/**< Transfer size mask. */
#define HCTSIZ_XFRSIZ(n) ((n)<<0) /**< Transfer size value. */
/** @} */
/**
* @name DCFG register bit definitions
* @{
*/
#define DCFG_PFIVL_MASK (3U<<11) /**< Periodic frame interval
mask. */
#define DCFG_PFIVL(n) ((n)<<11) /**< Periodic frame interval
value. */
#define DCFG_DAD_MASK (0x7FU<<4) /**< Device address mask. */
#define DCFG_DAD(n) ((n)<<4) /**< Device address value. */
#define DCFG_NZLSOHSK (1U<<2) /**< Non-Zero-Length status
OUT handshake. */
#define DCFG_DSPD_MASK (3U<<0) /**< Device speed mask. */
#define DCFG_DSPD_HS (0U<<0) /**< High speed (USB 2.0). */
#define DCFG_DSPD_HS_FS (1U<<0) /**< High speed (USB 2.0) in FS
mode. */
#define DCFG_DSPD_FS11 (3U<<0) /**< Full speed (USB 1.1
transceiver clock is 48
MHz). */
/** @} */
/**
* @name DCTL register bit definitions
* @{
*/
#define DCTL_POPRGDNE (1U<<11) /**< Power-on programming done. */
#define DCTL_CGONAK (1U<<10) /**< Clear global OUT NAK. */
#define DCTL_SGONAK (1U<<9) /**< Set global OUT NAK. */
#define DCTL_CGINAK (1U<<8) /**< Clear global non-periodic
IN NAK. */
#define DCTL_SGINAK (1U<<7) /**< Set global non-periodic
IN NAK. */
#define DCTL_TCTL_MASK (7U<<4) /**< Test control mask. */
#define DCTL_TCTL(n) ((n)<<4 /**< Test control value. */
#define DCTL_GONSTS (1U<<3) /**< Global OUT NAK status. */
#define DCTL_GINSTS (1U<<2) /**< Global non-periodic IN
NAK status. */
#define DCTL_SDIS (1U<<1) /**< Soft disconnect. */
#define DCTL_RWUSIG (1U<<0) /**< Remote wakeup signaling. */
/** @} */
/**
* @name DSTS register bit definitions
* @{
*/
#define DSTS_FNSOF_MASK (0x3FFU<<8) /**< Frame number of the received
SOF mask. */
#define DSTS_FNSOF(n) ((n)<<8) /**< Frame number of the received
SOF value. */
#define DSTS_FNSOF_ODD (1U<<8) /**< Frame parity of the received
SOF value. */
#define DSTS_EERR (1U<<3) /**< Erratic error. */
#define DSTS_ENUMSPD_MASK (3U<<1) /**< Enumerated speed mask. */
#define DSTS_ENUMSPD_FS_48 (3U<<1) /**< Full speed (PHY clock is
running at 48 MHz). */
#define DSTS_ENUMSPD_HS_480 (0U<<1) /**< High speed. */
#define DSTS_SUSPSTS (1U<<0) /**< Suspend status. */
/** @} */
/**
* @name DIEPMSK register bit definitions
* @{
*/
#define DIEPMSK_TXFEM (1U<<6) /**< Transmit FIFO empty mask. */
#define DIEPMSK_INEPNEM (1U<<6) /**< IN endpoint NAK effective
mask. */
#define DIEPMSK_ITTXFEMSK (1U<<4) /**< IN token received when
TxFIFO empty mask. */
#define DIEPMSK_TOCM (1U<<3) /**< Timeout condition mask. */
#define DIEPMSK_EPDM (1U<<1) /**< Endpoint disabled
interrupt mask. */
#define DIEPMSK_XFRCM (1U<<0) /**< Transfer completed
interrupt mask. */
/** @} */
/**
* @name DOEPMSK register bit definitions
* @{
*/
#define DOEPMSK_OTEPDM (1U<<4) /**< OUT token received when
endpoint disabled mask. */
#define DOEPMSK_STUPM (1U<<3) /**< SETUP phase done mask. */
#define DOEPMSK_EPDM (1U<<1) /**< Endpoint disabled
interrupt mask. */
#define DOEPMSK_XFRCM (1U<<0) /**< Transfer completed
interrupt mask. */
/** @} */
/**
* @name DAINT register bit definitions
* @{
*/
#define DAINT_OEPINT_MASK (0xFFFFU<<16)/**< OUT endpoint interrupt
bits mask. */
#define DAINT_OEPINT(n) ((n)<<16) /**< OUT endpoint interrupt
bits value. */
#define DAINT_IEPINT_MASK (0xFFFFU<<0)/**< IN endpoint interrupt
bits mask. */
#define DAINT_IEPINT(n) ((n)<<0) /**< IN endpoint interrupt
bits value. */
/** @} */
/**
* @name DAINTMSK register bit definitions
* @{
*/
#define DAINTMSK_OEPM_MASK (0xFFFFU<<16)/**< OUT EP interrupt mask
bits mask. */
#define DAINTMSK_OEPM(n) (1U<<(16+(n)))/**< OUT EP interrupt mask
bits value. */
#define DAINTMSK_IEPM_MASK (0xFFFFU<<0)/**< IN EP interrupt mask
bits mask. */
#define DAINTMSK_IEPM(n) (1U<<(n)) /**< IN EP interrupt mask
bits value. */
/** @} */
/**
* @name DVBUSDIS register bit definitions
* @{
*/
#define DVBUSDIS_VBUSDT_MASK (0xFFFFU<<0)/**< Device VBUS discharge
time mask. */
#define DVBUSDIS_VBUSDT(n) ((n)<<0) /**< Device VBUS discharge
time value. */
/** @} */
/**
* @name DVBUSPULSE register bit definitions
* @{
*/
#define DVBUSPULSE_DVBUSP_MASK (0xFFFU<<0) /**< Device VBUSpulsing time
mask. */
#define DVBUSPULSE_DVBUSP(n) ((n)<<0) /**< Device VBUS pulsing time
value. */
/** @} */
/**
* @name DIEPEMPMSK register bit definitions
* @{
*/
#define DIEPEMPMSK_INEPTXFEM(n) (1U<<(n)) /**< IN EP Tx FIFO empty
interrupt mask bit. */
/** @} */
/**
* @name DIEPCTL register bit definitions
* @{
*/
#define DIEPCTL_EPENA (1U<<31) /**< Endpoint enable. */
#define DIEPCTL_EPDIS (1U<<30) /**< Endpoint disable. */
#define DIEPCTL_SD1PID (1U<<29) /**< Set DATA1 PID. */
#define DIEPCTL_SODDFRM (1U<<29) /**< Set odd frame. */
#define DIEPCTL_SD0PID (1U<<28) /**< Set DATA0 PID. */
#define DIEPCTL_SEVNFRM (1U<<28) /**< Set even frame. */
#define DIEPCTL_SNAK (1U<<27) /**< Set NAK. */
#define DIEPCTL_CNAK (1U<<26) /**< Clear NAK. */
#define DIEPCTL_TXFNUM_MASK (15U<<22) /**< TxFIFO number mask. */
#define DIEPCTL_TXFNUM(n) ((n)<<22) /**< TxFIFO number value. */
#define DIEPCTL_STALL (1U<<21) /**< STALL handshake. */
#define DIEPCTL_SNPM (1U<<20) /**< Snoop mode. */
#define DIEPCTL_EPTYP_MASK (3<<18) /**< Endpoint type mask. */
#define DIEPCTL_EPTYP_CTRL (0U<<18) /**< Control. */
#define DIEPCTL_EPTYP_ISO (1U<<18) /**< Isochronous. */
#define DIEPCTL_EPTYP_BULK (2U<<18) /**< Bulk. */
#define DIEPCTL_EPTYP_INTR (3U<<18) /**< Interrupt. */
#define DIEPCTL_NAKSTS (1U<<17) /**< NAK status. */
#define DIEPCTL_EONUM (1U<<16) /**< Even/odd frame. */
#define DIEPCTL_DPID (1U<<16) /**< Endpoint data PID. */
#define DIEPCTL_USBAEP (1U<<15) /**< USB active endpoint. */
#define DIEPCTL_MPSIZ_MASK (0x3FFU<<0) /**< Maximum Packet size mask. */
#define DIEPCTL_MPSIZ(n) ((n)<<0) /**< Maximum Packet size value. */
/** @} */
/**
* @name DIEPINT register bit definitions
* @{
*/
#define DIEPINT_TXFE (1U<<7) /**< Transmit FIFO empty. */
#define DIEPINT_INEPNE (1U<<6) /**< IN endpoint NAK effective. */
#define DIEPINT_ITTXFE (1U<<4) /**< IN Token received when
TxFIFO is empty. */
#define DIEPINT_TOC (1U<<3) /**< Timeout condition. */
#define DIEPINT_EPDISD (1U<<1) /**< Endpoint disabled
interrupt. */
#define DIEPINT_XFRC (1U<<0) /**< Transfer completed. */
/** @} */
/**
* @name DIEPTSIZ register bit definitions
* @{
*/
#define DIEPTSIZ_MCNT_MASK (3U<<29) /**< Multi count mask. */
#define DIEPTSIZ_MCNT(n) ((n)<<29) /**< Multi count value. */
#define DIEPTSIZ_PKTCNT_MASK (0x3FF<<19) /**< Packet count mask. */
#define DIEPTSIZ_PKTCNT(n) ((n)<<19) /**< Packet count value. */
#define DIEPTSIZ_XFRSIZ_MASK (0x7FFFFU<<0)/**< Transfer size mask. */
#define DIEPTSIZ_XFRSIZ(n) ((n)<<0) /**< Transfer size value. */
/** @} */
/**
* @name DTXFSTS register bit definitions.
* @{
*/
#define DTXFSTS_INEPTFSAV_MASK (0xFFFF<<0) /**< IN endpoint TxFIFO space
available. */
/** @} */
/**
* @name DOEPCTL register bit definitions.
* @{
*/
#define DOEPCTL_EPENA (1U<<31) /**< Endpoint enable. */
#define DOEPCTL_EPDIS (1U<<30) /**< Endpoint disable. */
#define DOEPCTL_SD1PID (1U<<29) /**< Set DATA1 PID. */
#define DOEPCTL_SODDFRM (1U<<29) /**< Set odd frame. */
#define DOEPCTL_SD0PID (1U<<28) /**< Set DATA0 PID. */
#define DOEPCTL_SEVNFRM (1U<<28) /**< Set even frame. */
#define DOEPCTL_SNAK (1U<<27) /**< Set NAK. */
#define DOEPCTL_CNAK (1U<<26) /**< Clear NAK. */
#define DOEPCTL_STALL (1U<<21) /**< STALL handshake. */
#define DOEPCTL_SNPM (1U<<20) /**< Snoop mode. */
#define DOEPCTL_EPTYP_MASK (3U<<18) /**< Endpoint type mask. */
#define DOEPCTL_EPTYP_CTRL (0U<<18) /**< Control. */
#define DOEPCTL_EPTYP_ISO (1U<<18) /**< Isochronous. */
#define DOEPCTL_EPTYP_BULK (2U<<18) /**< Bulk. */
#define DOEPCTL_EPTYP_INTR (3U<<18) /**< Interrupt. */
#define DOEPCTL_NAKSTS (1U<<17) /**< NAK status. */
#define DOEPCTL_EONUM (1U<<16) /**< Even/odd frame. */
#define DOEPCTL_DPID (1U<<16) /**< Endpoint data PID. */
#define DOEPCTL_USBAEP (1U<<15) /**< USB active endpoint. */
#define DOEPCTL_MPSIZ_MASK (0x3FFU<<0) /**< Maximum Packet size mask. */
#define DOEPCTL_MPSIZ(n) ((n)<<0) /**< Maximum Packet size value. */
/** @} */
/**
* @name DOEPINT register bit definitions
* @{
*/
#define DOEPINT_B2BSTUP (1U<<6) /**< Back-to-back SETUP packets
received. */
#define DOEPINT_OTEPDIS (1U<<4) /**< OUT token received when
endpoint disabled. */
#define DOEPINT_STUP (1U<<3) /**< SETUP phase done. */
#define DOEPINT_EPDISD (1U<<1) /**< Endpoint disabled
interrupt. */
#define DOEPINT_XFRC (1U<<0) /**< Transfer completed
interrupt. */
/** @} */
/**
* @name DOEPTSIZ register bit definitions
* @{
*/
#define DOEPTSIZ_RXDPID_MASK (3U<<29) /**< Received data PID mask. */
#define DOEPTSIZ_RXDPID(n) ((n)<<29) /**< Received data PID value. */
#define DOEPTSIZ_STUPCNT_MASK (3U<<29) /**< SETUP packet count mask. */
#define DOEPTSIZ_STUPCNT(n) ((n)<<29) /**< SETUP packet count value. */
#define DOEPTSIZ_PKTCNT_MASK (0x3FFU<<19)/**< Packet count mask. */
#define DOEPTSIZ_PKTCNT(n) ((n)<<19) /**< Packet count value. */
#define DOEPTSIZ_XFRSIZ_MASK (0x7FFFFU<<0)/**< Transfer size mask. */
#define DOEPTSIZ_XFRSIZ(n) ((n)<<0) /**< Transfer size value. */
/** @} */
/**
* @name PCGCCTL register bit definitions
* @{
*/
#define PCGCCTL_PHYSUSP (1U<<4) /**< PHY Suspended. */
#define PCGCCTL_GATEHCLK (1U<<1) /**< Gate HCLK. */
#define PCGCCTL_STPPCLK (1U<<0) /**< Stop PCLK. */
/** @} */
/**
* @brief OTG_FS registers block memory address.
*/
#define OTG_FS_ADDR 0x50000000
/**
* @brief OTG_HS registers block memory address.
*/
#define OTG_HS_ADDR 0x40040000
/**
* @brief Accesses to the OTG_FS registers block.
*/
#define OTG_FS ((stm32_otg_t *)OTG_FS_ADDR)
/**
* @brief Accesses to the OTG_HS registers block.
*/
#define OTG_HS ((stm32_otg_t *)OTG_HS_ADDR)
#endif /* _STM32_OTG_H_ */
/** @} */

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,153 @@
/*
ChibiOS - Copyright (C) 2006..2015 Giovanni Di Sirio
Copyright (C) 2015 Diego Ismirlian, TISA, (dismirlian (at) google's mail)
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.
*/
#ifndef USBH_LLD_H_
#define USBH_LLD_H_
#include "hal.h"
#if HAL_USE_USBH
#include "osal.h"
#include "stm32_otg.h"
/* TODO:
*
* - Implement ISO/INT OUT and test
* - Consider DMA mode for OTG_HS, consider external PHY for HS.
* - Implement a data pump thread, so we don't have to copy data from the ISR
* This might be a bad idea for small endpoint packet sizes (the context switch
* could be longer than the copy)
*/
typedef enum {
USBH_LLD_CTRLPHASE_SETUP,
USBH_LLD_CTRLPHASE_DATA,
USBH_LLD_CTRLPHASE_STATUS
} usbh_lld_ctrlphase_t;
typedef enum {
USBH_LLD_HALTREASON_NONE,
USBH_LLD_HALTREASON_XFRC,
USBH_LLD_HALTREASON_NAK,
USBH_LLD_HALTREASON_STALL,
USBH_LLD_HALTREASON_ERROR,
USBH_LLD_HALTREASON_ABORT
} usbh_lld_halt_reason_t;
typedef struct stm32_hc_management {
struct list_head node;
stm32_otg_host_chn_t *hc;
volatile uint32_t *fifo;
usbh_ep_t *ep;
uint16_t haintmsk;
usbh_lld_halt_reason_t halt_reason;
} stm32_hc_management_t;
#define _usbhdriver_ll_data \
stm32_otg_t *otg; \
/* channels */ \
uint8_t channels_number; \
stm32_hc_management_t channels[STM32_OTG2_CHANNELS_NUMBER]; \
struct list_head ch_free[2]; \
/* Enpoints being processed */ \
struct list_head ep_active_lists[4]; \
/* Pending endpoints */ \
struct list_head ep_pending_lists[4];
#define _usbh_ep_ll_data \
struct list_head *active_list; /* shortcut to ep list */ \
struct list_head *pending_list; /* shortcut to ep list */ \
struct list_head urb_list; /* list of URBs queued in this EP */ \
struct list_head node; /* this EP */ \
uint32_t hcintmsk; \
uint32_t hcchar; \
uint32_t dt_mask; /* data-toggle mask */ \
/* current transfer */ \
struct { \
stm32_hc_management_t *hcm; /* assigned channel */ \
uint32_t len; /* this transfer's total length */ \
uint8_t *buf; /* this transfer's buffer */ \
uint32_t partial; /* this transfer's partial length */\
uint16_t packets; /* packets allocated */ \
union { \
uint32_t frame_counter; /* frame counter (for INT) */ \
usbh_lld_ctrlphase_t ctrl_phase; /* control phase (for CTRL) */ \
} u; \
uint8_t error_count; /* error count */ \
} xfer;
#define _usbh_port_ll_data \
uint16_t lld_c_status; \
uint16_t lld_status;
#define _usbh_device_ll_data
#define _usbh_hub_ll_data
#define _usbh_urb_ll_data \
struct list_head node; \
bool queued;
#define usbh_lld_urb_object_init(urb) \
do { \
osalDbgAssert(((uint32_t)urb->buff & 3) == 0, \
"use USBH_DEFINE_BUFFER() to declare the IO buffers"); \
urb->queued = FALSE; \
} while (0)
#define usbh_lld_urb_object_reset(urb) \
do { \
osalDbgAssert(urb->queued == FALSE, "wrong state"); \
osalDbgAssert(((uint32_t)urb->buff & 3) == 0, \
"use USBH_DEFINE_BUFFER() to declare the IO buffers"); \
} while (0)
void usbh_lld_init(void);
void usbh_lld_start(USBHDriver *usbh);
void usbh_lld_ep_object_init(usbh_ep_t *ep);
void usbh_lld_ep_open(usbh_ep_t *ep);
void usbh_lld_ep_close(usbh_ep_t *ep);
void usbh_lld_urb_submit(usbh_urb_t *urb);
bool usbh_lld_urb_abort(usbh_urb_t *urb, usbh_urbstatus_t status);
usbh_urbstatus_t usbh_lld_root_hub_request(USBHDriver *usbh, uint8_t bmRequestType, uint8_t bRequest,
uint16_t wvalue, uint16_t windex, uint16_t wlength, uint8_t *buf);
uint8_t usbh_lld_roothub_get_statuschange_bitmap(USBHDriver *usbh);
#define usbh_lld_epreset(ep) do {(ep)->dt_mask = HCTSIZ_DPID_DATA0;} while (0);
#ifdef __IAR_SYSTEMS_ICC__
#define USBH_LLD_DEFINE_BUFFER(type, name) type name
#else
#define USBH_LLD_DEFINE_BUFFER(type, name) type name __attribute__((aligned(4)))
#endif
#endif
#endif /* USBH_LLD_H_ */

View File

@ -1,6 +1,8 @@
include ${CHIBIOS}/os/hal/ports/STM32/STM32F0xx/platform.mk
PLATFORMSRC += ${CHIBIOS_CONTRIB}/os/hal/ports/STM32/LLD/CRCv1/crc_lld.c
PLATFORMSRC += ${CHIBIOS_CONTRIB}/os/hal/ports/STM32/LLD/CRCv1/crc_lld.c \
${CHIBIOS_CONTRIB}/os/hal/ports/STM32/LLD/TIMv1/timcap_lld.c \
PLATFORMINC += ${CHIBIOS_CONTRIB}/os/hal/ports/STM32/LLD/CRCv1 \
${CHIBIOS_CONTRIB}/os/hal/ports/STM32/LLD/TIMv1 \
${CHIBIOS_CONTRIB}/os/hal/ports/STM32/LLD

View File

@ -0,0 +1,9 @@
include ${CHIBIOS}/os/hal/ports/STM32/STM32F3xx/platform.mk
PLATFORMSRC += ${CHIBIOS_CONTRIB}/os/hal/ports/STM32/LLD/CRCv1/crc_lld.c \
${CHIBIOS_CONTRIB}/os/hal/ports/STM32/LLD/TIMv1/eicu_lld.c \
${CHIBIOS_CONTRIB}/os/hal/ports/STM32/LLD/TIMv1/timcap_lld.c
PLATFORMINC += ${CHIBIOS_CONTRIB}/os/hal/ports/STM32/LLD/CRCv1 \
${CHIBIOS_CONTRIB}/os/hal/ports/STM32/LLD/TIMv1 \
${CHIBIOS_CONTRIB}/os/hal/ports/STM32/LLD

View File

@ -6,10 +6,15 @@ PLATFORMSRC += ${CHIBIOS_CONTRIB}/os/hal/ports/STM32/LLD/DMA2Dv1/stm32_dma2d.c \
${CHIBIOS_CONTRIB}/os/hal/ports/STM32/LLD/FSMCv1/fsmc_sram.c \
${CHIBIOS_CONTRIB}/os/hal/ports/STM32/LLD/LTDCv1/stm32_ltdc.c \
${CHIBIOS_CONTRIB}/os/hal/ports/STM32/LLD/TIMv1/eicu_lld.c \
${CHIBIOS_CONTRIB}/os/hal/src/fsmc_sdram.c
${CHIBIOS_CONTRIB}/os/hal/ports/STM32/LLD/TIMv1/timcap_lld.c \
${CHIBIOS_CONTRIB}/os/hal/ports/STM32/LLD/USBHv1/usbh_lld.c \
${CHIBIOS_CONTRIB}/os/hal/src/fsmc_sdram.c \
${CHIBIOS_CONTRIB}/os/hal/ports/STM32/LLD/CRCv1/crc_lld.c
PLATFORMINC += ${CHIBIOS_CONTRIB}/os/hal/ports/STM32/LLD/DMA2Dv1 \
${CHIBIOS_CONTRIB}/os/hal/ports/STM32/LLD/FSMCv1 \
${CHIBIOS_CONTRIB}/os/hal/ports/STM32/LLD/LTDCv1 \
${CHIBIOS_CONTRIB}/os/hal/ports/STM32/LLD/TIMv1 \
${CHIBIOS_CONTRIB}/os/hal/ports/STM32/LLD/USBHv1 \
${CHIBIOS_CONTRIB}/os/hal/ports/STM32/LLD/CRCv1 \
${CHIBIOS_CONTRIB}/os/hal/ports/STM32/LLD

353
os/hal/src/ee24xx.c Normal file
View File

@ -0,0 +1,353 @@
/*
Copyright (c) 2013 Timon Wong
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.
*/
/*
Copyright 2012 Uladzimir Pylinski aka barthess.
You may use this work without restrictions, as long as this notice is included.
The work is provided "as is" without warranty of any kind, neither express nor implied.
*/
/*****************************************************************************
* DATASHEET NOTES
*****************************************************************************
Write cycle time (byte or page) - 5 ms
Note:
Page write operations are limited to writing bytes within a single physical
page, regardless of the number of bytes actually being written. Physical page
boundaries start at addresses that are integer multiples of the page buffer
size (or page size and end at addresses that are integer multiples of
[page size]. If a Page Write command attempts to write across a physical
page boundary, the result is that the data wraps around to the beginning of
the current page (overwriting data previously stored there), instead of
being written to the next page as might be expected.
*********************************************************************/
#include "ee24xx.h"
#include <string.h>
#if (defined(HAL_USE_EEPROM) && HAL_USE_EEPROM && EEPROM_USE_EE24XX) || defined(__DOXYGEN__)
/*
******************************************************************************
* DEFINES
******************************************************************************
*/
/*
#if defined(SAM7_PLATFORM)
#define EEPROM_I2C_CLOCK (MCK / (((i2cp->config->cwgr & 0xFF) + ((i2cp->config->cwgr >> 8) & 0xFF)) * (1 << ((i2cp->config->cwgr >> 16) & 7)) + 6))
#else
#define EEPROM_I2C_CLOCK (i2cp->config->clock_speed)
#endif
*/
#define EEPROM_I2C_CLOCK 400000
/*
******************************************************************************
* EXTERNS
******************************************************************************
*/
/*
******************************************************************************
* GLOBAL VARIABLES
******************************************************************************
*/
/*
*******************************************************************************
* LOCAL FUNCTIONS
*******************************************************************************
*/
/**
* @brief Split one uint16_t address to two uint8_t.
*
* @param[in] txbuf pointer to driver transmit buffer
* @param[in] addr uint16_t address
*/
#define eeprom_split_addr(txbuf, addr){ \
(txbuf)[0] = ((uint8_t)((addr >> 8) & 0xFF)); \
(txbuf)[1] = ((uint8_t)(addr & 0xFF)); \
}
/*
*******************************************************************************
* EXPORTED FUNCTIONS
*******************************************************************************
*/
/**
* @brief Calculates requred timeout.
*/
static systime_t calc_timeout(I2CDriver *i2cp, size_t txbytes, size_t rxbytes) {
(void)i2cp;
const uint32_t bitsinbyte = 10;
uint32_t tmo;
tmo = ((txbytes + rxbytes + 1) * bitsinbyte * 1000);
tmo /= EEPROM_I2C_CLOCK;
tmo += 10; /* some additional milliseconds to be safer */
return MS2ST(tmo);
}
/**
* @brief EEPROM read routine.
*
* @param[in] eepcfg pointer to configuration structure of eeprom file
* @param[in] offset addres of 1-st byte to be read
* @param[in] data pointer to buffer with data to be written
* @param[in] len number of bytes to be red
*/
static msg_t eeprom_read(const I2CEepromFileConfig *eepcfg,
uint32_t offset, uint8_t *data, size_t len) {
msg_t status = MSG_RESET;
systime_t tmo = calc_timeout(eepcfg->i2cp, 2, len);
osalDbgAssert(((len <= eepcfg->size) && ((offset + len) <= eepcfg->size)),
"out of device bounds");
eeprom_split_addr(eepcfg->write_buf, (offset + eepcfg->barrier_low));
#if I2C_USE_MUTUAL_EXCLUSION
i2cAcquireBus(eepcfg->i2cp);
#endif
status = i2cMasterTransmitTimeout(eepcfg->i2cp, eepcfg->addr,
eepcfg->write_buf, 2, data, len, tmo);
#if I2C_USE_MUTUAL_EXCLUSION
i2cReleaseBus(eepcfg->i2cp);
#endif
return status;
}
/**
* @brief EEPROM write routine.
* @details Function writes data to EEPROM.
* @pre Data must be fit to single EEPROM page.
*
* @param[in] eepcfg pointer to configuration structure of eeprom file
* @param[in] offset addres of 1-st byte to be write
* @param[in] data pointer to buffer with data to be written
* @param[in] len number of bytes to be written
*/
static msg_t eeprom_write(const I2CEepromFileConfig *eepcfg, uint32_t offset,
const uint8_t *data, size_t len) {
msg_t status = MSG_RESET;
systime_t tmo = calc_timeout(eepcfg->i2cp, (len + 2), 0);
osalDbgAssert(((len <= eepcfg->size) && ((offset + len) <= eepcfg->size)),
"out of device bounds");
osalDbgAssert((((offset + eepcfg->barrier_low) / eepcfg->pagesize) ==
(((offset + eepcfg->barrier_low) + len - 1) / eepcfg->pagesize)),
"data can not be fitted in single page");
/* write address bytes */
eeprom_split_addr(eepcfg->write_buf, (offset + eepcfg->barrier_low));
/* write data bytes */
memcpy(&(eepcfg->write_buf[2]), data, len);
#if I2C_USE_MUTUAL_EXCLUSION
i2cAcquireBus(eepcfg->i2cp);
#endif
status = i2cMasterTransmitTimeout(eepcfg->i2cp, eepcfg->addr,
eepcfg->write_buf, (len + 2), NULL, 0, tmo);
#if I2C_USE_MUTUAL_EXCLUSION
i2cReleaseBus(eepcfg->i2cp);
#endif
/* wait until EEPROM process data */
chThdSleep(eepcfg->write_time);
return status;
}
/**
* @brief Determines and returns size of data that can be processed
*/
static size_t __clamp_size(void *ip, size_t n) {
if (((size_t)eepfs_getposition(ip) + n) > (size_t)eepfs_getsize(ip))
return eepfs_getsize(ip) - eepfs_getposition(ip);
else
return n;
}
/**
* @brief Write data that can be fitted in one page boundary
*/
static void __fitted_write(void *ip, const uint8_t *data, size_t len, uint32_t *written) {
msg_t status = MSG_RESET;
osalDbgAssert(len != 0, "something broken in hi level part");
status = eeprom_write(((I2CEepromFileStream *)ip)->cfg,
eepfs_getposition(ip), data, len);
if (status == MSG_OK) {
*written += len;
eepfs_lseek(ip, eepfs_getposition(ip) + len);
}
}
/**
* @brief Write data to EEPROM.
* @details Only one EEPROM page can be written at once. So fucntion
* splits large data chunks in small EEPROM transactions if needed.
* @note To achieve the maximum effectivity use write operations
* aligned to EEPROM page boundaries.
*/
static size_t write(void *ip, const uint8_t *bp, size_t n) {
size_t len = 0; /* bytes to be written at one trasaction */
uint32_t written; /* total bytes successfully written */
uint16_t pagesize;
uint32_t firstpage;
uint32_t lastpage;
osalDbgCheck((ip != NULL) && (((EepromFileStream *)ip)->vmt != NULL));
if (n == 0)
return 0;
n = __clamp_size(ip, n);
if (n == 0)
return 0;
pagesize = ((EepromFileStream *)ip)->cfg->pagesize;
firstpage = (((EepromFileStream *)ip)->cfg->barrier_low +
eepfs_getposition(ip)) / pagesize;
lastpage = (((EepromFileStream *)ip)->cfg->barrier_low +
eepfs_getposition(ip) + n - 1) / pagesize;
written = 0;
/* data fitted in single page */
if (firstpage == lastpage) {
len = n;
__fitted_write(ip, bp, len, &written);
bp += len;
return written;
}
else {
/* write first piece of data to first page boundary */
len = ((firstpage + 1) * pagesize) - eepfs_getposition(ip);
len -= ((EepromFileStream *)ip)->cfg->barrier_low;
__fitted_write(ip, bp, len, &written);
bp += len;
/* now writes blocks at a size of pages (may be no one) */
while ((n - written) > pagesize) {
len = pagesize;
__fitted_write(ip, bp, len, &written);
bp += len;
}
/* wrtie tail */
len = n - written;
if (len == 0)
return written;
else {
__fitted_write(ip, bp, len, &written);
}
}
return written;
}
/**
* Read some bytes from current position in file. After successful
* read operation the position pointer will be increased by the number
* of read bytes.
*/
static size_t read(void *ip, uint8_t *bp, size_t n) {
msg_t status = MSG_OK;
osalDbgCheck((ip != NULL) && (((EepromFileStream *)ip)->vmt != NULL));
if (n == 0)
return 0;
n = __clamp_size(ip, n);
if (n == 0)
return 0;
/* Stupid I2C cell in STM32F1x does not allow to read single byte.
So we must read 2 bytes and return needed one. */
#if defined(STM32F1XX_I2C)
if (n == 1) {
uint8_t __buf[2];
/* if NOT last byte of file requested */
if ((eepfs_getposition(ip) + 1) < eepfs_getsize(ip)) {
if (read(ip, __buf, 2) == 2) {
eepfs_lseek(ip, (eepfs_getposition(ip) + 1));
bp[0] = __buf[0];
return 1;
}
else
return 0;
}
else {
eepfs_lseek(ip, (eepfs_getposition(ip) - 1));
if (read(ip, __buf, 2) == 2) {
eepfs_lseek(ip, (eepfs_getposition(ip) + 2));
bp[0] = __buf[1];
return 1;
}
else
return 0;
}
}
#endif /* defined(STM32F1XX_I2C) */
/* call low level function */
status = eeprom_read(((I2CEepromFileStream *)ip)->cfg,
eepfs_getposition(ip), bp, n);
if (status != MSG_OK)
return 0;
else {
eepfs_lseek(ip, (eepfs_getposition(ip) + n));
return n;
}
}
static const struct EepromFileStreamVMT vmt = {
write,
read,
eepfs_put,
eepfs_get,
eepfs_close,
eepfs_geterror,
eepfs_getsize,
eepfs_getposition,
eepfs_lseek,
};
EepromDevice eepdev_24xx = {
EEPROM_DEV_24XX,
&vmt
};
#endif /* EEPROM_USE_EE24XX */

404
os/hal/src/ee25xx.c Normal file
View File

@ -0,0 +1,404 @@
/*
Copyright (c) 2013 Timon Wong
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.
*/
/*
Copyright 2012 Uladzimir Pylinski aka barthess.
You may use this work without restrictions, as long as this notice is included.
The work is provided "as is" without warranty of any kind, neither express nor implied.
*/
/*****************************************************************************
* DATASHEET NOTES
*****************************************************************************
Write cycle time (byte or page) - 5 ms
Note:
Page write operations are limited to writing bytes within a single physical
page, regardless of the number of bytes actually being written. Physical page
boundaries start at addresses that are integer multiples of the page buffer
size (or page size and end at addresses that are integer multiples of
[page size]. If a Page Write command attempts to write across a physical
page boundary, the result is that the data wraps around to the beginning of
the current page (overwriting data previously stored there), instead of
being written to the next page as might be expected.
*********************************************************************/
#include "ee25xx.h"
#include <string.h>
#if (defined(HAL_USE_EEPROM) && HAL_USE_EEPROM && EEPROM_USE_EE25XX) || defined(__DOXYGEN__)
/**
* @name Commands of 25XX chip.
* @{
*/
#define CMD_READ 0x03 /**< @brief Read data from memory array beginning at
selected address. */
#define CMD_WRITE 0x02 /**< @brief Write data to memory array beginning at
selected address. */
#define CMD_WRDI 0x04 /**< Reset the write enable latch (disable write
operations). */
#define CMD_WREN 0x06 /**< Set the write enable latch (enable write
operations). */
#define CMD_RDSR 0x05 /**< Read STATUS register. */
#define CMD_WRSR 0x01 /**< Write STATUS register. */
/** @} */
/**
* @name Status of 25XX chip.
* @{}
*/
#define STAT_BP1 0x08 /**< @brief Block protection (high). */
#define STAT_BP0 0x04 /**< @brief Block protection (low). */
#define STAT_WEL 0x02 /**< @brief Write enable latch. */
#define STAT_WIP 0x01 /**< @brief Write-In-Progress. */
/** @} */
/**
* @brief 25XX low level write then read rountine.
*
* @param[in] eepcfg pointer to configuration structure of eeprom file.
* @param[in] txbuf pointer to buffer to be transfered.
* @param[in] txlen number of bytes to be transfered.
* @param[out] rxbuf pointer to buffer to be received.
* @param[in] rxlen number of bytes to be received.
*/
static void ll_25xx_transmit_receive(const SPIEepromFileConfig *eepcfg,
const uint8_t *txbuf, size_t txlen,
uint8_t *rxbuf, size_t rxlen) {
#if SPI_USE_MUTUAL_EXCLUSION
spiAcquireBus(eepcfg->spip);
#endif
spiSelect(eepcfg->spip);
spiSend(eepcfg->spip, txlen, txbuf);
if (rxlen) /* Check if receive is needed. */
spiReceive(eepcfg->spip, rxlen, rxbuf);
spiUnselect(eepcfg->spip);
#if SPI_USE_MUTUAL_EXCLUSION
spiReleaseBus(eepcfg->spip);
#endif
}
/**
* @brief Check whether the device is busy (writing in progress).
*
* @param[in] eepcfg pointer to configuration structure of eeprom file.
* @return @p true on busy.
*/
static bool ll_eeprom_is_busy(const SPIEepromFileConfig *eepcfg) {
uint8_t cmd = CMD_RDSR;
uint8_t stat;
ll_25xx_transmit_receive(eepcfg, &cmd, 1, &stat, 1);
if (stat & STAT_WIP)
return TRUE;
return FALSE;
}
/**
* @brief Lock device.
*
* @param[in] eepcfg pointer to configuration structure of eeprom file.
*/
static void ll_eeprom_lock(const SPIEepromFileConfig *eepcfg) {
uint8_t cmd = CMD_WRDI;
ll_25xx_transmit_receive(eepcfg, &cmd, 1, NULL, 0);
}
/**
* @brief Unlock device.
*
* @param[in] eepcfg pointer to configuration structure of eeprom file.
*/
static void ll_eeprom_unlock(const SPIEepromFileConfig *eepcfg) {
uint8_t cmd = CMD_WREN;
ll_25xx_transmit_receive(eepcfg, &cmd, 1, NULL, 0);
}
/**
* @brief Prepare byte sequence for command and address
*
* @param[in] seq pointer to first 3byte sequence
* @param[in] size size of the eeprom device
* @param[in] cmd command
* @param[in] addr address
* @return number of bytes of this sequence
*/
static uint8_t ll_eeprom_prepare_seq(uint8_t *seq, uint32_t size, uint8_t cmd,
uint32_t addr) {
seq[0] = ((uint8_t)cmd & 0xff);
if (size > 0xffffUL) {
/* High density, 24bit address. */
seq[1] = (uint8_t)((addr >> 16) & 0xff);
seq[2] = (uint8_t)((addr >> 8) & 0xff);
seq[3] = (uint8_t)(addr & 0xff);
return 4;
}
else if (size > 0x00ffUL) {
/* Medium density, 16bit address. */
seq[1] = (uint8_t)((addr >> 8) & 0xff);
seq[2] = (uint8_t)(addr & 0xff);
return 3;
}
/* Low density, 8bit address. */
seq[1] = (uint8_t)(addr & 0xff);
return 2;
}
/**
* @brief EEPROM read routine.
*
* @param[in] eepcfg pointer to configuration structure of eeprom file.
* @param[in] offset addres of 1-st byte to be read.
* @param[out] data pointer to buffer with data to be written.
* @param[in] len number of bytes to be red.
*/
static msg_t ll_eeprom_read(const SPIEepromFileConfig *eepcfg, uint32_t offset,
uint8_t *data, size_t len) {
uint8_t txbuff[4];
uint8_t txlen;
osalDbgAssert(((len <= eepcfg->size) && ((offset + len) <= eepcfg->size)),
"out of device bounds");
if (eepcfg->spip->state != SPI_READY)
return MSG_RESET;
txlen = ll_eeprom_prepare_seq(txbuff, eepcfg->size, CMD_READ,
(offset + eepcfg->barrier_low));
ll_25xx_transmit_receive(eepcfg, txbuff, txlen, data, len);
return MSG_OK;
}
/**
* @brief EEPROM write routine.
* @details Function writes data to EEPROM.
* @pre Data must be fit to single EEPROM page.
*
* @param[in] eepcfg pointer to configuration structure of eeprom file.
* @param[in] offset addres of 1-st byte to be writen.
* @param[in] data pointer to buffer with data to be written.
* @param[in] len number of bytes to be written.
*/
static msg_t ll_eeprom_write(const SPIEepromFileConfig *eepcfg, uint32_t offset,
const uint8_t *data, size_t len) {
uint8_t txbuff[4];
uint8_t txlen;
systime_t now;
osalDbgAssert(((len <= eepcfg->size) && ((offset + len) <= eepcfg->size)),
"out of device bounds");
osalDbgAssert((((offset + eepcfg->barrier_low) / eepcfg->pagesize) ==
(((offset + eepcfg->barrier_low) + len - 1) / eepcfg->pagesize)),
"data can not be fitted in single page");
if (eepcfg->spip->state != SPI_READY)
return MSG_RESET;
/* Unlock array for writting. */
ll_eeprom_unlock(eepcfg);
#if SPI_USE_MUTUAL_EXCLUSION
spiAcquireBus(eepcfg->spip);
#endif
spiSelect(eepcfg->spip);
txlen = ll_eeprom_prepare_seq(txbuff, eepcfg->size, CMD_WRITE,
(offset + eepcfg->barrier_low));
spiSend(eepcfg->spip, txlen, txbuff);
spiSend(eepcfg->spip, len, data);
spiUnselect(eepcfg->spip);
#if SPI_USE_MUTUAL_EXCLUSION
spiReleaseBus(eepcfg->spip);
#endif
/* Wait until EEPROM process data. */
now = chVTGetSystemTimeX();
while (ll_eeprom_is_busy(eepcfg)) {
if ((chVTGetSystemTimeX() - now) > eepcfg->write_time) {
return MSG_TIMEOUT;
}
chThdYield();
}
/* Lock array preventing unexpected access */
ll_eeprom_lock(eepcfg);
return MSG_OK;
}
/**
* @brief Determines and returns size of data that can be processed
*/
static size_t __clamp_size(void *ip, size_t n) {
if (((size_t)eepfs_getposition(ip) + n) > (size_t)eepfs_getsize(ip))
return eepfs_getsize(ip) - eepfs_getposition(ip);
else
return n;
}
/**
* @brief Write data that can be fitted in one page boundary
*/
static msg_t __fitted_write(void *ip, const uint8_t *data, size_t len, uint32_t *written) {
msg_t status = MSG_RESET;
osalDbgAssert(len != 0, "something broken in hi level part");
status = ll_eeprom_write(((SPIEepromFileStream *)ip)->cfg,
eepfs_getposition(ip), data, len);
if (status == MSG_OK) {
*written += len;
eepfs_lseek(ip, eepfs_getposition(ip) + len);
}
return status;
}
/**
* @brief Write data to EEPROM.
* @details Only one EEPROM page can be written at once. So fucntion
* splits large data chunks in small EEPROM transactions if needed.
* @note To achieve the maximum effectivity use write operations
* aligned to EEPROM page boundaries.
*/
static size_t write(void *ip, const uint8_t *bp, size_t n) {
size_t len = 0; /* bytes to be written at one trasaction */
uint32_t written; /* total bytes successfully written */
uint16_t pagesize;
uint32_t firstpage;
uint32_t lastpage;
volatile const SPIEepromFileConfig *cfg = ((SPIEepromFileStream *)ip)->cfg;
osalDbgCheck((ip != NULL) && (((SPIEepromFileStream *)ip)->vmt != NULL));
if (n == 0)
return 0;
n = __clamp_size(ip, n);
if (n == 0)
return 0;
pagesize = cfg->pagesize;
firstpage = (cfg->barrier_low + eepfs_getposition(ip)) / pagesize;
lastpage = ((cfg->barrier_low + eepfs_getposition(ip) + n) - 1) / pagesize;
written = 0;
/* data fitted in single page */
if (firstpage == lastpage) {
len = n;
__fitted_write(ip, bp, len, &written);
bp += len;
return written;
}
else {
/* write first piece of data to first page boundary */
len = ((firstpage + 1) * pagesize) - eepfs_getposition(ip);
len -= cfg->barrier_low;
__fitted_write(ip, bp, len, &written);
bp += len;
/* now writes blocks at a size of pages (may be no one) */
while ((n - written) > pagesize) {
len = pagesize;
if (__fitted_write(ip, bp, len, &written) != MSG_OK) // Fixed: Would increase bp forever and crash in case of timeouts...
return written;
bp += len;
}
/* wrtie tail */
len = n - written;
if (len == 0)
return written;
else {
__fitted_write(ip, bp, len, &written);
}
}
return written;
}
/**
* Read some bytes from current position in file. After successful
* read operation the position pointer will be increased by the number
* of read bytes.
*/
static size_t read(void *ip, uint8_t *bp, size_t n) {
msg_t status = MSG_OK;
osalDbgCheck((ip != NULL) && (((EepromFileStream *)ip)->vmt != NULL));
if (n == 0)
return 0;
n = __clamp_size(ip, n);
if (n == 0)
return 0;
/* call low level function */
status = ll_eeprom_read(((SPIEepromFileStream *)ip)->cfg,
eepfs_getposition(ip), bp, n);
if (status != MSG_OK)
return 0;
else {
eepfs_lseek(ip, (eepfs_getposition(ip) + n));
return n;
}
}
static const struct EepromFileStreamVMT vmt = {
write,
read,
eepfs_put,
eepfs_get,
eepfs_close,
eepfs_geterror,
eepfs_getsize,
eepfs_getposition,
eepfs_lseek,
};
EepromDevice eepdev_25xx = {
EEPROM_DEV_25XX,
&vmt
};
#endif /* EEPROM_USE_EE25XX */

197
os/hal/src/eeprom.c Normal file
View File

@ -0,0 +1,197 @@
/*
Copyright (c) 2013 Timon Wong
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.
*/
/*
Copyright 2012 Uladzimir Pylinski aka barthess.
You may use this work without restrictions, as long as this notice is included.
The work is provided "as is" without warranty of any kind, neither express nor implied.
*/
#include "eeprom.h"
#include <string.h>
#if defined(HAL_USE_EEPROM) && HAL_USE_EEPROM
extern EepromDevice eepdev_24xx;
extern EepromDevice eepdev_25xx;
EepromDevice *__eeprom_drv_table[] = {
/* I2C related. */
#if HAL_USE_I2C
# if EEPROM_USE_EE24XX
&eepdev_24xx,
# endif
#endif /* HAL_USE_I2C */
/* SPI related. */
#if HAL_USE_SPI
# if EEPROM_USE_EE25XX
&eepdev_25xx,
# endif
#endif /* HAL_USE_SPI */
};
/**
* @breif Find low level EEPROM device by id.
*/
const EepromDevice *EepromFindDevice(uint8_t id) {
uint8_t i;
const EepromDevice *drv;
for (i = 0; i < EEPROM_TABLE_SIZE; i++) {
drv = __eeprom_drv_table[i];
if (drv->id == id) {
return drv;
}
}
return NULL;
}
/**
* Open EEPROM IC as file and return pointer to the file stream object
* @note Fucntion allways successfully open file. All checking makes
* in read/write functions.
*/
EepromFileStream *EepromFileOpen(EepromFileStream *efs,
const EepromFileConfig *eepcfg,
const EepromDevice *eepdev) {
osalDbgAssert((efs != NULL) && (eepcfg != NULL) && (eepdev != NULL) &&
(eepdev->efsvmt != NULL), "EepromFileOpen");
osalDbgAssert(efs->vmt != eepdev->efsvmt, "File allready opened");
osalDbgAssert(eepcfg->barrier_hi > eepcfg->barrier_low, "Low barrier exceeds High barrier");
osalDbgAssert(eepcfg->pagesize < eepcfg->size, "Pagesize cannot be lager than EEPROM size");
osalDbgAssert(eepcfg->barrier_hi <= eepcfg->size, "Barrier exceeds EEPROM size");
efs->vmt = eepdev->efsvmt;
efs->cfg = eepcfg;
efs->errors = FILE_OK;
efs->position = 0;
return (EepromFileStream *)efs;
}
uint8_t EepromReadByte(EepromFileStream *efs) {
uint8_t buf;
fileStreamRead(efs, &buf, sizeof(buf));
return buf;
}
uint16_t EepromReadHalfword(EepromFileStream *efs) {
uint16_t buf;
fileStreamRead(efs, (uint8_t *)&buf, sizeof(buf));
return buf;
}
uint32_t EepromReadWord(EepromFileStream *efs) {
uint32_t buf;
fileStreamRead(efs, (uint8_t *)&buf, sizeof(buf));
return buf;
}
size_t EepromWriteByte(EepromFileStream *efs, uint8_t data) {
return fileStreamWrite(efs, &data, sizeof(data));
}
size_t EepromWriteHalfword(EepromFileStream *efs, uint16_t data) {
return fileStreamWrite(efs, (uint8_t *)&data, sizeof(data));
}
size_t EepromWriteWord(EepromFileStream *efs, uint32_t data) {
return fileStreamWrite(efs, (uint8_t *)&data, sizeof(data));
}
msg_t eepfs_getsize(void *ip) {
uint32_t h, l;
osalDbgCheck((ip != NULL) && (((EepromFileStream *)ip)->vmt != NULL) &&
(((EepromFileStream *)ip)->cfg != NULL));
h = ((EepromFileStream *)ip)->cfg->barrier_hi;
l = ((EepromFileStream *)ip)->cfg->barrier_low;
return h - l;
}
msg_t eepfs_getposition(void *ip) {
osalDbgCheck((ip != NULL) && (((EepromFileStream *)ip)->vmt != NULL));
return ((EepromFileStream *)ip)->position;
}
msg_t eepfs_lseek(void *ip, fileoffset_t offset) {
uint32_t size;
osalDbgCheck((ip != NULL) && (((EepromFileStream *)ip)->vmt != NULL));
size = eepfs_getsize(ip);
if (offset > size)
offset = size;
((EepromFileStream *)ip)->position = offset;
return offset;
}
msg_t eepfs_close(void *ip) {
osalDbgCheck((ip != NULL) && (((EepromFileStream *)ip)->vmt != NULL));
((EepromFileStream *)ip)->errors = FILE_OK;
((EepromFileStream *)ip)->position = 0;
((EepromFileStream *)ip)->vmt = NULL;
((EepromFileStream *)ip)->cfg = NULL;
return FILE_OK;
}
msg_t eepfs_geterror(void *ip) {
osalDbgCheck((ip != NULL) && (((EepromFileStream *)ip)->vmt != NULL));
return ((EepromFileStream *)ip)->errors;
}
msg_t eepfs_put(void *ip, uint8_t b) {
(void)ip;
(void)b;
return 0;
}
msg_t eepfs_get(void *ip) {
(void)ip;
return 0;
}
#endif /* #if defined(HAL_USE_EEPROM) && HAL_USE_EEPROM */

View File

@ -68,6 +68,14 @@ void halCommunityInit(void) {
#if HAL_USE_RNG || defined(__DOXYGEN__)
rngInit();
#endif
#if HAL_USE_USBH || defined(__DOXYGEN__)
usbhInit();
#endif
#if HAL_USE_TIMCAP || defined(__DOXYGEN__)
timcapInit();
#endif
}
#endif /* HAL_USE_COMMUNITY */

159
os/hal/src/timcap.c Normal file
View File

@ -0,0 +1,159 @@
/*
ChibiOS/RT - Copyright (C) 2006,2007,2008,2009,2010,
2011,2012,2013 Giovanni Di Sirio.
This file is part of ChibiOS/RT.
ChibiOS/RT is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 3 of the License, or
(at your option) any later version.
ChibiOS/RT is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
/**
* @file timcap.c
* @brief TIMCAP Driver code.
*
* @addtogroup TIMCAP
* @{
*/
#include "timcap.h"
#if HAL_USE_TIMCAP || defined(__DOXYGEN__)
/*===========================================================================*/
/* Driver local definitions. */
/*===========================================================================*/
/*===========================================================================*/
/* Driver exported variables. */
/*===========================================================================*/
/*===========================================================================*/
/* Driver local variables and types. */
/*===========================================================================*/
/*===========================================================================*/
/* Driver local functions. */
/*===========================================================================*/
/*===========================================================================*/
/* Driver exported functions. */
/*===========================================================================*/
/**
* @brief TIMCAP Driver initialization.
* @note This function is implicitly invoked by @p halInit(), there is
* no need to explicitly initialize the driver.
*
* @init
*/
void timcapInit(void) {
timcap_lld_init();
}
/**
* @brief Initializes the standard part of a @p TIMCAPDriver structure.
*
* @param[out] timcapp pointer to the @p TIMCAPDriver object
*
* @init
*/
void timcapObjectInit(TIMCAPDriver *timcapp) {
timcapp->state = TIMCAP_STOP;
timcapp->config = NULL;
}
/**
* @brief Configures and activates the TIMCAP peripheral.
*
* @param[in] timcapp pointer to the @p TIMCAPDriver object
* @param[in] config pointer to the @p TIMCAPConfig object
*
* @api
*/
void timcapStart(TIMCAPDriver *timcapp, const TIMCAPConfig *config) {
osalDbgCheck((timcapp != NULL) && (config != NULL));
osalSysLock();
osalDbgAssert((timcapp->state == TIMCAP_STOP) || (timcapp->state == TIMCAP_READY),
"invalid state");
timcapp->config = config;
timcap_lld_start(timcapp);
timcapp->state = TIMCAP_READY;
osalSysUnlock();
}
/**
* @brief Deactivates the TIMCAP peripheral.
*
* @param[in] timcapp pointer to the @p TIMCAPDriver object
*
* @api
*/
void timcapStop(TIMCAPDriver *timcapp) {
osalDbgCheck(timcapp != NULL);
osalSysLock();
osalDbgAssert((timcapp->state == TIMCAP_STOP) || (timcapp->state == TIMCAP_READY),
"invalid state");
timcap_lld_stop(timcapp);
timcapp->state = TIMCAP_STOP;
osalSysUnlock();
}
/**
* @brief Enables the input capture.
*
* @param[in] timcapp pointer to the @p TIMCAPDriver object
*
* @api
*/
void timcapEnable(TIMCAPDriver *timcapp) {
osalDbgCheck(timcapp != NULL);
osalSysLock();
osalDbgAssert(timcapp->state == TIMCAP_READY, "invalid state");
timcap_lld_enable(timcapp);
timcapp->state = TIMCAP_WAITING;
osalSysUnlock();
}
/**
* @brief Disables the input capture.
*
* @param[in] timcapp pointer to the @p TIMCAPDriver object
*
* @api
*/
void timcapDisable(TIMCAPDriver *timcapp) {
osalDbgCheck(timcapp != NULL);
osalSysLock();
osalDbgAssert((timcapp->state == TIMCAP_READY) || (timcapp->state == TIMCAP_WAITING) ||
(timcapp->state == TIMCAP_ACTIVE) || (timcapp->state == TIMCAP_IDLE),
"invalid state");
timcap_lld_disable(timcapp);
timcapp->state = TIMCAP_READY;
osalSysUnlock();
}
#endif /* HAL_USE_TIMCAP */
/** @} */

1395
os/hal/src/usbh.c Normal file

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,536 @@
/*
ChibiOS - Copyright (C) 2006..2015 Giovanni Di Sirio
Copyright (C) 2015 Diego Ismirlian, TISA, (dismirlian (at) google's mail)
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.
*/
#include "hal.h"
#if HAL_USE_USBH
#include "ch.h"
#include "usbh/debug.h"
#include <stdarg.h>
#include "chprintf.h"
#if USBH_DEBUG_ENABLE
#define MAX_FILLER 11
#define FLOAT_PRECISION 9
#define MPRINTF_USE_FLOAT 0
static char *long_to_string_with_divisor(char *p, long num, unsigned radix, long divisor)
{
int i;
char *q;
long l, ll;
l = num;
if (divisor == 0) {
ll = num;
} else {
ll = divisor;
}
q = p + MAX_FILLER;
do {
i = (int)(l % radix);
i += '0';
if (i > '9') {
i += 'A' - '0' - 10;
}
*--q = i;
l /= radix;
} while ((ll /= radix) != 0);
i = (int)(p + MAX_FILLER - q);
do {
*p++ = *q++;
} while (--i);
return p;
}
static char *ltoa(char *p, long num, unsigned radix) {
return long_to_string_with_divisor(p, num, radix, 0);
}
#if MPRINTF_USE_FLOAT
static const long _pow10[FLOAT_PRECISION] = {10, 100, 1000, 10000, 100000, 1000000,
10000000, 100000000, 1000000000};
static const double m10[FLOAT_PRECISION] = {5.0/100, 5.0/1000, 5.0/10000, 5.0/100000, 5.0/1000000,
5.0/10000000, 5.0/100000000, 5.0/1000000000, 5.0/10000000000};
static char *ftoa(char *p, double num, unsigned long precision, bool dot) {
long l;
char *q;
double r;
if (precision == 0) {
l = (long)(num + 0.5);
return long_to_string_with_divisor(p, l, 10, 0);
} else {
if (precision > FLOAT_PRECISION) precision = FLOAT_PRECISION;
r = m10[precision - 1];
precision = _pow10[precision - 1];
l = (long)num;
p = long_to_string_with_divisor(p, l, 10, 0);
if (dot) *p++ = '.';
l = (long)((num - l + r) * precision);
q = long_to_string_with_divisor(p, l, 10, precision / 10) - 1;
while (q > p) {
if (*q != '0') {
break;
}
--q;
}
return ++q;
}
}
#endif
static inline void _put(char c) {
input_queue_t *iqp = &USBH_DEBUG_USBHD.iq;
if (chIQIsFullI(iqp))
return;
iqp->q_counter++;
*iqp->q_wrptr++ = c;
if (iqp->q_wrptr >= iqp->q_top)
iqp->q_wrptr = iqp->q_buffer;
}
int _dbg_printf(const char *fmt, va_list ap) {
char *p, *s, c, filler;
int i, precision, width;
int n = 0;
bool is_long, left_align, sign;
long l;
#if MPRINTF_USE_FLOAT
double f;
char tmpbuf[2*MAX_FILLER + 1];
#else
char tmpbuf[MAX_FILLER + 1];
#endif
for (;;) {
//agarrar nuevo caracter de formato
c = *fmt++;
//chequeo eos
if (c == 0) return n;
//copio los caracteres comunes
if (c != '%') {
_put(c);
n++;
continue;
}
//encontré un '%'
p = tmpbuf;
s = tmpbuf;
//left align
left_align = FALSE;
if (*fmt == '-') {
fmt++;
left_align = TRUE;
}
sign = FALSE;
if (*fmt == '+') {
fmt++;
sign = TRUE;
}
//filler
filler = ' ';
if (*fmt == '0') {
fmt++;
filler = '0';
}
//width
width = 0;
while (TRUE) {
c = *fmt++;
if (c >= '0' && c <= '9')
c -= '0';
else if (c == '*')
c = va_arg(ap, int);
else
break;
width = width * 10 + c;
}
//precision
precision = 0;
if (c == '.') {
if (*fmt == 'n') {
fmt++;
}
while (TRUE) {
c = *fmt++;
if (c >= '0' && c <= '9')
c -= '0';
else if (c == '*')
c = va_arg(ap, int);
else
break;
precision = precision * 10 + c;
}
}
//long modifier
if (c == 'l' || c == 'L') {
is_long = TRUE;
if (*fmt)
c = *fmt++;
}
else
is_long = (c >= 'A') && (c <= 'Z');
/* Command decoding.*/
switch (c) {
//char
case 'c':
filler = ' ';
*p++ = va_arg(ap, int);
break;
//string
case 's':
filler = ' ';
if ((s = va_arg(ap, char *)) == 0)
s = (char *)"(null)";
if (precision == 0)
precision = 32767;
//strlen con límite hasta precision
for (p = s; *p && (--precision >= 0); p++)
;
break;
case 'D':
case 'd':
case 'I':
case 'i':
if (is_long)
l = va_arg(ap, long);
else
l = va_arg(ap, int);
if (l < 0) {
*p++ = '-';
l = -l;
sign = TRUE;
} else if (sign) {
*p++ = '+';
}
p = ltoa(p, l, 10);
break;
#if MPRINTF_USE_FLOAT
case 'f':
f = va_arg(ap, double);
if (f < 0) {
*p++ = '-';
f = -f;
sign = TRUE;
} else if (sign) {
*p++ = '+';
}
if (prec == FALSE) precision = 6;
p = ftoa(p, f, precision, dot);
break;
#endif
case 'X':
case 'x':
c = 16;
goto unsigned_common;
case 'U':
case 'u':
c = 10;
goto unsigned_common;
case 'O':
case 'o':
c = 8;
unsigned_common:
if (is_long)
l = va_arg(ap, unsigned long);
else
l = va_arg(ap, unsigned int);
p = ltoa(p, l, c);
break;
//copiar
default:
*p++ = c;
break;
}
//longitud
i = (int)(p - s);
//calculo cuántos caracteres de filler debo poner
if ((width -= i) < 0)
width = 0;
if (left_align == FALSE)
width = -width;
if (width < 0) {
//alineado a la derecha
//poner el signo adelante
if (sign && filler == '0') {
_put(*s++);
n++;
i--;
}
//fill a la izquierda
do {
_put(filler);
n++;
} while (++width != 0);
}
//copiar los caracteres
while (--i >= 0) {
_put(*s++);
n++;
}
//fill a la derecha
while (width) {
_put(filler);
n++;
width--;
}
}
//return n; // can raise 'code is unreachable' warning
}
static void _print_hdr(void)
{
uint32_t hfnum = USBH_DEBUG_USBHD.otg->HFNUM;
uint16_t hfir = USBH_DEBUG_USBHD.otg->HFIR;
_put(0xff);
_put(0xff);
_put(hfir & 0xff);
_put(hfir >> 8);
_put(hfnum & 0xff);
_put((hfnum >> 8) & 0xff);
_put((hfnum >> 16) & 0xff);
_put((hfnum >> 24) & 0xff);
}
void usbDbgPrintf(const char *fmt, ...)
{
va_list ap;
va_start(ap, fmt);
syssts_t sts = chSysGetStatusAndLockX();
_print_hdr();
_dbg_printf(fmt, ap);
_put(0);
chThdDequeueNextI(&USBH_DEBUG_USBHD.iq.q_waiting, Q_OK);
chSysRestoreStatusX(sts);
va_end(ap);
}
void usbDbgPuts(const char *s)
{
uint32_t buff[2] = {
0xffff | (USBH_DEBUG_USBHD.otg->HFIR << 16),
USBH_DEBUG_USBHD.otg->HFNUM
};
uint8_t *p = (uint8_t *)buff;
uint8_t *top = p + 8;
syssts_t sts = chSysGetStatusAndLockX();
input_queue_t *iqp = &USBH_DEBUG_USBHD.iq;
int rem = sizeof(USBH_DEBUG_USBHD.dbg_buff) - iqp->q_counter;
while (rem) {
*iqp->q_wrptr++ = *p;
if (iqp->q_wrptr >= iqp->q_top)
iqp->q_wrptr = iqp->q_buffer;
rem--;
if (++p == top) break;
}
while (rem) {
*iqp->q_wrptr++ = *s;
if (iqp->q_wrptr >= iqp->q_top)
iqp->q_wrptr = iqp->q_buffer;
rem--;
if (!*s++) break;
}
iqp->q_counter = sizeof(USBH_DEBUG_USBHD.dbg_buff) - rem;
chThdDequeueNextI(&USBH_DEBUG_USBHD.iq.q_waiting, Q_OK);
chSysRestoreStatusX(sts);
}
void usbDbgReset(void) {
const char *msg = "\r\n\r\n==== DEBUG OUTPUT RESET ====\r\n";
syssts_t sts = chSysGetStatusAndLockX();
chIQResetI(&USBH_DEBUG_USBHD.iq);
chOQResetI(&USBH_DEBUG_SD.oqueue);
while (*msg) {
*USBH_DEBUG_SD.oqueue.q_wrptr++ = *msg++;
USBH_DEBUG_SD.oqueue.q_counter--;
}
chSysRestoreStatusX(sts);
}
static int _get(void) {
if (!USBH_DEBUG_USBHD.iq.q_counter) return -1;
USBH_DEBUG_USBHD.iq.q_counter--;
uint8_t b = *USBH_DEBUG_USBHD.iq.q_rdptr++;
if (USBH_DEBUG_USBHD.iq.q_rdptr >= USBH_DEBUG_USBHD.iq.q_top) {
USBH_DEBUG_USBHD.iq.q_rdptr = USBH_DEBUG_USBHD.iq.q_buffer;
}
return b;
}
void usbDbgSystemHalted(void) {
while (true) {
if (!((bool)((USBH_DEBUG_SD.oqueue.q_wrptr == USBH_DEBUG_SD.oqueue.q_rdptr) && (USBH_DEBUG_SD.oqueue.q_counter != 0U))))
break;
USBH_DEBUG_SD.oqueue.q_counter++;
while (!(USART1->SR & USART_SR_TXE));
USART1->DR = *USBH_DEBUG_SD.oqueue.q_rdptr++;
if (USBH_DEBUG_SD.oqueue.q_rdptr >= USBH_DEBUG_SD.oqueue.q_top) {
USBH_DEBUG_SD.oqueue.q_rdptr = USBH_DEBUG_SD.oqueue.q_buffer;
}
}
int c;
int state = 0;
for (;;) {
c = _get(); if (c < 0) break;
if (state == 0) {
if (c == 0xff) state = 1;
} else if (state == 1) {
if (c == 0xff) state = 2;
else (state = 0);
} else {
c = _get(); if (c < 0) return;
c = _get(); if (c < 0) return;
c = _get(); if (c < 0) return;
c = _get(); if (c < 0) return;
c = _get(); if (c < 0) return;
while (true) {
c = _get(); if (c < 0) return;
if (!c) {
while (!(USART1->SR & USART_SR_TXE));
USART1->DR = '\r';
while (!(USART1->SR & USART_SR_TXE));
USART1->DR = '\n';
state = 0;
break;
}
while (!(USART1->SR & USART_SR_TXE));
USART1->DR = c;
}
}
}
}
static void usb_debug_thread(void *p) {
USBHDriver *host = (USBHDriver *)p;
uint8_t state = 0;
chRegSetThreadName("USBH_DBG");
while (true) {
msg_t c = chIQGet(&host->iq);
if (c < 0) goto reset;
if (state == 0) {
if (c == 0xff) state = 1;
} else if (state == 1) {
if (c == 0xff) state = 2;
else (state = 0);
} else {
uint16_t hfir;
uint32_t hfnum;
hfir = c;
c = chIQGet(&host->iq); if (c < 0) goto reset;
hfir |= c << 8;
c = chIQGet(&host->iq); if (c < 0) goto reset;
hfnum = c;
c = chIQGet(&host->iq); if (c < 0) goto reset;
hfnum |= c << 8;
c = chIQGet(&host->iq); if (c < 0) goto reset;
hfnum |= c << 16;
c = chIQGet(&host->iq); if (c < 0) goto reset;
hfnum |= c << 24;
uint32_t f = hfnum & 0xffff;
uint32_t p = 1000 - ((hfnum >> 16) / (hfir / 1000));
chprintf((BaseSequentialStream *)&USBH_DEBUG_SD, "%05d.%03d ", f, p);
while (true) {
c = chIQGet(&host->iq); if (c < 0) goto reset;
if (!c) {
sdPut(&USBH_DEBUG_SD, '\r');
sdPut(&USBH_DEBUG_SD, '\n');
state = 0;
break;
}
sdPut(&USBH_DEBUG_SD, (uint8_t)c);
}
}
continue;
reset:
state = 0;
}
}
void usbDbgInit(USBHDriver *host) {
if (host != &USBH_DEBUG_USBHD)
return;
chIQObjectInit(&USBH_DEBUG_USBHD.iq, USBH_DEBUG_USBHD.dbg_buff, sizeof(USBH_DEBUG_USBHD.dbg_buff), 0, 0);
chThdCreateStatic(USBH_DEBUG_USBHD.waDebug, sizeof(USBH_DEBUG_USBHD.waDebug), NORMALPRIO, usb_debug_thread, &USBH_DEBUG_USBHD);
}
#endif
#endif

View File

@ -0,0 +1,165 @@
/*
ChibiOS - Copyright (C) 2006..2015 Giovanni Di Sirio
Copyright (C) 2015 Diego Ismirlian, TISA, (dismirlian (at) google's mail)
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.
*/
#include "hal.h"
#if HAL_USE_USBH
#include "usbh/defs.h"
#include "usbh/desciter.h"
void cfg_iter_init(generic_iterator_t *icfg, const uint8_t *buff, uint16_t rem) {
icfg->valid = 0;
if ((buff[0] < 2) || (rem < 2) || (rem < buff[0])
|| (buff[0] < USBH_DT_CONFIG_SIZE)
|| (buff[1] != USBH_DT_CONFIG))
return;
if (rem > ((usbh_config_descriptor_t *)buff)->wTotalLength) {
rem = ((usbh_config_descriptor_t *)buff)->wTotalLength;
}
icfg->valid = 1;
icfg->rem = rem;
icfg->curr = buff;
}
void if_iter_next(if_iterator_t *iif) {
const uint8_t *curr = iif->curr;
uint16_t rem = iif->rem;
iif->valid = 0;
if ((curr[0] < 2) || (rem < 2) || (rem < curr[0]))
return;
for (;;) {
rem -= curr[0];
curr += curr[0];
if ((curr[0] < 2) || (rem < 2) || (rem < curr[0]))
return;
if (curr[1] == USBH_DT_INTERFACE_ASSOCIATION) {
if (curr[0] < USBH_DT_INTERFACE_ASSOCIATION_SIZE)
return;
iif->iad = (usbh_ia_descriptor_t *)curr;
} else if (curr[1] == USBH_DT_INTERFACE) {
if (curr[0] < USBH_DT_INTERFACE_SIZE)
return;
if (iif->iad) {
if ((curr[2] < iif->iad->bFirstInterface)
|| (curr[2] >= (iif->iad->bFirstInterface + iif->iad->bInterfaceCount)))
iif->iad = 0;
}
break;
}
}
iif->valid = 1;
iif->rem = rem;
iif->curr = curr;
}
void if_iter_init(if_iterator_t *iif, const generic_iterator_t *icfg) {
iif->iad = 0;
iif->curr = icfg->curr;
iif->rem = icfg->rem;
if_iter_next(iif);
}
void ep_iter_next(generic_iterator_t *iep) {
const uint8_t *curr = iep->curr;
uint16_t rem = iep->rem;
iep->valid = 0;
if ((curr[0] < 2) || (rem < 2) || (rem < curr[0]))
return;
for (;;) {
rem -= curr[0];
curr += curr[0];
if ((curr[0] < 2) || (rem < 2) || (rem < curr[0]))
return;
if ((curr[1] == USBH_DT_INTERFACE_ASSOCIATION)
|| (curr[1] == USBH_DT_INTERFACE)
|| (curr[1] == USBH_DT_CONFIG)) {
return;
} else if (curr[1] == USBH_DT_ENDPOINT) {
if (curr[0] < USBH_DT_ENDPOINT_SIZE)
return;
break;
}
}
iep->valid = 1;
iep->rem = rem;
iep->curr = curr;
}
void ep_iter_init(generic_iterator_t *iep, const if_iterator_t *iif) {
iep->curr = iif->curr;
iep->rem = iif->rem;
ep_iter_next(iep);
}
void cs_iter_next(generic_iterator_t *ics) {
const uint8_t *curr = ics->curr;
uint16_t rem = ics->rem;
ics->valid = 0;
if ((curr[0] < 2) || (rem < 2) || (rem < curr[0]))
return;
//for (;;) {
rem -= curr[0];
curr += curr[0];
if ((curr[0] < 2) || (rem < 2) || (rem < curr[0]))
return;
if ((curr[1] == USBH_DT_INTERFACE_ASSOCIATION)
|| (curr[1] == USBH_DT_INTERFACE)
|| (curr[1] == USBH_DT_CONFIG)
|| (curr[1] == USBH_DT_ENDPOINT)) {
return;
}
// break;
//}
ics->valid = 1;
ics->rem = rem;
ics->curr = curr;
}
void cs_iter_init(generic_iterator_t *ics, const generic_iterator_t *iter) {
ics->curr = iter->curr;
ics->rem = iter->rem;
cs_iter_next(ics);
}
#endif

717
os/hal/src/usbh/usbh_ftdi.c Normal file
View File

@ -0,0 +1,717 @@
/*
ChibiOS - Copyright (C) 2006..2015 Giovanni Di Sirio
Copyright (C) 2015 Diego Ismirlian, TISA, (dismirlian (at) google's mail)
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.
*/
#include "hal.h"
#include "usbh.h"
#if HAL_USBH_USE_FTDI
#if !HAL_USE_USBH
#error "USBHFTDI needs USBH"
#endif
#include <string.h>
#include "usbh/dev/ftdi.h"
#include "usbh/internal.h"
//#pragma GCC optimize("Og")
#if USBHFTDI_DEBUG_ENABLE_TRACE
#define udbgf(f, ...) usbDbgPrintf(f, ##__VA_ARGS__)
#define udbg(f, ...) usbDbgPuts(f, ##__VA_ARGS__)
#else
#define udbgf(f, ...) do {} while(0)
#define udbg(f, ...) do {} while(0)
#endif
#if USBHFTDI_DEBUG_ENABLE_INFO
#define uinfof(f, ...) usbDbgPrintf(f, ##__VA_ARGS__)
#define uinfo(f, ...) usbDbgPuts(f, ##__VA_ARGS__)
#else
#define uinfof(f, ...) do {} while(0)
#define uinfo(f, ...) do {} while(0)
#endif
#if USBHFTDI_DEBUG_ENABLE_WARNINGS
#define uwarnf(f, ...) usbDbgPrintf(f, ##__VA_ARGS__)
#define uwarn(f, ...) usbDbgPuts(f, ##__VA_ARGS__)
#else
#define uwarnf(f, ...) do {} while(0)
#define uwarn(f, ...) do {} while(0)
#endif
#if USBHFTDI_DEBUG_ENABLE_ERRORS
#define uerrf(f, ...) usbDbgPrintf(f, ##__VA_ARGS__)
#define uerr(f, ...) usbDbgPuts(f, ##__VA_ARGS__)
#else
#define uerrf(f, ...) do {} while(0)
#define uerr(f, ...) do {} while(0)
#endif
/*===========================================================================*/
/* USB Class driver loader for FTDI */
/*===========================================================================*/
USBHFTDIDriver USBHFTDID[HAL_USBHFTDI_MAX_INSTANCES];
static usbh_baseclassdriver_t *_ftdi_load(usbh_device_t *dev, const uint8_t *descriptor, uint16_t rem);
static void _ftdi_unload(usbh_baseclassdriver_t *drv);
static const usbh_classdriver_vmt_t class_driver_vmt = {
_ftdi_load,
_ftdi_unload
};
const usbh_classdriverinfo_t usbhftdiClassDriverInfo = {
0xff, 0xff, 0xff, "FTDI", &class_driver_vmt
};
static USBHFTDIPortDriver *_find_port(void) {
uint8_t i;
for (i = 0; i < HAL_USBHFTDI_MAX_PORTS; i++) {
if (FTDIPD[i].ftdip == NULL)
return &FTDIPD[i];
}
return NULL;
}
static usbh_baseclassdriver_t *_ftdi_load(usbh_device_t *dev, const uint8_t *descriptor, uint16_t rem) {
int i;
USBHFTDIDriver *ftdip;
if (dev->devDesc.idVendor != 0x0403) {
uerr("FTDI: Unrecognized VID");
return NULL;
}
switch (dev->devDesc.idProduct) {
case 0x6001:
case 0x6010:
case 0x6011:
case 0x6014:
case 0x6015:
break;
default:
uerr("FTDI: Unrecognized PID");
return NULL;
}
if ((rem < descriptor[0]) || (descriptor[1] != USBH_DT_INTERFACE))
return NULL;
const usbh_interface_descriptor_t * const ifdesc = (const usbh_interface_descriptor_t * const)descriptor;
if (ifdesc->bInterfaceNumber != 0) {
uwarn("FTDI: Will allocate driver along with IF #0");
}
/* alloc driver */
for (i = 0; i < HAL_USBHFTDI_MAX_INSTANCES; i++) {
if (USBHFTDID[i].dev == NULL) {
ftdip = &USBHFTDID[i];
goto alloc_ok;
}
}
uwarn("FTDI: Can't alloc driver");
/* can't alloc */
return NULL;
alloc_ok:
/* initialize the driver's variables */
ftdip->ports = 0;
switch (dev->devDesc.bcdDevice) {
case 0x200: //AM
uinfo("FTDI: Type A chip");
ftdip->type = USBHFTDI_TYPE_A;
break;
case 0x400: //BM
case 0x500: //2232C
case 0x600: //R
case 0x1000: //230X
uinfo("FTDI: Type B chip");
ftdip->type = USBHFTDI_TYPE_B;
break;
case 0x700: //2232H;
case 0x800: //4232H;
case 0x900: //232H;
uinfo("FTDI: Type H chip");
ftdip->type = USBHFTDI_TYPE_H;
default:
uerr("FTDI: Unrecognized chip type");
return NULL;
}
usbhEPSetName(&dev->ctrl, "FTD[CTRL]");
/* parse the configuration descriptor */
generic_iterator_t iep, icfg;
if_iterator_t iif;
cfg_iter_init(&icfg, dev->fullConfigurationDescriptor, dev->basicConfigDesc.wTotalLength);
for (if_iter_init(&iif, &icfg); iif.valid; if_iter_next(&iif)) {
const usbh_interface_descriptor_t *const ifdesc = if_get(&iif);
uinfof("FTDI: Interface #%d", ifdesc->bInterfaceNumber);
USBHFTDIPortDriver *const prt = _find_port();
if (prt == NULL) {
uwarn("\tCan't alloc port for this interface");
break;
}
prt->ifnum = ifdesc->bInterfaceNumber;
prt->epin.status = USBH_EPSTATUS_UNINITIALIZED;
prt->epout.status = USBH_EPSTATUS_UNINITIALIZED;
for (ep_iter_init(&iep, &iif); iep.valid; ep_iter_next(&iep)) {
const usbh_endpoint_descriptor_t *const epdesc = ep_get(&iep);
if ((epdesc->bEndpointAddress & 0x80) && (epdesc->bmAttributes == USBH_EPTYPE_BULK)) {
uinfof("BULK IN endpoint found: bEndpointAddress=%02x", epdesc->bEndpointAddress);
usbhEPObjectInit(&prt->epin, dev, epdesc);
usbhEPSetName(&prt->epin, "FTD[BIN ]");
} else if (((epdesc->bEndpointAddress & 0x80) == 0)
&& (epdesc->bmAttributes == USBH_EPTYPE_BULK)) {
uinfof("BULK OUT endpoint found: bEndpointAddress=%02x", epdesc->bEndpointAddress);
usbhEPObjectInit(&prt->epout, dev, epdesc);
usbhEPSetName(&prt->epout, "FTD[BOUT]");
} else {
uinfof("unsupported endpoint found: bEndpointAddress=%02x, bmAttributes=%02x",
epdesc->bEndpointAddress, epdesc->bmAttributes);
}
}
if ((prt->epin.status != USBH_EPSTATUS_CLOSED)
|| (prt->epout.status != USBH_EPSTATUS_CLOSED)) {
uwarn("\tCouldn't find endpoints; can't alloc port for this interface");
continue;
}
/* link the new block driver to the list */
prt->next = ftdip->ports;
ftdip->ports = prt;
prt->ftdip = ftdip;
prt->state = USBHFTDIP_STATE_ACTIVE;
}
return (usbh_baseclassdriver_t *)ftdip;
}
static void _stop(USBHFTDIPortDriver *ftdipp);
static void _ftdi_unload(usbh_baseclassdriver_t *drv) {
osalDbgCheck(drv != NULL);
USBHFTDIDriver *const ftdip = (USBHFTDIDriver *)drv;
USBHFTDIPortDriver *ftdipp = ftdip->ports;
osalMutexLock(&ftdip->mtx);
while (ftdipp) {
_stop(ftdipp);
ftdipp = ftdipp->next;
}
ftdipp = ftdip->ports;
osalSysLock();
while (ftdipp) {
USBHFTDIPortDriver *next = ftdipp->next;
usbhftdipObjectInit(ftdipp);
ftdipp = next;
}
osalSysUnlock();
osalMutexUnlock(&ftdip->mtx);
}
USBHFTDIPortDriver FTDIPD[HAL_USBHFTDI_MAX_PORTS];
#define FTDI_COMMAND_RESET 0
#define FTDI_RESET_ALL 0
#define FTDI_RESET_PURGE_RX 1
#define FTDI_RESET_PURGE_TX 2
#define FTDI_COMMAND_SETFLOW 2
#define FTDI_COMMAND_SETBAUD 3
#define FTDI_COMMAND_SETDATA 4
#define FTDI_SETDATA_BREAK (0x1 << 14)
#if 0
#define FTDI_COMMAND_MODEMCTRL 1
#define FTDI_COMMAND_GETMODEMSTATUS 5 /* Retrieve current value of modem status register */
#define FTDI_COMMAND_SETEVENTCHAR 6 /* Set the event character */
#define FTDI_COMMAND_SETERRORCHAR 7 /* Set the error character */
#define FTDI_COMMAND_SETLATENCYTIMER 9 /* Set the latency timer */
#define FTDI_COMMAND_GETLATENCYTIMER 10 /* Get the latency timer */
#endif
/*
* DATA FORMAT
*
* IN Endpoint
*
* The device reserves the first two bytes of data on this endpoint to contain
* the current values of the modem and line status registers. In the absence of
* data, the device generates a message consisting of these two status bytes
* every 40 ms
*
* Byte 0: Modem Status
*
* Offset Description
* B0 Reserved - must be 1
* B1 Reserved - must be 0
* B2 Reserved - must be 0
* B3 Reserved - must be 0
* B4 Clear to Send (CTS)
* B5 Data Set Ready (DSR)
* B6 Ring Indicator (RI)
* B7 Receive Line Signal Detect (RLSD)
*
* Byte 1: Line Status
*
* Offset Description
* B0 Data Ready (DR)
* B1 Overrun Error (OE)
* B2 Parity Error (PE)
* B3 Framing Error (FE)
* B4 Break Interrupt (BI)
* B5 Transmitter Holding Register (THRE)
* B6 Transmitter Empty (TEMT)
* B7 Error in RCVR FIFO
*
*/
#define FTDI_RS0_CTS (1 << 4)
#define FTDI_RS0_DSR (1 << 5)
#define FTDI_RS0_RI (1 << 6)
#define FTDI_RS0_RLSD (1 << 7)
#define FTDI_RS_DR 1
#define FTDI_RS_OE (1<<1)
#define FTDI_RS_PE (1<<2)
#define FTDI_RS_FE (1<<3)
#define FTDI_RS_BI (1<<4)
#define FTDI_RS_THRE (1<<5)
#define FTDI_RS_TEMT (1<<6)
#define FTDI_RS_FIFO (1<<7)
static usbh_urbstatus_t _ftdi_port_control(USBHFTDIPortDriver *ftdipp,
uint8_t bRequest, uint8_t wValue, uint8_t bHIndex, uint16_t wLength,
uint8_t *buff) {
static const uint8_t bmRequestType[] = {
USBH_REQTYPE_VENDOR | USBH_REQTYPE_OUT | USBH_REQTYPE_DEVICE, //0 FTDI_COMMAND_RESET
USBH_REQTYPE_VENDOR | USBH_REQTYPE_OUT | USBH_REQTYPE_DEVICE, //1 FTDI_COMMAND_MODEMCTRL
USBH_REQTYPE_VENDOR | USBH_REQTYPE_OUT | USBH_REQTYPE_DEVICE, //2 FTDI_COMMAND_SETFLOW
USBH_REQTYPE_VENDOR | USBH_REQTYPE_OUT | USBH_REQTYPE_DEVICE, //3 FTDI_COMMAND_SETBAUD
USBH_REQTYPE_VENDOR | USBH_REQTYPE_OUT | USBH_REQTYPE_DEVICE, //4 FTDI_COMMAND_SETDATA
};
osalDbgCheck(bRequest < sizeof_array(bmRequestType));
osalDbgCheck(bRequest != 1);
const USBH_DEFINE_BUFFER(usbh_control_request_t, req) = {
bmRequestType[bRequest],
bRequest,
wValue,
(bHIndex << 8) | (ftdipp->ifnum + 1),
wLength
};
return usbhControlRequestExtended(ftdipp->ftdip->dev, &req, buff, NULL, MS2ST(1000));
}
static uint32_t _get_divisor(uint32_t baud, usbhftdi_type_t type) {
static const uint8_t divfrac[8] = {0, 3, 2, 4, 1, 5, 6, 7};
uint32_t divisor;
if (type == USBHFTDI_TYPE_A) {
uint32_t divisor3 = ((48000000UL / 2) + baud / 2) / baud;
uinfof("FTDI: desired=%dbps, real=%dbps", baud, (48000000UL / 2) / divisor3);
if ((divisor3 & 0x7) == 7)
divisor3++; /* round x.7/8 up to x+1 */
divisor = divisor3 >> 3;
divisor3 &= 0x7;
if (divisor3 == 1)
divisor |= 0xc000;
else if (divisor3 >= 4)
divisor |= 0x4000;
else if (divisor3 != 0)
divisor |= 0x8000;
else if (divisor == 1)
divisor = 0; /* special case for maximum baud rate */
} else {
if (type == USBHFTDI_TYPE_B) {
divisor = ((48000000UL / 2) + baud / 2) / baud;
uinfof("FTDI: desired=%dbps, real=%dbps", baud, (48000000UL / 2) / divisor);
} else {
/* hi-speed baud rate is 10-bit sampling instead of 16-bit */
if (baud < 1200)
baud = 1200;
divisor = (120000000UL * 8 + baud * 5) / (baud * 10);
uinfof("FTDI: desired=%dbps, real=%dbps", baud, (120000000UL * 8) / divisor / 10);
}
divisor = (divisor >> 3) | (divfrac[divisor & 0x7] << 14);
/* Deal with special cases for highest baud rates. */
if (divisor == 1)
divisor = 0;
else if (divisor == 0x4001)
divisor = 1;
if (type == USBHFTDI_TYPE_H)
divisor |= 0x00020000;
}
return divisor;
}
static usbh_urbstatus_t _set_baudrate(USBHFTDIPortDriver *ftdipp, uint32_t baudrate) {
uint32_t divisor = _get_divisor(baudrate, ftdipp->ftdip->type);
uint16_t wValue = (uint16_t)divisor;
uint16_t wIndex = (uint16_t)(divisor >> 16);
if (ftdipp->ftdip->dev->basicConfigDesc.bNumInterfaces > 1)
wIndex = (wIndex << 8) | (ftdipp->ifnum + 1);
const USBH_DEFINE_BUFFER(usbh_control_request_t, req) = {
USBH_REQTYPE_VENDOR | USBH_REQTYPE_OUT | USBH_REQTYPE_DEVICE,
FTDI_COMMAND_SETBAUD,
wValue,
wIndex,
0
};
return usbhControlRequestExtended(ftdipp->ftdip->dev, &req, NULL, NULL, MS2ST(1000));
}
static void _submitOutI(USBHFTDIPortDriver *ftdipp, uint32_t len) {
udbgf("FTDI: Submit OUT %d", len);
ftdipp->oq_urb.requestedLength = len;
usbhURBObjectResetI(&ftdipp->oq_urb);
usbhURBSubmitI(&ftdipp->oq_urb);
}
static void _out_cb(usbh_urb_t *urb) {
USBHFTDIPortDriver *const ftdipp = (USBHFTDIPortDriver *)urb->userData;
switch (urb->status) {
case USBH_URBSTATUS_OK:
ftdipp->oq_ptr = ftdipp->oq_buff;
ftdipp->oq_counter = 64;
chThdDequeueNextI(&ftdipp->oq_waiting, Q_OK);
return;
case USBH_URBSTATUS_DISCONNECTED:
uwarn("FTDI: URB OUT disconnected");
chThdDequeueNextI(&ftdipp->oq_waiting, Q_RESET);
return;
default:
uerrf("FTDI: URB OUT status unexpected = %d", urb->status);
break;
}
usbhURBObjectResetI(&ftdipp->oq_urb);
usbhURBSubmitI(&ftdipp->oq_urb);
}
static size_t _write_timeout(USBHFTDIPortDriver *ftdipp, const uint8_t *bp,
size_t n, systime_t timeout) {
chDbgCheck(n > 0U);
size_t w = 0;
chSysLock();
while (true) {
if (ftdipp->state != USBHFTDIP_STATE_READY) {
chSysUnlock();
return w;
}
while (usbhURBIsBusy(&ftdipp->oq_urb)) {
if (chThdEnqueueTimeoutS(&ftdipp->oq_waiting, timeout) != Q_OK) {
chSysUnlock();
return w;
}
}
*ftdipp->oq_ptr++ = *bp++;
if (--ftdipp->oq_counter == 0) {
_submitOutI(ftdipp, 64);
chSchRescheduleS();
}
chSysUnlock(); /* Gives a preemption chance in a controlled point.*/
w++;
if (--n == 0U)
return w;
chSysLock();
}
}
static msg_t _put_timeout(USBHFTDIPortDriver *ftdipp, uint8_t b, systime_t timeout) {
chSysLock();
if (ftdipp->state != USBHFTDIP_STATE_READY) {
chSysUnlock();
return Q_RESET;
}
while (usbhURBIsBusy(&ftdipp->oq_urb)) {
msg_t msg = chThdEnqueueTimeoutS(&ftdipp->oq_waiting, timeout);
if (msg < Q_OK) {
chSysUnlock();
return msg;
}
}
*ftdipp->oq_ptr++ = b;
if (--ftdipp->oq_counter == 0) {
_submitOutI(ftdipp, 64);
chSchRescheduleS();
}
chSysUnlock();
return Q_OK;
}
static size_t _write(USBHFTDIPortDriver *ftdipp, const uint8_t *bp, size_t n) {
return _write_timeout(ftdipp, bp, n, TIME_INFINITE);
}
static msg_t _put(USBHFTDIPortDriver *ftdipp, uint8_t b) {
return _put_timeout(ftdipp, b, TIME_INFINITE);
}
static void _submitInI(USBHFTDIPortDriver *ftdipp) {
udbg("FTDI: Submit IN");
usbhURBObjectResetI(&ftdipp->iq_urb);
usbhURBSubmitI(&ftdipp->iq_urb);
}
static void _in_cb(usbh_urb_t *urb) {
USBHFTDIPortDriver *const ftdipp = (USBHFTDIPortDriver *)urb->userData;
switch (urb->status) {
case USBH_URBSTATUS_OK:
if (urb->actualLength < 2) {
uwarnf("FTDI: URB IN actualLength = %d, < 2", urb->actualLength);
} else if (urb->actualLength > 2) {
udbgf("FTDI: URB IN data len=%d, status=%02x %02x",
urb->actualLength - 2,
((uint8_t *)urb->buff)[0],
((uint8_t *)urb->buff)[1]);
ftdipp->iq_ptr = ftdipp->iq_buff + 2;
ftdipp->iq_counter = urb->actualLength - 2;
chThdDequeueNextI(&ftdipp->iq_waiting, Q_OK);
return;
} else {
udbgf("FTDI: URB IN no data, status=%02x %02x",
((uint8_t *)urb->buff)[0],
((uint8_t *)urb->buff)[1]);
return;
}
break;
case USBH_URBSTATUS_DISCONNECTED:
uwarn("FTDI: URB IN disconnected");
chThdDequeueNextI(&ftdipp->iq_waiting, Q_RESET);
return;
default:
uerrf("FTDI: URB IN status unexpected = %d", urb->status);
break;
}
_submitInI(ftdipp);
}
static size_t _read_timeout(USBHFTDIPortDriver *ftdipp, uint8_t *bp,
size_t n, systime_t timeout) {
size_t r = 0;
chDbgCheck(n > 0U);
chSysLock();
while (true) {
if (ftdipp->state != USBHFTDIP_STATE_READY) {
chSysUnlock();
return r;
}
while (ftdipp->iq_counter == 0) {
if (!usbhURBIsBusy(&ftdipp->iq_urb))
_submitInI(ftdipp);
if (chThdEnqueueTimeoutS(&ftdipp->iq_waiting, timeout) != Q_OK) {
chSysUnlock();
return r;
}
}
*bp++ = *ftdipp->iq_ptr++;
if (--ftdipp->iq_counter == 0) {
_submitInI(ftdipp);
chSchRescheduleS();
}
chSysUnlock();
r++;
if (--n == 0U)
return r;
chSysLock();
}
}
static msg_t _get_timeout(USBHFTDIPortDriver *ftdipp, systime_t timeout) {
uint8_t b;
chSysLock();
if (ftdipp->state != USBHFTDIP_STATE_READY) {
chSysUnlock();
return Q_RESET;
}
while (ftdipp->iq_counter == 0) {
if (!usbhURBIsBusy(&ftdipp->iq_urb))
_submitInI(ftdipp);
msg_t msg = chThdEnqueueTimeoutS(&ftdipp->iq_waiting, timeout);
if (msg < Q_OK) {
chSysUnlock();
return msg;
}
}
b = *ftdipp->iq_ptr++;
if (--ftdipp->iq_counter == 0) {
_submitInI(ftdipp);
chSchRescheduleS();
}
chSysUnlock();
return (msg_t)b;
}
static msg_t _get(USBHFTDIPortDriver *ftdipp) {
return _get_timeout(ftdipp, TIME_INFINITE);
}
static size_t _read(USBHFTDIPortDriver *ftdipp, uint8_t *bp, size_t n) {
return _read_timeout(ftdipp, bp, n, TIME_INFINITE);
}
static void _vt(void *p) {
USBHFTDIPortDriver *const ftdipp = (USBHFTDIPortDriver *)p;
chSysLockFromISR();
uint32_t len = ftdipp->oq_ptr - ftdipp->oq_buff;
if (len && !usbhURBIsBusy(&ftdipp->oq_urb)) {
_submitOutI(ftdipp, len);
}
if ((ftdipp->iq_counter == 0) && !usbhURBIsBusy(&ftdipp->iq_urb)) {
_submitInI(ftdipp);
}
chVTSetI(&ftdipp->vt, MS2ST(16), _vt, ftdipp);
chSysUnlockFromISR();
}
static const struct FTDIPortDriverVMT async_channel_vmt = {
(size_t (*)(void *, const uint8_t *, size_t))_write,
(size_t (*)(void *, uint8_t *, size_t))_read,
(msg_t (*)(void *, uint8_t))_put,
(msg_t (*)(void *))_get,
(msg_t (*)(void *, uint8_t, systime_t))_put_timeout,
(msg_t (*)(void *, systime_t))_get_timeout,
(size_t (*)(void *, const uint8_t *, size_t, systime_t))_write_timeout,
(size_t (*)(void *, uint8_t *, size_t, systime_t))_read_timeout
};
static void _stop(USBHFTDIPortDriver *ftdipp) {
osalSysLock();
chVTResetI(&ftdipp->vt);
usbhEPCloseS(&ftdipp->epin);
usbhEPCloseS(&ftdipp->epout);
chThdDequeueAllI(&ftdipp->iq_waiting, Q_RESET);
chThdDequeueAllI(&ftdipp->oq_waiting, Q_RESET);
osalOsRescheduleS();
ftdipp->state = USBHFTDIP_STATE_ACTIVE;
osalSysUnlock();
}
void usbhftdipStop(USBHFTDIPortDriver *ftdipp) {
osalDbgCheck((ftdipp->state == USBHFTDIP_STATE_ACTIVE)
|| (ftdipp->state == USBHFTDIP_STATE_READY));
if (ftdipp->state == USBHFTDIP_STATE_ACTIVE) {
return;
}
osalMutexLock(&ftdipp->ftdip->mtx);
_stop(ftdipp);
osalMutexUnlock(&ftdipp->ftdip->mtx);
}
void usbhftdipStart(USBHFTDIPortDriver *ftdipp, const USBHFTDIPortConfig *config) {
static const USBHFTDIPortConfig default_config = {
HAL_USBHFTDI_DEFAULT_SPEED,
HAL_USBHFTDI_DEFAULT_FRAMING,
HAL_USBHFTDI_DEFAULT_HANDSHAKE,
HAL_USBHFTDI_DEFAULT_XON,
HAL_USBHFTDI_DEFAULT_XOFF
};
osalDbgCheck((ftdipp->state == USBHFTDIP_STATE_ACTIVE)
|| (ftdipp->state == USBHFTDIP_STATE_READY));
if (ftdipp->state == USBHFTDIP_STATE_READY)
return;
osalMutexLock(&ftdipp->ftdip->mtx);
if (config == NULL)
config = &default_config;
uint16_t wValue = 0;
_ftdi_port_control(ftdipp, FTDI_COMMAND_RESET, FTDI_RESET_ALL, 0, 0, NULL);
_set_baudrate(ftdipp, config->speed);
_ftdi_port_control(ftdipp, FTDI_COMMAND_SETDATA, config->framing, 0, 0, NULL);
if (config->handshake & USBHFTDI_HANDSHAKE_XON_XOFF)
wValue = (config->xoff_character << 8) | config->xon_character;
_ftdi_port_control(ftdipp, FTDI_COMMAND_SETFLOW, wValue, config->handshake, 0, NULL);
usbhURBObjectInit(&ftdipp->oq_urb, &ftdipp->epout, _out_cb, ftdipp, ftdipp->oq_buff, 0);
chThdQueueObjectInit(&ftdipp->oq_waiting);
ftdipp->oq_counter = 64;
ftdipp->oq_ptr = ftdipp->oq_buff;
usbhEPOpen(&ftdipp->epout);
usbhURBObjectInit(&ftdipp->iq_urb, &ftdipp->epin, _in_cb, ftdipp, ftdipp->iq_buff, 64);
chThdQueueObjectInit(&ftdipp->iq_waiting);
ftdipp->iq_counter = 0;
ftdipp->iq_ptr = ftdipp->iq_buff;
usbhEPOpen(&ftdipp->epin);
osalSysLock();
usbhURBSubmitI(&ftdipp->iq_urb);
osalSysUnlock();
chVTObjectInit(&ftdipp->vt);
chVTSet(&ftdipp->vt, MS2ST(16), _vt, ftdipp);
ftdipp->state = USBHFTDIP_STATE_READY;
osalMutexUnlock(&ftdipp->ftdip->mtx);
}
void usbhftdiObjectInit(USBHFTDIDriver *ftdip) {
osalDbgCheck(ftdip != NULL);
memset(ftdip, 0, sizeof(*ftdip));
ftdip->info = &usbhftdiClassDriverInfo;
osalMutexObjectInit(&ftdip->mtx);
}
void usbhftdipObjectInit(USBHFTDIPortDriver *ftdipp) {
osalDbgCheck(ftdipp != NULL);
memset(ftdipp, 0, sizeof(*ftdipp));
ftdipp->vmt = &async_channel_vmt;
ftdipp->state = USBHFTDIP_STATE_STOP;
}
#endif

302
os/hal/src/usbh/usbh_hub.c Normal file
View File

@ -0,0 +1,302 @@
/*
ChibiOS - Copyright (C) 2006..2015 Giovanni Di Sirio
Copyright (C) 2015 Diego Ismirlian, TISA, (dismirlian (at) google's mail)
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.
*/
#include "hal.h"
#include "usbh.h"
#include "usbh/internal.h"
#if HAL_USBH_USE_HUB
#if !HAL_USE_USBH
#error "USBHHUB needs HAL_USE_USBH"
#endif
#include <string.h>
#include "usbh/dev/hub.h"
#if USBHHUB_DEBUG_ENABLE_TRACE
#define udbgf(f, ...) usbDbgPrintf(f, ##__VA_ARGS__)
#define udbg(f, ...) usbDbgPuts(f, ##__VA_ARGS__)
#else
#define udbgf(f, ...) do {} while(0)
#define udbg(f, ...) do {} while(0)
#endif
#if USBHHUB_DEBUG_ENABLE_INFO
#define uinfof(f, ...) usbDbgPrintf(f, ##__VA_ARGS__)
#define uinfo(f, ...) usbDbgPuts(f, ##__VA_ARGS__)
#else
#define uinfof(f, ...) do {} while(0)
#define uinfo(f, ...) do {} while(0)
#endif
#if USBHHUB_DEBUG_ENABLE_WARNINGS
#define uwarnf(f, ...) usbDbgPrintf(f, ##__VA_ARGS__)
#define uwarn(f, ...) usbDbgPuts(f, ##__VA_ARGS__)
#else
#define uwarnf(f, ...) do {} while(0)
#define uwarn(f, ...) do {} while(0)
#endif
#if USBHHUB_DEBUG_ENABLE_ERRORS
#define uerrf(f, ...) usbDbgPrintf(f, ##__VA_ARGS__)
#define uerr(f, ...) usbDbgPuts(f, ##__VA_ARGS__)
#else
#define uerrf(f, ...) do {} while(0)
#define uerr(f, ...) do {} while(0)
#endif
USBHHubDriver USBHHUBD[HAL_USBHHUB_MAX_INSTANCES];
usbh_port_t USBHPorts[HAL_USBHHUB_MAX_PORTS];
static usbh_baseclassdriver_t *hub_load(usbh_device_t *dev, const uint8_t *descriptor, uint16_t rem);
static void hub_unload(usbh_baseclassdriver_t *drv);
static const usbh_classdriver_vmt_t usbhhubClassDriverVMT = {
hub_load,
hub_unload
};
const usbh_classdriverinfo_t usbhhubClassDriverInfo = {
0x09, 0x00, -1, "HUB", &usbhhubClassDriverVMT
};
void _usbhub_port_object_init(usbh_port_t *port, USBHDriver *usbh,
USBHHubDriver *hub, uint8_t number) {
memset(port, 0, sizeof(*port));
port->number = number;
port->device.host = usbh;
port->hub = hub;
}
usbh_urbstatus_t usbhhubControlRequest(USBHDriver *host, USBHHubDriver *hub,
uint8_t bmRequestType,
uint8_t bRequest,
uint16_t wValue,
uint16_t wIndex,
uint16_t wLength,
uint8_t *buf) {
if (hub == NULL)
return usbh_lld_root_hub_request(host, bmRequestType, bRequest, wValue, wIndex, wLength, buf);
return usbhControlRequest(hub->dev,
bmRequestType, bRequest, wValue, wIndex, wLength, buf);
}
static void _urb_complete(usbh_urb_t *urb) {
USBHHubDriver *const hubdp = (USBHHubDriver *)urb->userData;
switch (urb->status) {
case USBH_URBSTATUS_TIMEOUT:
/* the device NAKed */
udbg("HUB: no info");
hubdp->statuschange = 0;
break;
case USBH_URBSTATUS_OK: {
uint8_t len = hubdp->hubDesc.bNbrPorts / 8 + 1;
if (urb->actualLength != len) {
uwarnf("Expected %d status change bytes but got %d", len, urb->actualLength);
}
if (urb->actualLength < len)
len = urb->actualLength;
if (len > 4)
len = 4;
uint8_t *sc = (uint8_t *)&hubdp->statuschange;
uint8_t *r = hubdp->scbuff;
while (len--)
*sc++ |= *r++;
uinfof("HUB: change, %08x", hubdp->statuschange);
} break;
case USBH_URBSTATUS_DISCONNECTED:
uwarn("HUB: URB disconnected, aborting poll");
return;
default:
uerrf("HUB: URB status unexpected = %d", urb->status);
break;
}
usbhURBObjectResetI(urb);
usbhURBSubmitI(urb);
}
static usbh_baseclassdriver_t *hub_load(usbh_device_t *dev,
const uint8_t *descriptor, uint16_t rem) {
int i;
USBHHubDriver *hubdp;
if ((rem < descriptor[0]) || (descriptor[1] != USBH_DT_DEVICE))
return NULL;
if (dev->devDesc.bDeviceProtocol != 0)
return NULL;
generic_iterator_t iep, icfg;
if_iterator_t iif;
cfg_iter_init(&icfg, dev->fullConfigurationDescriptor,
dev->basicConfigDesc.wTotalLength);
if_iter_init(&iif, &icfg);
if (!iif.valid)
return NULL;
const usbh_interface_descriptor_t *const ifdesc = if_get(&iif);
if ((ifdesc->bInterfaceClass != 0x09)
|| (ifdesc->bInterfaceSubClass != 0x00)
|| (ifdesc->bInterfaceProtocol != 0x00)) {
return NULL;
}
ep_iter_init(&iep, &iif);
if (!iep.valid)
return NULL;
const usbh_endpoint_descriptor_t *const epdesc = ep_get(&iep);
if ((epdesc->bmAttributes & 0x03) != USBH_EPTYPE_INT) {
return NULL;
}
/* alloc driver */
for (i = 0; i < HAL_USBHHUB_MAX_INSTANCES; i++) {
if (USBHHUBD[i].dev == NULL) {
hubdp = &USBHHUBD[i];
goto alloc_ok;
}
}
uwarn("Can't alloc HUB driver");
/* can't alloc */
return NULL;
alloc_ok:
/* initialize the driver's variables */
hubdp->epint.status = USBH_EPSTATUS_UNINITIALIZED;
hubdp->dev = dev;
hubdp->ports = 0;
usbhEPSetName(&dev->ctrl, "HUB[CTRL]");
/* read Hub descriptor */
uinfo("Read Hub descriptor");
if (usbhhubControlRequest(dev->host, hubdp,
USBH_REQTYPE_IN | USBH_REQTYPE_CLASS | USBH_REQTYPE_DEVICE,
USBH_REQ_GET_DESCRIPTOR,
(USBH_DT_HUB << 8), 0, sizeof(hubdp->hubDesc),
(uint8_t *)&hubdp->hubDesc) != USBH_URBSTATUS_OK) {
hubdp->dev = NULL;
return NULL;
}
const usbh_hub_descriptor_t *const hubdesc = &hubdp->hubDesc;
uinfof("Hub descriptor loaded; %d ports, wHubCharacteristics=%04x, bPwrOn2PwrGood=%d, bHubContrCurrent=%d",
hubdesc->bNbrPorts,
hubdesc->wHubCharacteristics,
hubdesc->bPwrOn2PwrGood,
hubdesc->bHubContrCurrent);
/* Alloc ports */
uint8_t ports = hubdesc->bNbrPorts;
for (i = 0; (ports > 0) && (i < HAL_USBHHUB_MAX_PORTS); i++) {
if (USBHPorts[i].hub == NULL) {
uinfof("Alloc port %d", ports);
_usbhub_port_object_init(&USBHPorts[i], dev->host, hubdp, ports);
USBHPorts[i].next = hubdp->ports;
hubdp->ports = &USBHPorts[i];
--ports;
}
}
if (ports) {
uwarn("Could not alloc all ports");
}
/* link hub to the host's list */
list_add_tail(&hubdp->node, &dev->host->hubs);
/* enable power to ports */
usbh_port_t *port = hubdp->ports;
while (port) {
uinfof("Enable power for port %d", port->number);
usbhhubSetFeaturePort(port, USBH_PORT_FEAT_POWER);
port = port->next;
}
if (hubdesc->bPwrOn2PwrGood)
osalThreadSleepMilliseconds(2 * hubdesc->bPwrOn2PwrGood);
/* initialize the status change endpoint and trigger the first transfer */
usbhEPObjectInit(&hubdp->epint, dev, epdesc);
usbhEPSetName(&hubdp->epint, "HUB[INT ]");
usbhEPOpen(&hubdp->epint);
usbhURBObjectInit(&hubdp->urb, &hubdp->epint,
_urb_complete, hubdp, hubdp->scbuff,
(hubdesc->bNbrPorts + 8) / 8);
osalSysLock();
usbhURBSubmitI(&hubdp->urb);
osalOsRescheduleS();
osalSysUnlock();
return (usbh_baseclassdriver_t *)hubdp;
}
static void hub_unload(usbh_baseclassdriver_t *drv) {
osalDbgCheck(drv != NULL);
USBHHubDriver *const hubdp = (USBHHubDriver *)drv;
/* close the status change endpoint (this cancels ongoing URBs) */
osalSysLock();
usbhEPCloseS(&hubdp->epint);
osalSysUnlock();
/* de-alloc ports and unload drivers */
usbh_port_t *port = hubdp->ports;
while (port) {
_usbh_port_disconnected(port);
port->hub = NULL;
port = port->next;
}
/* unlink the hub from the host's list */
list_del(&hubdp->node);
}
void usbhhubObjectInit(USBHHubDriver *hubdp) {
osalDbgCheck(hubdp != NULL);
memset(hubdp, 0, sizeof(*hubdp));
hubdp->info = &usbhhubClassDriverInfo;
}
#else
#if HAL_USE_USBH
void _usbhub_port_object_init(usbh_port_t *port, USBHDriver *usbh, uint8_t number) {
memset(port, 0, sizeof(*port));
port->number = number;
port->device.host = usbh;
}
#endif
#endif

939
os/hal/src/usbh/usbh_msd.c Normal file
View File

@ -0,0 +1,939 @@
/*
ChibiOS - Copyright (C) 2006..2015 Giovanni Di Sirio
Copyright (C) 2015 Diego Ismirlian, TISA, (dismirlian (at) google's mail)
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.
*/
#include "hal.h"
#include "usbh.h"
#if HAL_USBH_USE_MSD
#if !HAL_USE_USBH
#error "USBHMSD needs USBH"
#endif
#include <string.h>
#include "usbh/dev/msd.h"
#include "usbh/internal.h"
//#pragma GCC optimize("Og")
#if USBHMSD_DEBUG_ENABLE_TRACE
#define udbgf(f, ...) usbDbgPrintf(f, ##__VA_ARGS__)
#define udbg(f, ...) usbDbgPuts(f, ##__VA_ARGS__)
#else
#define udbgf(f, ...) do {} while(0)
#define udbg(f, ...) do {} while(0)
#endif
#if USBHMSD_DEBUG_ENABLE_INFO
#define uinfof(f, ...) usbDbgPrintf(f, ##__VA_ARGS__)
#define uinfo(f, ...) usbDbgPuts(f, ##__VA_ARGS__)
#else
#define uinfof(f, ...) do {} while(0)
#define uinfo(f, ...) do {} while(0)
#endif
#if USBHMSD_DEBUG_ENABLE_WARNINGS
#define uwarnf(f, ...) usbDbgPrintf(f, ##__VA_ARGS__)
#define uwarn(f, ...) usbDbgPuts(f, ##__VA_ARGS__)
#else
#define uwarnf(f, ...) do {} while(0)
#define uwarn(f, ...) do {} while(0)
#endif
#if USBHMSD_DEBUG_ENABLE_ERRORS
#define uerrf(f, ...) usbDbgPrintf(f, ##__VA_ARGS__)
#define uerr(f, ...) usbDbgPuts(f, ##__VA_ARGS__)
#else
#define uerrf(f, ...) do {} while(0)
#define uerr(f, ...) do {} while(0)
#endif
/*===========================================================================*/
/* USB Class driver loader for MSD */
/*===========================================================================*/
USBHMassStorageDriver USBHMSD[HAL_USBHMSD_MAX_INSTANCES];
static usbh_baseclassdriver_t *_msd_load(usbh_device_t *dev, const uint8_t *descriptor, uint16_t rem);
static void _msd_unload(usbh_baseclassdriver_t *drv);
static const usbh_classdriver_vmt_t class_driver_vmt = {
_msd_load,
_msd_unload
};
const usbh_classdriverinfo_t usbhmsdClassDriverInfo = {
0x08, 0x06, 0x50, "MSD", &class_driver_vmt
};
#define MSD_REQ_RESET 0xFF
#define MSD_GET_MAX_LUN 0xFE
static usbh_baseclassdriver_t *_msd_load(usbh_device_t *dev, const uint8_t *descriptor, uint16_t rem) {
int i;
USBHMassStorageDriver *msdp;
uint8_t luns; // should declare it here to eliminate 'control bypass initialization' warning
usbh_urbstatus_t stat; // should declare it here to eliminate 'control bypass initialization' warning
if ((rem < descriptor[0]) || (descriptor[1] != USBH_DT_INTERFACE))
return NULL;
const usbh_interface_descriptor_t * const ifdesc = (const usbh_interface_descriptor_t *)descriptor;
if ((ifdesc->bAlternateSetting != 0)
|| (ifdesc->bNumEndpoints < 2)
|| (ifdesc->bInterfaceSubClass != 0x06)
|| (ifdesc->bInterfaceProtocol != 0x50)) {
return NULL;
}
/* alloc driver */
for (i = 0; i < HAL_USBHMSD_MAX_INSTANCES; i++) {
if (USBHMSD[i].dev == NULL) {
msdp = &USBHMSD[i];
goto alloc_ok;
}
}
uwarn("Can't alloc MSD driver");
/* can't alloc */
return NULL;
alloc_ok:
/* initialize the driver's variables */
msdp->epin.status = USBH_EPSTATUS_UNINITIALIZED;
msdp->epout.status = USBH_EPSTATUS_UNINITIALIZED;
msdp->max_lun = 0;
msdp->tag = 0;
msdp->luns = 0;
msdp->ifnum = ifdesc->bInterfaceNumber;
usbhEPSetName(&dev->ctrl, "MSD[CTRL]");
/* parse the configuration descriptor */
if_iterator_t iif;
generic_iterator_t iep;
iif.iad = 0;
iif.curr = descriptor;
iif.rem = rem;
for (ep_iter_init(&iep, &iif); iep.valid; ep_iter_next(&iep)) {
const usbh_endpoint_descriptor_t *const epdesc = ep_get(&iep);
if ((epdesc->bEndpointAddress & 0x80) && (epdesc->bmAttributes == USBH_EPTYPE_BULK)) {
uinfof("BULK IN endpoint found: bEndpointAddress=%02x", epdesc->bEndpointAddress);
usbhEPObjectInit(&msdp->epin, dev, epdesc);
usbhEPSetName(&msdp->epin, "MSD[BIN ]");
} else if (((epdesc->bEndpointAddress & 0x80) == 0)
&& (epdesc->bmAttributes == USBH_EPTYPE_BULK)) {
uinfof("BULK OUT endpoint found: bEndpointAddress=%02x", epdesc->bEndpointAddress);
usbhEPObjectInit(&msdp->epout, dev, epdesc);
usbhEPSetName(&msdp->epout, "MSD[BOUT]");
} else {
uinfof("unsupported endpoint found: bEndpointAddress=%02x, bmAttributes=%02x",
epdesc->bEndpointAddress, epdesc->bmAttributes);
}
}
if ((msdp->epin.status != USBH_EPSTATUS_CLOSED) || (msdp->epout.status != USBH_EPSTATUS_CLOSED)) {
goto deinit;
}
/* read the number of LUNs */
uinfo("Reading Max LUN:");
USBH_DEFINE_BUFFER(uint8_t, buff[4]);
stat = usbhControlRequest(dev,
USBH_CLASSIN(USBH_REQTYPE_INTERFACE, MSD_GET_MAX_LUN, 0, msdp->ifnum),
1, buff);
if (stat == USBH_URBSTATUS_OK) {
msdp->max_lun = buff[0] + 1;
uinfof("\tmax_lun = %d", msdp->max_lun);
if (msdp->max_lun > HAL_USBHMSD_MAX_LUNS) {
msdp->max_lun = HAL_USBHMSD_MAX_LUNS;
uwarnf("\tUsing max_lun = %d", msdp->max_lun);
}
} else if (stat == USBH_URBSTATUS_STALL) {
uwarn("\tStall, max_lun = 1");
msdp->max_lun = 1;
} else {
uerr("\tError");
goto deinit;
}
/* open the bulk IN/OUT endpoints */
usbhEPOpen(&msdp->epin);
usbhEPOpen(&msdp->epout);
/* Alloc one block device per logical unit found */
luns = msdp->max_lun;
for (i = 0; (luns > 0) && (i < HAL_USBHMSD_MAX_LUNS); i++) {
if (MSBLKD[i].msdp == NULL) {
/* link the new block driver to the list */
MSBLKD[i].next = msdp->luns;
msdp->luns = &MSBLKD[i];
MSBLKD[i].msdp = msdp;
osalSysLock();
MSBLKD[i].state = BLK_ACTIVE; /* transition directly to active, instead of BLK_STOP */
osalSysUnlock();
/* connect the LUN (TODO: review if it's best to leave the LUN disconnected) */
usbhmsdLUNConnect(&MSBLKD[i]);
luns--;
}
}
return (usbh_baseclassdriver_t *)msdp;
deinit:
/* Here, the enpoints are closed, and the driver is unlinked */
return NULL;
}
static void _msd_unload(usbh_baseclassdriver_t *drv) {
osalDbgCheck(drv != NULL);
USBHMassStorageDriver *const msdp = (USBHMassStorageDriver *)drv;
USBHMassStorageLUNDriver *lunp = msdp->luns;
osalMutexLock(&msdp->mtx);
osalSysLock();
usbhEPCloseS(&msdp->epin);
usbhEPCloseS(&msdp->epout);
while (lunp) {
lunp->state = BLK_STOP;
lunp = lunp->next;
}
osalSysUnlock();
osalMutexUnlock(&msdp->mtx);
/* now that the LUNs are idle, deinit them */
lunp = msdp->luns;
osalSysLock();
while (lunp) {
usbhmsdLUNObjectInit(lunp);
lunp = lunp->next;
}
osalSysUnlock();
}
/*===========================================================================*/
/* MSD Class driver operations (Bulk-Only transport) */
/*===========================================================================*/
/* USB Bulk Only Transport SCSI Command block wrapper */
PACKED_STRUCT {
uint32_t dCBWSignature;
uint32_t dCBWTag;
uint32_t dCBWDataTransferLength;
uint8_t bmCBWFlags;
uint8_t bCBWLUN;
uint8_t bCBWCBLength;
uint8_t CBWCB[16];
} msd_cbw_t;
#define MSD_CBW_SIGNATURE 0x43425355
#define MSD_CBWFLAGS_D2H 0x80
#define MSD_CBWFLAGS_H2D 0x00
/* USB Bulk Only Transport SCSI Command status wrapper */
PACKED_STRUCT {
uint32_t dCSWSignature;
uint32_t dCSWTag;
uint32_t dCSWDataResidue;
uint8_t bCSWStatus;
} msd_csw_t;
#define MSD_CSW_SIGNATURE 0x53425355
typedef union {
msd_cbw_t cbw;
msd_csw_t csw;
} msd_transaction_t;
typedef enum {
MSD_TRANSACTIONRESULT_OK,
MSD_TRANSACTIONRESULT_DISCONNECTED,
MSD_TRANSACTIONRESULT_STALL,
MSD_TRANSACTIONRESULT_BUS_ERROR,
MSD_TRANSACTIONRESULT_SYNC_ERROR
} msd_transaction_result_t;
typedef enum {
MSD_COMMANDRESULT_PASSED = 0,
MSD_COMMANDRESULT_FAILED = 1,
MSD_COMMANDRESULT_PHASE_ERROR = 2
} msd_command_result_t;
typedef struct {
msd_transaction_result_t tres;
msd_command_result_t cres;
} msd_result_t;
/* ----------------------------------------------------- */
/* SCSI Commands */
/* ----------------------------------------------------- */
/* Read 10 and Write 10 */
#define SCSI_CMD_READ_10 0x28
#define SCSI_CMD_WRITE_10 0x2A
/* Request sense */
#define SCSI_CMD_REQUEST_SENSE 0x03
PACKED_STRUCT {
uint8_t byte[18];
} scsi_sense_response_t;
#define SCSI_SENSE_KEY_GOOD 0x00
#define SCSI_SENSE_KEY_RECOVERED_ERROR 0x01
#define SCSI_SENSE_KEY_NOT_READY 0x02
#define SCSI_SENSE_KEY_MEDIUM_ERROR 0x03
#define SCSI_SENSE_KEY_HARDWARE_ERROR 0x04
#define SCSI_SENSE_KEY_ILLEGAL_REQUEST 0x05
#define SCSI_SENSE_KEY_UNIT_ATTENTION 0x06
#define SCSI_SENSE_KEY_DATA_PROTECT 0x07
#define SCSI_SENSE_KEY_BLANK_CHECK 0x08
#define SCSI_SENSE_KEY_VENDOR_SPECIFIC 0x09
#define SCSI_SENSE_KEY_COPY_ABORTED 0x0A
#define SCSI_SENSE_KEY_ABORTED_COMMAND 0x0B
#define SCSI_SENSE_KEY_VOLUME_OVERFLOW 0x0D
#define SCSI_SENSE_KEY_MISCOMPARE 0x0E
#define SCSI_ASENSE_NO_ADDITIONAL_INFORMATION 0x00
#define SCSI_ASENSE_LOGICAL_UNIT_NOT_READY 0x04
#define SCSI_ASENSE_INVALID_FIELD_IN_CDB 0x24
#define SCSI_ASENSE_NOT_READY_TO_READY_CHANGE 0x28
#define SCSI_ASENSE_WRITE_PROTECTED 0x27
#define SCSI_ASENSE_FORMAT_ERROR 0x31
#define SCSI_ASENSE_INVALID_COMMAND 0x20
#define SCSI_ASENSE_LOGICAL_BLOCK_ADDRESS_OUT_OF_RANGE 0x21
#define SCSI_ASENSE_MEDIUM_NOT_PRESENT 0x3A
#define SCSI_ASENSEQ_NO_QUALIFIER 0x00
#define SCSI_ASENSEQ_FORMAT_COMMAND_FAILED 0x01
#define SCSI_ASENSEQ_INITIALIZING_COMMAND_REQUIRED 0x02
#define SCSI_ASENSEQ_OPERATION_IN_PROGRESS 0x07
/* Inquiry */
#define SCSI_CMD_INQUIRY 0x12
PACKED_STRUCT {
uint8_t peripheral;
uint8_t removable;
uint8_t version;
uint8_t response_data_format;
uint8_t additional_length;
uint8_t sccstp;
uint8_t bqueetc;
uint8_t cmdque;
uint8_t vendorID[8];
uint8_t productID[16];
uint8_t productRev[4];
} scsi_inquiry_response_t;
/* Read Capacity 10 */
#define SCSI_CMD_READ_CAPACITY_10 0x25
PACKED_STRUCT {
uint32_t last_block_addr;
uint32_t block_size;
} scsi_readcapacity10_response_t;
/* Start/Stop Unit */
#define SCSI_CMD_START_STOP_UNIT 0x1B
PACKED_STRUCT {
uint8_t op_code;
uint8_t lun_immed;
uint8_t res1;
uint8_t res2;
uint8_t loej_start;
uint8_t control;
} scsi_startstopunit_request_t;
/* test unit ready */
#define SCSI_CMD_TEST_UNIT_READY 0x00
/* Other commands, TODO: use or remove them
#define SCSI_CMD_PREVENT_ALLOW_MEDIUM_REMOVAL 0x1E
#define SCSI_CMD_VERIFY_10 0x2F
#define SCSI_CMD_SEND_DIAGNOSTIC 0x1D
#define SCSI_CMD_MODE_SENSE_6 0x1A
*/
static inline void _prepare_cbw(msd_transaction_t *tran, USBHMassStorageLUNDriver *lunp) {
tran->cbw.bCBWLUN = (uint8_t)(lunp - &lunp->msdp->luns[0]);
memset(&tran->cbw.CBWCB, 0, sizeof(tran->cbw.CBWCB));
}
static msd_transaction_result_t _msd_transaction(msd_transaction_t *tran, USBHMassStorageLUNDriver *lunp, void *data) {
uint32_t actual_len;
usbh_urbstatus_t status;
tran->cbw.dCBWSignature = MSD_CBW_SIGNATURE;
tran->cbw.dCBWTag = ++lunp->msdp->tag;
/* control phase */
status = usbhBulkTransfer(&lunp->msdp->epout, &tran->cbw,
sizeof(tran->cbw), &actual_len, MS2ST(1000));
if (status == USBH_URBSTATUS_CANCELLED) {
uerr("\tMSD: Control phase: USBH_URBSTATUS_CANCELLED");
return MSD_TRANSACTIONRESULT_DISCONNECTED;
} else if (status == USBH_URBSTATUS_STALL) {
uerr("\tMSD: Control phase: USBH_URBSTATUS_STALL");
return MSD_TRANSACTIONRESULT_STALL;
} else if (status != USBH_URBSTATUS_OK) {
uerrf("\tMSD: Control phase: status = %d, != OK", status);
return MSD_TRANSACTIONRESULT_BUS_ERROR;
} else if (actual_len != sizeof(tran->cbw)) {
uerrf("\tMSD: Control phase: wrong actual_len = %d", actual_len);
return MSD_TRANSACTIONRESULT_BUS_ERROR;
}
/* data phase */
if (tran->cbw.dCBWDataTransferLength) {
status = usbhBulkTransfer(
tran->cbw.bmCBWFlags & MSD_CBWFLAGS_D2H ? &lunp->msdp->epin : &lunp->msdp->epout,
data,
tran->cbw.dCBWDataTransferLength,
&actual_len, MS2ST(20000));
if (status == USBH_URBSTATUS_CANCELLED) {
uerr("\tMSD: Data phase: USBH_URBSTATUS_CANCELLED");
return MSD_TRANSACTIONRESULT_DISCONNECTED;
} else if (status == USBH_URBSTATUS_STALL) {
uerr("\tMSD: Data phase: USBH_URBSTATUS_STALL");
return MSD_TRANSACTIONRESULT_STALL;
} else if (status != USBH_URBSTATUS_OK) {
uerrf("\tMSD: Data phase: status = %d, != OK", status);
return MSD_TRANSACTIONRESULT_BUS_ERROR;
} else if (actual_len != tran->cbw.dCBWDataTransferLength) {
uerrf("\tMSD: Data phase: wrong actual_len = %d", actual_len);
return MSD_TRANSACTIONRESULT_BUS_ERROR;
}
}
/* status phase */
status = usbhBulkTransfer(&lunp->msdp->epin, &tran->csw,
sizeof(tran->csw), &actual_len, MS2ST(1000));
if (status == USBH_URBSTATUS_CANCELLED) {
uerr("\tMSD: Status phase: USBH_URBSTATUS_CANCELLED");
return MSD_TRANSACTIONRESULT_DISCONNECTED;
} else if (status == USBH_URBSTATUS_STALL) {
uerr("\tMSD: Status phase: USBH_URBSTATUS_STALL");
return MSD_TRANSACTIONRESULT_STALL;
} else if (status != USBH_URBSTATUS_OK) {
uerrf("\tMSD: Status phase: status = %d, != OK", status);
return MSD_TRANSACTIONRESULT_BUS_ERROR;
} else if (actual_len != sizeof(tran->csw)) {
uerrf("\tMSD: Status phase: wrong actual_len = %d", actual_len);
return MSD_TRANSACTIONRESULT_BUS_ERROR;
} else if (tran->csw.dCSWSignature != MSD_CSW_SIGNATURE) {
uerr("\tMSD: Status phase: wrong signature");
return MSD_TRANSACTIONRESULT_BUS_ERROR;
} else if (tran->csw.dCSWTag != lunp->msdp->tag) {
uerrf("\tMSD: Status phase: wrong tag (expected %d, got %d)",
lunp->msdp->tag, tran->csw.dCSWTag);
return MSD_TRANSACTIONRESULT_SYNC_ERROR;
}
if (tran->csw.dCSWDataResidue) {
uwarnf("\tMSD: Residue=%d", tran->csw.dCSWDataResidue);
}
return MSD_TRANSACTIONRESULT_OK;
}
static msd_result_t scsi_inquiry(USBHMassStorageLUNDriver *lunp, scsi_inquiry_response_t *resp) {
msd_transaction_t transaction;
msd_result_t res;
_prepare_cbw(&transaction, lunp);
transaction.cbw.dCBWDataTransferLength = sizeof(scsi_inquiry_response_t);
transaction.cbw.bmCBWFlags = MSD_CBWFLAGS_D2H;
transaction.cbw.bCBWCBLength = 6;
transaction.cbw.CBWCB[0] = SCSI_CMD_INQUIRY;
transaction.cbw.CBWCB[4] = sizeof(scsi_inquiry_response_t);
res.tres = _msd_transaction(&transaction, lunp, resp);
if (res.tres == MSD_TRANSACTIONRESULT_OK) {
res.cres = (msd_command_result_t) transaction.csw.bCSWStatus;
}
return res;
}
static msd_result_t scsi_requestsense(USBHMassStorageLUNDriver *lunp, scsi_sense_response_t *resp) {
msd_transaction_t transaction;
msd_result_t res;
_prepare_cbw(&transaction, lunp);
transaction.cbw.dCBWDataTransferLength = sizeof(scsi_sense_response_t);
transaction.cbw.bmCBWFlags = MSD_CBWFLAGS_D2H;
transaction.cbw.bCBWCBLength = 12;
transaction.cbw.CBWCB[0] = SCSI_CMD_REQUEST_SENSE;
transaction.cbw.CBWCB[4] = sizeof(scsi_sense_response_t);
res.tres = _msd_transaction(&transaction, lunp, resp);
if (res.tres == MSD_TRANSACTIONRESULT_OK) {
res.cres = (msd_command_result_t) transaction.csw.bCSWStatus;
}
return res;
}
static msd_result_t scsi_testunitready(USBHMassStorageLUNDriver *lunp) {
msd_transaction_t transaction;
msd_result_t res;
_prepare_cbw(&transaction, lunp);
transaction.cbw.dCBWDataTransferLength = 0;
transaction.cbw.bmCBWFlags = MSD_CBWFLAGS_D2H;
transaction.cbw.bCBWCBLength = 6;
transaction.cbw.CBWCB[0] = SCSI_CMD_TEST_UNIT_READY;
res.tres = _msd_transaction(&transaction, lunp, NULL);
if (res.tres == MSD_TRANSACTIONRESULT_OK) {
res.cres = (msd_command_result_t) transaction.csw.bCSWStatus;
}
return res;
}
static msd_result_t scsi_readcapacity10(USBHMassStorageLUNDriver *lunp, scsi_readcapacity10_response_t *resp) {
msd_transaction_t transaction;
msd_result_t res;
_prepare_cbw(&transaction, lunp);
transaction.cbw.dCBWDataTransferLength = sizeof(scsi_readcapacity10_response_t);
transaction.cbw.bmCBWFlags = MSD_CBWFLAGS_D2H;
transaction.cbw.bCBWCBLength = 12;
transaction.cbw.CBWCB[0] = SCSI_CMD_READ_CAPACITY_10;
res.tres = _msd_transaction(&transaction, lunp, resp);
if (res.tres == MSD_TRANSACTIONRESULT_OK) {
res.cres = (msd_command_result_t) transaction.csw.bCSWStatus;
}
return res;
}
static msd_result_t scsi_read10(USBHMassStorageLUNDriver *lunp, uint32_t lba, uint16_t n, uint8_t *data) {
msd_transaction_t transaction;
msd_result_t res;
_prepare_cbw(&transaction, lunp);
transaction.cbw.dCBWDataTransferLength = n * lunp->info.blk_size;
transaction.cbw.bmCBWFlags = MSD_CBWFLAGS_D2H;
transaction.cbw.bCBWCBLength = 10;
transaction.cbw.CBWCB[0] = SCSI_CMD_READ_10;
transaction.cbw.CBWCB[2] = (uint8_t)(lba >> 24);
transaction.cbw.CBWCB[3] = (uint8_t)(lba >> 16);
transaction.cbw.CBWCB[4] = (uint8_t)(lba >> 8);
transaction.cbw.CBWCB[5] = (uint8_t)(lba);
transaction.cbw.CBWCB[7] = (uint8_t)(n >> 8);
transaction.cbw.CBWCB[8] = (uint8_t)(n);
res.tres = _msd_transaction(&transaction, lunp, data);
if (res.tres == MSD_TRANSACTIONRESULT_OK) {
res.cres = (msd_command_result_t) transaction.csw.bCSWStatus;
}
return res;
}
static msd_result_t scsi_write10(USBHMassStorageLUNDriver *lunp, uint32_t lba, uint16_t n, const uint8_t *data) {
msd_transaction_t transaction;
msd_result_t res;
_prepare_cbw(&transaction, lunp);
transaction.cbw.dCBWDataTransferLength = n * lunp->info.blk_size;
transaction.cbw.bmCBWFlags = MSD_CBWFLAGS_H2D;
transaction.cbw.bCBWCBLength = 10;
transaction.cbw.CBWCB[0] = SCSI_CMD_WRITE_10;
transaction.cbw.CBWCB[2] = (uint8_t)(lba >> 24);
transaction.cbw.CBWCB[3] = (uint8_t)(lba >> 16);
transaction.cbw.CBWCB[4] = (uint8_t)(lba >> 8);
transaction.cbw.CBWCB[5] = (uint8_t)(lba);
transaction.cbw.CBWCB[7] = (uint8_t)(n >> 8);
transaction.cbw.CBWCB[8] = (uint8_t)(n);
res.tres = _msd_transaction(&transaction, lunp, (uint8_t *)data);
if (res.tres == MSD_TRANSACTIONRESULT_OK) {
res.cres = (msd_command_result_t) transaction.csw.bCSWStatus;
}
return res;
}
/*===========================================================================*/
/* Block driver data/functions */
/*===========================================================================*/
USBHMassStorageLUNDriver MSBLKD[HAL_USBHMSD_MAX_LUNS];
static const struct USBHMassStorageDriverVMT blk_vmt = {
(bool (*)(void *))usbhmsdLUNIsInserted,
(bool (*)(void *))usbhmsdLUNIsProtected,
(bool (*)(void *))usbhmsdLUNConnect,
(bool (*)(void *))usbhmsdLUNDisconnect,
(bool (*)(void *, uint32_t, uint8_t *, uint32_t))usbhmsdLUNRead,
(bool (*)(void *, uint32_t, const uint8_t *, uint32_t))usbhmsdLUNWrite,
(bool (*)(void *))usbhmsdLUNSync,
(bool (*)(void *, BlockDeviceInfo *))usbhmsdLUNGetInfo
};
static uint32_t _requestsense(USBHMassStorageLUNDriver *lunp) {
scsi_sense_response_t sense;
msd_result_t res;
res = scsi_requestsense(lunp, &sense);
if (res.tres != MSD_TRANSACTIONRESULT_OK) {
uerr("\tREQUEST SENSE: Transaction error");
goto failed;
} else if (res.cres == MSD_COMMANDRESULT_FAILED) {
uerr("\tREQUEST SENSE: Command Failed");
goto failed;
} else if (res.cres == MSD_COMMANDRESULT_PHASE_ERROR) {
//TODO: Do reset, etc.
uerr("\tREQUEST SENSE: Command Phase Error");
goto failed;
}
uerrf("\tREQUEST SENSE: Sense key=%x, ASC=%02x, ASCQ=%02x",
sense.byte[2] & 0xf, sense.byte[12], sense.byte[13]);
return (sense.byte[2] & 0xf) | (sense.byte[12] << 8) | (sense.byte[13] << 16);
failed:
return 0xffffffff;
}
void usbhmsdLUNObjectInit(USBHMassStorageLUNDriver *lunp) {
osalDbgCheck(lunp != NULL);
memset(lunp, 0, sizeof(*lunp));
lunp->vmt = &blk_vmt;
lunp->state = BLK_STOP;
/* Unnecessary because of the memset:
lunp->msdp = NULL;
lunp->next = NULL;
lunp->info.* = 0;
*/
}
void usbhmsdLUNStart(USBHMassStorageLUNDriver *lunp) {
osalDbgCheck(lunp != NULL);
osalSysLock();
osalDbgAssert((lunp->state == BLK_STOP) || (lunp->state == BLK_ACTIVE),
"invalid state");
//TODO: complete
//lunp->state = BLK_ACTIVE;
osalSysUnlock();
}
void usbhmsdLUNStop(USBHMassStorageLUNDriver *lunp) {
osalDbgCheck(lunp != NULL);
osalSysLock();
osalDbgAssert((lunp->state == BLK_STOP) || (lunp->state == BLK_ACTIVE),
"invalid state");
//TODO: complete
//lunp->state = BLK_STOP;
osalSysUnlock();
}
bool usbhmsdLUNConnect(USBHMassStorageLUNDriver *lunp) {
USBHMassStorageDriver *const msdp = lunp->msdp;
msd_result_t res;
osalDbgCheck(msdp != NULL);
osalSysLock();
//osalDbgAssert((lunp->state == BLK_ACTIVE) || (lunp->state == BLK_READY),
// "invalid state");
if (lunp->state == BLK_READY) {
osalSysUnlock();
return HAL_SUCCESS;
} else if (lunp->state != BLK_ACTIVE) {
osalSysUnlock();
return HAL_FAILED;
}
lunp->state = BLK_CONNECTING;
osalSysUnlock();
osalMutexLock(&msdp->mtx);
USBH_DEFINE_BUFFER(union {
scsi_inquiry_response_t inq;
scsi_readcapacity10_response_t cap; }, u);
uinfo("INQUIRY...");
res = scsi_inquiry(lunp, &u.inq);
if (res.tres != MSD_TRANSACTIONRESULT_OK) {
uerr("\tINQUIRY: Transaction error");
goto failed;
} else if (res.cres == MSD_COMMANDRESULT_FAILED) {
uerr("\tINQUIRY: Command Failed");
_requestsense(lunp);
goto failed;
} else if (res.cres == MSD_COMMANDRESULT_PHASE_ERROR) {
//TODO: Do reset, etc.
uerr("\tINQUIRY: Command Phase Error");
goto failed;
}
uinfof("\tPDT=%02x", u.inq.peripheral & 0x1f);
if (u.inq.peripheral != 0) {
uerr("\tUnsupported PDT");
goto failed;
}
// Test if unit ready
uint8_t i;
for (i = 0; i < 10; i++) {
uinfo("TEST UNIT READY...");
res = scsi_testunitready(lunp);
if (res.tres != MSD_TRANSACTIONRESULT_OK) {
uerr("\tTEST UNIT READY: Transaction error");
goto failed;
} else if (res.cres == MSD_COMMANDRESULT_FAILED) {
uerr("\tTEST UNIT READY: Command Failed");
_requestsense(lunp);
continue;
} else if (res.cres == MSD_COMMANDRESULT_PHASE_ERROR) {
//TODO: Do reset, etc.
uerr("\tTEST UNIT READY: Command Phase Error");
goto failed;
}
uinfo("\tReady.");
break;
// osalThreadSleepMilliseconds(200); // will raise 'code is unreachable' warning
}
if (i == 10) goto failed;
// Read capacity
uinfo("READ CAPACITY(10)...");
res = scsi_readcapacity10(lunp, &u.cap);
if (res.tres != MSD_TRANSACTIONRESULT_OK) {
uerr("\tREAD CAPACITY(10): Transaction error");
goto failed;
} else if (res.cres == MSD_COMMANDRESULT_FAILED) {
uerr("\tREAD CAPACITY(10): Command Failed");
_requestsense(lunp);
goto failed;
} else if (res.cres == MSD_COMMANDRESULT_PHASE_ERROR) {
//TODO: Do reset, etc.
uerr("\tREAD CAPACITY(10): Command Phase Error");
goto failed;
}
lunp->info.blk_size = __REV(u.cap.block_size);
lunp->info.blk_num = __REV(u.cap.last_block_addr) + 1;
uinfof("\tBlock size=%dbytes, blocks=%u (~%u MB)", lunp->info.blk_size, lunp->info.blk_num,
(uint32_t)(((uint64_t)lunp->info.blk_size * lunp->info.blk_num) / (1024UL * 1024UL)));
uinfo("MSD Connected.");
osalMutexUnlock(&msdp->mtx);
osalSysLock();
lunp->state = BLK_READY;
osalSysUnlock();
return HAL_SUCCESS;
/* Connection failed, state reset to BLK_ACTIVE.*/
failed:
osalMutexUnlock(&msdp->mtx);
osalSysLock();
lunp->state = BLK_ACTIVE;
osalSysUnlock();
return HAL_FAILED;
}
bool usbhmsdLUNDisconnect(USBHMassStorageLUNDriver *lunp) {
osalDbgCheck(lunp != NULL);
osalSysLock();
osalDbgAssert((lunp->state == BLK_ACTIVE) || (lunp->state == BLK_READY),
"invalid state");
if (lunp->state == BLK_ACTIVE) {
osalSysUnlock();
return HAL_SUCCESS;
}
lunp->state = BLK_DISCONNECTING;
osalSysUnlock();
//TODO: complete
osalSysLock();
lunp->state = BLK_ACTIVE;
osalSysUnlock();
return HAL_SUCCESS;
}
bool usbhmsdLUNRead(USBHMassStorageLUNDriver *lunp, uint32_t startblk,
uint8_t *buffer, uint32_t n) {
osalDbgCheck(lunp != NULL);
bool ret = HAL_FAILED;
uint16_t blocks;
msd_result_t res;
osalSysLock();
if (lunp->state != BLK_READY) {
osalSysUnlock();
return ret;
}
lunp->state = BLK_READING;
osalSysUnlock();
osalMutexLock(&lunp->msdp->mtx);
while (n) {
if (n > 0xffff) {
blocks = 0xffff;
} else {
blocks = (uint16_t)n;
}
res = scsi_read10(lunp, startblk, blocks, buffer);
if (res.tres != MSD_TRANSACTIONRESULT_OK) {
uerr("\tREAD (10): Transaction error");
goto exit;
} else if (res.cres == MSD_COMMANDRESULT_FAILED) {
//TODO: request sense, and act appropriately
uerr("\tREAD (10): Command Failed");
_requestsense(lunp);
goto exit;
} else if (res.cres == MSD_COMMANDRESULT_PHASE_ERROR) {
//TODO: Do reset, etc.
uerr("\tREAD (10): Command Phase Error");
goto exit;
}
n -= blocks;
startblk += blocks;
buffer += blocks * lunp->info.blk_size;
}
ret = HAL_SUCCESS;
exit:
osalMutexUnlock(&lunp->msdp->mtx);
osalSysLock();
if (lunp->state == BLK_READING) {
lunp->state = BLK_READY;
} else {
osalDbgCheck(lunp->state == BLK_STOP);
uwarn("MSD: State = BLK_STOP");
}
osalSysUnlock();
return ret;
}
bool usbhmsdLUNWrite(USBHMassStorageLUNDriver *lunp, uint32_t startblk,
const uint8_t *buffer, uint32_t n) {
osalDbgCheck(lunp != NULL);
bool ret = HAL_FAILED;
uint16_t blocks;
msd_result_t res;
osalSysLock();
if (lunp->state != BLK_READY) {
osalSysUnlock();
return ret;
}
lunp->state = BLK_WRITING;
osalSysUnlock();
osalMutexLock(&lunp->msdp->mtx);
while (n) {
if (n > 0xffff) {
blocks = 0xffff;
} else {
blocks = (uint16_t)n;
}
res = scsi_write10(lunp, startblk, blocks, buffer);
if (res.tres != MSD_TRANSACTIONRESULT_OK) {
uerr("\tWRITE (10): Transaction error");
goto exit;
} else if (res.cres == MSD_COMMANDRESULT_FAILED) {
//TODO: request sense, and act appropriately
uerr("\tWRITE (10): Command Failed");
_requestsense(lunp);
goto exit;
} else if (res.cres == MSD_COMMANDRESULT_PHASE_ERROR) {
//TODO: Do reset, etc.
uerr("\tWRITE (10): Command Phase Error");
goto exit;
}
n -= blocks;
startblk += blocks;
buffer += blocks * lunp->info.blk_size;
}
ret = HAL_SUCCESS;
exit:
osalMutexUnlock(&lunp->msdp->mtx);
osalSysLock();
if (lunp->state == BLK_WRITING) {
lunp->state = BLK_READY;
} else {
osalDbgCheck(lunp->state == BLK_STOP);
uwarn("MSD: State = BLK_STOP");
}
osalSysUnlock();
return ret;
}
bool usbhmsdLUNSync(USBHMassStorageLUNDriver *lunp) {
osalDbgCheck(lunp != NULL);
(void)lunp;
//TODO: Do SCSI Sync
return HAL_SUCCESS;
}
bool usbhmsdLUNGetInfo(USBHMassStorageLUNDriver *lunp, BlockDeviceInfo *bdip) {
osalDbgCheck(lunp != NULL);
osalDbgCheck(bdip != NULL);
*bdip = lunp->info;
return HAL_SUCCESS;
}
bool usbhmsdLUNIsInserted(USBHMassStorageLUNDriver *lunp) {
osalDbgCheck(lunp != NULL);
blkstate_t state;
osalSysLock();
state = lunp->state;
osalSysUnlock();
return (state >= BLK_ACTIVE);
}
bool usbhmsdLUNIsProtected(USBHMassStorageLUNDriver *lunp) {
osalDbgCheck(lunp != NULL);
return FALSE;
}
void usbhmsdObjectInit(USBHMassStorageDriver *msdp) {
osalDbgCheck(msdp != NULL);
memset(msdp, 0, sizeof(*msdp));
msdp->info = &usbhmsdClassDriverInfo;
osalMutexObjectInit(&msdp->mtx);
}
#endif

View File

@ -0,0 +1,89 @@
/*
ChibiOS - Copyright (C) 2006..2015 Giovanni Di Sirio
Copyright (C) 2015 Diego Ismirlian, TISA, (dismirlian (at) google's mail)
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.
*/
#include "hal.h"
#include "usbh.h"
#if HAL_USBH_USE_UVC
#if !HAL_USE_USBH
#error "USBHUVC needs HAL_USE_USBH"
#endif
#if !HAL_USBH_USE_IAD
#error "USBHUVC needs HAL_USBH_USE_IAD"
#endif
#if USBHUVC_DEBUG_ENABLE_TRACE
#define udbgf(f, ...) usbDbgPrintf(f, ##__VA_ARGS__)
#define udbg(f, ...) usbDbgPuts(f, ##__VA_ARGS__)
#else
#define udbgf(f, ...) do {} while(0)
#define udbg(f, ...) do {} while(0)
#endif
#if USBHUVC_DEBUG_ENABLE_INFO
#define uinfof(f, ...) usbDbgPrintf(f, ##__VA_ARGS__)
#define uinfo(f, ...) usbDbgPuts(f, ##__VA_ARGS__)
#else
#define uinfof(f, ...) do {} while(0)
#define uinfo(f, ...) do {} while(0)
#endif
#if USBHUVC_DEBUG_ENABLE_WARNINGS
#define uwarnf(f, ...) usbDbgPrintf(f, ##__VA_ARGS__)
#define uwarn(f, ...) usbDbgPuts(f, ##__VA_ARGS__)
#else
#define uwarnf(f, ...) do {} while(0)
#define uwarn(f, ...) do {} while(0)
#endif
#if USBHUVC_DEBUG_ENABLE_ERRORS
#define uerrf(f, ...) usbDbgPrintf(f, ##__VA_ARGS__)
#define uerr(f, ...) usbDbgPuts(f, ##__VA_ARGS__)
#else
#define uerrf(f, ...) do {} while(0)
#define uerr(f, ...) do {} while(0)
#endif
static usbh_baseclassdriver_t *uvc_load(usbh_device_t *dev,
const uint8_t *descriptor, uint16_t rem);
static void uvc_unload(usbh_baseclassdriver_t *drv);
static const usbh_classdriver_vmt_t class_driver_vmt = {
uvc_load,
uvc_unload
};
const usbh_classdriverinfo_t usbhuvcClassDriverInfo = {
0x0e, 0x03, 0x00, "UVC", &class_driver_vmt
};
static usbh_baseclassdriver_t *uvc_load(usbh_device_t *dev, const uint8_t *descriptor, uint16_t rem) {
(void)dev;
(void)descriptor;
(void)rem;
return NULL;
}
static void uvc_unload(usbh_baseclassdriver_t *drv) {
(void)drv;
}
#endif

146
os/various/bswap.h Normal file
View File

@ -0,0 +1,146 @@
/*
Copyright (C) 2016 Stephane D'Alu
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.
*/
#ifndef BSWAP_H
#define BSWAP_H
#if defined(__cplusplus)
extern "C" {
#endif
#if !(defined(ARCH_BIG_ENDIAN) || defined(ARCH_LITTLE_ENDIAN))
#error "Need to define one: ARCH_BIG_ENDIAN or ARCH_LITTLE_ENDIAN"
#endif
#if defined(ARCH_BIG_ENDIAN) && defined(ARCH_LITTLE_ENDIAN)
#error "ARCH_BIG_ENDIAN and ARCH_LITTLE_ENDIAN are both set"
#endif
#define BSWAP_16(x) \
(uint16_t)((((x) & 0xFF00) >> 8) | \
(((x) & 0x00FF) << 8))
#define BSWAP_32(x) \
(uint32_t)((((x) & 0xFF000000UL) >> 24UL) | \
(((x) & 0x00FF0000UL) >> 8UL) | \
(((x) & 0x0000FF00UL) << 8UL) | \
(((x) & 0x000000FFUL) << 24UL))
#if defined(ARCH_BIG_ENDIAN)
#define le16_to_cpu(x) bswap_16(x)
#define le32_to_cpu(x) bswap_32(x)
#define be16_to_cpu(x) (x)
#define be32_to_cpu(x) (x)
#define cpu_to_le16(x) bswap_16(x)
#define cpu_to_le32(x) bswap_32(x)
#define cpu_to_be16(x) (x)
#define cpu_to_be32(x) (x)
#define LE16_TO_CPU(x) BSWAP_16(x)
#define LE32_TO_CPU(x) BSWAP_32(x)
#define BE16_TO_CPU(x) (x)
#define BE32_TO_CPU(x) (x)
#define CPU_TO_LE16(x) BSWAP_16(x)
#define CPU_TO_LE32(x) BSWAP_32(x)
#define CPU_TO_BE16(x) (x)
#define CPU_TO_BE32(x) (x)
#endif
#if defined(ARCH_LITTLE_ENDIAN)
#define le16_to_cpu(x) (x)
#define le32_to_cpu(x) (x)
#define be16_to_cpu(x) bswap_16(x)
#define be32_to_cpu(x) bswap_32(x)
#define cpu_to_le16(x) (x)
#define cpu_to_le32(x) (x)
#define cpu_to_be16(x) bswap_16(x)
#define cpu_to_be32(x) bswap_32(x)
#define LE16_TO_CPU(x) (x)
#define LE32_TO_CPU(x) (x)
#define BE16_TO_CPU(x) BSWAP_16(x)
#define BE32_TO_CPU(x) BSWAP_32(x)
#define CPU_TO_LE16(x) (x)
#define CPU_TO_LE32(x) (x)
#define CPU_TO_BE16(x) BSWAP_16(x)
#define CPU_TO_BE32(x) BSWAP_32(x)
#endif
static inline uint16_t bswap_16(const uint16_t x)
__attribute__ ((warn_unused_result))
__attribute__ ((const))
__attribute__ ((always_inline));
static inline uint16_t bswap_16(const uint16_t x) {
if (__builtin_constant_p(x))
return BSWAP_16(x);
uint8_t tmp;
union { uint16_t x; uint8_t b[2]; } data;
data.x = x;
tmp = data.b[0];
data.b[0] = data.b[1];
data.b[1] = tmp;
return data.x;
}
static inline uint32_t bswap_32(const uint32_t x)
__attribute__ ((warn_unused_result))
__attribute__ ((const))
__attribute__ ((always_inline));
static inline uint32_t bswap_32(const uint32_t x) {
if (__builtin_constant_p(x))
return BSWAP_32(x);
uint8_t tmp;
union { uint32_t x; uint8_t b[4]; } data;
data.x = x;
tmp = data.b[0];
data.b[0] = data.b[3];
data.b[3] = tmp;
tmp = data.b[1];
data.b[1] = data.b[2];
data.b[2] = tmp;
return data.x;
}
static inline void bswap_n(void* const data, uint8_t len)
__attribute__ ((nonnull (1)));
static inline void bswap_n(void* const data, uint8_t len) {
uint8_t* ptr = (uint8_t*)data;
for ( ; len > 1 ; ptr++, len -= 2 ) {
uint8_t tmp = *ptr;
*ptr = *(ptr + len - 1);
*(ptr + len - 1) = tmp;
}
}
#if defined(__cplusplus)
}
#endif
#endif

View File

@ -0,0 +1,265 @@
/*
HDC100x for ChibiOS/RT - Copyright (C) 2016 Stephane D'Alu
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.
*/
/**
* @file HDC1000.c
* @brief HDC1000 interface module code.
*
* @addtogroup hdc1000
* @{
*/
#define I2C_HELPERS_AUTOMATIC_DRV TRUE
#include "hal.h"
#include "i2c_helpers.h"
#include "hdc1000.h"
/* DOC: http://www.ti.com/lit/ds/symlink/hdc1008.pdf
*/
/*===========================================================================*/
/* Driver local definitions. */
/*===========================================================================*/
/* I2C Register */
#define HDC1000_REG_TEMP_HUMID 0x00
#define HDC1000_REG_TEMP 0x00
#define HDC1000_REG_HUMID 0x01
#define HDC1000_REG_CONFIG 0x02
#define HDC1000_REG_SERIAL 0xFB
#define HDC1000_REG_SERIAL_1 0xFB
#define HDC1000_REG_SERIAL_2 0xFC
#define HDC1000_REG_SERIAL_3 0xFD
#define HDC1000_REG_MANUF_ID 0xFE
#define HDC1000_REG_DEVICE_ID 0xFF
/* Configuration */
#define HDC1000_CONFIG_RST (1 << 15)
#define HDC1000_CONFIG_HEATER (1 << 13)
#define HDC1000_CONFIG_MODE_ONE (0 << 12)
#define HDC1000_CONFIG_MODE_BOTH (1 << 12)
#define HDC1000_CONFIG_BATT (1 << 11)
#define HDC1000_CONFIG_TRES_14 (0)
#define HDC1000_CONFIG_TRES_11 (1 << 10)
#define HDC1000_CONFIG_HRES_14 (0)
#define HDC1000_CONFIG_HRES_11 (1 << 8)
#define HDC1000_CONFIG_HRES_8 (1 << 9)
/* Value */
#define HDC1000_MANUF_ID 0x5449
#define HDC1000_DEVICE_ID 0x1000
/* Delay in micro seconds */
#define HDC1000_DELAY_ACQUIRE_SAFETY 1000
#define HDC1000_DELAY_ACQUIRE_TRES_14 6350
#define HDC1000_DELAY_ACQUIRE_TRES_11 3650
#define HDC1000_DELAY_ACQUIRE_HRES_14 6500
#define HDC1000_DELAY_ACQUIRE_HRES_11 3850
#define HDC1000_DELAY_ACQUIRE_HRES_8 2500
#define HDC1000_DELAY_STARTUP 15000
// Deefault config (high res)
#define HDC1000_CONFIG_RES (HDC1000_CONFIG_TRES_14 | \
HDC1000_CONFIG_HRES_14)
#define HDC1000_DELAY_ACQUIRE (HDC1000_DELAY_ACQUIRE_TRES_14 + \
HDC1000_DELAY_ACQUIRE_HRES_14)
/*===========================================================================*/
/* Driver exported variables. */
/*===========================================================================*/
/*===========================================================================*/
/* Driver local variables and types. */
/*===========================================================================*/
/*===========================================================================*/
/* Driver local functions. */
/*===========================================================================*/
static inline msg_t
_apply_config(HDC1000_drv *drv) {
struct __attribute__((packed)) {
uint8_t reg;
uint16_t conf;
} tx = { HDC1000_REG_CONFIG, cpu_to_be16(drv->cfg) };
return i2c_send((uint8_t*)&tx, sizeof(tx));
}
static inline msg_t
_decode_measure(HDC1000_drv *drv,
uint32_t val, float *temperature, float *humidity) {
(void)drv;
/* Temperature */
if (temperature) {
float temp = (val >> 16);
temp /= 65536;
temp *= 165;
temp -= 40;
*temperature = temp;
}
/* Humidiy */
if (humidity) {
float hum = (val & 0xFFFF);
hum /= 65535;
hum *= 100;
*humidity = hum;
}
/* ok */
return MSG_OK;
}
/*===========================================================================*/
/* Driver exported functions. */
/*===========================================================================*/
void
HDC1000_init(HDC1000_drv *drv, HDC1000_config *config) {
drv->config = config;
drv->cfg = HDC1000_CONFIG_RST | HDC1000_CONFIG_MODE_BOTH |
HDC1000_CONFIG_RES;
drv->delay = (HDC1000_DELAY_ACQUIRE +
HDC1000_DELAY_ACQUIRE_SAFETY) / 1000;
drv->state = SENSOR_INIT;
}
msg_t
HDC1000_check(HDC1000_drv *drv) {
uint16_t manuf, device;
msg_t msg;
if (((msg = i2c_reg_recv16_be(HDC1000_REG_MANUF_ID, &manuf )) < MSG_OK) ||
((msg = i2c_reg_recv16_be(HDC1000_REG_DEVICE_ID, &device)) < MSG_OK))
return msg;
if ((manuf != HDC1000_MANUF_ID) || (device != HDC1000_DEVICE_ID))
return SENSOR_NOTFOUND;
return MSG_OK;
}
msg_t
HDC1000_start(HDC1000_drv *drv) {
osalDbgAssert((drv->state == SENSOR_INIT ) ||
(drv->state == SENSOR_ERROR ) ||
(drv->state == SENSOR_STOPPED),
"invalid state");
msg_t msg;
if ((msg = _apply_config(drv)) < MSG_OK) {
drv->state = SENSOR_ERROR;
return msg;
}
drv->state = SENSOR_STARTED;
return MSG_OK;
}
msg_t
HDC1000_stop(HDC1000_drv *drv) {
drv->state = SENSOR_STOPPED;
return MSG_OK;
}
msg_t
HDC1000_setHeater(HDC1000_drv *drv, bool on) {
if (on) { drv->cfg |= HDC1000_CONFIG_HEATER; }
else { drv->cfg &= ~HDC1000_CONFIG_HEATER; }
msg_t msg;
if ((msg = _apply_config(drv)) < MSG_OK) {
drv->state = SENSOR_ERROR;
return msg;
}
return MSG_OK;
}
msg_t
HDC1000_startMeasure(HDC1000_drv *drv) {
msg_t msg;
osalDbgAssert(drv->state == SENSOR_STARTED, "invalid state");
if ((msg = i2c_reg(HDC1000_REG_TEMP_HUMID)) < MSG_OK)
return msg;
drv->state = SENSOR_MEASURING;
return MSG_OK;
}
msg_t
HDC1000_readSerial(HDC1000_drv *drv, uint8_t *serial) {
msg_t msg;
osalDbgAssert(drv->state == SENSOR_STARTED, "invalid state");
if (((msg = i2c_reg_recv16(HDC1000_REG_SERIAL_1,
(uint16_t*)&serial[0])) < MSG_OK) ||
((msg = i2c_reg_recv16(HDC1000_REG_SERIAL_2,
(uint16_t*)&serial[2])) < MSG_OK) ||
((msg = i2c_reg_recv8 (HDC1000_REG_SERIAL_3,
(uint8_t*) &serial[4])) < MSG_OK))
return msg;
return MSG_OK;
}
msg_t
HDC1000_readMeasure(HDC1000_drv *drv,
float *temperature, float *humidity) {
msg_t msg;
uint32_t val;
osalDbgAssert((drv->state == SENSOR_MEASURING) ||
(drv->state == SENSOR_READY ),
"invalid state");
if ((msg = i2c_recv32_be(&val)) < MSG_OK) {
drv->state = SENSOR_ERROR;
return msg;
}
drv->state = SENSOR_STARTED;
return _decode_measure(drv, val, temperature, humidity);
}
msg_t
HDC1000_readTemperatureHumidity(HDC1000_drv *drv,
float *temperature, float *humidity) {
msg_t msg;
uint32_t val;
osalDbgAssert(drv->state == SENSOR_STARTED, "invalid state");
/* Request value */
if ((msg = i2c_reg(HDC1000_REG_TEMP_HUMID)) < MSG_OK)
return msg;
/* Wait */
osalThreadSleepMilliseconds(drv->delay);
/* Get value */
if ((msg = i2c_recv32_be(&val)) < MSG_OK) {
drv->state = SENSOR_ERROR;
return msg;
}
return _decode_measure(drv, val, temperature, humidity);
}
/** @} */

View File

@ -0,0 +1,240 @@
/*
HDC100x for ChibiOS/RT - Copyright (C) 2016 Stephane D'Alu
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.
*/
/**
* @file hdc1000.h
* @brief HDC1000 Temperature/Humidiry sensor interface module header.
*
* When changing sensor settings, you generally need to wait
* for 2 * getAquisitionTime(), as usually the first acquisition
* will be corrupted by the change of settings.
*
* No locking is done.
*
* @{
*/
#ifndef _SENSOR_HDC1000_H_
#define _SENSOR_HDC1000_H_
#include <math.h>
#include <stdbool.h>
#include "i2c_helpers.h"
#include "sensor.h"
/*===========================================================================*/
/* Driver constants. */
/*===========================================================================*/
#define HDC1000_CONTINUOUS_ACQUISITION_SUPPORTED FALSE
/* I2C address */
#define HDC1000_I2CADDR_1 0x40
#define HDC1000_I2CADDR_2 0x41
#define HDC1000_I2CADDR_3 0x42
#define HDC1000_I2CADDR_4 0x43
#define HDC1000_SERIAL_SIZE 5 /**< @brief Size of serial (40bits) */
/**
* @brief Time necessary for the sensor to boot
*/
#define HDC1000_BOOTUP_TIME 15
/**
* @brief Time necessary for the sensor to start
*/
#define HDC1000_STARTUP_TIME 0
/*===========================================================================*/
/* Driver pre-compile time settings. */
/*===========================================================================*/
/*===========================================================================*/
/* Derived constants and error checks. */
/*===========================================================================*/
#define HDC1000_I2CADDR_DEFAULT HDC1000_I2CADDR_1
/*===========================================================================*/
/* Driver data structures and types. */
/*===========================================================================*/
/**
* @brief HDC1000 configuration structure.
*/
typedef struct {
I2CHelper i2c; /* keep it first */
} HDC1000_config;
/**
* @brief HDC1000 configuration structure.
*/
typedef struct {
HDC1000_config *config;
sensor_state_t state;
unsigned int delay;
uint16_t cfg;
} HDC1000_drv;
/*===========================================================================*/
/* Driver macros. */
/*===========================================================================*/
/*===========================================================================*/
/* External declarations. */
/*===========================================================================*/
/**
* @brief Initialize the sensor driver
*/
void
HDC1000_init(HDC1000_drv *drv,
HDC1000_config *config);
/**
* @brief Start the sensor
*/
msg_t
HDC1000_start(HDC1000_drv *drv);
/**
* @brief Stop the sensor
*
* @details If the sensor support it, it will be put in low energy mode.
*/
msg_t
HDC1000_stop(HDC1000_drv *drv);
/**
* @brief Check that the sensor is really present
*/
msg_t
HDC1000_check(HDC1000_drv *drv);
msg_t
HDC1000_readSerial(HDC1000_drv *drv, uint8_t *serial);
/**
* @brief Control the HD1000 heater.
*/
msg_t
HDC1000_setHeater(HDC1000_drv *drv,
bool on);
/**
* @brief Time in milli-seconds necessary for acquiring a naw measure
*
* @returns
* unsigned int time in millis-seconds
*/
static inline unsigned int
HDC1000_getAcquisitionTime(HDC1000_drv *drv) {
return drv->delay;
}
/**
* @brief Trigger a mesure acquisition
*/
msg_t
HDC1000_startMeasure(HDC1000_drv *drv);
/**
* @brief Read the newly acquiered measure
*
* @note According the the sensor design the measure read
* can be any value acquired after the acquisition time
* and the call to readMeasure.
*/
msg_t
HDC1000_readMeasure(HDC1000_drv *drv,
float *temperature, float *humidity);
/**
* @brief Read temperature and humidity
*
* @details According to the sensor specification/configuration
* (see #HDC1000_CONTINUOUS_ACQUISITION_SUPPORTED),
* if the sensor is doing continuous measurement
* it's value will be requested and returned immediately.
* Otherwise a measure is started, the necessary amount of
* time for acquiring the value is spend sleeping (not spinning),
* and finally the measure is read.
*
* @note In continuous measurement mode, if you just started
* the sensor, you will need to wait getAcquisitionTime()
* in addition to the usual #HDC1000_STARTUP_TIME
* @note If using several sensors, it is better to start all the
* measure together, wait for the sensor having the longuest
* aquisition time, and finally read all the values
*/
msg_t
HDC1000_readTemperatureHumidity(HDC1000_drv *drv,
float *temperature, float *humidity);
/**
* @brief Return the humidity value in percent.
*
* @details Use readTemperatureHumidity() for returning the humidity value.
*
* @note Prefere readTemperatureHumidity(), if you need both temperature
* and humidity, or if you need better error handling.
*
* @returns
* float humidity percent
* NAN on failure
*/
static inline float
HDC1000_getHumidity(HDC1000_drv *drv) {
float humidity = NAN;
HDC1000_readTemperatureHumidity(drv, NULL, &humidity);
return humidity;
}
/**
* @brief Return the temperature value in °C.
*
* @details Use readTemperatureHumidity() for returning the humidity value.
*
* @note Prefere readTemperatureHumidity(), if you need both temperature
* and humidity, or if you need better error handling.
*
* @returns
* float humidity percent
* NAN on failure
*/
static inline float
HDC1000_getTemperature(HDC1000_drv *drv) {
float temperature = NAN;
HDC1000_readTemperatureHumidity(drv, &temperature, NULL);
return temperature;
}
#endif
/**
* @}
*/

View File

@ -0,0 +1,207 @@
/*
MCP9808 for ChibiOS/RT - Copyright (C) 2016 Stephane D'Alu
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.
*/
#define I2C_HELPERS_AUTOMATIC_DRV TRUE
#include "hal.h"
#include "i2c_helpers.h"
#include "mcp9808.h"
// http://www.mouser.com/ds/2/268/25095A-15487.pdf
// http://ww1.microchip.com/downloads/en/DeviceDoc/25095A.pdf
/*===========================================================================*/
/* Driver local definitions. */
/*===========================================================================*/
/* I2C Register */
#define MCP9808_REG_CONFIG 0x01
#define MCP9808_REG_UPPER_TEMP 0x02
#define MCP9808_REG_LOWER_TEMP 0x03
#define MCP9808_REG_CRIT_TEMP 0x04
#define MCP9808_REG_AMBIENT_TEMP 0x05
#define MCP9808_REG_MANUF_ID 0x06
#define MCP9808_REG_DEVICE_ID 0x07
#define MCP9808_REG_RESOLUTION 0x08
/* Config */
#define MCP9808_REG_CONFIG_SHUTDOWN 0x0100
#define MCP9808_REG_CONFIG_CRITLOCKED 0x0080
#define MCP9808_REG_CONFIG_WINLOCKED 0x0040
#define MCP9808_REG_CONFIG_INTCLR 0x0020
#define MCP9808_REG_CONFIG_ALERTSTAT 0x0010
#define MCP9808_REG_CONFIG_ALERTCTRL 0x0008
#define MCP9808_REG_CONFIG_ALERTSEL 0x0002
#define MCP9808_REG_CONFIG_ALERTPOL 0x0002
#define MCP9808_REG_CONFIG_ALERTMODE 0x0001
/* Device Id */
#define MCP9808_MANUF_ID 0x0054
#define MCP9808_DEVICE_ID 0x0400
/* Resolution */
#define MCP9808_RES_2 0x00 /* 1/2 = 0.5 */
#define MCP9808_RES_4 0x01 /* 1/4 = 0.25 */
#define MCP9808_RES_8 0x10 /* 1/8 = 0.125 */
#define MCP9808_RES_16 0x11 /* 1/16 = 0.0625 */
/* Time in milli-seconds */
#define MCP9808_DELAY_ACQUIRE_RES_2 30
#define MCP9808_DELAY_ACQUIRE_RES_4 65
#define MCP9808_DELAY_ACQUIRE_RES_8 130
#define MCP9808_DELAY_ACQUIRE_RES_16 250
/*===========================================================================*/
/* Driver exported variables. */
/*===========================================================================*/
/*===========================================================================*/
/* Driver local variables and types. */
/*===========================================================================*/
/*===========================================================================*/
/* Driver local functions. */
/*===========================================================================*/
static inline msg_t
_apply_config(MCP9808_drv *drv) {
struct __attribute__((packed)) {
uint8_t reg;
uint16_t conf;
} tx = { MCP9808_REG_CONFIG, cpu_to_be16(drv->cfg) };
return i2c_send((uint8_t*)&tx, sizeof(tx));
}
static inline msg_t
_decode_measure(MCP9808_drv *drv,
uint16_t val, float *temperature) {
/* Temperature */
if (temperature) {
float temp = val & 0x0fff;
if (val & 0x1000) temp -= 0x1000;
float factor = 16.0F;
switch(drv->resolution) {
case RES_2 : factor = 2.0F; break;
case RES_4 : factor = 4.0F; break;
case RES_8 : factor = 8.0F; break;
case RES_16: factor = 16.0F; break;
}
*temperature = temp / factor;
}
/* Ok */
return MSG_OK;
}
/*===========================================================================*/
/* Driver exported functions. */
/*===========================================================================*/
void
MCP9808_init(MCP9808_drv *drv, MCP9808_config *config) {
drv->config = config;
drv->cfg = 0;
drv->resolution = RES_16; /* power up default */
drv->state = SENSOR_INIT;
}
msg_t
MCP9808_check(MCP9808_drv *drv) {
uint16_t manuf, device;
msg_t msg;
if (((msg = i2c_reg_recv16_be(MCP9808_REG_MANUF_ID, &manuf )) < MSG_OK) ||
((msg = i2c_reg_recv16_be(MCP9808_REG_DEVICE_ID, &device)) < MSG_OK))
return msg;
if ((manuf != MCP9808_MANUF_ID) || (device != MCP9808_DEVICE_ID))
return SENSOR_NOTFOUND;
return MSG_OK;
}
msg_t
MCP9808_setResolution(MCP9808_drv *drv, MCP9808_resolution_t res) {
struct __attribute__((packed)) {
uint8_t reg;
uint8_t resolution;
} tx = { MCP9808_REG_RESOLUTION, res };
msg_t msg;
if ((msg = i2c_send((uint8_t*)&tx, sizeof(tx))) < MSG_OK)
return msg;
drv->resolution = res;
return MSG_OK;
}
msg_t
MCP9808_start(MCP9808_drv *drv) {
drv->cfg &= ~(MCP9808_REG_CONFIG_SHUTDOWN);
return _apply_config(drv);
}
msg_t
MCP9808_stop(MCP9808_drv *drv) {
drv->cfg |= (MCP9808_REG_CONFIG_SHUTDOWN);
return _apply_config(drv);
}
unsigned int
MCP9808_getAcquisitionTime(MCP9808_drv *drv) {
switch(drv->resolution) {
case RES_2 : return MCP9808_DELAY_ACQUIRE_RES_2;
case RES_4 : return MCP9808_DELAY_ACQUIRE_RES_4;
case RES_8 : return MCP9808_DELAY_ACQUIRE_RES_8;
case RES_16: return MCP9808_DELAY_ACQUIRE_RES_16;
}
osalDbgAssert(false, "OOPS");
return 0;
}
msg_t
MCP9808_readMeasure(MCP9808_drv *drv,
float *temperature) {
msg_t msg;
uint16_t val;
if ((msg = i2c_reg_recv16_be(MCP9808_REG_AMBIENT_TEMP, &val)) < MSG_OK)
return msg;
return _decode_measure(drv, val, temperature);
}
msg_t
MCP9808_readTemperature(MCP9808_drv *drv,
float *temperature) {
osalDbgAssert(drv->state == SENSOR_STARTED, "invalid state");
msg_t msg;
uint16_t val;
if ((msg = i2c_reg_recv16_be(MCP9808_REG_AMBIENT_TEMP, &val)) < MSG_OK)
return msg;
return _decode_measure(drv, val, temperature);
}

View File

@ -0,0 +1,204 @@
/*
MCP9808 for ChibiOS/RT - Copyright (C) 2016 Stephane D'Alu
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.
*/
#ifndef _SENSOR_MCP9808_H_
#define _SENSOR_MCP9808_H_
#include <math.h>
#include "i2c_helpers.h"
#include "sensor.h"
/*===========================================================================*/
/* Driver constants. */
/*===========================================================================*/
#define MCP9808_CONTINUOUS_ACQUISITION_SUPPORTED TRUE
#define MCP9808_I2CADDR_FIXED 0x18
/**
* @brief Time necessary for the sensor to boot
*/
#define MCP9808_BOOTUP_TIME 0
/**
* @brief Time necessary for the sensor to start
*/
#define MCP9808_STARTUP_TIME 0
/*===========================================================================*/
/* Driver pre-compile time settings. */
/*===========================================================================*/
/*===========================================================================*/
/* Derived constants and error checks. */
/*===========================================================================*/
#define MCP9808_I2CADDR_DEFAULT MCP9808_I2CADDR_FIXED
/*===========================================================================*/
/* Driver data structures and types. */
/*===========================================================================*/
/**
* @brief Different possible resolution
*/
typedef enum {
RES_2 = 0x00, /**< @brief Resolution of 1/2 = 0.5 */
RES_4 = 0x01, /**< @brief Resolution of 1/4 = 0.25 */
RES_8 = 0x10, /**< @brief Resolution of 1/8 = 0.125 */
RES_16 = 0x11, /**< @brief Resolution of 1/16 = 0.0625 */
} MCP9808_resolution_t;
/**
* @brief MCP9808 configuration structure.
*/
typedef struct {
I2CHelper i2c; /* keep it first */
} MCP9808_config;
/**
* @brief MCP9808 configuration structure.
*/
typedef struct {
MCP9808_config *config;
sensor_state_t state;
MCP9808_resolution_t resolution;
uint16_t cfg;
} MCP9808_drv;
/**
* @brief MCP9808 measure reading
*/
typedef struct {
float temperature;
} MCP9808_measure;
/*===========================================================================*/
/* Driver macros. */
/*===========================================================================*/
/*===========================================================================*/
/* External declarations. */
/*===========================================================================*/
/**
* @brief Initialize the sensor driver
*/
void
MCP9808_init(MCP9808_drv *drv,
MCP9808_config *config);
/**
* @brief Check that the sensor is really present
*/
msg_t
MCP9808_check(MCP9808_drv *drv);
/**
* @brief Start the sensor
*/
msg_t
MCP9808_start(MCP9808_drv *drv);
/**
* @brief Stop the sensor
*
* @details If the sensor support it, it will be put in low energy mode.
*/
msg_t
MCP9808_stop(MCP9808_drv *drv);
/**
* @brief Control the MCP9809 resolution.
*/
msg_t
MCP9808_setResolution(MCP9808_drv *drv,
MCP9808_resolution_t res);
/**
* @brief Time in milli-seconds necessary for acquiring a naw measure
*
* @returns
* unsigned int time in millis-seconds
*/
unsigned int
MCP9808_getAcquisitionTime(MCP9808_drv *drv);
/**
* @brief Trigger a mesure acquisition
*/
static inline msg_t
MCP9808_startMeasure(MCP9808_drv *drv) {
(void)drv;
return MSG_OK;
}
/**
* @brief Read the newly acquiered measure
*
* @note According the the sensor design the measure read
* can be any value acquired after the acquisition time
* and the call to readMeasure.
*/
msg_t
MCP9808_readMeasure(MCP9808_drv *drv,
float *temperature);
/**
* @brief Read temperature and humidity
*
* @details According to the sensor specification/configuration
* (see #MCP9808_CONTINUOUS_ACQUISITION_SUPPORTED),
* if the sensor is doing continuous measurement
* it's value will be requested and returned immediately.
* Otherwise a measure is started, the necessary amount of
* time for acquiring the value is spend sleeping (not spinning),
* and finally the measure is read.
*
* @note In continuous measurement mode, if you just started
* the sensor, you will need to wait getAcquisitionTime()
* in addition to the usual getStartupTime()
* @note If using several sensors, it is better to start all the
* measure together, wait for the sensor having the longuest
* aquisition time, and finally read all the values
*/
msg_t
MCP9808_readTemperature(MCP9808_drv *drv,
float *temperature);
/**
* @brief Return the temperature value in °C.
*
* @note Prefere readTemperature(), if you need better error handling.
*
* @return The temperature in °C
* @retval float humidity percent
* @retval NAN on failure
*/
static inline float
MCP9808_getTemperature(MCP9808_drv *drv) {
float temperature = NAN;
MCP9808_readTemperature(drv, &temperature);
return temperature;
}
#endif

View File

@ -0,0 +1,81 @@
/*
Copyright (C) 2016 Stephane D'Alu
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.
*/
/**
*
* Example of function calls.
*
* @code
* static SENSOR_config sensor_config = {
* };
* static SENSOR_drv sensor_drv;
* @endcode
*
*
* @code
* osalThreadSleepMilliseconds(SENSOR_BOOTUP_TIME);
* SENSOR_init(&sensor_drv);
* @endcode
*
* @code
* SENSOR_start(&sensor_drv, &sensor_config);
* osalThreadSleepMilliseconds(SENSOR_STARTUP_TIME);
* @endcode
*
* If using SENSOR_startMeasure()/SENSOR_readMeasure()
* @code
* while(true) {
* SENSOR_startMeasure(&sensor_drv);
* osalThreadSleepMilliseconds(SENSOR_getAcquisitionTime());
* SENSOR_readMeasure(&sensor_drv, ...);
* }
* @endcode
*
* If using SENSOR_readValue() or SENSOR_getValue()
* @code
* #if SENSOR_CONTINUOUS_ACQUISITION_SUPPORTED == TRUE
* osalThreadSleepMilliseconds(SENSOR_getAcquisitionTime())
* #endif
*
* while(true) {
* SENSOR_readValue(&sensor_drv, ...);
* }
* @encode
*/
#ifndef _SENSOR_H_
#define _SENSOR_H_
#define SENSOR_OK MSG_OK /**< @brief Operation successful. */
#define SENSOR_TIMEOUT MSG_TIMEOUT /**< @brief Communication timeout */
#define SENSOR_RESET MSG_REST /**< @brief Communication error. */
#define SENSOR_NOTFOUND (msg_t)-20 /**< @brief Sensor not found. */
/**
* @brief Driver state machine possible states.
*/
typedef enum __attribute__ ((__packed__)) {
SENSOR_UNINIT = 0, /**< Not initialized. */
SENSOR_INIT = 1, /**< Initialized. */
SENSOR_STARTED = 2, /**< Started. */
SENSOR_MEASURING = 4, /**< Measuring. */
SENSOR_READY = 3, /**< Ready. */
SENSOR_STOPPED = 5, /**< Stopped. */
SENSOR_ERROR = 6, /**< Error. */
} sensor_state_t;
#endif

View File

@ -0,0 +1,386 @@
/*
TSL2561 for ChibiOS/RT - Copyright (C) 2016 Stephane D'Alu
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.
*/
/**
* Illuminance calculation code provided by www.taosinc.com
* DOC: http://ams.com/eng/content/download/250096/975518/143687
*/
#define I2C_HELPERS_AUTOMATIC_DRV TRUE
#include "hal.h"
#include "i2c_helpers.h"
#include "tsl2561.h"
/*===========================================================================*/
/* Driver local definitions. */
/*===========================================================================*/
// Integration time in µs
#define TSL2561_DELAY_INTTIME_SHORT 13700 // 13.7 ms
#define TSL2561_DELAY_INTTIME_MEDIUM 120000 // 120.0 ms
#define TSL2561_DELAY_INTTIME_LONG 450000 // 450.0 ms
#define TSL2561_COMMAND_BIT (0x80)
#define TSL2561_CLEAR_BIT (0x40)
#define TSL2561_WORD_BIT (0x20)
#define TSL2561_BLOCK_BIT (0x10)
#define TSL2561_CONTROL_POWERON (0x03)
#define TSL2561_CONTROL_POWEROFF (0x00)
#define TSL2561_LUX_LUXSCALE (14)
#define TSL2561_LUX_RATIOSCALE (9)
#define TSL2561_LUX_CHSCALE (10) // Scale channel values by 2^10
#define TSL2561_LUX_CHSCALE_TINT0 (0x7517) // 322/11 * 2^TSL2561_LUX_CHSCALE
#define TSL2561_LUX_CHSCALE_TINT1 (0x0FE7) // 322/81 * 2^TSL2561_LUX_CHSCALE
// I2C Register
#define TSL2561_REG_CONTROL 0x00
#define TSL2561_REG_TIMING 0x01
#define TSL2561_REG_THRESHHOLDLLOW 0x02
#define TSL2561_REG_THRESHHOLDLHIGH 0x03
#define TSL2561_REG_THRESHHOLDHLOW 0x04
#define TSL2561_REG_THRESHHOLDHHIGH 0x05
#define TSL2561_REG_INTERRUPT 0x06
#define TSL2561_REG_CRC 0x08
#define TSL2561_REG_ID 0x0A
#define TSL2561_REG_DATA0LOW 0x0C
#define TSL2561_REG_DATA0HIGH 0x0D
#define TSL2561_REG_DATA1LOW 0x0E
#define TSL2561_REG_DATA1HIGH 0x0F
// Auto-gain thresholds
#define TSL2561_AGC_THI_SHORT (4850) // Max value at Ti 13ms = 5047
#define TSL2561_AGC_TLO_SHORT (100)
#define TSL2561_AGC_THI_MEDIUM (36000) // Max value at Ti 101ms = 37177
#define TSL2561_AGC_TLO_MEDIUM (200)
#define TSL2561_AGC_THI_LONG (63000) // Max value at Ti 402ms = 65535
#define TSL2561_AGC_TLO_LONG (500)
// Clipping thresholds
#define TSL2561_CLIPPING_SHORT (4900)
#define TSL2561_CLIPPING_MEDIUM (37000)
#define TSL2561_CLIPPING_LONG (65000)
// T, FN and CL package values
#define TSL2561_LUX_K1T (0x0040) // 0.125 * 2^RATIO_SCALE
#define TSL2561_LUX_B1T (0x01f2) // 0.0304 * 2^LUX_SCALE
#define TSL2561_LUX_M1T (0x01be) // 0.0272 * 2^LUX_SCALE
#define TSL2561_LUX_K2T (0x0080) // 0.250 * 2^RATIO_SCALE
#define TSL2561_LUX_B2T (0x0214) // 0.0325 * 2^LUX_SCALE
#define TSL2561_LUX_M2T (0x02d1) // 0.0440 * 2^LUX_SCALE
#define TSL2561_LUX_K3T (0x00c0) // 0.375 * 2^RATIO_SCALE
#define TSL2561_LUX_B3T (0x023f) // 0.0351 * 2^LUX_SCALE
#define TSL2561_LUX_M3T (0x037b) // 0.0544 * 2^LUX_SCALE
#define TSL2561_LUX_K4T (0x0100) // 0.50 * 2^RATIO_SCALE
#define TSL2561_LUX_B4T (0x0270) // 0.0381 * 2^LUX_SCALE
#define TSL2561_LUX_M4T (0x03fe) // 0.0624 * 2^LUX_SCALE
#define TSL2561_LUX_K5T (0x0138) // 0.61 * 2^RATIO_SCALE
#define TSL2561_LUX_B5T (0x016f) // 0.0224 * 2^LUX_SCALE
#define TSL2561_LUX_M5T (0x01fc) // 0.0310 * 2^LUX_SCALE
#define TSL2561_LUX_K6T (0x019a) // 0.80 * 2^RATIO_SCALE
#define TSL2561_LUX_B6T (0x00d2) // 0.0128 * 2^LUX_SCALE
#define TSL2561_LUX_M6T (0x00fb) // 0.0153 * 2^LUX_SCALE
#define TSL2561_LUX_K7T (0x029a) // 1.3 * 2^RATIO_SCALE
#define TSL2561_LUX_B7T (0x0018) // 0.00146 * 2^LUX_SCALE
#define TSL2561_LUX_M7T (0x0012) // 0.00112 * 2^LUX_SCALE
#define TSL2561_LUX_K8T (0x029a) // 1.3 * 2^RATIO_SCALE
#define TSL2561_LUX_B8T (0x0000) // 0.000 * 2^LUX_SCALE
#define TSL2561_LUX_M8T (0x0000) // 0.000 * 2^LUX_SCALE
// CS package values
#define TSL2561_LUX_K1C (0x0043) // 0.130 * 2^RATIO_SCALE
#define TSL2561_LUX_B1C (0x0204) // 0.0315 * 2^LUX_SCALE
#define TSL2561_LUX_M1C (0x01ad) // 0.0262 * 2^LUX_SCALE
#define TSL2561_LUX_K2C (0x0085) // 0.260 * 2^RATIO_SCALE
#define TSL2561_LUX_B2C (0x0228) // 0.0337 * 2^LUX_SCALE
#define TSL2561_LUX_M2C (0x02c1) // 0.0430 * 2^LUX_SCALE
#define TSL2561_LUX_K3C (0x00c8) // 0.390 * 2^RATIO_SCALE
#define TSL2561_LUX_B3C (0x0253) // 0.0363 * 2^LUX_SCALE
#define TSL2561_LUX_M3C (0x0363) // 0.0529 * 2^LUX_SCALE
#define TSL2561_LUX_K4C (0x010a) // 0.520 * 2^RATIO_SCALE
#define TSL2561_LUX_B4C (0x0282) // 0.0392 * 2^LUX_SCALE
#define TSL2561_LUX_M4C (0x03df) // 0.0605 * 2^LUX_SCALE
#define TSL2561_LUX_K5C (0x014d) // 0.65 * 2^RATIO_SCALE
#define TSL2561_LUX_B5C (0x0177) // 0.0229 * 2^LUX_SCALE
#define TSL2561_LUX_M5C (0x01dd) // 0.0291 * 2^LUX_SCALE
#define TSL2561_LUX_K6C (0x019a) // 0.80 * 2^RATIO_SCALE
#define TSL2561_LUX_B6C (0x0101) // 0.0157 * 2^LUX_SCALE
#define TSL2561_LUX_M6C (0x0127) // 0.0180 * 2^LUX_SCALE
#define TSL2561_LUX_K7C (0x029a) // 1.3 * 2^RATIO_SCALE
#define TSL2561_LUX_B7C (0x0037) // 0.00338 * 2^LUX_SCALE
#define TSL2561_LUX_M7C (0x002b) // 0.00260 * 2^LUX_SCALE
#define TSL2561_LUX_K8C (0x029a) // 1.3 * 2^RATIO_SCALE
#define TSL2561_LUX_B8C (0x0000) // 0.000 * 2^LUX_SCALE
#define TSL2561_LUX_M8C (0x0000) // 0.000 * 2^LUX_SCALE
/*===========================================================================*/
/* Driver exported variables. */
/*===========================================================================*/
/*===========================================================================*/
/* Driver local variables and types. */
/*===========================================================================*/
/*===========================================================================*/
/* Driver local functions. */
/*===========================================================================*/
#define CEILING(x,y) (((x) + (y) - 1) / (y))
static inline unsigned int
calculateIlluminance(TSL2561_integration_time_t integration_time,
TSL2561_gain_t gain,
uint16_t broadband, uint16_t ir,
unsigned int partno) {
unsigned long channel_1;
unsigned long channel_0;
/* Get value for channel scaling, and clipping */
uint16_t clip_threshold = 0;
unsigned long channel_scale = 0;
switch (integration_time) {
case TSL2561_INTEGRATIONTIME_SHORT:
clip_threshold = TSL2561_CLIPPING_SHORT;
channel_scale = TSL2561_LUX_CHSCALE_TINT0;
break;
case TSL2561_INTEGRATIONTIME_MEDIUM:
clip_threshold = TSL2561_CLIPPING_MEDIUM;
channel_scale = TSL2561_LUX_CHSCALE_TINT1;
break;
case TSL2561_INTEGRATIONTIME_LONG:
clip_threshold = TSL2561_CLIPPING_LONG;
channel_scale = (1 << TSL2561_LUX_CHSCALE);
break;
default:
// assert failed
break;
}
/* Check for saturated sensor (ie: clipping) */
if ((broadband > clip_threshold) || (ir > clip_threshold)) {
return TSL2561_OVERLOADED;
}
/* Scale for gain (1x or 16x) */
if (gain == TSL2561_GAIN_1X)
channel_scale <<= 4;
/* Scale the channel values */
channel_0 = (broadband * channel_scale) >> TSL2561_LUX_CHSCALE;
channel_1 = (ir * channel_scale) >> TSL2561_LUX_CHSCALE;
/* Find the ratio of the channel values (Channel_1/Channel_0) */
unsigned long _ratio = 0;
if (channel_0 != 0)
_ratio = (channel_1 << (TSL2561_LUX_RATIOSCALE+1)) / channel_0;
unsigned long ratio = (_ratio + 1) >> 1; /* round the ratio value */
/* Find linear approximation */
unsigned int b = 0;
unsigned int m = 0;
switch (partno) {
#if TSL2561_WITH_CS
case 0x1: // 0001 = TSL2561 CS
if ((ratio >= 0) && (ratio <= TSL2561_LUX_K1C))
{ b=TSL2561_LUX_B1C; m=TSL2561_LUX_M1C; }
else if (ratio <= TSL2561_LUX_K2C)
{ b=TSL2561_LUX_B2C; m=TSL2561_LUX_M2C; }
else if (ratio <= TSL2561_LUX_K3C)
{ b=TSL2561_LUX_B3C; m=TSL2561_LUX_M3C; }
else if (ratio <= TSL2561_LUX_K4C)
{ b=TSL2561_LUX_B4C; m=TSL2561_LUX_M4C; }
else if (ratio <= TSL2561_LUX_K5C)
{ b=TSL2561_LUX_B5C; m=TSL2561_LUX_M5C; }
else if (ratio <= TSL2561_LUX_K6C)
{ b=TSL2561_LUX_B6C; m=TSL2561_LUX_M6C; }
else if (ratio <= TSL2561_LUX_K7C)
{ b=TSL2561_LUX_B7C; m=TSL2561_LUX_M7C; }
else if (ratio > TSL2561_LUX_K8C)
{ b=TSL2561_LUX_B8C; m=TSL2561_LUX_M8C; }
break;
#endif
#if TSL2561_WITH_T_FN_CL
case 0x5: // 0101 = TSL2561 T/FN/CL
if ((ratio >= 0) && (ratio <= TSL2561_LUX_K1T))
{ b=TSL2561_LUX_B1T; m=TSL2561_LUX_M1T; }
else if (ratio <= TSL2561_LUX_K2T)
{ b=TSL2561_LUX_B2T; m=TSL2561_LUX_M2T; }
else if (ratio <= TSL2561_LUX_K3T)
{ b=TSL2561_LUX_B3T; m=TSL2561_LUX_M3T; }
else if (ratio <= TSL2561_LUX_K4T)
{ b=TSL2561_LUX_B4T; m=TSL2561_LUX_M4T; }
else if (ratio <= TSL2561_LUX_K5T)
{ b=TSL2561_LUX_B5T; m=TSL2561_LUX_M5T; }
else if (ratio <= TSL2561_LUX_K6T)
{ b=TSL2561_LUX_B6T; m=TSL2561_LUX_M6T; }
else if (ratio <= TSL2561_LUX_K7T)
{ b=TSL2561_LUX_B7T; m=TSL2561_LUX_M7T; }
else if (ratio > TSL2561_LUX_K8T)
{ b=TSL2561_LUX_B8T; m=TSL2561_LUX_M8T; }
break;
#endif
default:
// assert failed
break;
}
/* Compute illuminance */
long ill = ((channel_0 * b) - (channel_1 * m));
if (ill < 0) ill = 0; /* Do not allow negative lux value */
ill += (1 << (TSL2561_LUX_LUXSCALE-1)); /* Round lsb (2^(LUX_SCALE-1)) */
ill >>= TSL2561_LUX_LUXSCALE; /* Strip fractional part */
/* Signal I2C had no errors */
return ill;
}
static inline msg_t
_readChannel(TSL2561_drv *drv, uint16_t *broadband, uint16_t *ir) {
msg_t msg;
if (((msg = i2c_reg_recv16_le(
TSL2561_COMMAND_BIT | TSL2561_WORD_BIT | TSL2561_REG_DATA0LOW,
broadband)) < MSG_OK) ||
((msg = i2c_reg_recv16_le(
TSL2561_COMMAND_BIT | TSL2561_WORD_BIT | TSL2561_REG_DATA1LOW,
ir )) < MSG_OK))
return msg;
return MSG_OK;
}
/*===========================================================================*/
/* Driver exported functions. */
/*===========================================================================*/
void
TSL2561_init(TSL2561_drv *drv, TSL2561_config *config) {
drv->config = config;
drv->gain = TSL2561_GAIN_1X;
drv->integration_time = TSL2561_INTEGRATIONTIME_LONG;
drv->state = SENSOR_INIT;
i2c_reg_recv8(TSL2561_COMMAND_BIT | TSL2561_REG_ID,
(uint8_t*)&drv->id);
}
msg_t
TSL2561_check(TSL2561_drv *drv) {
uint8_t rx;
msg_t msg;
if ((msg = i2c_reg_recv8(TSL2561_REG_ID, &rx)) < MSG_OK)
return msg;
if (!(rx & 0x0A))
return SENSOR_NOTFOUND;
return MSG_OK;
}
msg_t
TSL2561_stop(TSL2561_drv *drv) {
struct __attribute__((packed)) {
uint8_t reg;
uint8_t conf;
} tx = { TSL2561_COMMAND_BIT | TSL2561_REG_CONTROL,
TSL2561_CONTROL_POWEROFF };
return i2c_send((uint8_t*)&tx, sizeof(tx));
}
msg_t
TSL2561_start(TSL2561_drv *drv) {
struct __attribute__((packed)) {
uint8_t reg;
uint8_t conf;
} tx = { TSL2561_COMMAND_BIT | TSL2561_REG_CONTROL,
TSL2561_CONTROL_POWERON };
return i2c_send((uint8_t*)&tx, sizeof(tx));
}
msg_t
TSL2561_setIntegrationTime(TSL2561_drv *drv,
TSL2561_integration_time_t time) {
struct __attribute__((packed)) {
uint8_t reg;
uint8_t conf;
} tx = { TSL2561_COMMAND_BIT | TSL2561_REG_TIMING,
(uint8_t)(time | drv->gain) };
msg_t msg;
if ((msg = i2c_send((uint8_t*)&tx, sizeof(tx))) < MSG_OK)
return msg;
drv->integration_time = time;
return MSG_OK;
}
msg_t
TSL2561_setGain(TSL2561_drv *drv,
TSL2561_gain_t gain) {
struct __attribute__((packed)) {
uint8_t reg;
uint8_t conf;
} tx = { TSL2561_COMMAND_BIT | TSL2561_REG_TIMING,
(uint8_t)(drv->integration_time | gain) };
msg_t msg;
if ((msg = i2c_send((uint8_t*)&tx, sizeof(tx))) < MSG_OK)
return msg;
drv->gain = gain;
return MSG_OK;
}
unsigned int
TSL2561_getAcquisitionTime(TSL2561_drv *drv) {
switch (drv->integration_time) {
case TSL2561_INTEGRATIONTIME_SHORT:
return CEILING(TSL2561_DELAY_INTTIME_SHORT , 1000);
case TSL2561_INTEGRATIONTIME_MEDIUM:
return CEILING(TSL2561_DELAY_INTTIME_MEDIUM, 1000);
case TSL2561_INTEGRATIONTIME_LONG:
return CEILING(TSL2561_DELAY_INTTIME_LONG , 1000);
}
return -1;
}
msg_t
TSL2561_readIlluminance(TSL2561_drv *drv,
unsigned int *illuminance) {
uint16_t broadband;
uint16_t ir;
/* Read channels */
msg_t msg;
if ((msg = _readChannel(drv, &broadband, &ir)) < MSG_OK)
return msg;
/* Calculate illuminance */
*illuminance =
calculateIlluminance(drv->integration_time, drv->gain,
broadband, ir, drv->id.partno);
/* Ok */
return SENSOR_OK;
}

View File

@ -0,0 +1,241 @@
/*
TSL2561 for ChibiOS/RT - Copyright (C) 2016 Stephane D'Alu
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.
*/
/**
* @file tsl2561.h
* @brief TSL2561 Light sensor interface module header.
*
* @{
*/
#ifndef _SENSOR_TSL2561_H_
#define _SENSOR_TSL2561_H_
#include <math.h>
#include "i2c_helpers.h"
#include "sensor.h"
/*===========================================================================*/
/* Driver constants. */
/*===========================================================================*/
#define TSL2561_CONTINUOUS_ACQUISITION_SUPPORTED TRUE
#define TSL2561_OVERLOADED (-1)
/* I2C address */
#define TSL2561_I2CADDR_LOW (0x29)
#define TSL2561_I2CADDR_FLOAT (0x39)
#define TSL2561_I2CADDR_HIGH (0x49)
/**
* @brief Time necessary for the sensor to boot
*/
#define TSL2561_BOOTUP_TIME 0
/**
* @brief Time necessary for the sensor to start
*/
#define TSL2561_STARTUP_TIME 0
/*===========================================================================*/
/* Driver pre-compile time settings. */
/*===========================================================================*/
#ifndef TSL2561_WITH_CS
#define TSL2561_WITH_CS 0
#endif
#ifndef TSL2561_WITH_T_FN_CL
#define TSL2561_WITH_T_FN_CL 1
#endif
/*===========================================================================*/
/* Derived constants and error checks. */
/*===========================================================================*/
#define TSL2561_I2CADDR_DEFAULT TSL2561_I2CADDR_FLOAT
/*===========================================================================*/
/* Driver data structures and types. */
/*===========================================================================*/
/**
* @brief TSL2561 configuration structure.
*/
typedef struct {
I2CHelper i2c; /* keep it first */
} TSL2561_config;
/**
* @brief Available integration time
*
* @details Available integration time are:
* 13.7ms, 101ms, 402ms
*/
typedef enum {
TSL2561_INTEGRATIONTIME_SHORT = 0x00, /**< @brief 13.7ms */
TSL2561_INTEGRATIONTIME_MEDIUM = 0x01, /**< @brief 101.0ms */
TSL2561_INTEGRATIONTIME_LONG = 0x02, /**< @brief 402.0ms */
} TSL2561_integration_time_t;
/**
* @brief Available gain
*
* @details Available gain are 1x, 16x
*/
typedef enum {
TSL2561_GAIN_1X = 0x00, /**< @brief 1x gain */
TSL2561_GAIN_16X = 0x10, /**< @brief 16x gain */
} TSL2561_gain_t;
/**
* @brief TSL2561 configuration structure.
*/
typedef struct {
TSL2561_config *config;
sensor_state_t state;
TSL2561_gain_t gain;
TSL2561_integration_time_t integration_time;
struct PACKED {
uint8_t revno : 4;
uint8_t partno : 4; } id;
} TSL2561_drv;
/*===========================================================================*/
/* Driver macros. */
/*===========================================================================*/
/*===========================================================================*/
/* External declarations. */
/*===========================================================================*/
/**
* @brief Initialize the sensor driver
*/
void
TSL2561_init(TSL2561_drv *drv,
TSL2561_config *config);
/**
* @brief Start the sensor
*/
msg_t
TSL2561_start(TSL2561_drv *drv);
/**
* @brief Stop the sensor
*
* @details If the sensor support it, it will be put in low energy mode.
*/
msg_t
TSL2561_stop(TSL2561_drv *drv);
/**
* @brief Check that the sensor is really present
*/
msg_t
TSL2561_check(TSL2561_drv *drv);
/**
* @brief Time in milli-seconds necessary for acquiring a naw measure
*
* @returns
* unsigned int time in millis-seconds
*/
unsigned int
TSL2561_getAcquisitionTime(TSL2561_drv *drv);
/**
* @brief Trigger a mesure acquisition
*/
static inline msg_t
TSL2561_startMeasure(TSL2561_drv *drv) {
(void)drv;
return MSG_OK;
};
/**
* @brief Read the newly acquiered measure
*
* @note According the the sensor design the measure read
* can be any value acquired after the acquisition time
* and the call to readMeasure.
*/
msg_t
TSL2561_readMeasure(TSL2561_drv *drv,
unsigned int illuminance);
msg_t
TSL2561_setGain(TSL2561_drv *drv,
TSL2561_gain_t gain);
msg_t
TSL2561_setIntegrationTime(TSL2561_drv *drv,
TSL2561_integration_time_t time);
/**
* @brief Read temperature and humidity
*
* @details According to the sensor specification/configuration
* (see #TSL2561_CONTINUOUS_ACQUISITION_SUPPORTED),
* if the sensor is doing continuous measurement
* it's value will be requested and returned immediately.
* Otherwise a measure is started, the necessary amount of
* time for acquiring the value is spend sleeping (not spinning),
* and finally the measure is read.
*
* @note In continuous measurement mode, if you just started
* the sensor, you will need to wait getAcquisitionTime()
* in addition to the usual getStartupTime()
* @note If using several sensors, it is better to start all the
* measure together, wait for the sensor having the longuest
* aquisition time, and finally read all the values
*/
msg_t
TSL2561_readIlluminance(TSL2561_drv *drv,
unsigned int *illuminance);
/**
* @brief Return the illuminance value in Lux
*
* @details Use readIlluminance() for returning the humidity value.
*
* @note Prefere readIlluminance()if you need better error handling.
*
* @return Illuminance in Lux
* @retval unsigned int illuminace value
* @retval -1 on failure
*/
static inline unsigned int
TSL2561_getIlluminance(TSL2561_drv *drv) {
unsigned int illuminance = -1;
TSL2561_readIlluminance(drv, &illuminance);
return illuminance;
}
#endif

View File

@ -0,0 +1,272 @@
/*
TSL2591 for ChibiOS/RT - Copyright (C) 2016 Stephane D'Alu
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.
*/
/**
*
* DOC: http://ams.com/eng/content/download/389383/1251117/221235
*/
#define I2C_HELPERS_AUTOMATIC_DRV TRUE
#include "hal.h"
#include "i2c_helpers.h"
#include "tsl2591.h"
/*===========================================================================*/
/* Driver local definitions. */
/*===========================================================================*/
#define TSL2591_LUX_DF (408.0F)
#define TSL2591_LUX_COEFB (1.64F) // CH0 coefficient
#define TSL2591_LUX_COEFC (0.59F) // CH1 coefficient A
#define TSL2591_LUX_COEFD (0.86F) // CH2 coefficient B
/* I2C registers */
#define TSL2591_REG_ENABLE 0x00
#define TSL2591_REG_CONFIG 0x01 /**< @brief gain and integration */
#define TSL2591_REG_AILTL 0x04
#define TSL2591_REG_AILTH 0x05
#define TSL2591_REG_AIHTL 0x06
#define TSL2591_REG_AIHTH 0x07
#define TSL2591_REG_NPAILTL 0x08
#define TSL2591_REG_NPAILTH 0x09
#define TSL2591_REG_NPAIHTL 0x0A
#define TSL2591_REG_NPAIHTH 0x0B
#define TSL2591_REG_PERSIST 0x0C
#define TSL2591_REG_PID 0x11 /**< @brief Package ID */
#define TSL2591_REG_ID 0x12 /**< @brief Device ID */
#define TSL2591_REG_STATUS 0x13 /**< @brief Device status */
#define TSL2591_REG_C0DATAL 0x14 /**< @brief CH0 ADC low data byte */
#define TSL2591_REG_C0DATAH 0x15 /**< @brief CH0 ADC high data byte */
#define TSL2591_REG_C1DATAL 0x16 /**< @brief CH1 ADC low data byte */
#define TSL2591_REG_C1DATAH 0x17 /**< @brief CH1 ADC high data byte */
#define TSL2591_REG_COMMAND 0x80 /**< @brief Select command register */
#define TSL2591_REG_NORMAL 0x20 /**< @brief Normal opearation */
#define TSL2591_REG_SPECIAL 0x60 /**< @brief Special function */
#define TSL2591_ID_TSL2591 0x50
#define TSL2591_VISIBLE (2) // channel 0 - channel 1
#define TSL2591_INFRARED (1) // channel 1
#define TSL2591_FULLSPECTRUM (0) // channel 0
#define TSL2591_ENABLE_POWERON (0x01)
#define TSL2591_ENABLE_POWEROFF (0x00)
#define TSL2591_ENABLE_AEN (0x02)
#define TSL2591_ENABLE_AIEN (0x10)
#define TSL2591_CONTROL_RESET (0x80)
/*===========================================================================*/
/* Driver exported variables. */
/*===========================================================================*/
/*===========================================================================*/
/* Driver local variables and types. */
/*===========================================================================*/
/*===========================================================================*/
/* Driver local functions. */
/*===========================================================================*/
static inline uint32_t
calculateIlluminance(TSL2591_integration_time_t integration_time,
TSL2591_gain_t gain,
uint16_t broadband, uint16_t ir) {
uint16_t atime, again;
/* Check for overflow conditions first */
if ((broadband == 0xFFFF) | (ir == 0xFFFF)) {
return 0xFFFFFFFF; /* Signal overflow */
}
switch (integration_time) {
case TSL2591_INTEGRATIONTIME_100MS : atime = 100; break;
case TSL2591_INTEGRATIONTIME_200MS : atime = 200; break;
case TSL2591_INTEGRATIONTIME_300MS : atime = 300; break;
case TSL2591_INTEGRATIONTIME_400MS : atime = 400; break;
case TSL2591_INTEGRATIONTIME_500MS : atime = 500; break;
case TSL2591_INTEGRATIONTIME_600MS : atime = 600; break;
}
switch (gain) {
case TSL2591_GAIN_1X : again = 1; break;
case TSL2591_GAIN_25X : again = 25; break;
case TSL2591_GAIN_415X : again = 415; break;
case TSL2591_GAIN_10000X : again = 10000; break;
}
// cpl = (ATIME * AGAIN) / DF
float cpl = ((float)(atime * again)) / ((float)TSL2591_LUX_DF);
float lux1 = ( ((float)broadband) - (TSL2591_LUX_COEFB * (float)ir) ) / cpl;
float lux2 = ( (TSL2591_LUX_COEFC * (float)broadband) -
(TSL2591_LUX_COEFD * (float)ir ) ) / cpl;
return (uint32_t) (lux1 > lux2 ? lux1 : lux2);
}
static inline msg_t
_readChannel(TSL2591_drv *drv, uint16_t *broadband, uint16_t *ir) {
msg_t msg;
if (((msg = i2c_reg_recv16_le(
TSL2591_REG_COMMAND | TSL2591_REG_NORMAL | TSL2591_REG_C0DATAL,
broadband)) < MSG_OK) ||
((msg = i2c_reg_recv16_le(
TSL2591_REG_COMMAND | TSL2591_REG_NORMAL | TSL2591_REG_C1DATAL,
ir )) < MSG_OK))
return msg;
return MSG_OK;
}
/*===========================================================================*/
/* Driver exported functions. */
/*===========================================================================*/
void
TSL2591_init(TSL2591_drv *drv, TSL2591_config *config) {
drv->config = config;
drv->gain = TSL2591_GAIN_1X;
drv->integration_time = TSL2591_INTEGRATIONTIME_100MS;
drv->state = SENSOR_INIT;
}
msg_t
TSL2591_check(TSL2591_drv *drv) {
uint8_t id;
msg_t msg;
if ((msg = i2c_reg_recv8(TSL2591_REG_COMMAND | TSL2591_REG_NORMAL |
TSL2591_REG_ID, &id)) < MSG_OK)
return msg;
if (id != TSL2591_ID_TSL2591)
return SENSOR_NOTFOUND;
return MSG_OK;
}
msg_t
TSL2591_start(TSL2591_drv *drv) {
struct __attribute__((packed)) {
uint8_t reg;
uint8_t conf;
} tx_config = {
TSL2591_REG_COMMAND | TSL2591_REG_NORMAL | TSL2591_REG_CONFIG,
(uint8_t)(drv->integration_time | drv->gain) };
struct __attribute__((packed)) {
uint8_t reg;
uint8_t conf;
} tx_start = {
TSL2591_REG_COMMAND | TSL2591_REG_NORMAL | TSL2591_REG_ENABLE,
TSL2591_ENABLE_POWERON };
msg_t msg;
if (((msg = i2c_send((uint8_t*)&tx_config, sizeof(tx_config))) < MSG_OK) ||
((msg = i2c_send((uint8_t*)&tx_start, sizeof(tx_start ))) < MSG_OK)) {
drv->state = SENSOR_ERROR;
return msg;
}
drv->state = SENSOR_STARTED;
return MSG_OK;
}
msg_t
TSL2591_stop(TSL2591_drv *drv) {
struct __attribute__((packed)) {
uint8_t reg;
uint8_t conf;
} tx_stop = {
TSL2591_REG_COMMAND | TSL2591_REG_NORMAL | TSL2591_REG_ENABLE,
TSL2591_ENABLE_POWEROFF };
return i2c_send((uint8_t*)&tx_stop, sizeof(tx_stop));
}
msg_t
TSL2591_setIntegrationTime(TSL2591_drv *drv,
TSL2591_integration_time_t time) {
struct __attribute__((packed)) {
uint8_t reg;
uint8_t conf;
} tx = { TSL2591_REG_COMMAND | TSL2591_REG_NORMAL | TSL2591_REG_CONFIG,
(uint8_t)(time | drv->gain) };
msg_t msg;
if ((msg = i2c_send((uint8_t*)&tx, sizeof(tx))) < MSG_OK)
return msg;
drv->integration_time = time;
return MSG_OK;
}
msg_t
TSL2591_setGain(TSL2591_drv *drv,
TSL2591_gain_t gain) {
struct __attribute__((packed)) {
uint8_t reg;
uint8_t conf;
} tx = { TSL2591_REG_COMMAND | TSL2591_REG_NORMAL | TSL2591_REG_CONFIG,
(uint8_t)(drv->integration_time | gain) };
msg_t msg;
if ((msg = i2c_send((uint8_t*)&tx, sizeof(tx))) < MSG_OK)
return msg;
drv->gain = gain;
return MSG_OK;
}
unsigned int
TSL2591_getAcquisitionTime(TSL2591_drv *drv) {
switch (drv->integration_time) {
case TSL2591_INTEGRATIONTIME_100MS : return 100;
case TSL2591_INTEGRATIONTIME_200MS : return 200;
case TSL2591_INTEGRATIONTIME_300MS : return 300;
case TSL2591_INTEGRATIONTIME_400MS : return 400;
case TSL2591_INTEGRATIONTIME_500MS : return 500;
case TSL2591_INTEGRATIONTIME_600MS : return 600;
}
return -1;
}
msg_t
TSL2591_readIlluminance(TSL2591_drv *drv,
unsigned int *illuminance) {
uint16_t broadband;
uint16_t ir;
/* Read channels */
msg_t msg;
if ((msg = _readChannel(drv, &broadband, &ir)) < MSG_OK)
return msg;
/* Calculate illuminance */
*illuminance =
calculateIlluminance(drv->integration_time, drv->gain,
broadband, ir);
/* Ok */
return SENSOR_OK;
}

View File

@ -0,0 +1,238 @@
/*
TSL2591 for ChibiOS/RT - Copyright (C) 2016 Stephane D'Alu
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.
*/
/**
* @file tsl2591.h
* @brief TSL2591 Light sensor interface module header.
*
* @{
*/
#ifndef _SENSOR_TSL2591_H_
#define _SENSOR_TSL2591_H_
#include <math.h>
#include "i2c_helpers.h"
#include "sensor.h"
/*===========================================================================*/
/* Driver constants. */
/*===========================================================================*/
/**
* @brief Device sensor continuous acquisition support.
*/
#define TSL2591_CONTINUOUS_ACQUISITION_SUPPORTED TRUE
/**
* @brief I2C address.
*/
#define TSL2591_I2CADDR_FIXED 0x29
/**
* @brief Time necessary for the sensor to boot
*/
#define TSL2591_BOOTUP_TIME 0
/**
* @brief Time necessary for the sensor to start
*/
#define TSL2591_STARTUP_TIME 0
/*===========================================================================*/
/* Driver pre-compile time settings. */
/*===========================================================================*/
/*===========================================================================*/
/* Derived constants and error checks. */
/*===========================================================================*/
/**
* @brief Default I2C address (when pin unconfigured)
*/
#define TSL2591_I2CADDR_DEFAULT TSL2591_I2CADDR_FIXED
/*===========================================================================*/
/* Driver data structures and types. */
/*===========================================================================*/
/**
* @brief TSL2591 configuration structure.
*/
typedef struct {
I2CHelper i2c; /* keep it first */
} TSL2591_config;
/**
* @brief Available integration time
*
* @details Available integration time are:
* 100ms, 200ms, 300ms, 400ms, 500ms and 600ms
*/
typedef enum {
TSL2591_INTEGRATIONTIME_100MS = 0x00, /**< @brief 100ms */
TSL2591_INTEGRATIONTIME_200MS = 0x01, /**< @brief 200ms */
TSL2591_INTEGRATIONTIME_300MS = 0x02, /**< @brief 300ms */
TSL2591_INTEGRATIONTIME_400MS = 0x03, /**< @brief 400ms */
TSL2591_INTEGRATIONTIME_500MS = 0x04, /**< @brief 500ms */
TSL2591_INTEGRATIONTIME_600MS = 0x05, /**< @brief 600ms */
} TSL2591_integration_time_t;
/**
* @brief Available gain
*
* @details Available gain are 1x, 25x, 415x, 10000x
*/
typedef enum {
TSL2591_GAIN_1X = 0x00, /**< @brief 1x gain */
TSL2591_GAIN_25X = 0x10, /**< @brief 25x gain */
TSL2591_GAIN_415X = 0x20, /**< @brief 415x gain */
TSL2591_GAIN_10000X = 0x30, /**< @brief 10000x gain */
} TSL2591_gain_t;
/**
* @brief TSL2591 configuration structure.
*/
typedef struct {
TSL2591_config *config;
sensor_state_t state;
TSL2591_gain_t gain;
TSL2591_integration_time_t integration_time;
} TSL2591_drv;
/*===========================================================================*/
/* Driver macros. */
/*===========================================================================*/
/*===========================================================================*/
/* External declarations. */
/*===========================================================================*/
/**
* @brief Initialize the sensor driver
*/
void
TSL2591_init(TSL2591_drv *drv,
TSL2591_config *config);
/**
* @brief Start the sensor
*/
msg_t
TSL2591_start(TSL2591_drv *drv);
/**
* @brief Stop the sensor
*
* @details If the sensor support it, it will be put in low energy mode.
*/
msg_t
TSL2591_stop(TSL2591_drv *drv);
/**
* @brief Check that the sensor is really present
*/
msg_t
TSL2591_check(TSL2591_drv *drv);
/**
* @brief Time in milli-seconds necessary for acquiring a naw measure
*
* @returns
* unsigned int time in millis-seconds
*/
unsigned int
TSL2591_getAcquisitionTime(TSL2591_drv *drv);
/**
* @brief Trigger a mesure acquisition
*/
static inline msg_t
TSL2591_startMeasure(TSL2591_drv *drv) {
(void)drv;
return MSG_OK;
};
msg_t
TSL2591_setGain(TSL2591_drv *drv,
TSL2591_gain_t gain);
msg_t
TSL2591_setIntegrationTime(TSL2591_drv *drv,
TSL2591_integration_time_t time);
/**
* @brief Read the newly acquiered measure
*
* @note According the the sensor design the measure read
* can be any value acquired after the acquisition time
* and the call to readMeasure.
*/
msg_t
TSL2591_readMeasure(TSL2591_drv *drv,
unsigned int illuminance);
/**
* @brief Read temperature and humidity
*
* @details According to the sensor specification/configuration
* (see #TSL2591_CONTINUOUS_ACQUISITION_SUPPORTED),
* if the sensor is doing continuous measurement
* it's value will be requested and returned immediately.
* Otherwise a measure is started, the necessary amount of
* time for acquiring the value is spend sleeping (not spinning),
* and finally the measure is read.
*
* @note In continuous measurement mode, if you just started
* the sensor, you will need to wait getAcquisitionTime()
* in addition to the usual getStartupTime()
* @note If using several sensors, it is better to start all the
* measure together, wait for the sensor having the longuest
* aquisition time, and finally read all the values
*/
msg_t
TSL2591_readIlluminance(TSL2591_drv *drv,
unsigned int *illuminance);
/**
* @brief Return the illuminance value in Lux
*
* @details Use readIlluminance() for returning the humidity value.
*
* @note Prefere readIlluminance()if you need better error handling.
*
* @return Illuminance in Lux
* @retval unsigned int illuminace value
* @retval -1 on failure
*/
static inline unsigned int
TSL2591_getIlluminance(TSL2591_drv *drv) {
unsigned int illuminance = -1;
TSL2591_readIlluminance(drv, &illuminance);
return illuminance;
}
#endif

13
os/various/gdb.mk Normal file
View File

@ -0,0 +1,13 @@
GDB ?= arm-none-eabi-gdb
GDB_PROGRAM ?= $(BUILDDIR)/$(PROJECT).elf
GDB_PORT ?= 2331
GDB_START_ADDRESS ?= 0
GDB_BREAK ?= main
gdb-debug:
printf "target remote localhost:$(GDB_PORT)\nmem $(GDB_START_ADDRESS) 0\nbreak $(GDB_BREAK)\nload\nmon reset\ncontinue" > .gdbinit
$(GDB) --command=.gdbinit $(GDB_PROGRAM)
.PHONY: gdb-debug

283
os/various/i2c_helpers.h Normal file
View File

@ -0,0 +1,283 @@
/*
Copyright (C) 2016 Stephane D'Alu
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.
*/
#ifndef I2C_HELPERS_H
#define I2C_HELPERS_H
#include "hal.h"
#include "bswap.h"
typedef struct {
/**
* @brief Pointer to the I2C driver.
*/
I2CDriver *driver;
/**
* @brief I2C address.
*/
i2caddr_t addr;
} I2CHelper;
#if !defined(I2C_HELPERS_AUTOMATIC_DRV) || (I2C_HELPERS_AUTOMATIC_DRV == FALSE)
#define i2c_send(i2c, txbuf, txbytes) \
_i2c_send(i2c, txbuf, txbytes)
#define i2c_transmit(i2c, txbuf, txbytes, rxbuf, rxbytes) \
_i2c_transmit(i2c, txbuf, txbytes, rxbuf, rxbytes)
#define i2c_receive(i2, rxbuf, rxbytes) \
_i2c_receive(i2c, rxbuf, rxbytes)
#define i2c_send_timeout(i2c, txbuf, txbytes) \
_i2c_send(i2c, txbuf, txbytes)
#define i2c_transmit_timeout(i2c, txbuf, txbytes, rxbuf, rxbytes) \
_i2c_transmit(i2c, txbuf, txbytes, rxbuf, rxbytes)
#define i2c_receive_timeout(i2, rxbuf, rxbytes) \
_i2c_receive(i2c, rxbuf, rxbytes)
#define i2c_reg(i2c, reg) \
_i2c_reg(i2c, reg)
#define i2c_reg_recv8(i2c, reg, val) \
_i2c_reg_recv8(i2c, reg, val)
#define i2c_reg_recv16(i2c, reg, val) \
_i2c_reg_recv16(i2c, reg, val)
#define i2c_reg_recv16_le(i2c, reg, val) \
_i2c_reg_recv16_le(i2c, reg, val)
#define i2c_reg_recv16_be(i2c, reg, val) \
_i2c_reg_recv16_be(i2c, reg, val)
#define i2c_reg_recv32(i2c, reg, val) \
_i2c_reg_recv32(i2c, reg, val)
#define i2c_reg_recv32_le(i2c, reg, val) \
_i2c_reg_recv32_le(i2c, reg, val)
#define i2c_reg_recv32_be(i2c, reg, val) \
_i2c_reg_recv32_be(i2c, reg, val)
#define i2c_recv8(i2c, val) \
_i2c_recv8(i2c, val)
#define i2c_recv16(i2c, val) \
_i2c_recv16(i2c, val)
#define i2c_recv16_le(i2c, val) \
_i2c_recv16_le(i2c, val)
#define i2c_recv16_be(i2c, val) \
_i2c_recv16_be(i2c, val)
#define i2c_recv32(i2c, val) \
_i2c_recv32(i2c, val)
#define i2c_recv32_le(i2c, val) \
_i2c_recv32_le(i2c, val)
#define i2c_recv32_be(i2c, val) \
_i2c_recv32_be(i2c, val)
#else
#define i2c_send(txbuf, txbytes) \
_i2c_send(&drv->config->i2c, txbuf, txbytes)
#define i2c_transmit(txbuf, txbytes, rxbuf, rxbytes) \
_i2c_transmit(&drv->config->i2c, txbuf, txbytes, rxbuf, rxbytes)
#define i2c_receive(rxbuf, rxbytes) \
_i2c_receive(&drv->config->i2c, rxbuf, rxbytes)
#define i2c_send_timeout(txbuf, txbytes) \
_i2c_send(&drv->config->i2c, txbuf, txbytes)
#define i2c_transmit_timeout(txbuf, txbytes, rxbuf, rxbytes) \
_i2c_transmit(&drv->config->i2c, txbuf, txbytes, rxbuf, rxbytes)
#define i2c_receive_timeout(rxbuf, rxbytes) \
_i2c_receive(&drv->config->i2c, rxbuf, rxbytes)
#define i2c_reg(reg) \
_i2c_reg(&drv->config->i2c, reg)
#define i2c_reg_recv8(reg, val) \
_i2c_reg_recv8(&drv->config->i2c, reg, val)
#define i2c_reg_recv16(reg, val) \
_i2c_reg_recv16(&drv->config->i2c, reg, val)
#define i2c_reg_recv16_le(reg, val) \
_i2c_reg_recv16_le(&drv->config->i2c, reg, val)
#define i2c_reg_recv16_be(reg, val) \
_i2c_reg_recv16_be(&drv->config->i2c, reg, val)
#define i2c_reg_recv32(reg, val) \
_i2c_reg_recv32(&drv->config->i2c, reg, val)
#define i2c_reg_recv32_le(reg, val) \
_i2c_reg_recv32_le(&drv->config->i2c, reg, val)
#define i2c_reg_recv32_be(reg, val) \
_i2c_reg_recv32_be(&drv->config->i2c, reg, val)
#define i2c_recv8(val) \
_i2c_recv8(&drv->config->i2c, val)
#define i2c_recv16(val) \
_i2c_recv16(&drv->config->i2c, val)
#define i2c_recv16_le(val) \
_i2c_recv16_le(&drv->config->i2c, val)
#define i2c_recv16_be(val) \
_i2c_recv16_be(&drv->config->i2c, val)
#define i2c_recv32(val) \
_i2c_recv32(&drv->config->i2c, val)
#define i2c_recv32_le(val) \
_i2c_recv32_le(&drv->config->i2c, val)
#define i2c_recv32_be(val) \
_i2c_recv32_be(&drv->config->i2c, val)
#endif
static inline msg_t
_i2c_send(I2CHelper *i2c, const uint8_t *txbuf, size_t txbytes) {
return i2cMasterTransmitTimeout(i2c->driver, i2c->addr,
txbuf, txbytes, NULL, 0, TIME_INFINITE);
};
static inline msg_t
_i2c_transmit(I2CHelper *i2c, const uint8_t *txbuf, size_t txbytes,
uint8_t *rxbuf, size_t rxbytes) {
return i2cMasterTransmitTimeout(i2c->driver, i2c->addr,
txbuf, txbytes, rxbuf, rxbytes, TIME_INFINITE);
}
static inline msg_t
_i2c_receive(I2CHelper *i2c, uint8_t *rxbuf, size_t rxbytes) {
return i2cMasterReceiveTimeout(i2c->driver, i2c->addr,
rxbuf, rxbytes, TIME_INFINITE);
};
static inline msg_t
_i2c_send_timeout(I2CHelper *i2c, const uint8_t *txbuf, size_t txbytes,
systime_t timeout) {
return i2cMasterTransmitTimeout(i2c->driver, i2c->addr,
txbuf, txbytes, NULL, 0, timeout);
};
static inline msg_t
_i2c_transmit_timeout(I2CHelper *i2c, const uint8_t *txbuf, size_t txbytes,
uint8_t *rxbuf, size_t rxbytes, systime_t timeout) {
return i2cMasterTransmitTimeout(i2c->driver, i2c->addr,
txbuf, txbytes, rxbuf, rxbytes, timeout);
}
static inline msg_t
_i2c_receive_timeout(I2CHelper *i2c, uint8_t *rxbuf, size_t rxbytes, systime_t timeout) {
return i2cMasterReceiveTimeout(i2c->driver, i2c->addr,
rxbuf, rxbytes, timeout);
};
/*======================================================================*/
static inline msg_t
_i2c_reg(I2CHelper *i2c, uint8_t reg) {
return _i2c_transmit(i2c, &reg, sizeof(reg), NULL, 0);
};
/*======================================================================*/
static inline msg_t
_i2c_reg_recv8(I2CHelper *i2c, uint8_t reg, uint8_t *val) {
return _i2c_transmit(i2c, &reg, sizeof(reg), (uint8_t*)val, sizeof(val));
};
static inline msg_t
_i2c_reg_recv16(I2CHelper *i2c, uint8_t reg, uint16_t *val) {
return _i2c_transmit(i2c, &reg, sizeof(reg), (uint8_t*)val, sizeof(val));
};
static inline msg_t
_i2c_reg_recv16_le(I2CHelper *i2c, uint8_t reg, uint16_t *val) {
int msg = _i2c_reg_recv16(i2c, reg, val);
if (msg >= 0) *val = le16_to_cpu(*val);
return msg;
};
static inline msg_t
_i2c_reg_recv16_be(I2CHelper *i2c, uint8_t reg, uint16_t *val) {
int msg = _i2c_reg_recv16(i2c, reg, val);
if (msg >= 0) *val = be16_to_cpu(*val);
return msg;
};
static inline msg_t
_i2c_reg_recv32(I2CHelper *i2c, uint8_t reg, uint32_t *val) {
return _i2c_transmit(i2c, &reg, sizeof(reg), (uint8_t*)val, sizeof(val));
};
static inline msg_t
_i2c_reg_recv32_le(I2CHelper *i2c, uint8_t reg, uint32_t *val) {
int msg = _i2c_reg_recv32(i2c, reg, val);
if (msg >= 0) *val = le32_to_cpu(*val);
return msg;
};
static inline msg_t
_i2c_reg_recv32_be(I2CHelper *i2c, uint8_t reg, uint32_t *val) {
int msg = _i2c_reg_recv32(i2c, reg, val);
if (msg >= 0) *val = be32_to_cpu(*val);
return msg;
};
/*======================================================================*/
static inline msg_t
_i2c_recv8(I2CHelper *i2c, uint8_t *val) {
return _i2c_receive(i2c, (uint8_t*)val, sizeof(val));
};
static inline msg_t
_i2c_recv16(I2CHelper *i2c, uint16_t *val) {
return _i2c_receive(i2c, (uint8_t*)val, sizeof(val));
};
static inline msg_t
_i2c_recv16_le(I2CHelper *i2c, uint16_t *val) {
int msg = _i2c_recv16(i2c, val);
if (msg >= 0) *val = le16_to_cpu(*val);
return msg;
};
static inline msg_t
_i2c_recv16_be(I2CHelper *i2c, uint16_t *val) {
int msg = _i2c_recv16(i2c, val);
if (msg >= 0) *val = be16_to_cpu(*val);
return msg;
};
static inline msg_t
_i2c_recv32(I2CHelper *i2c, uint32_t *val) {
return _i2c_receive(i2c, (uint8_t*)val, sizeof(val));
};
static inline msg_t
_i2c_recv32_le(I2CHelper *i2c, uint32_t *val) {
int msg = _i2c_recv32(i2c, val);
if (msg >= 0) *val = le32_to_cpu(*val);
return msg;
};
static inline msg_t
_i2c_recv32_be(I2CHelper *i2c, uint32_t *val) {
int msg = _i2c_recv32(i2c, val);
if (msg >= 0) *val = be32_to_cpu(*val);
return msg;
};
#endif

33
os/various/jlink.mk Normal file
View File

@ -0,0 +1,33 @@
JLINK ?= JLinkExe
JLINK_GDB_SERVER ?= JLinkGDBServer
JLINK_GDB_PORT ?= 2331
JLINK_IF ?= swd
JLINK_SPEED ?= 2000
JLINK_START_ADDRESS ?= 0
JLINK_BURN ?= $(BUILDDIR)/$(PROJECT).bin
JLINK_COMMON_OPTS ?= -device $(JLINK_DEVICE) -if $(JLINK_IF) -speed $(JLINK_SPEED)
jlink-flash:
printf "$(JLINK_PRE_FLASH)\nloadbin $(JLINK_BURN) $(JLINK_START_ADDRESS)\nverifybin $(JLINK_BURN) $(JLINK_START_ADDRESS)\nr\ng\nexit\n" > $(BUILDDIR)/flash.jlink
$(JLINK) $(JLINK_COMMON_OPTS) $(BUILDDIR)/flash.jlink
ifneq ($(SOFTDEVICE),)
jlink-flash-softdevice:
printf "w4 4001e504 1\nloadbin $(NRF51SDK)/components/softdevice/$(SOFTDEVICE)/hex/$(SOFTDEVICE)_nrf51_$(SOFTDEVICE_RELEASE)_softdevice.hex 0\nr\ng\nexit\n" > $(BUILDDIR)/flash.softdevice.jlink
$(JLINK) $(JLINK_COMMON_OPTS) $(BUILDDIR)/flash.softdevice.jlink
endif
ifneq ($(JLINK_ERASE_ALL),)
jlink-erase-all:
printf "$(JLINK_ERASE_ALL)\nr\nexit\n" > $(BUILDDIR)/erase-all.jlink
$(JLINK) $(JLINK_COMMON_OPTS) $(BUILDDIR)/erase-all.jlink
endif
jlink-reset:
printf "r\nexit\n" > $(BUILDDIR)/reset.jlink
$(JLINK) $(JLINK_COMMON_OPTS) $(BUILDDIR)/reset.jlink
jlink-debug-server:
$(JLINK_GDB_SERVER) $(JLINK_COMMON_OPTS) -port $(JLINK_GDB_PORT)
.PHONY: jlink-flash jlink-flash-softdevice jlink-erase-all jlink-reset jlink-debug-server

View File

@ -0,0 +1,230 @@
##############################################################################
# Build global options
# NOTE: Can be overridden externally.
#
# Compiler options here.
ifeq ($(USE_OPT),)
USE_OPT = -O2 -ggdb -fomit-frame-pointer -falign-functions=16
endif
# C specific options here (added to USE_OPT).
ifeq ($(USE_COPT),)
USE_COPT =
endif
# C++ specific options here (added to USE_OPT).
ifeq ($(USE_CPPOPT),)
USE_CPPOPT = -fno-rtti
endif
# Enable this if you want the linker to remove unused code and data
ifeq ($(USE_LINK_GC),)
USE_LINK_GC = yes
endif
# Linker extra options here.
ifeq ($(USE_LDOPT),)
USE_LDOPT =
endif
# Enable this if you want link time optimizations (LTO)
ifeq ($(USE_LTO),)
USE_LTO = yes
endif
# If enabled, this option allows to compile the application in THUMB mode.
ifeq ($(USE_THUMB),)
USE_THUMB = yes
endif
# Enable this if you want to see the full log while compiling.
ifeq ($(USE_VERBOSE_COMPILE),)
USE_VERBOSE_COMPILE = no
endif
# If enabled, this option makes the build process faster by not compiling
# modules not used in the current configuration.
ifeq ($(USE_SMART_BUILD),)
USE_SMART_BUILD = yes
endif
#
# Build global options
##############################################################################
##############################################################################
# Architecture or project specific options
#
# Stack size to be allocated to the Cortex-M process stack. This stack is
# the stack used by the main() thread.
ifeq ($(USE_PROCESS_STACKSIZE),)
USE_PROCESS_STACKSIZE = 0x200
endif
# Stack size to the allocated to the Cortex-M main/exceptions stack. This
# stack is used for processing interrupts and exceptions.
ifeq ($(USE_EXCEPTIONS_STACKSIZE),)
USE_EXCEPTIONS_STACKSIZE = 0x400
endif
#
# Architecture or project specific options
##############################################################################
##############################################################################
# Project, sources and paths
#
# Define project name here
PROJECT = ch
# Imported source files and paths
#CHIBIOS = ../../../../../ChibiOS-RT
#CHIBIOS_CONTRIB = $(CHIBIOS)/../ChibiOS-Contrib
CHIBIOS = /home/sdalu/ChibiOS/ChibiOS_16.1.2
CHIBIOS_CONTRIB = /home/sdalu/ChibiOS/Z/ChibiOS-Contrib
# Startup files.
include $(CHIBIOS_CONTRIB)/os/common/ports/ARMCMx/compilers/GCC/mk/startup_nrf51.mk
# HAL-OSAL files (optional).
include $(CHIBIOS)/os/hal/hal.mk
include $(CHIBIOS_CONTRIB)/os/hal/hal.mk
include $(CHIBIOS_CONTRIB)/os/hal/ports/NRF51/NRF51822/platform.mk
include $(CHIBIOS_CONTRIB)/os/hal/boards/NRF51-DK/board.mk
include $(CHIBIOS)/os/hal/osal/rt/osal.mk
# RTOS files (optional).
include $(CHIBIOS)/os/rt/rt.mk
include $(CHIBIOS)/os/rt/ports/ARMCMx/compilers/GCC/mk/port_v6m.mk
# Define linker script file here
LDSCRIPT= $(STARTUPLD)/NRF51822.ld
# C sources that can be compiled in ARM or THUMB mode depending on the global
# setting.
CSRC = $(STARTUPSRC) \
$(KERNSRC) \
$(PORTSRC) \
$(OSALSRC) \
$(HALSRC) \
$(PLATFORMSRC) \
$(BOARDSRC) \
$(TESTSRC) \
$(CHIBIOS)/os/various/shell.c \
$(CHIBIOS)/os/hal/lib/streams/memstreams.c \
$(CHIBIOS)/os/hal/lib/streams/chprintf.c \
main.c
# C++ sources that can be compiled in ARM or THUMB mode depending on the global
# setting.
CPPSRC =
# C sources to be compiled in ARM mode regardless of the global setting.
# NOTE: Mixing ARM and THUMB mode enables the -mthumb-interwork compiler
# option that results in lower performance and larger code size.
ACSRC =
# C++ sources to be compiled in ARM mode regardless of the global setting.
# NOTE: Mixing ARM and THUMB mode enables the -mthumb-interwork compiler
# option that results in lower performance and larger code size.
ACPPSRC =
# C sources to be compiled in THUMB mode regardless of the global setting.
# NOTE: Mixing ARM and THUMB mode enables the -mthumb-interwork compiler
# option that results in lower performance and larger code size.
TCSRC =
# C sources to be compiled in THUMB mode regardless of the global setting.
# NOTE: Mixing ARM and THUMB mode enables the -mthumb-interwork compiler
# option that results in lower performance and larger code size.
TCPPSRC =
# List ASM source files here
ASMSRC = $(STARTUPASM) $(PORTASM) $(OSALASM)
INCDIR = $(STARTUPINC) $(KERNINC) $(PORTINC) $(OSALINC) \
$(HALINC) $(PLATFORMINC) $(BOARDINC) $(TESTINC) \
$(CHIBIOS)/os/hal/lib/streams $(CHIBIOS)/os/various
#
# Project, sources and paths
##############################################################################
##############################################################################
# Compiler settings
#
MCU = cortex-m0
TRGT = arm-none-eabi-
CC = $(TRGT)gcc
CPPC = $(TRGT)g++
# Enable loading with g++ only if you need C++ runtime support.
# NOTE: You can use C++ even without C++ support if you are careful. C++
# runtime support makes code size explode.
LD = $(TRGT)gcc
#LD = $(TRGT)g++
CP = $(TRGT)objcopy
AS = $(TRGT)gcc -x assembler-with-cpp
AR = $(TRGT)ar
OD = $(TRGT)objdump
SZ = $(TRGT)size
HEX = $(CP) -O ihex
BIN = $(CP) -O binary
# ARM-specific options here
AOPT =
# THUMB-specific options here
TOPT = -mthumb -DTHUMB
# Define C warning options here
CWARN = -Wall -Wextra -Wundef -Wstrict-prototypes
# Define C++ warning options here
CPPWARN = -Wall -Wextra -Wundef
#
# Compiler settings
##############################################################################
##############################################################################
# Start of user section
#
# List all user C define here, like -D_DEBUG=1
UDEFS =
# Define ASM defines here
UADEFS =
# List all user directories here
UINCDIR =
# List the user directory to look for the libraries here
ULIBDIR =
# List all user libraries here
ULIBS =
#
# End of user defines
##############################################################################
RULESPATH = $(CHIBIOS)/os/common/ports/ARMCMx/compilers/GCC
include $(RULESPATH)/rules.mk
# Flash
JLINK_DEVICE = nrf51422
JLINK_PRE_FLASH = w4 4001e504 1
JLINK_ERASE_ALL = w4 4001e504 2\nw4 4001e50c 1\nsleep 100
include /home/sdalu/ChibiOS/W/ChibiOS-Contrib/os/various/jlink.mk
include /home/sdalu/ChibiOS/W/ChibiOS-Contrib/os/various/gdb.mk
flash: all jlink-flash
debug: gdb-debug

View File

@ -0,0 +1,499 @@
/*
Copyright (C) 2016 Stephane D'Alu
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.
*/
/**
* @file templates/chconf.h
* @brief Configuration file template.
* @details A copy of this file must be placed in each project directory, it
* contains the application specific kernel settings.
*
* @addtogroup config
* @details Kernel related settings and hooks.
* @{
*/
#ifndef _CHCONF_H_
#define _CHCONF_H_
/*===========================================================================*/
/**
* @name System timers settings
* @{
*/
/*===========================================================================*/
/**
* @brief System time counter resolution.
* @note Allowed values are 16 or 32 bits.
*/
#define CH_CFG_ST_RESOLUTION 32
/**
* @brief System tick frequency.
* @details Frequency of the system timer that drives the system ticks. This
* setting also defines the system tick time unit.
*/
#define CH_CFG_ST_FREQUENCY 1000
/**
* @brief Time delta constant for the tick-less mode.
* @note If this value is zero then the system uses the classic
* periodic tick. This value represents the minimum number
* of ticks that is safe to specify in a timeout directive.
* The value one is not valid, timeouts are rounded up to
* this value.
*/
#define CH_CFG_ST_TIMEDELTA 0
/** @} */
/*===========================================================================*/
/**
* @name Kernel parameters and options
* @{
*/
/*===========================================================================*/
/**
* @brief Round robin interval.
* @details This constant is the number of system ticks allowed for the
* threads before preemption occurs. Setting this value to zero
* disables the preemption for threads with equal priority and the
* round robin becomes cooperative. Note that higher priority
* threads can still preempt, the kernel is always preemptive.
* @note Disabling the round robin preemption makes the kernel more compact
* and generally faster.
* @note The round robin preemption is not supported in tickless mode and
* must be set to zero in that case.
*/
#define CH_CFG_TIME_QUANTUM 20
/**
* @brief Managed RAM size.
* @details Size of the RAM area to be managed by the OS. If set to zero
* then the whole available RAM is used. The core memory is made
* available to the heap allocator and/or can be used directly through
* the simplified core memory allocator.
*
* @note In order to let the OS manage the whole RAM the linker script must
* provide the @p __heap_base__ and @p __heap_end__ symbols.
* @note Requires @p CH_CFG_USE_MEMCORE.
*/
#define CH_CFG_MEMCORE_SIZE 0
/**
* @brief Idle thread automatic spawn suppression.
* @details When this option is activated the function @p chSysInit()
* does not spawn the idle thread. The application @p main()
* function becomes the idle thread and must implement an
* infinite loop.
*/
#define CH_CFG_NO_IDLE_THREAD FALSE
/** @} */
/*===========================================================================*/
/**
* @name Performance options
* @{
*/
/*===========================================================================*/
/**
* @brief OS optimization.
* @details If enabled then time efficient rather than space efficient code
* is used when two possible implementations exist.
*
* @note This is not related to the compiler optimization options.
* @note The default is @p TRUE.
*/
#define CH_CFG_OPTIMIZE_SPEED TRUE
/** @} */
/*===========================================================================*/
/**
* @name Subsystem options
* @{
*/
/*===========================================================================*/
/**
* @brief Time Measurement APIs.
* @details If enabled then the time measurement APIs are included in
* the kernel.
*
* @note The default is @p TRUE.
*/
#define CH_CFG_USE_TM FALSE
/**
* @brief Threads registry APIs.
* @details If enabled then the registry APIs are included in the kernel.
*
* @note The default is @p TRUE.
*/
#define CH_CFG_USE_REGISTRY TRUE
/**
* @brief Threads synchronization APIs.
* @details If enabled then the @p chThdWait() function is included in
* the kernel.
*
* @note The default is @p TRUE.
*/
#define CH_CFG_USE_WAITEXIT TRUE
/**
* @brief Semaphores APIs.
* @details If enabled then the Semaphores APIs are included in the kernel.
*
* @note The default is @p TRUE.
*/
#define CH_CFG_USE_SEMAPHORES TRUE
/**
* @brief Semaphores queuing mode.
* @details If enabled then the threads are enqueued on semaphores by
* priority rather than in FIFO order.
*
* @note The default is @p FALSE. Enable this if you have special
* requirements.
* @note Requires @p CH_CFG_USE_SEMAPHORES.
*/
#define CH_CFG_USE_SEMAPHORES_PRIORITY FALSE
/**
* @brief Mutexes APIs.
* @details If enabled then the mutexes APIs are included in the kernel.
*
* @note The default is @p TRUE.
*/
#define CH_CFG_USE_MUTEXES TRUE
/**
* @brief Enables recursive behavior on mutexes.
* @note Recursive mutexes are heavier and have an increased
* memory footprint.
*
* @note The default is @p FALSE.
* @note Requires @p CH_CFG_USE_MUTEXES.
*/
#define CH_CFG_USE_MUTEXES_RECURSIVE FALSE
/**
* @brief Conditional Variables APIs.
* @details If enabled then the conditional variables APIs are included
* in the kernel.
*
* @note The default is @p TRUE.
* @note Requires @p CH_CFG_USE_MUTEXES.
*/
#define CH_CFG_USE_CONDVARS TRUE
/**
* @brief Conditional Variables APIs with timeout.
* @details If enabled then the conditional variables APIs with timeout
* specification are included in the kernel.
*
* @note The default is @p TRUE.
* @note Requires @p CH_CFG_USE_CONDVARS.
*/
#define CH_CFG_USE_CONDVARS_TIMEOUT TRUE
/**
* @brief Events Flags APIs.
* @details If enabled then the event flags APIs are included in the kernel.
*
* @note The default is @p TRUE.
*/
#define CH_CFG_USE_EVENTS TRUE
/**
* @brief Events Flags APIs with timeout.
* @details If enabled then the events APIs with timeout specification
* are included in the kernel.
*
* @note The default is @p TRUE.
* @note Requires @p CH_CFG_USE_EVENTS.
*/
#define CH_CFG_USE_EVENTS_TIMEOUT TRUE
/**
* @brief Synchronous Messages APIs.
* @details If enabled then the synchronous messages APIs are included
* in the kernel.
*
* @note The default is @p TRUE.
*/
#define CH_CFG_USE_MESSAGES TRUE
/**
* @brief Synchronous Messages queuing mode.
* @details If enabled then messages are served by priority rather than in
* FIFO order.
*
* @note The default is @p FALSE. Enable this if you have special
* requirements.
* @note Requires @p CH_CFG_USE_MESSAGES.
*/
#define CH_CFG_USE_MESSAGES_PRIORITY FALSE
/**
* @brief Mailboxes APIs.
* @details If enabled then the asynchronous messages (mailboxes) APIs are
* included in the kernel.
*
* @note The default is @p TRUE.
* @note Requires @p CH_CFG_USE_SEMAPHORES.
*/
#define CH_CFG_USE_MAILBOXES TRUE
/**
* @brief I/O Queues APIs.
* @details If enabled then the I/O queues APIs are included in the kernel.
*
* @note The default is @p TRUE.
*/
#define CH_CFG_USE_QUEUES TRUE
/**
* @brief Core Memory Manager APIs.
* @details If enabled then the core memory manager APIs are included
* in the kernel.
*
* @note The default is @p TRUE.
*/
#define CH_CFG_USE_MEMCORE TRUE
/**
* @brief Heap Allocator APIs.
* @details If enabled then the memory heap allocator APIs are included
* in the kernel.
*
* @note The default is @p TRUE.
* @note Requires @p CH_CFG_USE_MEMCORE and either @p CH_CFG_USE_MUTEXES or
* @p CH_CFG_USE_SEMAPHORES.
* @note Mutexes are recommended.
*/
#define CH_CFG_USE_HEAP TRUE
/**
* @brief Memory Pools Allocator APIs.
* @details If enabled then the memory pools allocator APIs are included
* in the kernel.
*
* @note The default is @p TRUE.
*/
#define CH_CFG_USE_MEMPOOLS TRUE
/**
* @brief Dynamic Threads APIs.
* @details If enabled then the dynamic threads creation APIs are included
* in the kernel.
*
* @note The default is @p TRUE.
* @note Requires @p CH_CFG_USE_WAITEXIT.
* @note Requires @p CH_CFG_USE_HEAP and/or @p CH_CFG_USE_MEMPOOLS.
*/
#define CH_CFG_USE_DYNAMIC TRUE
/** @} */
/*===========================================================================*/
/**
* @name Debug options
* @{
*/
/*===========================================================================*/
/**
* @brief Debug option, kernel statistics.
*
* @note The default is @p FALSE.
*/
#define CH_DBG_STATISTICS FALSE
/**
* @brief Debug option, system state check.
* @details If enabled the correct call protocol for system APIs is checked
* at runtime.
*
* @note The default is @p FALSE.
*/
#define CH_DBG_SYSTEM_STATE_CHECK TRUE
/**
* @brief Debug option, parameters checks.
* @details If enabled then the checks on the API functions input
* parameters are activated.
*
* @note The default is @p FALSE.
*/
#define CH_DBG_ENABLE_CHECKS TRUE
/**
* @brief Debug option, consistency checks.
* @details If enabled then all the assertions in the kernel code are
* activated. This includes consistency checks inside the kernel,
* runtime anomalies and port-defined checks.
*
* @note The default is @p FALSE.
*/
#define CH_DBG_ENABLE_ASSERTS TRUE
/**
* @brief Debug option, trace buffer.
* @details If enabled then the context switch circular trace buffer is
* activated.
*
* @note The default is @p FALSE.
*/
#define CH_DBG_ENABLE_TRACE TRUE
/**
* @brief Debug option, stack checks.
* @details If enabled then a runtime stack check is performed.
*
* @note The default is @p FALSE.
* @note The stack check is performed in a architecture/port dependent way.
* It may not be implemented or some ports.
* @note The default failure mode is to halt the system with the global
* @p panic_msg variable set to @p NULL.
*/
#define CH_DBG_ENABLE_STACK_CHECK TRUE
/**
* @brief Debug option, stacks initialization.
* @details If enabled then the threads working area is filled with a byte
* value when a thread is created. This can be useful for the
* runtime measurement of the used stack.
*
* @note The default is @p FALSE.
*/
#define CH_DBG_FILL_THREADS TRUE
/**
* @brief Debug option, threads profiling.
* @details If enabled then a field is added to the @p thread_t structure that
* counts the system ticks occurred while executing the thread.
*
* @note The default is @p FALSE.
* @note This debug option is not currently compatible with the
* tickless mode.
*/
#define CH_DBG_THREADS_PROFILING FALSE
/** @} */
/*===========================================================================*/
/**
* @name Kernel hooks
* @{
*/
/*===========================================================================*/
/**
* @brief Threads descriptor structure extension.
* @details User fields added to the end of the @p thread_t structure.
*/
#define CH_CFG_THREAD_EXTRA_FIELDS \
/* Add threads custom fields here.*/
/**
* @brief Threads initialization hook.
* @details User initialization code added to the @p chThdInit() API.
*
* @note It is invoked from within @p chThdInit() and implicitly from all
* the threads creation APIs.
*/
#define CH_CFG_THREAD_INIT_HOOK(tp) { \
/* Add threads initialization code here.*/ \
}
/**
* @brief Threads finalization hook.
* @details User finalization code added to the @p chThdExit() API.
*
* @note It is inserted into lock zone.
* @note It is also invoked when the threads simply return in order to
* terminate.
*/
#define CH_CFG_THREAD_EXIT_HOOK(tp) { \
/* Add threads finalization code here.*/ \
}
/**
* @brief Context switch hook.
* @details This hook is invoked just before switching between threads.
*/
#define CH_CFG_CONTEXT_SWITCH_HOOK(ntp, otp) { \
/* Context switch code here.*/ \
}
/**
* @brief Idle thread enter hook.
* @note This hook is invoked within a critical zone, no OS functions
* should be invoked from here.
* @note This macro can be used to activate a power saving mode.
*/
#define CH_CFG_IDLE_ENTER_HOOK() { \
}
/**
* @brief Idle thread leave hook.
* @note This hook is invoked within a critical zone, no OS functions
* should be invoked from here.
* @note This macro can be used to deactivate a power saving mode.
*/
#define CH_CFG_IDLE_LEAVE_HOOK() { \
}
/**
* @brief Idle Loop hook.
* @details This hook is continuously invoked by the idle thread loop.
*/
#define CH_CFG_IDLE_LOOP_HOOK() { \
/* Idle loop code here.*/ \
}
/**
* @brief System tick event hook.
* @details This hook is invoked in the system tick handler immediately
* after processing the virtual timers queue.
*/
#define CH_CFG_SYSTEM_TICK_HOOK() { \
/* System tick event code here.*/ \
}
/**
* @brief System halt hook.
* @details This hook is invoked in case to a system halting error before
* the system is halted.
*/
#define CH_CFG_SYSTEM_HALT_HOOK(reason) { \
/* System halt code here.*/ \
}
/** @} */
/*===========================================================================*/
/* Port-specific settings (override port settings defaulted in chcore.h). */
/*===========================================================================*/
#endif /* _CHCONF_H_ */
/** @} */

View File

@ -0,0 +1,178 @@
/*
Copyright (C) 2016 Stephane D'Alu
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.
*/
/**
* @file templates/halconf.h
* @brief HAL configuration header.
* @details HAL configuration file, this file allows to enable or disable the
* various device drivers from your application. You may also use
* this file in order to override the device drivers default settings.
*
* @addtogroup HAL_CONF
* @{
*/
#ifndef _HALCONF_H_
#define _HALCONF_H_
#include "mcuconf.h"
/**
* @brief Enables the PAL subsystem.
*/
#if !defined(HAL_USE_PAL) || defined(__DOXYGEN__)
#define HAL_USE_PAL TRUE
#endif
/**
* @brief Enables the DAC subsystem.
*/
#if !defined(HAL_USE_DAC) || defined(__DOXYGEN__)
#define HAL_USE_DAC FALSE
#endif
/**
* @brief Enables the ADC subsystem.
*/
#if !defined(HAL_USE_ADC) || defined(__DOXYGEN__)
#define HAL_USE_ADC FALSE
#endif
/**
* @brief Enables the CAN subsystem.
*/
#if !defined(HAL_USE_CAN) || defined(__DOXYGEN__)
#define HAL_USE_CAN FALSE
#endif
/**
* @brief Enables the EXT subsystem.
*/
#if !defined(HAL_USE_EXT) || defined(__DOXYGEN__)
#define HAL_USE_EXT FALSE
#endif
/**
* @brief Enables the GPT subsystem.
*/
#if !defined(HAL_USE_GPT) || defined(__DOXYGEN__)
#define HAL_USE_GPT FALSE
#endif
/**
* @brief Enables the I2C subsystem.
*/
#if !defined(HAL_USE_I2C) || defined(__DOXYGEN__)
#define HAL_USE_I2C FALSE
#endif
/**
* @brief Enables the I2S subsystem.
*/
#if !defined(HAL_USE_I2S) || defined(__DOXYGEN__)
#define HAL_USE_I2S FALSE
#endif
/**
* @brief Enables the ICU subsystem.
*/
#if !defined(HAL_USE_ICU) || defined(__DOXYGEN__)
#define HAL_USE_ICU FALSE
#endif
/**
* @brief Enables the MAC subsystem.
*/
#if !defined(HAL_USE_MAC) || defined(__DOXYGEN__)
#define HAL_USE_MAC FALSE
#endif
/**
* @brief Enables the MMC_SPI subsystem.
*/
#if !defined(HAL_USE_MMC_SPI) || defined(__DOXYGEN__)
#define HAL_USE_MMC_SPI FALSE
#endif
/**
* @brief Enables the PWM subsystem.
*/
#if !defined(HAL_USE_PWM) || defined(__DOXYGEN__)
#define HAL_USE_PWM FALSE
#endif
/**
* @brief Enables the RTC subsystem.
*/
#if !defined(HAL_USE_RTC) || defined(__DOXYGEN__)
#define HAL_USE_RTC FALSE
#endif
/**
* @brief Enables the SDC subsystem.
*/
#if !defined(HAL_USE_SDC) || defined(__DOXYGEN__)
#define HAL_USE_SDC FALSE
#endif
/**
* @brief Enables the SERIAL subsystem.
*/
#if !defined(HAL_USE_SERIAL) || defined(__DOXYGEN__)
#define HAL_USE_SERIAL TRUE
#endif
/**
* @brief Enables the SERIAL over USB subsystem.
*/
#if !defined(HAL_USE_SERIAL_USB) || defined(__DOXYGEN__)
#define HAL_USE_SERIAL_USB FALSE
#endif
/**
* @brief Enables the SPI subsystem.
*/
#if !defined(HAL_USE_SPI) || defined(__DOXYGEN__)
#define HAL_USE_SPI FALSE
#endif
/**
* @brief Enables the UART subsystem.
*/
#if !defined(HAL_USE_UART) || defined(__DOXYGEN__)
#define HAL_USE_UART FALSE
#endif
/**
* @brief Enables the USB subsystem.
*/
#if !defined(HAL_USE_USB) || defined(__DOXYGEN__)
#define HAL_USE_USB FALSE
#endif
/**
* @brief Enables the WDG subsystem.
*/
#if !defined(HAL_USE_WDG) || defined(__DOXYGEN__)
#define HAL_USE_WDG FALSE
#endif
#include "halconf_community.h"
#endif /* _HALCONF_H_ */
/** @} */

View File

@ -0,0 +1,117 @@
/*
Copyright (C) 2016 Stéphane D'Alu
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.
*/
#ifndef _HALCONF_COMMUNITY_H_
#define _HALCONF_COMMUNITY_H_
/**
* @brief Enables the community overlay.
*/
#if !defined(HAL_USE_COMMUNITY) || defined(__DOXYGEN__)
#define HAL_USE_COMMUNITY TRUE
#endif
/**
* @brief Enables the FSMC subsystem.
*/
#if !defined(HAL_USE_FSMC) || defined(__DOXYGEN__)
#define HAL_USE_FSMC FALSE
#endif
/**
* @brief Enables the NAND subsystem.
*/
#if !defined(HAL_USE_NAND) || defined(__DOXYGEN__)
#define HAL_USE_NAND FALSE
#endif
/**
* @brief Enables the 1-wire subsystem.
*/
#if !defined(HAL_USE_ONEWIRE) || defined(__DOXYGEN__)
#define HAL_USE_ONEWIRE FALSE
#endif
/**
* @brief Enables the EICU subsystem.
*/
#if !defined(HAL_USE_EICU) || defined(__DOXYGEN__)
#define HAL_USE_EICU FALSE
#endif
/**
* @brief Enables the community subsystem.
*/
#if !defined(HAL_USE_CRC) || defined(__DOXYGEN__)
#define HAL_USE_CRC FALSE
#endif
/**
* @brief Enables the community subsystem.
*/
#if !defined(HAL_USE_RNG) || defined(__DOXYGEN__)
#define HAL_USE_RNG TRUE
#endif
/*===========================================================================*/
/* FSMCNAND driver related settings. */
/*===========================================================================*/
/**
* @brief Enables the @p nandAcquireBus() and @p nanReleaseBus() APIs.
* @note Disabling this option saves both code and data space.
*/
#if !defined(NAND_USE_MUTUAL_EXCLUSION) || defined(__DOXYGEN__)
#define NAND_USE_MUTUAL_EXCLUSION FALSE
#endif
/*===========================================================================*/
/* 1-wire driver related settings. */
/*===========================================================================*/
/**
* @brief Enables strong pull up feature.
* @note Disabling this option saves both code and data space.
*/
#define ONEWIRE_USE_STRONG_PULLUP FALSE
/**
* @brief Enables search ROM feature.
* @note Disabling this option saves both code and data space.
*/
#define ONEWIRE_USE_SEARCH_ROM FALSE
/*===========================================================================*/
/* CRC driver settings. */
/*===========================================================================*/
/**
* @brief Enables DMA engine when performing CRC transactions.
* @note Enabling this option also enables asynchronous API.
*/
#if !defined(CRC_USE_DMA) || defined(__DOXYGEN__)
#define CRC_USE_DMA FALSE
#endif
/**
* @brief Enables the @p crcAcquireUnit() and @p crcReleaseUnit() APIs.
* @note Disabling this option saves both code and data space.
*/
#if !defined(CRC_USE_MUTUAL_EXCLUSION) || defined(__DOXYGEN__)
#define CRC_USE_MUTUAL_EXCLUSION FALSE
#endif
#endif /* _HALCONF_COMMUNITY_H_ */
/** @} */

View File

@ -0,0 +1,118 @@
/*
Copyright (C) 2016 Stephane D'Alu
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.
*/
#include "ch.h"
#include "hal.h"
#include "shell.h"
#include "chprintf.h"
#include <stdlib.h>
/*
* Command Random
*/
#define RANDOM_BUFFER_SIZE 1024
static uint8_t random_buffer[RANDOM_BUFFER_SIZE];
static void cmd_random(BaseSequentialStream *chp, int argc, char *argv[]) {
uint16_t size = 16;
uint16_t i = 0;
uint8_t nl = 0;
if (argc > 0) {
size = atoi(argv[0]);
}
if (size > RANDOM_BUFFER_SIZE) {
chprintf(chp, "random: maximum size is %d.\r\n", RANDOM_BUFFER_SIZE);
return;
}
chprintf(chp, "Fetching %d random byte(s):\r\n", size);
rngStart(&RNGD1, NULL);
rngWrite(&RNGD1, random_buffer, size, TIME_INFINITE);
rngStop(&RNGD1);
for (i = 0 ; i < size ; i++) {
chprintf(chp, "%02x ", random_buffer[i]);
if (nl = (((i+1) % 20) == 0))
chprintf(chp, "\r\n");
}
if (!nl)
chprintf(chp, "\r\n");
}
/*
* Shell
*/
#define SHELL_WA_SIZE THD_WORKING_AREA_SIZE(2048)
static const ShellCommand commands[] = {
{"random", cmd_random},
{NULL, NULL}
};
static const ShellConfig shell_cfg1 = {
(BaseSequentialStream *)&SD1,
commands
};
/*
* Application entry point.
*/
int main(void) {
/*
* System initializations.
* - HAL initialization, this also initializes the configured device drivers
* and performs the board-specific initializations.
* - Kernel initialization, the main() function becomes a thread and the
* RTOS is active.
*/
halInit();
chSysInit();
/*
* Serial device
*/
SerialConfig serial_config = {
.speed = 115200,
.tx_pad = UART_TX,
.rx_pad = UART_RX,
};
sdStart(&SD1, &serial_config);
/*
* Shell manager initialization.
*/
shellInit();
shellCreate(&shell_cfg1, SHELL_WA_SIZE, NORMALPRIO);
/*
* Normal main() thread activity, in this demo it does nothing.
*/
while (true) {
chThdSleepMilliseconds(500);
palTogglePad(IOPORT1, LED1);
}
}

View File

@ -0,0 +1,24 @@
/*
Copyright (C) 2016 Stephane D'Alu
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.
*/
#ifndef _MCUCONF_H_
#define _MCUCONF_H_
#define NRF51_RNG_USE_RNG1 TRUE
#define NRF51_SERIAL_USE_UART0 TRUE
#endif /* _MCUCONF_H_ */

View File

@ -0,0 +1,17 @@
*****************************************************************************
** ChibiOS/HAL - GPT driver demo for NRF51x22. **
*****************************************************************************
** TARGET **
The demo runs on an NRF51-DK board.
** The Demo **
The application demonstrates the use of the NRF51x22 RNG driver.
** Board Setup **
** Build Procedure **
Just modify the TRGT line in the makefile in order to use different GCC ports.

View File

@ -0,0 +1,217 @@
##############################################################################
# Build global options
# NOTE: Can be overridden externally.
#
# Compiler options here.
ifeq ($(USE_OPT),)
USE_OPT = -O2 -ggdb -fomit-frame-pointer -falign-functions=16
endif
# C specific options here (added to USE_OPT).
ifeq ($(USE_COPT),)
USE_COPT =
endif
# C++ specific options here (added to USE_OPT).
ifeq ($(USE_CPPOPT),)
USE_CPPOPT = -fno-rtti
endif
# Enable this if you want the linker to remove unused code and data
ifeq ($(USE_LINK_GC),)
USE_LINK_GC = yes
endif
# Linker extra options here.
ifeq ($(USE_LDOPT),)
USE_LDOPT =
endif
# Enable this if you want link time optimizations (LTO)
ifeq ($(USE_LTO),)
USE_LTO = yes
endif
# If enabled, this option allows to compile the application in THUMB mode.
ifeq ($(USE_THUMB),)
USE_THUMB = yes
endif
# Enable this if you want to see the full log while compiling.
ifeq ($(USE_VERBOSE_COMPILE),)
USE_VERBOSE_COMPILE = no
endif
# If enabled, this option makes the build process faster by not compiling
# modules not used in the current configuration.
ifeq ($(USE_SMART_BUILD),)
USE_SMART_BUILD = yes
endif
#
# Build global options
##############################################################################
##############################################################################
# Architecture or project specific options
#
# Stack size to be allocated to the Cortex-M process stack. This stack is
# the stack used by the main() thread.
ifeq ($(USE_PROCESS_STACKSIZE),)
USE_PROCESS_STACKSIZE = 0x400
endif
# Stack size to the allocated to the Cortex-M main/exceptions stack. This
# stack is used for processing interrupts and exceptions.
ifeq ($(USE_EXCEPTIONS_STACKSIZE),)
USE_EXCEPTIONS_STACKSIZE = 0x400
endif
# Enables the use of FPU on Cortex-M4 (no, softfp, hard).
ifeq ($(USE_FPU),)
USE_FPU = no
endif
#
# Architecture or project specific options
##############################################################################
##############################################################################
# Project, sources and paths
#
# Define project name here
PROJECT = ch
# Imported source files and paths
CHIBIOS = ../../../../../ChibiOS-RT
CHIBIOS_CONTRIB = $(CHIBIOS)/../ChibiOS-Contrib
# Startup files.
include $(CHIBIOS)/os/common/ports/ARMCMx/compilers/GCC/mk/startup_stm32f3xx.mk
# HAL-OSAL files (optional).
include $(CHIBIOS_CONTRIB)/os/hal/hal.mk
include $(CHIBIOS_CONTRIB)/os/hal/ports/STM32/STM32F3xx/platform.mk
include $(CHIBIOS)/os/hal/boards/ST_STM32F3_DISCOVERY/board.mk
include $(CHIBIOS)/os/hal/osal/rt/osal.mk
# RTOS files (optional).
include $(CHIBIOS)/os/rt/rt.mk
include $(CHIBIOS)/os/rt/ports/ARMCMx/compilers/GCC/mk/port_v7m.mk
# Other files (optional).
#include $(CHIBIOS)/test/rt/test.mk
# Define linker script file here
LDSCRIPT= $(STARTUPLD)/STM32F303xC.ld
# C sources that can be compiled in ARM or THUMB mode depending on the global
# setting.
CSRC = $(STARTUPSRC) \
$(KERNSRC) \
$(PORTSRC) \
$(OSALSRC) \
$(HALSRC) \
$(PLATFORMSRC) \
$(BOARDSRC) \
$(TESTSRC) \
main.c
# C++ sources that can be compiled in ARM or THUMB mode depending on the global
# setting.
CPPSRC =
# C sources to be compiled in ARM mode regardless of the global setting.
# NOTE: Mixing ARM and THUMB mode enables the -mthumb-interwork compiler
# option that results in lower performance and larger code size.
ACSRC =
# C++ sources to be compiled in ARM mode regardless of the global setting.
# NOTE: Mixing ARM and THUMB mode enables the -mthumb-interwork compiler
# option that results in lower performance and larger code size.
ACPPSRC =
# C sources to be compiled in THUMB mode regardless of the global setting.
# NOTE: Mixing ARM and THUMB mode enables the -mthumb-interwork compiler
# option that results in lower performance and larger code size.
TCSRC =
# C sources to be compiled in THUMB mode regardless of the global setting.
# NOTE: Mixing ARM and THUMB mode enables the -mthumb-interwork compiler
# option that results in lower performance and larger code size.
TCPPSRC =
# List ASM source files here
ASMSRC = $(STARTUPASM) $(PORTASM) $(OSALASM)
INCDIR = $(STARTUPINC) $(KERNINC) $(PORTINC) $(OSALINC) \
$(HALINC) $(PLATFORMINC) $(BOARDINC) $(TESTINC) \
$(CHIBIOS)/os/various
#
# Project, sources and paths
##############################################################################
##############################################################################
# Compiler settings
#
MCU = cortex-m4
#TRGT = arm-elf-
TRGT = arm-none-eabi-
CC = $(TRGT)gcc
CPPC = $(TRGT)g++
# Enable loading with g++ only if you need C++ runtime support.
# NOTE: You can use C++ even without C++ support if you are careful. C++
# runtime support makes code size explode.
LD = $(TRGT)gcc
#LD = $(TRGT)g++
CP = $(TRGT)objcopy
AS = $(TRGT)gcc -x assembler-with-cpp
AR = $(TRGT)ar
OD = $(TRGT)objdump
SZ = $(TRGT)size
HEX = $(CP) -O ihex
BIN = $(CP) -O binary
# ARM-specific options here
AOPT =
# THUMB-specific options here
TOPT = -mthumb -DTHUMB
# Define C warning options here
CWARN = -Wall -Wextra -Wundef -Wstrict-prototypes
# Define C++ warning options here
CPPWARN = -Wall -Wextra -Wundef
#
# Compiler settings
##############################################################################
##############################################################################
# Start of user section
#
# List all user C define here, like -D_DEBUG=1
UDEFS =
# Define ASM defines here
UADEFS =
# List all user directories here
UINCDIR =
# List the user directory to look for the libraries here
ULIBDIR =
# List all user libraries here
ULIBS =
#
# End of user defines
##############################################################################
RULESPATH = $(CHIBIOS)/os/common/ports/ARMCMx/compilers/GCC
include $(RULESPATH)/rules.mk

View File

@ -0,0 +1,499 @@
/*
ChibiOS - Copyright (C) 2006..2015 Giovanni Di Sirio
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.
*/
/**
* @file templates/chconf.h
* @brief Configuration file template.
* @details A copy of this file must be placed in each project directory, it
* contains the application specific kernel settings.
*
* @addtogroup config
* @details Kernel related settings and hooks.
* @{
*/
#ifndef _CHCONF_H_
#define _CHCONF_H_
/*===========================================================================*/
/**
* @name System timers settings
* @{
*/
/*===========================================================================*/
/**
* @brief System time counter resolution.
* @note Allowed values are 16 or 32 bits.
*/
#define CH_CFG_ST_RESOLUTION 32
/**
* @brief System tick frequency.
* @details Frequency of the system timer that drives the system ticks. This
* setting also defines the system tick time unit.
*/
#define CH_CFG_ST_FREQUENCY 10000
/**
* @brief Time delta constant for the tick-less mode.
* @note If this value is zero then the system uses the classic
* periodic tick. This value represents the minimum number
* of ticks that is safe to specify in a timeout directive.
* The value one is not valid, timeouts are rounded up to
* this value.
*/
#define CH_CFG_ST_TIMEDELTA 2
/** @} */
/*===========================================================================*/
/**
* @name Kernel parameters and options
* @{
*/
/*===========================================================================*/
/**
* @brief Round robin interval.
* @details This constant is the number of system ticks allowed for the
* threads before preemption occurs. Setting this value to zero
* disables the preemption for threads with equal priority and the
* round robin becomes cooperative. Note that higher priority
* threads can still preempt, the kernel is always preemptive.
* @note Disabling the round robin preemption makes the kernel more compact
* and generally faster.
* @note The round robin preemption is not supported in tickless mode and
* must be set to zero in that case.
*/
#define CH_CFG_TIME_QUANTUM 0
/**
* @brief Managed RAM size.
* @details Size of the RAM area to be managed by the OS. If set to zero
* then the whole available RAM is used. The core memory is made
* available to the heap allocator and/or can be used directly through
* the simplified core memory allocator.
*
* @note In order to let the OS manage the whole RAM the linker script must
* provide the @p __heap_base__ and @p __heap_end__ symbols.
* @note Requires @p CH_CFG_USE_MEMCORE.
*/
#define CH_CFG_MEMCORE_SIZE 0
/**
* @brief Idle thread automatic spawn suppression.
* @details When this option is activated the function @p chSysInit()
* does not spawn the idle thread. The application @p main()
* function becomes the idle thread and must implement an
* infinite loop.
*/
#define CH_CFG_NO_IDLE_THREAD FALSE
/** @} */
/*===========================================================================*/
/**
* @name Performance options
* @{
*/
/*===========================================================================*/
/**
* @brief OS optimization.
* @details If enabled then time efficient rather than space efficient code
* is used when two possible implementations exist.
*
* @note This is not related to the compiler optimization options.
* @note The default is @p TRUE.
*/
#define CH_CFG_OPTIMIZE_SPEED TRUE
/** @} */
/*===========================================================================*/
/**
* @name Subsystem options
* @{
*/
/*===========================================================================*/
/**
* @brief Time Measurement APIs.
* @details If enabled then the time measurement APIs are included in
* the kernel.
*
* @note The default is @p TRUE.
*/
#define CH_CFG_USE_TM TRUE
/**
* @brief Threads registry APIs.
* @details If enabled then the registry APIs are included in the kernel.
*
* @note The default is @p TRUE.
*/
#define CH_CFG_USE_REGISTRY TRUE
/**
* @brief Threads synchronization APIs.
* @details If enabled then the @p chThdWait() function is included in
* the kernel.
*
* @note The default is @p TRUE.
*/
#define CH_CFG_USE_WAITEXIT TRUE
/**
* @brief Semaphores APIs.
* @details If enabled then the Semaphores APIs are included in the kernel.
*
* @note The default is @p TRUE.
*/
#define CH_CFG_USE_SEMAPHORES TRUE
/**
* @brief Semaphores queuing mode.
* @details If enabled then the threads are enqueued on semaphores by
* priority rather than in FIFO order.
*
* @note The default is @p FALSE. Enable this if you have special
* requirements.
* @note Requires @p CH_CFG_USE_SEMAPHORES.
*/
#define CH_CFG_USE_SEMAPHORES_PRIORITY FALSE
/**
* @brief Mutexes APIs.
* @details If enabled then the mutexes APIs are included in the kernel.
*
* @note The default is @p TRUE.
*/
#define CH_CFG_USE_MUTEXES TRUE
/**
* @brief Enables recursive behavior on mutexes.
* @note Recursive mutexes are heavier and have an increased
* memory footprint.
*
* @note The default is @p FALSE.
* @note Requires @p CH_CFG_USE_MUTEXES.
*/
#define CH_CFG_USE_MUTEXES_RECURSIVE FALSE
/**
* @brief Conditional Variables APIs.
* @details If enabled then the conditional variables APIs are included
* in the kernel.
*
* @note The default is @p TRUE.
* @note Requires @p CH_CFG_USE_MUTEXES.
*/
#define CH_CFG_USE_CONDVARS TRUE
/**
* @brief Conditional Variables APIs with timeout.
* @details If enabled then the conditional variables APIs with timeout
* specification are included in the kernel.
*
* @note The default is @p TRUE.
* @note Requires @p CH_CFG_USE_CONDVARS.
*/
#define CH_CFG_USE_CONDVARS_TIMEOUT TRUE
/**
* @brief Events Flags APIs.
* @details If enabled then the event flags APIs are included in the kernel.
*
* @note The default is @p TRUE.
*/
#define CH_CFG_USE_EVENTS TRUE
/**
* @brief Events Flags APIs with timeout.
* @details If enabled then the events APIs with timeout specification
* are included in the kernel.
*
* @note The default is @p TRUE.
* @note Requires @p CH_CFG_USE_EVENTS.
*/
#define CH_CFG_USE_EVENTS_TIMEOUT TRUE
/**
* @brief Synchronous Messages APIs.
* @details If enabled then the synchronous messages APIs are included
* in the kernel.
*
* @note The default is @p TRUE.
*/
#define CH_CFG_USE_MESSAGES TRUE
/**
* @brief Synchronous Messages queuing mode.
* @details If enabled then messages are served by priority rather than in
* FIFO order.
*
* @note The default is @p FALSE. Enable this if you have special
* requirements.
* @note Requires @p CH_CFG_USE_MESSAGES.
*/
#define CH_CFG_USE_MESSAGES_PRIORITY FALSE
/**
* @brief Mailboxes APIs.
* @details If enabled then the asynchronous messages (mailboxes) APIs are
* included in the kernel.
*
* @note The default is @p TRUE.
* @note Requires @p CH_CFG_USE_SEMAPHORES.
*/
#define CH_CFG_USE_MAILBOXES TRUE
/**
* @brief I/O Queues APIs.
* @details If enabled then the I/O queues APIs are included in the kernel.
*
* @note The default is @p TRUE.
*/
#define CH_CFG_USE_QUEUES TRUE
/**
* @brief Core Memory Manager APIs.
* @details If enabled then the core memory manager APIs are included
* in the kernel.
*
* @note The default is @p TRUE.
*/
#define CH_CFG_USE_MEMCORE TRUE
/**
* @brief Heap Allocator APIs.
* @details If enabled then the memory heap allocator APIs are included
* in the kernel.
*
* @note The default is @p TRUE.
* @note Requires @p CH_CFG_USE_MEMCORE and either @p CH_CFG_USE_MUTEXES or
* @p CH_CFG_USE_SEMAPHORES.
* @note Mutexes are recommended.
*/
#define CH_CFG_USE_HEAP TRUE
/**
* @brief Memory Pools Allocator APIs.
* @details If enabled then the memory pools allocator APIs are included
* in the kernel.
*
* @note The default is @p TRUE.
*/
#define CH_CFG_USE_MEMPOOLS TRUE
/**
* @brief Dynamic Threads APIs.
* @details If enabled then the dynamic threads creation APIs are included
* in the kernel.
*
* @note The default is @p TRUE.
* @note Requires @p CH_CFG_USE_WAITEXIT.
* @note Requires @p CH_CFG_USE_HEAP and/or @p CH_CFG_USE_MEMPOOLS.
*/
#define CH_CFG_USE_DYNAMIC TRUE
/** @} */
/*===========================================================================*/
/**
* @name Debug options
* @{
*/
/*===========================================================================*/
/**
* @brief Debug option, kernel statistics.
*
* @note The default is @p FALSE.
*/
#define CH_DBG_STATISTICS TRUE
/**
* @brief Debug option, system state check.
* @details If enabled the correct call protocol for system APIs is checked
* at runtime.
*
* @note The default is @p FALSE.
*/
#define CH_DBG_SYSTEM_STATE_CHECK TRUE
/**
* @brief Debug option, parameters checks.
* @details If enabled then the checks on the API functions input
* parameters are activated.
*
* @note The default is @p FALSE.
*/
#define CH_DBG_ENABLE_CHECKS TRUE
/**
* @brief Debug option, consistency checks.
* @details If enabled then all the assertions in the kernel code are
* activated. This includes consistency checks inside the kernel,
* runtime anomalies and port-defined checks.
*
* @note The default is @p FALSE.
*/
#define CH_DBG_ENABLE_ASSERTS TRUE
/**
* @brief Debug option, trace buffer.
* @details If enabled then the context switch circular trace buffer is
* activated.
*
* @note The default is @p FALSE.
*/
#define CH_DBG_ENABLE_TRACE TRUE
/**
* @brief Debug option, stack checks.
* @details If enabled then a runtime stack check is performed.
*
* @note The default is @p FALSE.
* @note The stack check is performed in a architecture/port dependent way.
* It may not be implemented or some ports.
* @note The default failure mode is to halt the system with the global
* @p panic_msg variable set to @p NULL.
*/
#define CH_DBG_ENABLE_STACK_CHECK TRUE
/**
* @brief Debug option, stacks initialization.
* @details If enabled then the threads working area is filled with a byte
* value when a thread is created. This can be useful for the
* runtime measurement of the used stack.
*
* @note The default is @p FALSE.
*/
#define CH_DBG_FILL_THREADS TRUE
/**
* @brief Debug option, threads profiling.
* @details If enabled then a field is added to the @p thread_t structure that
* counts the system ticks occurred while executing the thread.
*
* @note The default is @p FALSE.
* @note This debug option is not currently compatible with the
* tickless mode.
*/
#define CH_DBG_THREADS_PROFILING FALSE
/** @} */
/*===========================================================================*/
/**
* @name Kernel hooks
* @{
*/
/*===========================================================================*/
/**
* @brief Threads descriptor structure extension.
* @details User fields added to the end of the @p thread_t structure.
*/
#define CH_CFG_THREAD_EXTRA_FIELDS \
/* Add threads custom fields here.*/
/**
* @brief Threads initialization hook.
* @details User initialization code added to the @p chThdInit() API.
*
* @note It is invoked from within @p chThdInit() and implicitly from all
* the threads creation APIs.
*/
#define CH_CFG_THREAD_INIT_HOOK(tp) { \
/* Add threads initialization code here.*/ \
}
/**
* @brief Threads finalization hook.
* @details User finalization code added to the @p chThdExit() API.
*
* @note It is inserted into lock zone.
* @note It is also invoked when the threads simply return in order to
* terminate.
*/
#define CH_CFG_THREAD_EXIT_HOOK(tp) { \
/* Add threads finalization code here.*/ \
}
/**
* @brief Context switch hook.
* @details This hook is invoked just before switching between threads.
*/
#define CH_CFG_CONTEXT_SWITCH_HOOK(ntp, otp) { \
/* Context switch code here.*/ \
}
/**
* @brief Idle thread enter hook.
* @note This hook is invoked within a critical zone, no OS functions
* should be invoked from here.
* @note This macro can be used to activate a power saving mode.
*/
#define CH_CFG_IDLE_ENTER_HOOK() { \
}
/**
* @brief Idle thread leave hook.
* @note This hook is invoked within a critical zone, no OS functions
* should be invoked from here.
* @note This macro can be used to deactivate a power saving mode.
*/
#define CH_CFG_IDLE_LEAVE_HOOK() { \
}
/**
* @brief Idle Loop hook.
* @details This hook is continuously invoked by the idle thread loop.
*/
#define CH_CFG_IDLE_LOOP_HOOK() { \
/* Idle loop code here.*/ \
}
/**
* @brief System tick event hook.
* @details This hook is invoked in the system tick handler immediately
* after processing the virtual timers queue.
*/
#define CH_CFG_SYSTEM_TICK_HOOK() { \
/* System tick event code here.*/ \
}
/**
* @brief System halt hook.
* @details This hook is invoked in case to a system halting error before
* the system is halted.
*/
#define CH_CFG_SYSTEM_HALT_HOOK(reason) { \
/* System halt code here.*/ \
}
/** @} */
/*===========================================================================*/
/* Port-specific settings (override port settings defaulted in chcore.h). */
/*===========================================================================*/
#endif /* _CHCONF_H_ */
/** @} */

View File

@ -0,0 +1,387 @@
/*
ChibiOS - Copyright (C) 2006..2015 Giovanni Di Sirio
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.
*/
/**
* @file templates/halconf.h
* @brief HAL configuration header.
* @details HAL configuration file, this file allows to enable or disable the
* various device drivers from your application. You may also use
* this file in order to override the device drivers default settings.
*
* @addtogroup HAL_CONF
* @{
*/
#ifndef _HALCONF_H_
#define _HALCONF_H_
#include "mcuconf.h"
/**
* @brief Enables the PAL subsystem.
*/
#if !defined(HAL_USE_PAL) || defined(__DOXYGEN__)
#define HAL_USE_PAL TRUE
#endif
/**
* @brief Enables the ADC subsystem.
*/
#if !defined(HAL_USE_ADC) || defined(__DOXYGEN__)
#define HAL_USE_ADC FALSE
#endif
/**
* @brief Enables the CAN subsystem.
*/
#if !defined(HAL_USE_CAN) || defined(__DOXYGEN__)
#define HAL_USE_CAN FALSE
#endif
/**
* @brief Enables the DAC subsystem.
*/
#if !defined(HAL_USE_DAC) || defined(__DOXYGEN__)
#define HAL_USE_DAC FALSE
#endif
/**
* @brief Enables the EXT subsystem.
*/
#if !defined(HAL_USE_EXT) || defined(__DOXYGEN__)
#define HAL_USE_EXT FALSE
#endif
/**
* @brief Enables the GPT subsystem.
*/
#if !defined(HAL_USE_GPT) || defined(__DOXYGEN__)
#define HAL_USE_GPT FALSE
#endif
/**
* @brief Enables the I2C subsystem.
*/
#if !defined(HAL_USE_I2C) || defined(__DOXYGEN__)
#define HAL_USE_I2C TRUE
#endif
/**
* @brief Enables the I2S subsystem.
*/
#if !defined(HAL_USE_I2S) || defined(__DOXYGEN__)
#define HAL_USE_I2S FALSE
#endif
/**
* @brief Enables the ICU subsystem.
*/
#if !defined(HAL_USE_ICU) || defined(__DOXYGEN__)
#define HAL_USE_ICU FALSE
#endif
/**
* @brief Enables the MAC subsystem.
*/
#if !defined(HAL_USE_MAC) || defined(__DOXYGEN__)
#define HAL_USE_MAC FALSE
#endif
/**
* @brief Enables the MMC_SPI subsystem.
*/
#if !defined(HAL_USE_MMC_SPI) || defined(__DOXYGEN__)
#define HAL_USE_MMC_SPI FALSE
#endif
/**
* @brief Enables the PWM subsystem.
*/
#if !defined(HAL_USE_PWM) || defined(__DOXYGEN__)
#define HAL_USE_PWM FALSE
#endif
/**
* @brief Enables the RTC subsystem.
*/
#if !defined(HAL_USE_RTC) || defined(__DOXYGEN__)
#define HAL_USE_RTC FALSE
#endif
/**
* @brief Enables the SDC subsystem.
*/
#if !defined(HAL_USE_SDC) || defined(__DOXYGEN__)
#define HAL_USE_SDC FALSE
#endif
/**
* @brief Enables the SERIAL subsystem.
*/
#if !defined(HAL_USE_SERIAL) || defined(__DOXYGEN__)
#define HAL_USE_SERIAL FALSE
#endif
/**
* @brief Enables the SERIAL over USB subsystem.
*/
#if !defined(HAL_USE_SERIAL_USB) || defined(__DOXYGEN__)
#define HAL_USE_SERIAL_USB FALSE
#endif
/**
* @brief Enables the SPI subsystem.
*/
#if !defined(HAL_USE_SPI) || defined(__DOXYGEN__)
#define HAL_USE_SPI TRUE
#endif
/**
* @brief Enables the UART subsystem.
*/
#if !defined(HAL_USE_UART) || defined(__DOXYGEN__)
#define HAL_USE_UART FALSE
#endif
/**
* @brief Enables the USB subsystem.
*/
#if !defined(HAL_USE_USB) || defined(__DOXYGEN__)
#define HAL_USE_USB FALSE
#endif
/**
* @brief Enables the WDG subsystem.
*/
#if !defined(HAL_USE_WDG) || defined(__DOXYGEN__)
#define HAL_USE_WDG TRUE
#endif
/*===========================================================================*/
/* ADC driver related settings. */
/*===========================================================================*/
/**
* @brief Enables synchronous APIs.
* @note Disabling this option saves both code and data space.
*/
#if !defined(ADC_USE_WAIT) || defined(__DOXYGEN__)
#define ADC_USE_WAIT TRUE
#endif
/**
* @brief Enables the @p adcAcquireBus() and @p adcReleaseBus() APIs.
* @note Disabling this option saves both code and data space.
*/
#if !defined(ADC_USE_MUTUAL_EXCLUSION) || defined(__DOXYGEN__)
#define ADC_USE_MUTUAL_EXCLUSION TRUE
#endif
/*===========================================================================*/
/* CAN driver related settings. */
/*===========================================================================*/
/**
* @brief Sleep mode related APIs inclusion switch.
*/
#if !defined(CAN_USE_SLEEP_MODE) || defined(__DOXYGEN__)
#define CAN_USE_SLEEP_MODE TRUE
#endif
/*===========================================================================*/
/* I2C driver related settings. */
/*===========================================================================*/
/**
* @brief Enables the mutual exclusion APIs on the I2C bus.
*/
#if !defined(I2C_USE_MUTUAL_EXCLUSION) || defined(__DOXYGEN__)
#define I2C_USE_MUTUAL_EXCLUSION TRUE
#endif
/*===========================================================================*/
/* MAC driver related settings. */
/*===========================================================================*/
/**
* @brief Enables an event sources for incoming packets.
*/
#if !defined(MAC_USE_ZERO_COPY) || defined(__DOXYGEN__)
#define MAC_USE_ZERO_COPY FALSE
#endif
/**
* @brief Enables an event sources for incoming packets.
*/
#if !defined(MAC_USE_EVENTS) || defined(__DOXYGEN__)
#define MAC_USE_EVENTS TRUE
#endif
/*===========================================================================*/
/* MMC_SPI driver related settings. */
/*===========================================================================*/
/**
* @brief Delays insertions.
* @details If enabled this options inserts delays into the MMC waiting
* routines releasing some extra CPU time for the threads with
* lower priority, this may slow down the driver a bit however.
* This option is recommended also if the SPI driver does not
* use a DMA channel and heavily loads the CPU.
*/
#if !defined(MMC_NICE_WAITING) || defined(__DOXYGEN__)
#define MMC_NICE_WAITING TRUE
#endif
/*===========================================================================*/
/* SDC driver related settings. */
/*===========================================================================*/
/**
* @brief Number of initialization attempts before rejecting the card.
* @note Attempts are performed at 10mS intervals.
*/
#if !defined(SDC_INIT_RETRY) || defined(__DOXYGEN__)
#define SDC_INIT_RETRY 100
#endif
/**
* @brief Include support for MMC cards.
* @note MMC support is not yet implemented so this option must be kept
* at @p FALSE.
*/
#if !defined(SDC_MMC_SUPPORT) || defined(__DOXYGEN__)
#define SDC_MMC_SUPPORT FALSE
#endif
/**
* @brief Delays insertions.
* @details If enabled this options inserts delays into the MMC waiting
* routines releasing some extra CPU time for the threads with
* lower priority, this may slow down the driver a bit however.
*/
#if !defined(SDC_NICE_WAITING) || defined(__DOXYGEN__)
#define SDC_NICE_WAITING TRUE
#endif
/*===========================================================================*/
/* SERIAL driver related settings. */
/*===========================================================================*/
/**
* @brief Default bit rate.
* @details Configuration parameter, this is the baud rate selected for the
* default configuration.
*/
#if !defined(SERIAL_DEFAULT_BITRATE) || defined(__DOXYGEN__)
#define SERIAL_DEFAULT_BITRATE 38400
#endif
/**
* @brief Serial buffers size.
* @details Configuration parameter, you can change the depth of the queue
* buffers depending on the requirements of your application.
* @note The default is 16 bytes for both the transmission and receive
* buffers.
*/
#if !defined(SERIAL_BUFFERS_SIZE) || defined(__DOXYGEN__)
#define SERIAL_BUFFERS_SIZE 16
#endif
/*===========================================================================*/
/* SERIAL_USB driver related setting. */
/*===========================================================================*/
/**
* @brief Serial over USB buffers size.
* @details Configuration parameter, the buffer size must be a multiple of
* the USB data endpoint maximum packet size.
* @note The default is 256 bytes for both the transmission and receive
* buffers.
*/
#if !defined(SERIAL_USB_BUFFERS_SIZE) || defined(__DOXYGEN__)
#define SERIAL_USB_BUFFERS_SIZE 256
#endif
/**
* @brief Serial over USB number of buffers.
* @note The default is 2 buffers.
*/
#if !defined(SERIAL_USB_BUFFERS_NUMBER) || defined(__DOXYGEN__)
#define SERIAL_USB_BUFFERS_NUMBER 2
#endif
/*===========================================================================*/
/* SPI driver related settings. */
/*===========================================================================*/
/**
* @brief Enables synchronous APIs.
* @note Disabling this option saves both code and data space.
*/
#if !defined(SPI_USE_WAIT) || defined(__DOXYGEN__)
#define SPI_USE_WAIT TRUE
#endif
/**
* @brief Enables the @p spiAcquireBus() and @p spiReleaseBus() APIs.
* @note Disabling this option saves both code and data space.
*/
#if !defined(SPI_USE_MUTUAL_EXCLUSION) || defined(__DOXYGEN__)
#define SPI_USE_MUTUAL_EXCLUSION TRUE
#endif
/*===========================================================================*/
/* UART driver related settings. */
/*===========================================================================*/
/**
* @brief Enables synchronous APIs.
* @note Disabling this option saves both code and data space.
*/
#if !defined(UART_USE_WAIT) || defined(__DOXYGEN__)
#define UART_USE_WAIT FALSE
#endif
/**
* @brief Enables the @p uartAcquireBus() and @p uartReleaseBus() APIs.
* @note Disabling this option saves both code and data space.
*/
#if !defined(UART_USE_MUTUAL_EXCLUSION) || defined(__DOXYGEN__)
#define UART_USE_MUTUAL_EXCLUSION FALSE
#endif
/*===========================================================================*/
/* USB driver related settings. */
/*===========================================================================*/
/**
* @brief Enables synchronous APIs.
* @note Disabling this option saves both code and data space.
*/
#if !defined(USB_USE_WAIT) || defined(__DOXYGEN__)
#define USB_USE_WAIT FALSE
#endif
/*===========================================================================*/
/* Community drivers's includes */
/*===========================================================================*/
#include "halconf_community.h"
#endif /* _HALCONF_H_ */
/** @} */

View File

@ -0,0 +1,114 @@
/*
ChibiOS - Copyright (C) 2014 Uladzimir Pylinsky aka barthess
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.
*/
#ifndef _HALCONF_COMMUNITY_H_
#define _HALCONF_COMMUNITY_H_
/**
* @brief Enables the community overlay.
*/
#if !defined(HAL_USE_COMMUNITY) || defined(__DOXYGEN__)
#define HAL_USE_COMMUNITY TRUE
#endif
/**
* @brief Enables the FSMC subsystem.
*/
#if !defined(HAL_USE_FSMC) || defined(__DOXYGEN__)
#define HAL_USE_FSMC FALSE
#endif
/**
* @brief Enables the NAND subsystem.
*/
#if !defined(HAL_USE_NAND) || defined(__DOXYGEN__)
#define HAL_USE_NAND FALSE
#endif
/**
* @brief Enables the 1-wire subsystem.
*/
#if !defined(HAL_USE_ONEWIRE) || defined(__DOXYGEN__)
#define HAL_USE_ONEWIRE FALSE
#endif
/**
* @brief Enables the EICU subsystem.
*/
#if !defined(HAL_USE_EICU) || defined(__DOXYGEN__)
#define HAL_USE_EICU FALSE
#endif
/**
* @brief Enables the community subsystem.
*/
#if !defined(HAL_USE_CRC) || defined(__DOXYGEN__)
#define HAL_USE_CRC FALSE
#endif
/**
* @brief Enables the EEPROM subsystem.
*/
#if !defined(HAL_USE_EEPROM) || defined(__DOXYGEN__)
#define HAL_USE_EEPROM TRUE
#endif
/*===========================================================================*/
/* FSMCNAND driver related settings. */
/*===========================================================================*/
/**
* @brief Enables the @p nandAcquireBus() and @p nanReleaseBus() APIs.
* @note Disabling this option saves both code and data space.
*/
#if !defined(NAND_USE_MUTUAL_EXCLUSION) || defined(__DOXYGEN__)
#define NAND_USE_MUTUAL_EXCLUSION TRUE
#endif
/*===========================================================================*/
/* 1-wire driver related settings. */
/*===========================================================================*/
/**
* @brief Enables strong pull up feature.
* @note Disabling this option saves both code and data space.
*/
#define ONEWIRE_USE_STRONG_PULLUP FALSE
/**
* @brief Enables search ROM feature.
* @note Disabling this option saves both code and data space.
*/
#define ONEWIRE_USE_SEARCH_ROM TRUE
/*===========================================================================*/
/* EEProm driver related settings. */
/*===========================================================================*/
/**
* @brief Enables 24xx series I2C eeprom device driver.
* @note Disabling this option saves both code and data space.
*/
#define EEPROM_USE_EE24XX TRUE
/**
* @brief Enables 25xx series SPI eeprom device driver.
* @note Disabling this option saves both code and data space.
*/
#define EEPROM_USE_EE25XX TRUE
#endif /* _HALCONF_COMMUNITY_H_ */
/** @} */

View File

@ -0,0 +1,99 @@
/*
ChibiOS - Copyright (C) 2006..2015 Giovanni Di Sirio
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.
*/
#include "ch.h"
#include "hal.h"
#define EEPROM_SIZE 8192 // 64Kb, 8KB
#define EEPROM_PAGE_SIZE 32
#define EEPROM_WRITE_TIME_MS 10 // byte/page write time
#define EEPROM_SPID SPID1
#define EEPROM_SPIDCONFIG spi1cfg
static const SPIConfig EEPROM_SPIDCONFIG = {
NULL,
GPIOA,
12,
0, // Up to 20Mhz
SPI_CR2_DS_2 | SPI_CR2_DS_1 | SPI_CR2_DS_0
};
static SPIEepromFileConfig eeCfg = {
0,
EEPROM_SIZE,
EEPROM_SIZE,
EEPROM_PAGE_SIZE,
MS2ST(EEPROM_WRITE_TIME_MS),
&EEPROM_SPID,
&EEPROM_SPIDCONFIG,
};
static SPIEepromFileStream eeFile;
static EepromFileStream *eeFS;
static uint8_t buffer[64];
THD_WORKING_AREA(waThreadEE, 256);
static THD_FUNCTION(ThreadEE, arg)
{
(void)arg;
uint8_t len = 64;
while (TRUE)
{
eeFS = SPIEepromFileOpen(&eeFile, &eeCfg, EepromFindDevice(EEPROM_DEV_25XX));
fileStreamSeek(eeFS, 0);
fileStreamWrite(eeFS, buffer, len);
fileStreamRead(eeFS, buffer, len);
fileStreamClose(eeFS);
chThdSleepMilliseconds(500);
}
return;
}
/*
* Application entry point.
*/
int main(void) {
/*
* System initializations.
* - HAL initialization, this also initializes the configured device drivers
* and performs the board-specific initializations.
* - Kernel initialization, the main() function becomes a thread and the
* RTOS is active.
*/
halInit();
chSysInit();
spiStart(&EEPROM_SPID, &EEPROM_SPIDCONFIG);
chThdCreateStatic(waThreadEE, sizeof(waThreadEE), NORMALPRIO, ThreadEE, NULL);
/*
* Normal main() thread activity, it resets the watchdog.
*/
while (true) {
palToggleLine(LINE_LED4_BLUE);
chThdSleepMilliseconds(500);
}
return 0;
}

View File

@ -0,0 +1,258 @@
/*
ChibiOS - Copyright (C) 2006..2015 Giovanni Di Sirio
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.
*/
#ifndef _MCUCONF_H_
#define _MCUCONF_H_
/*
* STM32F3xx drivers configuration.
* The following settings override the default settings present in
* the various device driver implementation headers.
* Note that the settings for each driver only have effect if the whole
* driver is enabled in halconf.h.
*
* IRQ priorities:
* 15...0 Lowest...Highest.
*
* DMA priorities:
* 0...3 Lowest...Highest.
*/
#define STM32F3xx_MCUCONF
/*
* HAL driver system settings.
*/
#define STM32_NO_INIT FALSE
#define STM32_PVD_ENABLE FALSE
#define STM32_PLS STM32_PLS_LEV0
#define STM32_HSI_ENABLED TRUE
#define STM32_LSI_ENABLED TRUE
#define STM32_HSE_ENABLED TRUE
#define STM32_LSE_ENABLED FALSE
#define STM32_SW STM32_SW_PLL
#define STM32_PLLSRC STM32_PLLSRC_HSE
#define STM32_PREDIV_VALUE 1
#define STM32_PLLMUL_VALUE 9
#define STM32_HPRE STM32_HPRE_DIV1
#define STM32_PPRE1 STM32_PPRE1_DIV2
#define STM32_PPRE2 STM32_PPRE2_DIV2
#define STM32_MCOSEL STM32_MCOSEL_NOCLOCK
#define STM32_ADC12PRES STM32_ADC12PRES_DIV1
#define STM32_ADC34PRES STM32_ADC34PRES_DIV1
#define STM32_USART1SW STM32_USART1SW_PCLK
#define STM32_USART2SW STM32_USART2SW_PCLK
#define STM32_USART3SW STM32_USART3SW_PCLK
#define STM32_UART4SW STM32_UART4SW_PCLK
#define STM32_UART5SW STM32_UART5SW_PCLK
#define STM32_I2C1SW STM32_I2C1SW_SYSCLK
#define STM32_I2C2SW STM32_I2C2SW_SYSCLK
#define STM32_TIM1SW STM32_TIM1SW_PCLK2
#define STM32_TIM8SW STM32_TIM8SW_PCLK2
#define STM32_RTCSEL STM32_RTCSEL_LSI
#define STM32_USB_CLOCK_REQUIRED TRUE
#define STM32_USBPRE STM32_USBPRE_DIV1P5
/*
* ADC driver system settings.
*/
#define STM32_ADC_DUAL_MODE FALSE
#define STM32_ADC_COMPACT_SAMPLES FALSE
#define STM32_ADC_USE_ADC1 FALSE
#define STM32_ADC_USE_ADC2 FALSE
#define STM32_ADC_USE_ADC3 FALSE
#define STM32_ADC_USE_ADC4 FALSE
#define STM32_ADC_ADC1_DMA_STREAM STM32_DMA_STREAM_ID(1, 1)
#define STM32_ADC_ADC2_DMA_STREAM STM32_DMA_STREAM_ID(2, 1)
#define STM32_ADC_ADC3_DMA_STREAM STM32_DMA_STREAM_ID(2, 5)
#define STM32_ADC_ADC4_DMA_STREAM STM32_DMA_STREAM_ID(2, 2)
#define STM32_ADC_ADC1_DMA_PRIORITY 2
#define STM32_ADC_ADC2_DMA_PRIORITY 2
#define STM32_ADC_ADC3_DMA_PRIORITY 2
#define STM32_ADC_ADC4_DMA_PRIORITY 2
#define STM32_ADC_ADC12_IRQ_PRIORITY 5
#define STM32_ADC_ADC3_IRQ_PRIORITY 5
#define STM32_ADC_ADC4_IRQ_PRIORITY 5
#define STM32_ADC_ADC1_DMA_IRQ_PRIORITY 5
#define STM32_ADC_ADC2_DMA_IRQ_PRIORITY 5
#define STM32_ADC_ADC3_DMA_IRQ_PRIORITY 5
#define STM32_ADC_ADC4_DMA_IRQ_PRIORITY 5
#define STM32_ADC_ADC12_CLOCK_MODE ADC_CCR_CKMODE_AHB_DIV1
#define STM32_ADC_ADC34_CLOCK_MODE ADC_CCR_CKMODE_AHB_DIV1
/*
* CAN driver system settings.
*/
#define STM32_CAN_USE_CAN1 TRUE
#define STM32_CAN_CAN1_IRQ_PRIORITY 11
/*
* DAC driver system settings.
*/
#define STM32_DAC_DUAL_MODE FALSE
#define STM32_DAC_USE_DAC1_CH1 TRUE
#define STM32_DAC_USE_DAC1_CH2 TRUE
#define STM32_DAC_DAC1_CH1_IRQ_PRIORITY 10
#define STM32_DAC_DAC1_CH2_IRQ_PRIORITY 10
#define STM32_DAC_DAC1_CH1_DMA_PRIORITY 2
#define STM32_DAC_DAC1_CH2_DMA_PRIORITY 2
/*
* EXT driver system settings.
*/
#define STM32_EXT_EXTI0_IRQ_PRIORITY 6
#define STM32_EXT_EXTI1_IRQ_PRIORITY 6
#define STM32_EXT_EXTI2_IRQ_PRIORITY 6
#define STM32_EXT_EXTI3_IRQ_PRIORITY 6
#define STM32_EXT_EXTI4_IRQ_PRIORITY 6
#define STM32_EXT_EXTI5_9_IRQ_PRIORITY 6
#define STM32_EXT_EXTI10_15_IRQ_PRIORITY 6
#define STM32_EXT_EXTI16_IRQ_PRIORITY 6
#define STM32_EXT_EXTI17_IRQ_PRIORITY 6
#define STM32_EXT_EXTI18_IRQ_PRIORITY 6
#define STM32_EXT_EXTI19_IRQ_PRIORITY 6
#define STM32_EXT_EXTI20_IRQ_PRIORITY 6
#define STM32_EXT_EXTI21_22_29_IRQ_PRIORITY 6
#define STM32_EXT_EXTI30_32_IRQ_PRIORITY 6
#define STM32_EXT_EXTI33_IRQ_PRIORITY 6
/*
* GPT driver system settings.
*/
#define STM32_GPT_USE_TIM1 FALSE
#define STM32_GPT_USE_TIM2 FALSE
#define STM32_GPT_USE_TIM3 FALSE
#define STM32_GPT_USE_TIM4 FALSE
#define STM32_GPT_USE_TIM6 FALSE
#define STM32_GPT_USE_TIM7 FALSE
#define STM32_GPT_USE_TIM8 FALSE
#define STM32_GPT_TIM1_IRQ_PRIORITY 7
#define STM32_GPT_TIM2_IRQ_PRIORITY 7
#define STM32_GPT_TIM3_IRQ_PRIORITY 7
#define STM32_GPT_TIM4_IRQ_PRIORITY 7
#define STM32_GPT_TIM6_IRQ_PRIORITY 7
#define STM32_GPT_TIM7_IRQ_PRIORITY 7
#define STM32_GPT_TIM8_IRQ_PRIORITY 7
/*
* I2C driver system settings.
*/
#define STM32_I2C_USE_I2C1 TRUE
#define STM32_I2C_USE_I2C2 FALSE
#define STM32_I2C_BUSY_TIMEOUT 50
#define STM32_I2C_I2C1_IRQ_PRIORITY 10
#define STM32_I2C_I2C2_IRQ_PRIORITY 10
#define STM32_I2C_USE_DMA TRUE
#define STM32_I2C_I2C1_DMA_PRIORITY 1
#define STM32_I2C_I2C2_DMA_PRIORITY 1
#define STM32_I2C_DMA_ERROR_HOOK(i2cp) osalSysHalt("DMA failure")
/*
* ICU driver system settings.
*/
#define STM32_ICU_USE_TIM1 FALSE
#define STM32_ICU_USE_TIM2 FALSE
#define STM32_ICU_USE_TIM3 FALSE
#define STM32_ICU_USE_TIM4 FALSE
#define STM32_ICU_USE_TIM8 FALSE
#define STM32_ICU_TIM1_IRQ_PRIORITY 7
#define STM32_ICU_TIM2_IRQ_PRIORITY 7
#define STM32_ICU_TIM3_IRQ_PRIORITY 7
#define STM32_ICU_TIM4_IRQ_PRIORITY 7
#define STM32_ICU_TIM8_IRQ_PRIORITY 7
/*
* PWM driver system settings.
*/
#define STM32_PWM_USE_ADVANCED FALSE
#define STM32_PWM_USE_TIM1 FALSE
#define STM32_PWM_USE_TIM2 FALSE
#define STM32_PWM_USE_TIM3 FALSE
#define STM32_PWM_USE_TIM4 FALSE
#define STM32_PWM_USE_TIM8 FALSE
#define STM32_PWM_TIM1_IRQ_PRIORITY 7
#define STM32_PWM_TIM2_IRQ_PRIORITY 7
#define STM32_PWM_TIM3_IRQ_PRIORITY 7
#define STM32_PWM_TIM4_IRQ_PRIORITY 7
#define STM32_PWM_TIM8_IRQ_PRIORITY 7
/*
* SERIAL driver system settings.
*/
#define STM32_SERIAL_USE_USART1 FALSE
#define STM32_SERIAL_USE_USART2 FALSE
#define STM32_SERIAL_USE_USART3 FALSE
#define STM32_SERIAL_USE_UART4 FALSE
#define STM32_SERIAL_USE_UART5 FALSE
#define STM32_SERIAL_USART1_PRIORITY 12
#define STM32_SERIAL_USART2_PRIORITY 12
#define STM32_SERIAL_USART3_PRIORITY 12
#define STM32_SERIAL_UART4_PRIORITY 12
#define STM32_SERIAL_UART5_PRIORITY 12
/*
* SPI driver system settings.
*/
#define STM32_SPI_USE_SPI1 TRUE
#define STM32_SPI_USE_SPI2 FALSE
#define STM32_SPI_USE_SPI3 FALSE
#define STM32_SPI_SPI1_DMA_PRIORITY 1
#define STM32_SPI_SPI2_DMA_PRIORITY 1
#define STM32_SPI_SPI3_DMA_PRIORITY 1
#define STM32_SPI_SPI1_IRQ_PRIORITY 10
#define STM32_SPI_SPI2_IRQ_PRIORITY 10
#define STM32_SPI_SPI3_IRQ_PRIORITY 10
#define STM32_SPI_DMA_ERROR_HOOK(spip) osalSysHalt("DMA failure")
/*
* ST driver system settings.
*/
#define STM32_ST_IRQ_PRIORITY 8
#define STM32_ST_USE_TIMER 2
/*
* UART driver system settings.
*/
#define STM32_UART_USE_USART1 FALSE
#define STM32_UART_USE_USART2 FALSE
#define STM32_UART_USE_USART3 FALSE
#define STM32_UART_USART1_IRQ_PRIORITY 12
#define STM32_UART_USART2_IRQ_PRIORITY 12
#define STM32_UART_USART3_IRQ_PRIORITY 12
#define STM32_UART_USART1_DMA_PRIORITY 0
#define STM32_UART_USART2_DMA_PRIORITY 0
#define STM32_UART_USART3_DMA_PRIORITY 0
#define STM32_UART_DMA_ERROR_HOOK(uartp) osalSysHalt("DMA failure")
/*
* USB driver system settings.
*/
#define STM32_USB_USE_USB1 FALSE
#define STM32_USB_LOW_POWER_ON_SUSPEND FALSE
#define STM32_USB_USB1_HP_IRQ_PRIORITY 13
#define STM32_USB_USB1_LP_IRQ_PRIORITY 14
/*
* WDG driver system settings.
*/
#define STM32_WDG_USE_IWDG TRUE
/*
* header for community drivers.
*/
#include "mcuconf_community.h"
#endif /* _MCUCONF_H_ */

View File

@ -0,0 +1,45 @@
/*
ChibiOS/RT - Copyright (C) 2014 Uladzimir Pylinsky aka barthess
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.
*/
/*
* FSMC driver system settings.
*/
#define STM32_FSMC_USE_FSMC1 FALSE
#define STM32_FSMC_FSMC1_IRQ_PRIORITY 10
/*
* FSMC NAND driver system settings.
*/
#define STM32_NAND_USE_FSMC_NAND1 FALSE
#define STM32_NAND_USE_FSMC_NAND2 FALSE
#define STM32_NAND_USE_EXT_INT FALSE
#define STM32_NAND_DMA_STREAM STM32_DMA_STREAM_ID(2, 7)
#define STM32_NAND_DMA_PRIORITY 0
#define STM32_NAND_DMA_ERROR_HOOK(nandp) osalSysHalt("DMA failure")
/*
* FSMC SRAM driver system settings.
*/
#define STM32_USE_FSMC_SRAM FALSE
#define STM32_SRAM_USE_FSMC_SRAM1 FALSE
#define STM32_SRAM_USE_FSMC_SRAM2 FALSE
#define STM32_SRAM_USE_FSMC_SRAM3 FLASE
#define STM32_SRAM_USE_FSMC_SRAM4 FALSE
/*
* FSMC SDRAM driver system settings.
*/
#define STM32_USE_FSMC_SDRAM FALSE

View File

@ -0,0 +1,217 @@
##############################################################################
# Build global options
# NOTE: Can be overridden externally.
#
# Compiler options here.
ifeq ($(USE_OPT),)
USE_OPT = -O2 -ggdb -fomit-frame-pointer -falign-functions=16
endif
# C specific options here (added to USE_OPT).
ifeq ($(USE_COPT),)
USE_COPT =
endif
# C++ specific options here (added to USE_OPT).
ifeq ($(USE_CPPOPT),)
USE_CPPOPT = -fno-rtti
endif
# Enable this if you want the linker to remove unused code and data
ifeq ($(USE_LINK_GC),)
USE_LINK_GC = yes
endif
# Linker extra options here.
ifeq ($(USE_LDOPT),)
USE_LDOPT =
endif
# Enable this if you want link time optimizations (LTO)
ifeq ($(USE_LTO),)
USE_LTO = yes
endif
# If enabled, this option allows to compile the application in THUMB mode.
ifeq ($(USE_THUMB),)
USE_THUMB = yes
endif
# Enable this if you want to see the full log while compiling.
ifeq ($(USE_VERBOSE_COMPILE),)
USE_VERBOSE_COMPILE = no
endif
# If enabled, this option makes the build process faster by not compiling
# modules not used in the current configuration.
ifeq ($(USE_SMART_BUILD),)
USE_SMART_BUILD = yes
endif
#
# Build global options
##############################################################################
##############################################################################
# Architecture or project specific options
#
# Stack size to be allocated to the Cortex-M process stack. This stack is
# the stack used by the main() thread.
ifeq ($(USE_PROCESS_STACKSIZE),)
USE_PROCESS_STACKSIZE = 0x400
endif
# Stack size to the allocated to the Cortex-M main/exceptions stack. This
# stack is used for processing interrupts and exceptions.
ifeq ($(USE_EXCEPTIONS_STACKSIZE),)
USE_EXCEPTIONS_STACKSIZE = 0x400
endif
# Enables the use of FPU on Cortex-M4 (no, softfp, hard).
ifeq ($(USE_FPU),)
USE_FPU = no
endif
#
# Architecture or project specific options
##############################################################################
##############################################################################
# Project, sources and paths
#
# Define project name here
PROJECT = ch
# Imported source files and paths
CHIBIOS = ../../../../../ChibiOS-RT
CHIBIOS_CONTRIB = $(CHIBIOS)/../ChibiOS-Contrib
# Startup files.
include $(CHIBIOS)/os/common/ports/ARMCMx/compilers/GCC/mk/startup_stm32f3xx.mk
# HAL-OSAL files (optional).
include $(CHIBIOS_CONTRIB)/os/hal/hal.mk
include $(CHIBIOS_CONTRIB)/os/hal/ports/STM32/STM32F3xx/platform.mk
include $(CHIBIOS)/os/hal/boards/ST_STM32F3_DISCOVERY/board.mk
include $(CHIBIOS)/os/hal/osal/rt/osal.mk
# RTOS files (optional).
include $(CHIBIOS)/os/rt/rt.mk
include $(CHIBIOS)/os/rt/ports/ARMCMx/compilers/GCC/mk/port_v7m.mk
# Other files (optional).
#include $(CHIBIOS)/test/rt/test.mk
# Define linker script file here
LDSCRIPT= $(STARTUPLD)/STM32F303xC.ld
# C sources that can be compiled in ARM or THUMB mode depending on the global
# setting.
CSRC = $(STARTUPSRC) \
$(KERNSRC) \
$(PORTSRC) \
$(OSALSRC) \
$(HALSRC) \
$(PLATFORMSRC) \
$(BOARDSRC) \
$(TESTSRC) \
main.c
# C++ sources that can be compiled in ARM or THUMB mode depending on the global
# setting.
CPPSRC =
# C sources to be compiled in ARM mode regardless of the global setting.
# NOTE: Mixing ARM and THUMB mode enables the -mthumb-interwork compiler
# option that results in lower performance and larger code size.
ACSRC =
# C++ sources to be compiled in ARM mode regardless of the global setting.
# NOTE: Mixing ARM and THUMB mode enables the -mthumb-interwork compiler
# option that results in lower performance and larger code size.
ACPPSRC =
# C sources to be compiled in THUMB mode regardless of the global setting.
# NOTE: Mixing ARM and THUMB mode enables the -mthumb-interwork compiler
# option that results in lower performance and larger code size.
TCSRC =
# C sources to be compiled in THUMB mode regardless of the global setting.
# NOTE: Mixing ARM and THUMB mode enables the -mthumb-interwork compiler
# option that results in lower performance and larger code size.
TCPPSRC =
# List ASM source files here
ASMSRC = $(STARTUPASM) $(PORTASM) $(OSALASM)
INCDIR = $(STARTUPINC) $(KERNINC) $(PORTINC) $(OSALINC) \
$(HALINC) $(PLATFORMINC) $(BOARDINC) $(TESTINC) \
$(CHIBIOS)/os/various
#
# Project, sources and paths
##############################################################################
##############################################################################
# Compiler settings
#
MCU = cortex-m4
#TRGT = arm-elf-
TRGT = arm-none-eabi-
CC = $(TRGT)gcc
CPPC = $(TRGT)g++
# Enable loading with g++ only if you need C++ runtime support.
# NOTE: You can use C++ even without C++ support if you are careful. C++
# runtime support makes code size explode.
LD = $(TRGT)gcc
#LD = $(TRGT)g++
CP = $(TRGT)objcopy
AS = $(TRGT)gcc -x assembler-with-cpp
AR = $(TRGT)ar
OD = $(TRGT)objdump
SZ = $(TRGT)size
HEX = $(CP) -O ihex
BIN = $(CP) -O binary
# ARM-specific options here
AOPT =
# THUMB-specific options here
TOPT = -mthumb -DTHUMB
# Define C warning options here
CWARN = -Wall -Wextra -Wundef -Wstrict-prototypes
# Define C++ warning options here
CPPWARN = -Wall -Wextra -Wundef
#
# Compiler settings
##############################################################################
##############################################################################
# Start of user section
#
# List all user C define here, like -D_DEBUG=1
UDEFS =
# Define ASM defines here
UADEFS =
# List all user directories here
UINCDIR =
# List the user directory to look for the libraries here
ULIBDIR =
# List all user libraries here
ULIBS =
#
# End of user defines
##############################################################################
RULESPATH = $(CHIBIOS)/os/common/ports/ARMCMx/compilers/GCC
include $(RULESPATH)/rules.mk

View File

@ -0,0 +1,499 @@
/*
ChibiOS - Copyright (C) 2006..2015 Giovanni Di Sirio
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.
*/
/**
* @file templates/chconf.h
* @brief Configuration file template.
* @details A copy of this file must be placed in each project directory, it
* contains the application specific kernel settings.
*
* @addtogroup config
* @details Kernel related settings and hooks.
* @{
*/
#ifndef _CHCONF_H_
#define _CHCONF_H_
/*===========================================================================*/
/**
* @name System timers settings
* @{
*/
/*===========================================================================*/
/**
* @brief System time counter resolution.
* @note Allowed values are 16 or 32 bits.
*/
#define CH_CFG_ST_RESOLUTION 32
/**
* @brief System tick frequency.
* @details Frequency of the system timer that drives the system ticks. This
* setting also defines the system tick time unit.
*/
#define CH_CFG_ST_FREQUENCY 10000
/**
* @brief Time delta constant for the tick-less mode.
* @note If this value is zero then the system uses the classic
* periodic tick. This value represents the minimum number
* of ticks that is safe to specify in a timeout directive.
* The value one is not valid, timeouts are rounded up to
* this value.
*/
#define CH_CFG_ST_TIMEDELTA 2
/** @} */
/*===========================================================================*/
/**
* @name Kernel parameters and options
* @{
*/
/*===========================================================================*/
/**
* @brief Round robin interval.
* @details This constant is the number of system ticks allowed for the
* threads before preemption occurs. Setting this value to zero
* disables the preemption for threads with equal priority and the
* round robin becomes cooperative. Note that higher priority
* threads can still preempt, the kernel is always preemptive.
* @note Disabling the round robin preemption makes the kernel more compact
* and generally faster.
* @note The round robin preemption is not supported in tickless mode and
* must be set to zero in that case.
*/
#define CH_CFG_TIME_QUANTUM 0
/**
* @brief Managed RAM size.
* @details Size of the RAM area to be managed by the OS. If set to zero
* then the whole available RAM is used. The core memory is made
* available to the heap allocator and/or can be used directly through
* the simplified core memory allocator.
*
* @note In order to let the OS manage the whole RAM the linker script must
* provide the @p __heap_base__ and @p __heap_end__ symbols.
* @note Requires @p CH_CFG_USE_MEMCORE.
*/
#define CH_CFG_MEMCORE_SIZE 0
/**
* @brief Idle thread automatic spawn suppression.
* @details When this option is activated the function @p chSysInit()
* does not spawn the idle thread. The application @p main()
* function becomes the idle thread and must implement an
* infinite loop.
*/
#define CH_CFG_NO_IDLE_THREAD FALSE
/** @} */
/*===========================================================================*/
/**
* @name Performance options
* @{
*/
/*===========================================================================*/
/**
* @brief OS optimization.
* @details If enabled then time efficient rather than space efficient code
* is used when two possible implementations exist.
*
* @note This is not related to the compiler optimization options.
* @note The default is @p TRUE.
*/
#define CH_CFG_OPTIMIZE_SPEED TRUE
/** @} */
/*===========================================================================*/
/**
* @name Subsystem options
* @{
*/
/*===========================================================================*/
/**
* @brief Time Measurement APIs.
* @details If enabled then the time measurement APIs are included in
* the kernel.
*
* @note The default is @p TRUE.
*/
#define CH_CFG_USE_TM TRUE
/**
* @brief Threads registry APIs.
* @details If enabled then the registry APIs are included in the kernel.
*
* @note The default is @p TRUE.
*/
#define CH_CFG_USE_REGISTRY TRUE
/**
* @brief Threads synchronization APIs.
* @details If enabled then the @p chThdWait() function is included in
* the kernel.
*
* @note The default is @p TRUE.
*/
#define CH_CFG_USE_WAITEXIT TRUE
/**
* @brief Semaphores APIs.
* @details If enabled then the Semaphores APIs are included in the kernel.
*
* @note The default is @p TRUE.
*/
#define CH_CFG_USE_SEMAPHORES TRUE
/**
* @brief Semaphores queuing mode.
* @details If enabled then the threads are enqueued on semaphores by
* priority rather than in FIFO order.
*
* @note The default is @p FALSE. Enable this if you have special
* requirements.
* @note Requires @p CH_CFG_USE_SEMAPHORES.
*/
#define CH_CFG_USE_SEMAPHORES_PRIORITY FALSE
/**
* @brief Mutexes APIs.
* @details If enabled then the mutexes APIs are included in the kernel.
*
* @note The default is @p TRUE.
*/
#define CH_CFG_USE_MUTEXES TRUE
/**
* @brief Enables recursive behavior on mutexes.
* @note Recursive mutexes are heavier and have an increased
* memory footprint.
*
* @note The default is @p FALSE.
* @note Requires @p CH_CFG_USE_MUTEXES.
*/
#define CH_CFG_USE_MUTEXES_RECURSIVE FALSE
/**
* @brief Conditional Variables APIs.
* @details If enabled then the conditional variables APIs are included
* in the kernel.
*
* @note The default is @p TRUE.
* @note Requires @p CH_CFG_USE_MUTEXES.
*/
#define CH_CFG_USE_CONDVARS TRUE
/**
* @brief Conditional Variables APIs with timeout.
* @details If enabled then the conditional variables APIs with timeout
* specification are included in the kernel.
*
* @note The default is @p TRUE.
* @note Requires @p CH_CFG_USE_CONDVARS.
*/
#define CH_CFG_USE_CONDVARS_TIMEOUT TRUE
/**
* @brief Events Flags APIs.
* @details If enabled then the event flags APIs are included in the kernel.
*
* @note The default is @p TRUE.
*/
#define CH_CFG_USE_EVENTS TRUE
/**
* @brief Events Flags APIs with timeout.
* @details If enabled then the events APIs with timeout specification
* are included in the kernel.
*
* @note The default is @p TRUE.
* @note Requires @p CH_CFG_USE_EVENTS.
*/
#define CH_CFG_USE_EVENTS_TIMEOUT TRUE
/**
* @brief Synchronous Messages APIs.
* @details If enabled then the synchronous messages APIs are included
* in the kernel.
*
* @note The default is @p TRUE.
*/
#define CH_CFG_USE_MESSAGES TRUE
/**
* @brief Synchronous Messages queuing mode.
* @details If enabled then messages are served by priority rather than in
* FIFO order.
*
* @note The default is @p FALSE. Enable this if you have special
* requirements.
* @note Requires @p CH_CFG_USE_MESSAGES.
*/
#define CH_CFG_USE_MESSAGES_PRIORITY FALSE
/**
* @brief Mailboxes APIs.
* @details If enabled then the asynchronous messages (mailboxes) APIs are
* included in the kernel.
*
* @note The default is @p TRUE.
* @note Requires @p CH_CFG_USE_SEMAPHORES.
*/
#define CH_CFG_USE_MAILBOXES TRUE
/**
* @brief I/O Queues APIs.
* @details If enabled then the I/O queues APIs are included in the kernel.
*
* @note The default is @p TRUE.
*/
#define CH_CFG_USE_QUEUES TRUE
/**
* @brief Core Memory Manager APIs.
* @details If enabled then the core memory manager APIs are included
* in the kernel.
*
* @note The default is @p TRUE.
*/
#define CH_CFG_USE_MEMCORE TRUE
/**
* @brief Heap Allocator APIs.
* @details If enabled then the memory heap allocator APIs are included
* in the kernel.
*
* @note The default is @p TRUE.
* @note Requires @p CH_CFG_USE_MEMCORE and either @p CH_CFG_USE_MUTEXES or
* @p CH_CFG_USE_SEMAPHORES.
* @note Mutexes are recommended.
*/
#define CH_CFG_USE_HEAP TRUE
/**
* @brief Memory Pools Allocator APIs.
* @details If enabled then the memory pools allocator APIs are included
* in the kernel.
*
* @note The default is @p TRUE.
*/
#define CH_CFG_USE_MEMPOOLS TRUE
/**
* @brief Dynamic Threads APIs.
* @details If enabled then the dynamic threads creation APIs are included
* in the kernel.
*
* @note The default is @p TRUE.
* @note Requires @p CH_CFG_USE_WAITEXIT.
* @note Requires @p CH_CFG_USE_HEAP and/or @p CH_CFG_USE_MEMPOOLS.
*/
#define CH_CFG_USE_DYNAMIC TRUE
/** @} */
/*===========================================================================*/
/**
* @name Debug options
* @{
*/
/*===========================================================================*/
/**
* @brief Debug option, kernel statistics.
*
* @note The default is @p FALSE.
*/
#define CH_DBG_STATISTICS TRUE
/**
* @brief Debug option, system state check.
* @details If enabled the correct call protocol for system APIs is checked
* at runtime.
*
* @note The default is @p FALSE.
*/
#define CH_DBG_SYSTEM_STATE_CHECK TRUE
/**
* @brief Debug option, parameters checks.
* @details If enabled then the checks on the API functions input
* parameters are activated.
*
* @note The default is @p FALSE.
*/
#define CH_DBG_ENABLE_CHECKS TRUE
/**
* @brief Debug option, consistency checks.
* @details If enabled then all the assertions in the kernel code are
* activated. This includes consistency checks inside the kernel,
* runtime anomalies and port-defined checks.
*
* @note The default is @p FALSE.
*/
#define CH_DBG_ENABLE_ASSERTS TRUE
/**
* @brief Debug option, trace buffer.
* @details If enabled then the context switch circular trace buffer is
* activated.
*
* @note The default is @p FALSE.
*/
#define CH_DBG_ENABLE_TRACE TRUE
/**
* @brief Debug option, stack checks.
* @details If enabled then a runtime stack check is performed.
*
* @note The default is @p FALSE.
* @note The stack check is performed in a architecture/port dependent way.
* It may not be implemented or some ports.
* @note The default failure mode is to halt the system with the global
* @p panic_msg variable set to @p NULL.
*/
#define CH_DBG_ENABLE_STACK_CHECK TRUE
/**
* @brief Debug option, stacks initialization.
* @details If enabled then the threads working area is filled with a byte
* value when a thread is created. This can be useful for the
* runtime measurement of the used stack.
*
* @note The default is @p FALSE.
*/
#define CH_DBG_FILL_THREADS TRUE
/**
* @brief Debug option, threads profiling.
* @details If enabled then a field is added to the @p thread_t structure that
* counts the system ticks occurred while executing the thread.
*
* @note The default is @p FALSE.
* @note This debug option is not currently compatible with the
* tickless mode.
*/
#define CH_DBG_THREADS_PROFILING FALSE
/** @} */
/*===========================================================================*/
/**
* @name Kernel hooks
* @{
*/
/*===========================================================================*/
/**
* @brief Threads descriptor structure extension.
* @details User fields added to the end of the @p thread_t structure.
*/
#define CH_CFG_THREAD_EXTRA_FIELDS \
/* Add threads custom fields here.*/
/**
* @brief Threads initialization hook.
* @details User initialization code added to the @p chThdInit() API.
*
* @note It is invoked from within @p chThdInit() and implicitly from all
* the threads creation APIs.
*/
#define CH_CFG_THREAD_INIT_HOOK(tp) { \
/* Add threads initialization code here.*/ \
}
/**
* @brief Threads finalization hook.
* @details User finalization code added to the @p chThdExit() API.
*
* @note It is inserted into lock zone.
* @note It is also invoked when the threads simply return in order to
* terminate.
*/
#define CH_CFG_THREAD_EXIT_HOOK(tp) { \
/* Add threads finalization code here.*/ \
}
/**
* @brief Context switch hook.
* @details This hook is invoked just before switching between threads.
*/
#define CH_CFG_CONTEXT_SWITCH_HOOK(ntp, otp) { \
/* Context switch code here.*/ \
}
/**
* @brief Idle thread enter hook.
* @note This hook is invoked within a critical zone, no OS functions
* should be invoked from here.
* @note This macro can be used to activate a power saving mode.
*/
#define CH_CFG_IDLE_ENTER_HOOK() { \
}
/**
* @brief Idle thread leave hook.
* @note This hook is invoked within a critical zone, no OS functions
* should be invoked from here.
* @note This macro can be used to deactivate a power saving mode.
*/
#define CH_CFG_IDLE_LEAVE_HOOK() { \
}
/**
* @brief Idle Loop hook.
* @details This hook is continuously invoked by the idle thread loop.
*/
#define CH_CFG_IDLE_LOOP_HOOK() { \
/* Idle loop code here.*/ \
}
/**
* @brief System tick event hook.
* @details This hook is invoked in the system tick handler immediately
* after processing the virtual timers queue.
*/
#define CH_CFG_SYSTEM_TICK_HOOK() { \
/* System tick event code here.*/ \
}
/**
* @brief System halt hook.
* @details This hook is invoked in case to a system halting error before
* the system is halted.
*/
#define CH_CFG_SYSTEM_HALT_HOOK(reason) { \
/* System halt code here.*/ \
}
/** @} */
/*===========================================================================*/
/* Port-specific settings (override port settings defaulted in chcore.h). */
/*===========================================================================*/
#endif /* _CHCONF_H_ */
/** @} */

View File

@ -0,0 +1,387 @@
/*
ChibiOS - Copyright (C) 2006..2015 Giovanni Di Sirio
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.
*/
/**
* @file templates/halconf.h
* @brief HAL configuration header.
* @details HAL configuration file, this file allows to enable or disable the
* various device drivers from your application. You may also use
* this file in order to override the device drivers default settings.
*
* @addtogroup HAL_CONF
* @{
*/
#ifndef _HALCONF_H_
#define _HALCONF_H_
#include "mcuconf.h"
/**
* @brief Enables the PAL subsystem.
*/
#if !defined(HAL_USE_PAL) || defined(__DOXYGEN__)
#define HAL_USE_PAL TRUE
#endif
/**
* @brief Enables the ADC subsystem.
*/
#if !defined(HAL_USE_ADC) || defined(__DOXYGEN__)
#define HAL_USE_ADC FALSE
#endif
/**
* @brief Enables the CAN subsystem.
*/
#if !defined(HAL_USE_CAN) || defined(__DOXYGEN__)
#define HAL_USE_CAN FALSE
#endif
/**
* @brief Enables the DAC subsystem.
*/
#if !defined(HAL_USE_DAC) || defined(__DOXYGEN__)
#define HAL_USE_DAC FALSE
#endif
/**
* @brief Enables the EXT subsystem.
*/
#if !defined(HAL_USE_EXT) || defined(__DOXYGEN__)
#define HAL_USE_EXT FALSE
#endif
/**
* @brief Enables the GPT subsystem.
*/
#if !defined(HAL_USE_GPT) || defined(__DOXYGEN__)
#define HAL_USE_GPT FALSE
#endif
/**
* @brief Enables the I2C subsystem.
*/
#if !defined(HAL_USE_I2C) || defined(__DOXYGEN__)
#define HAL_USE_I2C FALSE
#endif
/**
* @brief Enables the I2S subsystem.
*/
#if !defined(HAL_USE_I2S) || defined(__DOXYGEN__)
#define HAL_USE_I2S FALSE
#endif
/**
* @brief Enables the ICU subsystem.
*/
#if !defined(HAL_USE_ICU) || defined(__DOXYGEN__)
#define HAL_USE_ICU FALSE
#endif
/**
* @brief Enables the MAC subsystem.
*/
#if !defined(HAL_USE_MAC) || defined(__DOXYGEN__)
#define HAL_USE_MAC FALSE
#endif
/**
* @brief Enables the MMC_SPI subsystem.
*/
#if !defined(HAL_USE_MMC_SPI) || defined(__DOXYGEN__)
#define HAL_USE_MMC_SPI FALSE
#endif
/**
* @brief Enables the PWM subsystem.
*/
#if !defined(HAL_USE_PWM) || defined(__DOXYGEN__)
#define HAL_USE_PWM FALSE
#endif
/**
* @brief Enables the RTC subsystem.
*/
#if !defined(HAL_USE_RTC) || defined(__DOXYGEN__)
#define HAL_USE_RTC FALSE
#endif
/**
* @brief Enables the SDC subsystem.
*/
#if !defined(HAL_USE_SDC) || defined(__DOXYGEN__)
#define HAL_USE_SDC FALSE
#endif
/**
* @brief Enables the SERIAL subsystem.
*/
#if !defined(HAL_USE_SERIAL) || defined(__DOXYGEN__)
#define HAL_USE_SERIAL FALSE
#endif
/**
* @brief Enables the SERIAL over USB subsystem.
*/
#if !defined(HAL_USE_SERIAL_USB) || defined(__DOXYGEN__)
#define HAL_USE_SERIAL_USB FALSE
#endif
/**
* @brief Enables the SPI subsystem.
*/
#if !defined(HAL_USE_SPI) || defined(__DOXYGEN__)
#define HAL_USE_SPI FALSE
#endif
/**
* @brief Enables the UART subsystem.
*/
#if !defined(HAL_USE_UART) || defined(__DOXYGEN__)
#define HAL_USE_UART FALSE
#endif
/**
* @brief Enables the USB subsystem.
*/
#if !defined(HAL_USE_USB) || defined(__DOXYGEN__)
#define HAL_USE_USB FALSE
#endif
/**
* @brief Enables the WDG subsystem.
*/
#if !defined(HAL_USE_WDG) || defined(__DOXYGEN__)
#define HAL_USE_WDG FALSE
#endif
/*===========================================================================*/
/* ADC driver related settings. */
/*===========================================================================*/
/**
* @brief Enables synchronous APIs.
* @note Disabling this option saves both code and data space.
*/
#if !defined(ADC_USE_WAIT) || defined(__DOXYGEN__)
#define ADC_USE_WAIT TRUE
#endif
/**
* @brief Enables the @p adcAcquireBus() and @p adcReleaseBus() APIs.
* @note Disabling this option saves both code and data space.
*/
#if !defined(ADC_USE_MUTUAL_EXCLUSION) || defined(__DOXYGEN__)
#define ADC_USE_MUTUAL_EXCLUSION TRUE
#endif
/*===========================================================================*/
/* CAN driver related settings. */
/*===========================================================================*/
/**
* @brief Sleep mode related APIs inclusion switch.
*/
#if !defined(CAN_USE_SLEEP_MODE) || defined(__DOXYGEN__)
#define CAN_USE_SLEEP_MODE TRUE
#endif
/*===========================================================================*/
/* I2C driver related settings. */
/*===========================================================================*/
/**
* @brief Enables the mutual exclusion APIs on the I2C bus.
*/
#if !defined(I2C_USE_MUTUAL_EXCLUSION) || defined(__DOXYGEN__)
#define I2C_USE_MUTUAL_EXCLUSION TRUE
#endif
/*===========================================================================*/
/* MAC driver related settings. */
/*===========================================================================*/
/**
* @brief Enables an event sources for incoming packets.
*/
#if !defined(MAC_USE_ZERO_COPY) || defined(__DOXYGEN__)
#define MAC_USE_ZERO_COPY FALSE
#endif
/**
* @brief Enables an event sources for incoming packets.
*/
#if !defined(MAC_USE_EVENTS) || defined(__DOXYGEN__)
#define MAC_USE_EVENTS TRUE
#endif
/*===========================================================================*/
/* MMC_SPI driver related settings. */
/*===========================================================================*/
/**
* @brief Delays insertions.
* @details If enabled this options inserts delays into the MMC waiting
* routines releasing some extra CPU time for the threads with
* lower priority, this may slow down the driver a bit however.
* This option is recommended also if the SPI driver does not
* use a DMA channel and heavily loads the CPU.
*/
#if !defined(MMC_NICE_WAITING) || defined(__DOXYGEN__)
#define MMC_NICE_WAITING TRUE
#endif
/*===========================================================================*/
/* SDC driver related settings. */
/*===========================================================================*/
/**
* @brief Number of initialization attempts before rejecting the card.
* @note Attempts are performed at 10mS intervals.
*/
#if !defined(SDC_INIT_RETRY) || defined(__DOXYGEN__)
#define SDC_INIT_RETRY 100
#endif
/**
* @brief Include support for MMC cards.
* @note MMC support is not yet implemented so this option must be kept
* at @p FALSE.
*/
#if !defined(SDC_MMC_SUPPORT) || defined(__DOXYGEN__)
#define SDC_MMC_SUPPORT FALSE
#endif
/**
* @brief Delays insertions.
* @details If enabled this options inserts delays into the MMC waiting
* routines releasing some extra CPU time for the threads with
* lower priority, this may slow down the driver a bit however.
*/
#if !defined(SDC_NICE_WAITING) || defined(__DOXYGEN__)
#define SDC_NICE_WAITING TRUE
#endif
/*===========================================================================*/
/* SERIAL driver related settings. */
/*===========================================================================*/
/**
* @brief Default bit rate.
* @details Configuration parameter, this is the baud rate selected for the
* default configuration.
*/
#if !defined(SERIAL_DEFAULT_BITRATE) || defined(__DOXYGEN__)
#define SERIAL_DEFAULT_BITRATE 38400
#endif
/**
* @brief Serial buffers size.
* @details Configuration parameter, you can change the depth of the queue
* buffers depending on the requirements of your application.
* @note The default is 16 bytes for both the transmission and receive
* buffers.
*/
#if !defined(SERIAL_BUFFERS_SIZE) || defined(__DOXYGEN__)
#define SERIAL_BUFFERS_SIZE 16
#endif
/*===========================================================================*/
/* SERIAL_USB driver related setting. */
/*===========================================================================*/
/**
* @brief Serial over USB buffers size.
* @details Configuration parameter, the buffer size must be a multiple of
* the USB data endpoint maximum packet size.
* @note The default is 256 bytes for both the transmission and receive
* buffers.
*/
#if !defined(SERIAL_USB_BUFFERS_SIZE) || defined(__DOXYGEN__)
#define SERIAL_USB_BUFFERS_SIZE 256
#endif
/**
* @brief Serial over USB number of buffers.
* @note The default is 2 buffers.
*/
#if !defined(SERIAL_USB_BUFFERS_NUMBER) || defined(__DOXYGEN__)
#define SERIAL_USB_BUFFERS_NUMBER 2
#endif
/*===========================================================================*/
/* SPI driver related settings. */
/*===========================================================================*/
/**
* @brief Enables synchronous APIs.
* @note Disabling this option saves both code and data space.
*/
#if !defined(SPI_USE_WAIT) || defined(__DOXYGEN__)
#define SPI_USE_WAIT TRUE
#endif
/**
* @brief Enables the @p spiAcquireBus() and @p spiReleaseBus() APIs.
* @note Disabling this option saves both code and data space.
*/
#if !defined(SPI_USE_MUTUAL_EXCLUSION) || defined(__DOXYGEN__)
#define SPI_USE_MUTUAL_EXCLUSION TRUE
#endif
/*===========================================================================*/
/* UART driver related settings. */
/*===========================================================================*/
/**
* @brief Enables synchronous APIs.
* @note Disabling this option saves both code and data space.
*/
#if !defined(UART_USE_WAIT) || defined(__DOXYGEN__)
#define UART_USE_WAIT FALSE
#endif
/**
* @brief Enables the @p uartAcquireBus() and @p uartReleaseBus() APIs.
* @note Disabling this option saves both code and data space.
*/
#if !defined(UART_USE_MUTUAL_EXCLUSION) || defined(__DOXYGEN__)
#define UART_USE_MUTUAL_EXCLUSION FALSE
#endif
/*===========================================================================*/
/* USB driver related settings. */
/*===========================================================================*/
/**
* @brief Enables synchronous APIs.
* @note Disabling this option saves both code and data space.
*/
#if !defined(USB_USE_WAIT) || defined(__DOXYGEN__)
#define USB_USE_WAIT FALSE
#endif
/*===========================================================================*/
/* Community drivers's includes */
/*===========================================================================*/
#include "halconf_community.h"
#endif /* _HALCONF_H_ */
/** @} */

View File

@ -0,0 +1,121 @@
/*
ChibiOS - Copyright (C) 2014 Uladzimir Pylinsky aka barthess
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.
*/
#ifndef _HALCONF_COMMUNITY_H_
#define _HALCONF_COMMUNITY_H_
/**
* @brief Enables the community overlay.
*/
#if !defined(HAL_USE_COMMUNITY) || defined(__DOXYGEN__)
#define HAL_USE_COMMUNITY TRUE
#endif
/**
* @brief Enables the FSMC subsystem.
*/
#if !defined(HAL_USE_FSMC) || defined(__DOXYGEN__)
#define HAL_USE_FSMC FALSE
#endif
/**
* @brief Enables the NAND subsystem.
*/
#if !defined(HAL_USE_NAND) || defined(__DOXYGEN__)
#define HAL_USE_NAND FALSE
#endif
/**
* @brief Enables the 1-wire subsystem.
*/
#if !defined(HAL_USE_ONEWIRE) || defined(__DOXYGEN__)
#define HAL_USE_ONEWIRE FALSE
#endif
/**
* @brief Enables the EICU subsystem.
*/
#if !defined(HAL_USE_EICU) || defined(__DOXYGEN__)
#define HAL_USE_EICU FALSE
#endif
/**
* @brief Enables the community subsystem.
*/
#if !defined(HAL_USE_CRC) || defined(__DOXYGEN__)
#define HAL_USE_CRC FALSE
#endif
/**
* @brief Enables the EEPROM subsystem.
*/
#if !defined(HAL_USE_EEPROM) || defined(__DOXYGEN__)
#define HAL_USE_EEPROM FALSE
#endif
/**
* @brief Enables the TIMCAP subsystem.
*/
#if !defined(HAL_USE_TIMCAP) || defined(__DOXYGEN__)
#define HAL_USE_TIMCAP TRUE
#endif
/*===========================================================================*/
/* FSMCNAND driver related settings. */
/*===========================================================================*/
/**
* @brief Enables the @p nandAcquireBus() and @p nanReleaseBus() APIs.
* @note Disabling this option saves both code and data space.
*/
#if !defined(NAND_USE_MUTUAL_EXCLUSION) || defined(__DOXYGEN__)
#define NAND_USE_MUTUAL_EXCLUSION TRUE
#endif
/*===========================================================================*/
/* 1-wire driver related settings. */
/*===========================================================================*/
/**
* @brief Enables strong pull up feature.
* @note Disabling this option saves both code and data space.
*/
#define ONEWIRE_USE_STRONG_PULLUP FALSE
/**
* @brief Enables search ROM feature.
* @note Disabling this option saves both code and data space.
*/
#define ONEWIRE_USE_SEARCH_ROM TRUE
/*===========================================================================*/
/* EEProm driver related settings. */
/*===========================================================================*/
/**
* @brief Enables 24xx series I2C eeprom device driver.
* @note Disabling this option saves both code and data space.
*/
#define EEPROM_USE_EE24XX TRUE
/**
* @brief Enables 25xx series SPI eeprom device driver.
* @note Disabling this option saves both code and data space.
*/
#define EEPROM_USE_EE25XX TRUE
#endif /* _HALCONF_COMMUNITY_H_ */
/** @} */

View File

@ -0,0 +1,194 @@
/*
ChibiOS - Copyright (C) 2006..2015 Giovanni Di Sirio
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.
*/
#include "ch.h"
#include "hal.h"
static uint8_t TIM3CC1CaptureNumber, TIM3CC2CaptureNumber;
static uint16_t TIM3CC1ReadValue1, TIM3CC1ReadValue2;
static uint16_t TIM3CC2ReadValue1, TIM3CC2ReadValue2;
static bool TIM3CC1UD, TIM3CC2UD;
static uint16_t freq1, freq2;
void reEnableInputCapture(TIMCAPDriver *timcapp)
{
if ((timcapp->tim->DIER & TIM_DIER_CC1IE) == 0)
{
TIM3CC1CaptureNumber = 0;
TIM3CC1UD = false;
timcapp->tim->DIER |= TIM_DIER_CC1IE;
}
if ((timcapp->tim->DIER & TIM_DIER_CC2IE) == 0)
{
TIM3CC2CaptureNumber = 0;
TIM3CC2UD = false;
timcapp->tim->DIER |= TIM_DIER_CC2IE;
}
}
void captureOverflowCb(TIMCAPDriver *timcapp)
{
if (TIM3CC1UD && (timcapp->tim->DIER & TIM_DIER_CC1IE))
{
timcapp->tim->DIER &= ~TIM_DIER_CC1IE;
freq1 = 0;
}
if (TIM3CC2UD && (timcapp->tim->DIER & TIM_DIER_CC2IE))
{
timcapp->tim->DIER &= ~TIM_DIER_CC2IE;
freq2 = 0;
}
TIM3CC1UD = true;
TIM3CC2UD = true;
}
void capture1Cb(TIMCAPDriver *timcapp)
{
if(TIM3CC1CaptureNumber == 0)
{
/* Get the Input Capture value */
TIM3CC1ReadValue1 = timcapp->tim->CCR[0];
TIM3CC1CaptureNumber = 1;
TIM3CC1UD = false;
}
else if(TIM3CC1CaptureNumber == 1)
{
uint32_t Capture;
/* Get the Input Capture value */
TIM3CC1ReadValue2 = timcapp->tim->CCR[0];
TIM3CC1UD = false;
/* Capture computation */
if (TIM3CC1ReadValue2 > TIM3CC1ReadValue1)
{
Capture = ((uint32_t)TIM3CC1ReadValue2 - (uint32_t)TIM3CC1ReadValue1);
}
else
{
Capture = (((uint32_t)TIM3CC1ReadValue2 + 0x10000) - (uint32_t)TIM3CC1ReadValue1);
}
/* Frequency computation */
freq1 = (timcapp->config->frequency / Capture);
TIM3CC1ReadValue1 = TIM3CC1ReadValue2;
TIM3CC1CaptureNumber = 0;
/* Disable CC1 interrupt */
timcapp->tim->DIER &= ~TIM_DIER_CC1IE;
}
}
void capture2Cb(TIMCAPDriver *timcapp)
{
if(TIM3CC2CaptureNumber == 0)
{
/* Get the Input Capture value */
TIM3CC2ReadValue1 = timcapp->tim->CCR[1];
TIM3CC2CaptureNumber = 1;
TIM3CC2UD = false;
}
else if(TIM3CC2CaptureNumber == 1)
{
uint32_t Capture;
/* Get the Input Capture value */
TIM3CC2ReadValue2 = timcapp->tim->CCR[1];
TIM3CC2UD = false;
/* Capture computation */
if (TIM3CC2ReadValue2 > TIM3CC2ReadValue1)
{
Capture = ((uint32_t)TIM3CC2ReadValue2 - (uint32_t)TIM3CC2ReadValue1);
}
else
{
Capture = (((uint32_t)TIM3CC2ReadValue2 + 0x10000) - (uint32_t)TIM3CC2ReadValue1);
}
/* Frequency computation */
freq2 = (timcapp->config->frequency / Capture);
TIM3CC2ReadValue1 = TIM3CC2ReadValue2;
TIM3CC2CaptureNumber = 0;
/* Disable CC2 interrupt */
timcapp->tim->DIER &= ~TIM_DIER_CC2IE;
}
}
TIMCAPConfig tc_conf = {
{TIMCAP_INPUT_ACTIVE_HIGH,
TIMCAP_INPUT_ACTIVE_HIGH,
TIMCAP_INPUT_DISABLED,
TIMCAP_INPUT_DISABLED},
200000, /* TIM3 Runs at 36Mhz max. (1/200000)*65536 = 0.32s Max, 3.12Hz Min */
{capture1Cb, capture2Cb, NULL, NULL},
captureOverflowCb,
0,
0
};
THD_WORKING_AREA(waThreadTimcap, 256);
static THD_FUNCTION(ThreadTimcap, arg)
{
(void)arg;
while (TRUE)
{
reEnableInputCapture(&TIMCAPD3);
chThdSleepMilliseconds(200);
}
return;
}
/*
* Application entry point.
*/
int main(void) {
/*
* System initializations.
* - HAL initialization, this also initializes the configured device drivers
* and performs the board-specific initializations.
* - Kernel initialization, the main() function becomes a thread and the
* RTOS is active.
*/
halInit();
chSysInit();
timcapStart(&TIMCAPD3, &tc_conf);
chThdCreateStatic(waThreadTimcap, sizeof(waThreadTimcap), NORMALPRIO, ThreadTimcap, NULL);
/*
* Normal main() thread activity, it resets the watchdog.
*/
while (true) {
palToggleLine(LINE_LED4_BLUE);
chThdSleepMilliseconds(500);
}
return 0;
}

View File

@ -0,0 +1,258 @@
/*
ChibiOS - Copyright (C) 2006..2015 Giovanni Di Sirio
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.
*/
#ifndef _MCUCONF_H_
#define _MCUCONF_H_
/*
* STM32F3xx drivers configuration.
* The following settings override the default settings present in
* the various device driver implementation headers.
* Note that the settings for each driver only have effect if the whole
* driver is enabled in halconf.h.
*
* IRQ priorities:
* 15...0 Lowest...Highest.
*
* DMA priorities:
* 0...3 Lowest...Highest.
*/
#define STM32F3xx_MCUCONF
/*
* HAL driver system settings.
*/
#define STM32_NO_INIT FALSE
#define STM32_PVD_ENABLE FALSE
#define STM32_PLS STM32_PLS_LEV0
#define STM32_HSI_ENABLED TRUE
#define STM32_LSI_ENABLED TRUE
#define STM32_HSE_ENABLED TRUE
#define STM32_LSE_ENABLED FALSE
#define STM32_SW STM32_SW_PLL
#define STM32_PLLSRC STM32_PLLSRC_HSE
#define STM32_PREDIV_VALUE 1
#define STM32_PLLMUL_VALUE 9
#define STM32_HPRE STM32_HPRE_DIV1
#define STM32_PPRE1 STM32_PPRE1_DIV2
#define STM32_PPRE2 STM32_PPRE2_DIV2
#define STM32_MCOSEL STM32_MCOSEL_NOCLOCK
#define STM32_ADC12PRES STM32_ADC12PRES_DIV1
#define STM32_ADC34PRES STM32_ADC34PRES_DIV1
#define STM32_USART1SW STM32_USART1SW_PCLK
#define STM32_USART2SW STM32_USART2SW_PCLK
#define STM32_USART3SW STM32_USART3SW_PCLK
#define STM32_UART4SW STM32_UART4SW_PCLK
#define STM32_UART5SW STM32_UART5SW_PCLK
#define STM32_I2C1SW STM32_I2C1SW_SYSCLK
#define STM32_I2C2SW STM32_I2C2SW_SYSCLK
#define STM32_TIM1SW STM32_TIM1SW_PCLK2
#define STM32_TIM8SW STM32_TIM8SW_PCLK2
#define STM32_RTCSEL STM32_RTCSEL_LSI
#define STM32_USB_CLOCK_REQUIRED TRUE
#define STM32_USBPRE STM32_USBPRE_DIV1P5
/*
* ADC driver system settings.
*/
#define STM32_ADC_DUAL_MODE FALSE
#define STM32_ADC_COMPACT_SAMPLES FALSE
#define STM32_ADC_USE_ADC1 FALSE
#define STM32_ADC_USE_ADC2 FALSE
#define STM32_ADC_USE_ADC3 FALSE
#define STM32_ADC_USE_ADC4 FALSE
#define STM32_ADC_ADC1_DMA_STREAM STM32_DMA_STREAM_ID(1, 1)
#define STM32_ADC_ADC2_DMA_STREAM STM32_DMA_STREAM_ID(2, 1)
#define STM32_ADC_ADC3_DMA_STREAM STM32_DMA_STREAM_ID(2, 5)
#define STM32_ADC_ADC4_DMA_STREAM STM32_DMA_STREAM_ID(2, 2)
#define STM32_ADC_ADC1_DMA_PRIORITY 2
#define STM32_ADC_ADC2_DMA_PRIORITY 2
#define STM32_ADC_ADC3_DMA_PRIORITY 2
#define STM32_ADC_ADC4_DMA_PRIORITY 2
#define STM32_ADC_ADC12_IRQ_PRIORITY 5
#define STM32_ADC_ADC3_IRQ_PRIORITY 5
#define STM32_ADC_ADC4_IRQ_PRIORITY 5
#define STM32_ADC_ADC1_DMA_IRQ_PRIORITY 5
#define STM32_ADC_ADC2_DMA_IRQ_PRIORITY 5
#define STM32_ADC_ADC3_DMA_IRQ_PRIORITY 5
#define STM32_ADC_ADC4_DMA_IRQ_PRIORITY 5
#define STM32_ADC_ADC12_CLOCK_MODE ADC_CCR_CKMODE_AHB_DIV1
#define STM32_ADC_ADC34_CLOCK_MODE ADC_CCR_CKMODE_AHB_DIV1
/*
* CAN driver system settings.
*/
#define STM32_CAN_USE_CAN1 TRUE
#define STM32_CAN_CAN1_IRQ_PRIORITY 11
/*
* DAC driver system settings.
*/
#define STM32_DAC_DUAL_MODE FALSE
#define STM32_DAC_USE_DAC1_CH1 TRUE
#define STM32_DAC_USE_DAC1_CH2 TRUE
#define STM32_DAC_DAC1_CH1_IRQ_PRIORITY 10
#define STM32_DAC_DAC1_CH2_IRQ_PRIORITY 10
#define STM32_DAC_DAC1_CH1_DMA_PRIORITY 2
#define STM32_DAC_DAC1_CH2_DMA_PRIORITY 2
/*
* EXT driver system settings.
*/
#define STM32_EXT_EXTI0_IRQ_PRIORITY 6
#define STM32_EXT_EXTI1_IRQ_PRIORITY 6
#define STM32_EXT_EXTI2_IRQ_PRIORITY 6
#define STM32_EXT_EXTI3_IRQ_PRIORITY 6
#define STM32_EXT_EXTI4_IRQ_PRIORITY 6
#define STM32_EXT_EXTI5_9_IRQ_PRIORITY 6
#define STM32_EXT_EXTI10_15_IRQ_PRIORITY 6
#define STM32_EXT_EXTI16_IRQ_PRIORITY 6
#define STM32_EXT_EXTI17_IRQ_PRIORITY 6
#define STM32_EXT_EXTI18_IRQ_PRIORITY 6
#define STM32_EXT_EXTI19_IRQ_PRIORITY 6
#define STM32_EXT_EXTI20_IRQ_PRIORITY 6
#define STM32_EXT_EXTI21_22_29_IRQ_PRIORITY 6
#define STM32_EXT_EXTI30_32_IRQ_PRIORITY 6
#define STM32_EXT_EXTI33_IRQ_PRIORITY 6
/*
* GPT driver system settings.
*/
#define STM32_GPT_USE_TIM1 FALSE
#define STM32_GPT_USE_TIM2 FALSE
#define STM32_GPT_USE_TIM3 FALSE
#define STM32_GPT_USE_TIM4 FALSE
#define STM32_GPT_USE_TIM6 FALSE
#define STM32_GPT_USE_TIM7 FALSE
#define STM32_GPT_USE_TIM8 FALSE
#define STM32_GPT_TIM1_IRQ_PRIORITY 7
#define STM32_GPT_TIM2_IRQ_PRIORITY 7
#define STM32_GPT_TIM3_IRQ_PRIORITY 7
#define STM32_GPT_TIM4_IRQ_PRIORITY 7
#define STM32_GPT_TIM6_IRQ_PRIORITY 7
#define STM32_GPT_TIM7_IRQ_PRIORITY 7
#define STM32_GPT_TIM8_IRQ_PRIORITY 7
/*
* I2C driver system settings.
*/
#define STM32_I2C_USE_I2C1 TRUE
#define STM32_I2C_USE_I2C2 FALSE
#define STM32_I2C_BUSY_TIMEOUT 50
#define STM32_I2C_I2C1_IRQ_PRIORITY 10
#define STM32_I2C_I2C2_IRQ_PRIORITY 10
#define STM32_I2C_USE_DMA TRUE
#define STM32_I2C_I2C1_DMA_PRIORITY 1
#define STM32_I2C_I2C2_DMA_PRIORITY 1
#define STM32_I2C_DMA_ERROR_HOOK(i2cp) osalSysHalt("DMA failure")
/*
* ICU driver system settings.
*/
#define STM32_ICU_USE_TIM1 FALSE
#define STM32_ICU_USE_TIM2 FALSE
#define STM32_ICU_USE_TIM3 FALSE
#define STM32_ICU_USE_TIM4 FALSE
#define STM32_ICU_USE_TIM8 FALSE
#define STM32_ICU_TIM1_IRQ_PRIORITY 7
#define STM32_ICU_TIM2_IRQ_PRIORITY 7
#define STM32_ICU_TIM3_IRQ_PRIORITY 7
#define STM32_ICU_TIM4_IRQ_PRIORITY 7
#define STM32_ICU_TIM8_IRQ_PRIORITY 7
/*
* PWM driver system settings.
*/
#define STM32_PWM_USE_ADVANCED FALSE
#define STM32_PWM_USE_TIM1 FALSE
#define STM32_PWM_USE_TIM2 FALSE
#define STM32_PWM_USE_TIM3 FALSE
#define STM32_PWM_USE_TIM4 FALSE
#define STM32_PWM_USE_TIM8 FALSE
#define STM32_PWM_TIM1_IRQ_PRIORITY 7
#define STM32_PWM_TIM2_IRQ_PRIORITY 7
#define STM32_PWM_TIM3_IRQ_PRIORITY 7
#define STM32_PWM_TIM4_IRQ_PRIORITY 7
#define STM32_PWM_TIM8_IRQ_PRIORITY 7
/*
* SERIAL driver system settings.
*/
#define STM32_SERIAL_USE_USART1 FALSE
#define STM32_SERIAL_USE_USART2 FALSE
#define STM32_SERIAL_USE_USART3 FALSE
#define STM32_SERIAL_USE_UART4 FALSE
#define STM32_SERIAL_USE_UART5 FALSE
#define STM32_SERIAL_USART1_PRIORITY 12
#define STM32_SERIAL_USART2_PRIORITY 12
#define STM32_SERIAL_USART3_PRIORITY 12
#define STM32_SERIAL_UART4_PRIORITY 12
#define STM32_SERIAL_UART5_PRIORITY 12
/*
* SPI driver system settings.
*/
#define STM32_SPI_USE_SPI1 TRUE
#define STM32_SPI_USE_SPI2 FALSE
#define STM32_SPI_USE_SPI3 FALSE
#define STM32_SPI_SPI1_DMA_PRIORITY 1
#define STM32_SPI_SPI2_DMA_PRIORITY 1
#define STM32_SPI_SPI3_DMA_PRIORITY 1
#define STM32_SPI_SPI1_IRQ_PRIORITY 10
#define STM32_SPI_SPI2_IRQ_PRIORITY 10
#define STM32_SPI_SPI3_IRQ_PRIORITY 10
#define STM32_SPI_DMA_ERROR_HOOK(spip) osalSysHalt("DMA failure")
/*
* ST driver system settings.
*/
#define STM32_ST_IRQ_PRIORITY 8
#define STM32_ST_USE_TIMER 2
/*
* UART driver system settings.
*/
#define STM32_UART_USE_USART1 FALSE
#define STM32_UART_USE_USART2 FALSE
#define STM32_UART_USE_USART3 FALSE
#define STM32_UART_USART1_IRQ_PRIORITY 12
#define STM32_UART_USART2_IRQ_PRIORITY 12
#define STM32_UART_USART3_IRQ_PRIORITY 12
#define STM32_UART_USART1_DMA_PRIORITY 0
#define STM32_UART_USART2_DMA_PRIORITY 0
#define STM32_UART_USART3_DMA_PRIORITY 0
#define STM32_UART_DMA_ERROR_HOOK(uartp) osalSysHalt("DMA failure")
/*
* USB driver system settings.
*/
#define STM32_USB_USE_USB1 FALSE
#define STM32_USB_LOW_POWER_ON_SUSPEND FALSE
#define STM32_USB_USB1_HP_IRQ_PRIORITY 13
#define STM32_USB_USB1_LP_IRQ_PRIORITY 14
/*
* WDG driver system settings.
*/
#define STM32_WDG_USE_IWDG TRUE
/*
* header for community drivers.
*/
#include "mcuconf_community.h"
#endif /* _MCUCONF_H_ */

View File

@ -0,0 +1,65 @@
/*
ChibiOS/RT - Copyright (C) 2014 Uladzimir Pylinsky aka barthess
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.
*/
/*
* FSMC driver system settings.
*/
#define STM32_FSMC_USE_FSMC1 FALSE
#define STM32_FSMC_FSMC1_IRQ_PRIORITY 10
/*
* FSMC NAND driver system settings.
*/
#define STM32_NAND_USE_FSMC_NAND1 FALSE
#define STM32_NAND_USE_FSMC_NAND2 FALSE
#define STM32_NAND_USE_EXT_INT FALSE
#define STM32_NAND_DMA_STREAM STM32_DMA_STREAM_ID(2, 7)
#define STM32_NAND_DMA_PRIORITY 0
#define STM32_NAND_DMA_ERROR_HOOK(nandp) osalSysHalt("DMA failure")
/*
* FSMC SRAM driver system settings.
*/
#define STM32_USE_FSMC_SRAM FALSE
#define STM32_SRAM_USE_FSMC_SRAM1 FALSE
#define STM32_SRAM_USE_FSMC_SRAM2 FALSE
#define STM32_SRAM_USE_FSMC_SRAM3 FLASE
#define STM32_SRAM_USE_FSMC_SRAM4 FALSE
/*
* FSMC SDRAM driver system settings.
*/
#define STM32_USE_FSMC_SDRAM FALSE
/*
* TIMCAP driver system settings.
*/
#define STM32_TIMCAP_USE_TIM1 FALSE
#define STM32_TIMCAP_USE_TIM2 FALSE
#define STM32_TIMCAP_USE_TIM3 TRUE
#define STM32_TIMCAP_USE_TIM4 FALSE
#define STM32_TIMCAP_USE_TIM5 FALSE
#define STM32_TIMCAP_USE_TIM8 FALSE
#define STM32_TIMCAP_USE_TIM9 FALSE
#define STM32_TIMCAP_TIM1_IRQ_PRIORITY 3
#define STM32_TIMCAP_TIM2_IRQ_PRIORITY 3
#define STM32_TIMCAP_TIM3_IRQ_PRIORITY 3
#define STM32_TIMCAP_TIM4_IRQ_PRIORITY 3
#define STM32_TIMCAP_TIM5_IRQ_PRIORITY 3
#define STM32_TIMCAP_TIM8_IRQ_PRIORITY 3
#define STM32_TIMCAP_TIM9_IRQ_PRIORITY 3

View File

@ -0,0 +1,220 @@
##############################################################################
# Build global options
# NOTE: Can be overridden externally.
#
# Compiler options here.
ifeq ($(USE_OPT),)
USE_OPT = -Os -ggdb -fomit-frame-pointer -falign-functions=16
endif
# C specific options here (added to USE_OPT).
ifeq ($(USE_COPT),)
USE_COPT =
endif
# C++ specific options here (added to USE_OPT).
ifeq ($(USE_CPPOPT),)
USE_CPPOPT = -fno-rtti
endif
# Enable this if you want the linker to remove unused code and data
ifeq ($(USE_LINK_GC),)
USE_LINK_GC = yes
endif
# Linker extra options here.
ifeq ($(USE_LDOPT),)
USE_LDOPT =
endif
# Enable this if you want link time optimizations (LTO)
ifeq ($(USE_LTO),)
USE_LTO = yes
endif
# If enabled, this option allows to compile the application in THUMB mode.
ifeq ($(USE_THUMB),)
USE_THUMB = yes
endif
# Enable this if you want to see the full log while compiling.
ifeq ($(USE_VERBOSE_COMPILE),)
USE_VERBOSE_COMPILE = no
endif
# If enabled, this option makes the build process faster by not compiling
# modules not used in the current configuration.
ifeq ($(USE_SMART_BUILD),)
USE_SMART_BUILD = no
endif
#
# Build global options
##############################################################################
##############################################################################
# Architecture or project specific options
#
# Stack size to be allocated to the Cortex-M process stack. This stack is
# the stack used by the main() thread.
ifeq ($(USE_PROCESS_STACKSIZE),)
USE_PROCESS_STACKSIZE = 0x800
endif
# Stack size to the allocated to the Cortex-M main/exceptions stack. This
# stack is used for processing interrupts and exceptions.
ifeq ($(USE_EXCEPTIONS_STACKSIZE),)
USE_EXCEPTIONS_STACKSIZE = 0x800
endif
# Enables the use of FPU on Cortex-M4 (no, softfp, hard).
ifeq ($(USE_FPU),)
USE_FPU = no
endif
#
# Architecture or project specific options
##############################################################################
##############################################################################
# Project, sources and paths
#
# Define project name here
PROJECT = ch
# Imported source files and paths
CHIBIOS = ../../../../../ChibiOS-RT
CHIBIOS_CONTRIB = $(CHIBIOS)/../ChibiOS-Contrib
# Startup files.
include $(CHIBIOS)/os/common/ports/ARMCMx/compilers/GCC/mk/startup_stm32f4xx.mk
# HAL-OSAL files (optional).
include $(CHIBIOS_CONTRIB)/os/hal/hal.mk
include $(CHIBIOS_CONTRIB)/os/hal/ports/STM32/STM32F4xx/platform.mk
include $(CHIBIOS)/os/hal/boards/ST_STM32F4_DISCOVERY/board.mk
include $(CHIBIOS)/os/hal/osal/rt/osal.mk
# RTOS files (optional).
include $(CHIBIOS)/os/rt/rt.mk
include $(CHIBIOS)/os/rt/ports/ARMCMx/compilers/GCC/mk/port_v7m.mk
# Other files (optional).
include $(CHIBIOS)/test/rt/test.mk
# Define linker script file here
LDSCRIPT= $(STARTUPLD)/STM32F407xG.ld
# C sources that can be compiled in ARM or THUMB mode depending on the global
# setting.
CSRC = $(STARTUPSRC) \
$(KERNSRC) \
$(PORTSRC) \
$(OSALSRC) \
$(HALSRC) \
$(PLATFORMSRC) \
$(BOARDSRC) \
$(TESTSRC) \
$(CHIBIOS)/os/various/shell.c \
$(CHIBIOS)/os/hal/lib/streams/memstreams.c \
$(CHIBIOS)/os/hal/lib/streams/chprintf.c \
ff.c fatfs_diskio.c main.c
# C++ sources that can be compiled in ARM or THUMB mode depending on the global
# setting.
CPPSRC =
# C sources to be compiled in ARM mode regardless of the global setting.
# NOTE: Mixing ARM and THUMB mode enables the -mthumb-interwork compiler
# option that results in lower performance and larger code size.
ACSRC =
# C++ sources to be compiled in ARM mode regardless of the global setting.
# NOTE: Mixing ARM and THUMB mode enables the -mthumb-interwork compiler
# option that results in lower performance and larger code size.
ACPPSRC =
# C sources to be compiled in THUMB mode regardless of the global setting.
# NOTE: Mixing ARM and THUMB mode enables the -mthumb-interwork compiler
# option that results in lower performance and larger code size.
TCSRC =
# C sources to be compiled in THUMB mode regardless of the global setting.
# NOTE: Mixing ARM and THUMB mode enables the -mthumb-interwork compiler
# option that results in lower performance and larger code size.
TCPPSRC =
# List ASM source files here
ASMSRC = $(STARTUPASM) $(PORTASM) $(OSALASM)
INCDIR = $(STARTUPINC) $(KERNINC) $(PORTINC) $(OSALINC) \
$(HALINC) $(PLATFORMINC) $(BOARDINC) $(TESTINC) \
$(CHIBIOS)/os/hal/lib/streams $(CHIBIOS)/os/various
#
# Project, sources and paths
##############################################################################
##############################################################################
# Compiler settings
#
MCU = cortex-m4
#TRGT = arm-elf-
TRGT = arm-none-eabi-
CC = $(TRGT)gcc
CPPC = $(TRGT)g++
# Enable loading with g++ only if you need C++ runtime support.
# NOTE: You can use C++ even without C++ support if you are careful. C++
# runtime support makes code size explode.
LD = $(TRGT)gcc
#LD = $(TRGT)g++
CP = $(TRGT)objcopy
AS = $(TRGT)gcc -x assembler-with-cpp
AR = $(TRGT)ar
OD = $(TRGT)objdump
SZ = $(TRGT)size
HEX = $(CP) -O ihex
BIN = $(CP) -O binary
# ARM-specific options here
AOPT =
# THUMB-specific options here
TOPT = -mthumb -DTHUMB
# Define C warning options here
CWARN = -Wall -Wextra -Wundef -Wstrict-prototypes
# Define C++ warning options here
CPPWARN = -Wall -Wextra -Wundef
#
# Compiler settings
##############################################################################
##############################################################################
# Start of user section
#
# List all user C define here, like -D_DEBUG=1
UDEFS =
# Define ASM defines here
UADEFS =
# List all user directories here
UINCDIR =
# List the user directory to look for the libraries here
ULIBDIR =
# List all user libraries here
ULIBS =
#
# End of user defines
##############################################################################
RULESPATH = $(CHIBIOS)/os/common/ports/ARMCMx/compilers/GCC
include $(RULESPATH)/rules.mk

View File

@ -0,0 +1,501 @@
/*
ChibiOS - Copyright (C) 2006..2015 Giovanni Di Sirio
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.
*/
/**
* @file templates/chconf.h
* @brief Configuration file template.
* @details A copy of this file must be placed in each project directory, it
* contains the application specific kernel settings.
*
* @addtogroup config
* @details Kernel related settings and hooks.
* @{
*/
#ifndef _CHCONF_H_
#define _CHCONF_H_
/*===========================================================================*/
/**
* @name System timers settings
* @{
*/
/*===========================================================================*/
/**
* @brief System time counter resolution.
* @note Allowed values are 16 or 32 bits.
*/
#define CH_CFG_ST_RESOLUTION 32
/**
* @brief System tick frequency.
* @details Frequency of the system timer that drives the system ticks. This
* setting also defines the system tick time unit.
*/
#define CH_CFG_ST_FREQUENCY 1000
/**
* @brief Time delta constant for the tick-less mode.
* @note If this value is zero then the system uses the classic
* periodic tick. This value represents the minimum number
* of ticks that is safe to specify in a timeout directive.
* The value one is not valid, timeouts are rounded up to
* this value.
*/
#define CH_CFG_ST_TIMEDELTA 0
/** @} */
/*===========================================================================*/
/**
* @name Kernel parameters and options
* @{
*/
/*===========================================================================*/
/**
* @brief Round robin interval.
* @details This constant is the number of system ticks allowed for the
* threads before preemption occurs. Setting this value to zero
* disables the preemption for threads with equal priority and the
* round robin becomes cooperative. Note that higher priority
* threads can still preempt, the kernel is always preemptive.
* @note Disabling the round robin preemption makes the kernel more compact
* and generally faster.
* @note The round robin preemption is not supported in tickless mode and
* must be set to zero in that case.
*/
#define CH_CFG_TIME_QUANTUM 0
/**
* @brief Managed RAM size.
* @details Size of the RAM area to be managed by the OS. If set to zero
* then the whole available RAM is used. The core memory is made
* available to the heap allocator and/or can be used directly through
* the simplified core memory allocator.
*
* @note In order to let the OS manage the whole RAM the linker script must
* provide the @p __heap_base__ and @p __heap_end__ symbols.
* @note Requires @p CH_CFG_USE_MEMCORE.
*/
#define CH_CFG_MEMCORE_SIZE 0
/**
* @brief Idle thread automatic spawn suppression.
* @details When this option is activated the function @p chSysInit()
* does not spawn the idle thread. The application @p main()
* function becomes the idle thread and must implement an
* infinite loop.
*/
#define CH_CFG_NO_IDLE_THREAD FALSE
/** @} */
/*===========================================================================*/
/**
* @name Performance options
* @{
*/
/*===========================================================================*/
/**
* @brief OS optimization.
* @details If enabled then time efficient rather than space efficient code
* is used when two possible implementations exist.
*
* @note This is not related to the compiler optimization options.
* @note The default is @p TRUE.
*/
#define CH_CFG_OPTIMIZE_SPEED TRUE
/** @} */
/*===========================================================================*/
/**
* @name Subsystem options
* @{
*/
/*===========================================================================*/
/**
* @brief Time Measurement APIs.
* @details If enabled then the time measurement APIs are included in
* the kernel.
*
* @note The default is @p TRUE.
*/
#define CH_CFG_USE_TM TRUE
/**
* @brief Threads registry APIs.
* @details If enabled then the registry APIs are included in the kernel.
*
* @note The default is @p TRUE.
*/
#define CH_CFG_USE_REGISTRY TRUE
/**
* @brief Threads synchronization APIs.
* @details If enabled then the @p chThdWait() function is included in
* the kernel.
*
* @note The default is @p TRUE.
*/
#define CH_CFG_USE_WAITEXIT TRUE
/**
* @brief Semaphores APIs.
* @details If enabled then the Semaphores APIs are included in the kernel.
*
* @note The default is @p TRUE.
*/
#define CH_CFG_USE_SEMAPHORES TRUE
/**
* @brief Semaphores queuing mode.
* @details If enabled then the threads are enqueued on semaphores by
* priority rather than in FIFO order.
*
* @note The default is @p FALSE. Enable this if you have special
* requirements.
* @note Requires @p CH_CFG_USE_SEMAPHORES.
*/
#define CH_CFG_USE_SEMAPHORES_PRIORITY FALSE
/**
* @brief Mutexes APIs.
* @details If enabled then the mutexes APIs are included in the kernel.
*
* @note The default is @p TRUE.
*/
#define CH_CFG_USE_MUTEXES TRUE
/**
* @brief Enables recursive behavior on mutexes.
* @note Recursive mutexes are heavier and have an increased
* memory footprint.
*
* @note The default is @p FALSE.
* @note Requires @p CH_CFG_USE_MUTEXES.
*/
#define CH_CFG_USE_MUTEXES_RECURSIVE FALSE
/**
* @brief Conditional Variables APIs.
* @details If enabled then the conditional variables APIs are included
* in the kernel.
*
* @note The default is @p TRUE.
* @note Requires @p CH_CFG_USE_MUTEXES.
*/
#define CH_CFG_USE_CONDVARS TRUE
/**
* @brief Conditional Variables APIs with timeout.
* @details If enabled then the conditional variables APIs with timeout
* specification are included in the kernel.
*
* @note The default is @p TRUE.
* @note Requires @p CH_CFG_USE_CONDVARS.
*/
#define CH_CFG_USE_CONDVARS_TIMEOUT TRUE
/**
* @brief Events Flags APIs.
* @details If enabled then the event flags APIs are included in the kernel.
*
* @note The default is @p TRUE.
*/
#define CH_CFG_USE_EVENTS TRUE
/**
* @brief Events Flags APIs with timeout.
* @details If enabled then the events APIs with timeout specification
* are included in the kernel.
*
* @note The default is @p TRUE.
* @note Requires @p CH_CFG_USE_EVENTS.
*/
#define CH_CFG_USE_EVENTS_TIMEOUT TRUE
/**
* @brief Synchronous Messages APIs.
* @details If enabled then the synchronous messages APIs are included
* in the kernel.
*
* @note The default is @p TRUE.
*/
#define CH_CFG_USE_MESSAGES TRUE
/**
* @brief Synchronous Messages queuing mode.
* @details If enabled then messages are served by priority rather than in
* FIFO order.
*
* @note The default is @p FALSE. Enable this if you have special
* requirements.
* @note Requires @p CH_CFG_USE_MESSAGES.
*/
#define CH_CFG_USE_MESSAGES_PRIORITY FALSE
/**
* @brief Mailboxes APIs.
* @details If enabled then the asynchronous messages (mailboxes) APIs are
* included in the kernel.
*
* @note The default is @p TRUE.
* @note Requires @p CH_CFG_USE_SEMAPHORES.
*/
#define CH_CFG_USE_MAILBOXES TRUE
/**
* @brief I/O Queues APIs.
* @details If enabled then the I/O queues APIs are included in the kernel.
*
* @note The default is @p TRUE.
*/
#define CH_CFG_USE_QUEUES TRUE
/**
* @brief Core Memory Manager APIs.
* @details If enabled then the core memory manager APIs are included
* in the kernel.
*
* @note The default is @p TRUE.
*/
#define CH_CFG_USE_MEMCORE TRUE
/**
* @brief Heap Allocator APIs.
* @details If enabled then the memory heap allocator APIs are included
* in the kernel.
*
* @note The default is @p TRUE.
* @note Requires @p CH_CFG_USE_MEMCORE and either @p CH_CFG_USE_MUTEXES or
* @p CH_CFG_USE_SEMAPHORES.
* @note Mutexes are recommended.
*/
#define CH_CFG_USE_HEAP TRUE
/**
* @brief Memory Pools Allocator APIs.
* @details If enabled then the memory pools allocator APIs are included
* in the kernel.
*
* @note The default is @p TRUE.
*/
#define CH_CFG_USE_MEMPOOLS TRUE
/**
* @brief Dynamic Threads APIs.
* @details If enabled then the dynamic threads creation APIs are included
* in the kernel.
*
* @note The default is @p TRUE.
* @note Requires @p CH_CFG_USE_WAITEXIT.
* @note Requires @p CH_CFG_USE_HEAP and/or @p CH_CFG_USE_MEMPOOLS.
*/
#define CH_CFG_USE_DYNAMIC TRUE
/** @} */
/*===========================================================================*/
/**
* @name Debug options
* @{
*/
/*===========================================================================*/
/**
* @brief Debug option, kernel statistics.
*
* @note The default is @p FALSE.
*/
#define CH_DBG_STATISTICS FALSE
/**
* @brief Debug option, system state check.
* @details If enabled the correct call protocol for system APIs is checked
* at runtime.
*
* @note The default is @p FALSE.
*/
#define CH_DBG_SYSTEM_STATE_CHECK TRUE
/**
* @brief Debug option, parameters checks.
* @details If enabled then the checks on the API functions input
* parameters are activated.
*
* @note The default is @p FALSE.
*/
#define CH_DBG_ENABLE_CHECKS TRUE
/**
* @brief Debug option, consistency checks.
* @details If enabled then all the assertions in the kernel code are
* activated. This includes consistency checks inside the kernel,
* runtime anomalies and port-defined checks.
*
* @note The default is @p FALSE.
*/
#define CH_DBG_ENABLE_ASSERTS TRUE
/**
* @brief Debug option, trace buffer.
* @details If enabled then the context switch circular trace buffer is
* activated.
*
* @note The default is @p FALSE.
*/
#define CH_DBG_ENABLE_TRACE FALSE
/**
* @brief Debug option, stack checks.
* @details If enabled then a runtime stack check is performed.
*
* @note The default is @p FALSE.
* @note The stack check is performed in a architecture/port dependent way.
* It may not be implemented or some ports.
* @note The default failure mode is to halt the system with the global
* @p panic_msg variable set to @p NULL.
*/
#define CH_DBG_ENABLE_STACK_CHECK TRUE
/**
* @brief Debug option, stacks initialization.
* @details If enabled then the threads working area is filled with a byte
* value when a thread is created. This can be useful for the
* runtime measurement of the used stack.
*
* @note The default is @p FALSE.
*/
#define CH_DBG_FILL_THREADS TRUE
/**
* @brief Debug option, threads profiling.
* @details If enabled then a field is added to the @p thread_t structure that
* counts the system ticks occurred while executing the thread.
*
* @note The default is @p FALSE.
* @note This debug option is not currently compatible with the
* tickless mode.
*/
#define CH_DBG_THREADS_PROFILING FALSE
/** @} */
/*===========================================================================*/
/**
* @name Kernel hooks
* @{
*/
/*===========================================================================*/
/**
* @brief Threads descriptor structure extension.
* @details User fields added to the end of the @p thread_t structure.
*/
#define CH_CFG_THREAD_EXTRA_FIELDS \
/* Add threads custom fields here.*/
/**
* @brief Threads initialization hook.
* @details User initialization code added to the @p chThdInit() API.
*
* @note It is invoked from within @p chThdInit() and implicitly from all
* the threads creation APIs.
*/
#define CH_CFG_THREAD_INIT_HOOK(tp) { \
/* Add threads initialization code here.*/ \
}
/**
* @brief Threads finalization hook.
* @details User finalization code added to the @p chThdExit() API.
*
* @note It is inserted into lock zone.
* @note It is also invoked when the threads simply return in order to
* terminate.
*/
#define CH_CFG_THREAD_EXIT_HOOK(tp) { \
/* Add threads finalization code here.*/ \
}
/**
* @brief Context switch hook.
* @details This hook is invoked just before switching between threads.
*/
#define CH_CFG_CONTEXT_SWITCH_HOOK(ntp, otp) { \
/* Context switch code here.*/ \
}
/**
* @brief Idle thread enter hook.
* @note This hook is invoked within a critical zone, no OS functions
* should be invoked from here.
* @note This macro can be used to activate a power saving mode.
*/
#define CH_CFG_IDLE_ENTER_HOOK() { \
}
/**
* @brief Idle thread leave hook.
* @note This hook is invoked within a critical zone, no OS functions
* should be invoked from here.
* @note This macro can be used to deactivate a power saving mode.
*/
#define CH_CFG_IDLE_LEAVE_HOOK() { \
}
/**
* @brief Idle Loop hook.
* @details This hook is continuously invoked by the idle thread loop.
*/
#define CH_CFG_IDLE_LOOP_HOOK() { \
/* Idle loop code here.*/ \
}
/**
* @brief System tick event hook.
* @details This hook is invoked in the system tick handler immediately
* after processing the virtual timers queue.
*/
#define CH_CFG_SYSTEM_TICK_HOOK() { \
/* System tick event code here.*/ \
}
/**
* @brief System halt hook.
* @details This hook is invoked in case to a system halting error before
* the system is halted.
*/
#define CH_CFG_SYSTEM_HALT_HOOK(reason) { \
/* System halt code here.*/ \
void usbDbgSystemHalted(void); \
usbDbgSystemHalted(); \
}
/** @} */
/*===========================================================================*/
/* Port-specific settings (override port settings defaulted in chcore.h). */
/*===========================================================================*/
#endif /* _CHCONF_H_ */
/** @} */

View File

@ -0,0 +1,80 @@
/*-----------------------------------------------------------------------/
/ Low level disk interface modlue include file (C)ChaN, 2014 /
/-----------------------------------------------------------------------*/
#ifndef _DISKIO_DEFINED
#define _DISKIO_DEFINED
#ifdef __cplusplus
extern "C" {
#endif
#define _USE_WRITE 1 /* 1: Enable disk_write function */
#define _USE_IOCTL 1 /* 1: Enable disk_ioctl fucntion */
#include "integer.h"
/* Status of Disk Functions */
typedef BYTE DSTATUS;
/* Results of Disk Functions */
typedef enum {
RES_OK = 0, /* 0: Successful */
RES_ERROR, /* 1: R/W Error */
RES_WRPRT, /* 2: Write Protected */
RES_NOTRDY, /* 3: Not Ready */
RES_PARERR /* 4: Invalid Parameter */
} DRESULT;
/*---------------------------------------*/
/* Prototypes for disk control functions */
DSTATUS disk_initialize (BYTE pdrv);
DSTATUS disk_status (BYTE pdrv);
DRESULT disk_read (BYTE pdrv, BYTE* buff, DWORD sector, UINT count);
DRESULT disk_write (BYTE pdrv, const BYTE* buff, DWORD sector, UINT count);
DRESULT disk_ioctl (BYTE pdrv, BYTE cmd, void* buff);
/* Disk Status Bits (DSTATUS) */
#define STA_NOINIT 0x01 /* Drive not initialized */
#define STA_NODISK 0x02 /* No medium in the drive */
#define STA_PROTECT 0x04 /* Write protected */
/* Command code for disk_ioctrl fucntion */
/* Generic command (Used by FatFs) */
#define CTRL_SYNC 0 /* Complete pending write process (needed at _FS_READONLY == 0) */
#define GET_SECTOR_COUNT 1 /* Get media size (needed at _USE_MKFS == 1) */
#define GET_SECTOR_SIZE 2 /* Get sector size (needed at _MAX_SS != _MIN_SS) */
#define GET_BLOCK_SIZE 3 /* Get erase block size (needed at _USE_MKFS == 1) */
#define CTRL_TRIM 4 /* Inform device that the data on the block of sectors is no longer used (needed at _USE_TRIM == 1) */
/* Generic command (Not used by FatFs) */
#define CTRL_POWER 5 /* Get/Set power status */
#define CTRL_LOCK 6 /* Lock/Unlock media removal */
#define CTRL_EJECT 7 /* Eject media */
#define CTRL_FORMAT 8 /* Create physical format on the media */
/* MMC/SDC specific ioctl command */
#define MMC_GET_TYPE 10 /* Get card type */
#define MMC_GET_CSD 11 /* Get CSD */
#define MMC_GET_CID 12 /* Get CID */
#define MMC_GET_OCR 13 /* Get OCR */
#define MMC_GET_SDSTAT 14 /* Get SD status */
/* ATA/CF specific ioctl command */
#define ATA_GET_REV 20 /* Get F/W revision */
#define ATA_GET_MODEL 21 /* Get model name */
#define ATA_GET_SN 22 /* Get serial number */
#ifdef __cplusplus
}
#endif
#endif

View File

@ -0,0 +1,144 @@
/*-----------------------------------------------------------------------*/
/* Low level disk I/O module skeleton for FatFs (C)ChaN, 2007 */
/*-----------------------------------------------------------------------*/
/* This is a stub disk I/O module that acts as front end of the existing */
/* disk I/O modules and attach it to FatFs module with common interface. */
/*-----------------------------------------------------------------------*/
#include "hal.h"
#include "ffconf.h"
#include "diskio.h"
#include "usbh.h"
#include "usbh/dev/msd.h"
/*-----------------------------------------------------------------------*/
/* Correspondence between physical drive number and physical drive. */
#define MSDLUN0 0
/*-----------------------------------------------------------------------*/
/* Inidialize a Drive */
DSTATUS disk_initialize (
BYTE pdrv /* Physical drive nmuber (0..) */
)
{
DSTATUS stat;
switch (pdrv) {
case MSDLUN0:
stat = 0;
/* It is initialized externally, just reads the status.*/
if (blkGetDriverState(&MSBLKD[0]) != BLK_READY)
stat |= STA_NOINIT;
return stat;
}
return STA_NOINIT;
}
/*-----------------------------------------------------------------------*/
/* Return Disk Status */
DSTATUS disk_status (
BYTE pdrv /* Physical drive nmuber (0..) */
)
{
DSTATUS stat;
switch (pdrv) {
case MSDLUN0:
stat = 0;
/* It is initialized externally, just reads the status.*/
if (blkGetDriverState(&MSBLKD[0]) != BLK_READY)
stat |= STA_NOINIT;
return stat;
}
return STA_NOINIT;
}
/*-----------------------------------------------------------------------*/
/* Read Sector(s) */
DRESULT disk_read (
BYTE pdrv, /* Physical drive nmuber (0..) */
BYTE *buff, /* Data buffer to store read data */
DWORD sector, /* Sector address (LBA) */
UINT count /* Number of sectors to read (1..255) */
)
{
switch (pdrv) {
case MSDLUN0:
/* It is initialized externally, just reads the status.*/
if (blkGetDriverState(&MSBLKD[0]) != BLK_READY)
return RES_NOTRDY;
if (usbhmsdLUNRead(&MSBLKD[0], sector, buff, count))
return RES_ERROR;
return RES_OK;
}
return RES_PARERR;
}
/*-----------------------------------------------------------------------*/
/* Write Sector(s) */
#if _USE_WRITE
DRESULT disk_write (
BYTE pdrv, /* Physical drive nmuber (0..) */
const BYTE *buff, /* Data to be written */
DWORD sector, /* Sector address (LBA) */
UINT count /* Number of sectors to write (1..255) */
)
{
switch (pdrv) {
case MSDLUN0:
/* It is initialized externally, just reads the status.*/
if (blkGetDriverState(&MSBLKD[0]) != BLK_READY)
return RES_NOTRDY;
if (usbhmsdLUNWrite(&MSBLKD[0], sector, buff, count))
return RES_ERROR;
return RES_OK;
}
return RES_PARERR;
}
#endif /* _USE_WRITE */
/*-----------------------------------------------------------------------*/
/* Miscellaneous Functions */
#if _USE_IOCTL
DRESULT disk_ioctl (
BYTE pdrv, /* Physical drive nmuber (0..) */
BYTE cmd, /* Control code */
void *buff /* Buffer to send/receive control data */
)
{
switch (pdrv) {
case MSDLUN0:
switch (cmd) {
case CTRL_SYNC:
return RES_OK;
case GET_SECTOR_COUNT:
*((DWORD *)buff) = MSBLKD[0].info.blk_num;
return RES_OK;
case GET_SECTOR_SIZE:
*((WORD *)buff) = MSBLKD[0].info.blk_size;
return RES_OK;
default:
return RES_PARERR;
}
}
return RES_PARERR;
}
#endif /* _USE_IOCTL */
DWORD get_fattime(void) {
return ((uint32_t)0 | (1 << 16)) | (1 << 21); /* wrong but valid time */
}

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,341 @@
/*---------------------------------------------------------------------------/
/ FatFs - FAT file system module include file R0.10c (C)ChaN, 2014
/----------------------------------------------------------------------------/
/ FatFs module is a generic FAT file system module for small embedded systems.
/ This is a free software that opened for education, research and commercial
/ developments under license policy of following terms.
/
/ Copyright (C) 2014, ChaN, all right reserved.
/
/ * The FatFs module is a free software and there is NO WARRANTY.
/ * No restriction on use. You can use, modify and redistribute it for
/ personal, non-profit or commercial product UNDER YOUR RESPONSIBILITY.
/ * Redistributions of source code must retain the above copyright notice.
/
/----------------------------------------------------------------------------*/
#ifndef _FATFS
#define _FATFS 80376 /* Revision ID */
#ifdef __cplusplus
extern "C" {
#endif
#include "integer.h" /* Basic integer types */
#include "ffconf.h" /* FatFs configuration options */
#if _FATFS != _FFCONF
#error Wrong configuration file (ffconf.h).
#endif
/* Definitions of volume management */
#if _MULTI_PARTITION /* Multiple partition configuration */
typedef struct {
BYTE pd; /* Physical drive number */
BYTE pt; /* Partition: 0:Auto detect, 1-4:Forced partition) */
} PARTITION;
extern PARTITION VolToPart[]; /* Volume - Partition resolution table */
#define LD2PD(vol) (VolToPart[vol].pd) /* Get physical drive number */
#define LD2PT(vol) (VolToPart[vol].pt) /* Get partition index */
#else /* Single partition configuration */
#define LD2PD(vol) (BYTE)(vol) /* Each logical drive is bound to the same physical drive number */
#define LD2PT(vol) 0 /* Find first valid partition or in SFD */
#endif
/* Type of path name strings on FatFs API */
#if _LFN_UNICODE /* Unicode string */
#if !_USE_LFN
#error _LFN_UNICODE must be 0 at non-LFN cfg.
#endif
#ifndef _INC_TCHAR
typedef WCHAR TCHAR;
#define _T(x) L ## x
#define _TEXT(x) L ## x
#endif
#else /* ANSI/OEM string */
#ifndef _INC_TCHAR
typedef char TCHAR;
#define _T(x) x
#define _TEXT(x) x
#endif
#endif
/* File system object structure (FATFS) */
typedef struct {
BYTE fs_type; /* FAT sub-type (0:Not mounted) */
BYTE drv; /* Physical drive number */
BYTE csize; /* Sectors per cluster (1,2,4...128) */
BYTE n_fats; /* Number of FAT copies (1 or 2) */
BYTE wflag; /* win[] flag (b0:dirty) */
BYTE fsi_flag; /* FSINFO flags (b7:disabled, b0:dirty) */
WORD id; /* File system mount ID */
WORD n_rootdir; /* Number of root directory entries (FAT12/16) */
#if _MAX_SS != _MIN_SS
WORD ssize; /* Bytes per sector (512, 1024, 2048 or 4096) */
#endif
#if _FS_REENTRANT
_SYNC_t sobj; /* Identifier of sync object */
#endif
#if !_FS_READONLY
DWORD last_clust; /* Last allocated cluster */
DWORD free_clust; /* Number of free clusters */
#endif
#if _FS_RPATH
DWORD cdir; /* Current directory start cluster (0:root) */
#endif
DWORD n_fatent; /* Number of FAT entries, = number of clusters + 2 */
DWORD fsize; /* Sectors per FAT */
DWORD volbase; /* Volume start sector */
DWORD fatbase; /* FAT start sector */
DWORD dirbase; /* Root directory start sector (FAT32:Cluster#) */
DWORD database; /* Data start sector */
DWORD winsect; /* Current sector appearing in the win[] */
BYTE win[_MAX_SS]; /* Disk access window for Directory, FAT (and file data at tiny cfg) */
} FATFS;
/* File object structure (FIL) */
typedef struct {
FATFS* fs; /* Pointer to the related file system object (**do not change order**) */
WORD id; /* Owner file system mount ID (**do not change order**) */
BYTE flag; /* Status flags */
BYTE err; /* Abort flag (error code) */
DWORD fptr; /* File read/write pointer (Zeroed on file open) */
DWORD fsize; /* File size */
DWORD sclust; /* File start cluster (0:no cluster chain, always 0 when fsize is 0) */
DWORD clust; /* Current cluster of fpter (not valid when fprt is 0) */
DWORD dsect; /* Sector number appearing in buf[] (0:invalid) */
#if !_FS_READONLY
DWORD dir_sect; /* Sector number containing the directory entry */
BYTE* dir_ptr; /* Pointer to the directory entry in the win[] */
#endif
#if _USE_FASTSEEK
DWORD* cltbl; /* Pointer to the cluster link map table (Nulled on file open) */
#endif
#if _FS_LOCK
UINT lockid; /* File lock ID origin from 1 (index of file semaphore table Files[]) */
#endif
#if !_FS_TINY
BYTE buf[_MAX_SS]; /* File private data read/write window */
#endif
} FIL;
/* Directory object structure (DIR) */
typedef struct {
FATFS* fs; /* Pointer to the owner file system object (**do not change order**) */
WORD id; /* Owner file system mount ID (**do not change order**) */
WORD index; /* Current read/write index number */
DWORD sclust; /* Table start cluster (0:Root dir) */
DWORD clust; /* Current cluster */
DWORD sect; /* Current sector */
BYTE* dir; /* Pointer to the current SFN entry in the win[] */
BYTE* fn; /* Pointer to the SFN (in/out) {file[8],ext[3],status[1]} */
#if _FS_LOCK
UINT lockid; /* File lock ID (index of file semaphore table Files[]) */
#endif
#if _USE_LFN
WCHAR* lfn; /* Pointer to the LFN working buffer */
WORD lfn_idx; /* Last matched LFN index number (0xFFFF:No LFN) */
#endif
} DIR;
/* File status structure (FILINFO) */
typedef struct {
DWORD fsize; /* File size */
WORD fdate; /* Last modified date */
WORD ftime; /* Last modified time */
BYTE fattrib; /* Attribute */
TCHAR fname[13]; /* Short file name (8.3 format) */
#if _USE_LFN
TCHAR* lfname; /* Pointer to the LFN buffer */
UINT lfsize; /* Size of LFN buffer in TCHAR */
#endif
} FILINFO;
/* File function return code (FRESULT) */
typedef enum {
FR_OK = 0, /* (0) Succeeded */
FR_DISK_ERR, /* (1) A hard error occurred in the low level disk I/O layer */
FR_INT_ERR, /* (2) Assertion failed */
FR_NOT_READY, /* (3) The physical drive cannot work */
FR_NO_FILE, /* (4) Could not find the file */
FR_NO_PATH, /* (5) Could not find the path */
FR_INVALID_NAME, /* (6) The path name format is invalid */
FR_DENIED, /* (7) Access denied due to prohibited access or directory full */
FR_EXIST, /* (8) Access denied due to prohibited access */
FR_INVALID_OBJECT, /* (9) The file/directory object is invalid */
FR_WRITE_PROTECTED, /* (10) The physical drive is write protected */
FR_INVALID_DRIVE, /* (11) The logical drive number is invalid */
FR_NOT_ENABLED, /* (12) The volume has no work area */
FR_NO_FILESYSTEM, /* (13) There is no valid FAT volume */
FR_MKFS_ABORTED, /* (14) The f_mkfs() aborted due to any parameter error */
FR_TIMEOUT, /* (15) Could not get a grant to access the volume within defined period */
FR_LOCKED, /* (16) The operation is rejected according to the file sharing policy */
FR_NOT_ENOUGH_CORE, /* (17) LFN working buffer could not be allocated */
FR_TOO_MANY_OPEN_FILES, /* (18) Number of open files > _FS_SHARE */
FR_INVALID_PARAMETER /* (19) Given parameter is invalid */
} FRESULT;
/*--------------------------------------------------------------*/
/* FatFs module application interface */
FRESULT f_open (FIL* fp, const TCHAR* path, BYTE mode); /* Open or create a file */
FRESULT f_close (FIL* fp); /* Close an open file object */
FRESULT f_read (FIL* fp, void* buff, UINT btr, UINT* br); /* Read data from a file */
FRESULT f_write (FIL* fp, const void* buff, UINT btw, UINT* bw); /* Write data to a file */
FRESULT f_forward (FIL* fp, UINT(*func)(const BYTE*,UINT), UINT btf, UINT* bf); /* Forward data to the stream */
FRESULT f_lseek (FIL* fp, DWORD ofs); /* Move file pointer of a file object */
FRESULT f_truncate (FIL* fp); /* Truncate file */
FRESULT f_sync (FIL* fp); /* Flush cached data of a writing file */
FRESULT f_opendir (DIR* dp, const TCHAR* path); /* Open a directory */
FRESULT f_closedir (DIR* dp); /* Close an open directory */
FRESULT f_readdir (DIR* dp, FILINFO* fno); /* Read a directory item */
FRESULT f_mkdir (const TCHAR* path); /* Create a sub directory */
FRESULT f_unlink (const TCHAR* path); /* Delete an existing file or directory */
FRESULT f_rename (const TCHAR* path_old, const TCHAR* path_new); /* Rename/Move a file or directory */
FRESULT f_stat (const TCHAR* path, FILINFO* fno); /* Get file status */
FRESULT f_chmod (const TCHAR* path, BYTE value, BYTE mask); /* Change attribute of the file/dir */
FRESULT f_utime (const TCHAR* path, const FILINFO* fno); /* Change times-tamp of the file/dir */
FRESULT f_chdir (const TCHAR* path); /* Change current directory */
FRESULT f_chdrive (const TCHAR* path); /* Change current drive */
FRESULT f_getcwd (TCHAR* buff, UINT len); /* Get current directory */
FRESULT f_getfree (const TCHAR* path, DWORD* nclst, FATFS** fatfs); /* Get number of free clusters on the drive */
FRESULT f_getlabel (const TCHAR* path, TCHAR* label, DWORD* vsn); /* Get volume label */
FRESULT f_setlabel (const TCHAR* label); /* Set volume label */
FRESULT f_mount (FATFS* fs, const TCHAR* path, BYTE opt); /* Mount/Unmount a logical drive */
FRESULT f_mkfs (const TCHAR* path, BYTE sfd, UINT au); /* Create a file system on the volume */
FRESULT f_fdisk (BYTE pdrv, const DWORD szt[], void* work); /* Divide a physical drive into some partitions */
int f_putc (TCHAR c, FIL* fp); /* Put a character to the file */
int f_puts (const TCHAR* str, FIL* cp); /* Put a string to the file */
int f_printf (FIL* fp, const TCHAR* str, ...); /* Put a formatted string to the file */
TCHAR* f_gets (TCHAR* buff, int len, FIL* fp); /* Get a string from the file */
#define f_eof(fp) ((int)((fp)->fptr == (fp)->fsize))
#define f_error(fp) ((fp)->err)
#define f_tell(fp) ((fp)->fptr)
#define f_size(fp) ((fp)->fsize)
#ifndef EOF
#define EOF (-1)
#endif
/*--------------------------------------------------------------*/
/* Additional user defined functions */
/* RTC function */
#if !_FS_READONLY && !_FS_NORTC
DWORD get_fattime (void);
#endif
/* Unicode support functions */
#if _USE_LFN /* Unicode - OEM code conversion */
WCHAR ff_convert (WCHAR chr, UINT dir); /* OEM-Unicode bidirectional conversion */
WCHAR ff_wtoupper (WCHAR chr); /* Unicode upper-case conversion */
#if _USE_LFN == 3 /* Memory functions */
void* ff_memalloc (UINT msize); /* Allocate memory block */
void ff_memfree (void* mblock); /* Free memory block */
#endif
#endif
/* Sync functions */
#if _FS_REENTRANT
int ff_cre_syncobj (BYTE vol, _SYNC_t* sobj); /* Create a sync object */
int ff_req_grant (_SYNC_t sobj); /* Lock sync object */
void ff_rel_grant (_SYNC_t sobj); /* Unlock sync object */
int ff_del_syncobj (_SYNC_t sobj); /* Delete a sync object */
#endif
/*--------------------------------------------------------------*/
/* Flags and offset address */
/* File access control and file status flags (FIL.flag) */
#define FA_READ 0x01
#define FA_OPEN_EXISTING 0x00
#if !_FS_READONLY
#define FA_WRITE 0x02
#define FA_CREATE_NEW 0x04
#define FA_CREATE_ALWAYS 0x08
#define FA_OPEN_ALWAYS 0x10
#define FA__WRITTEN 0x20
#define FA__DIRTY 0x40
#endif
/* FAT sub type (FATFS.fs_type) */
#define FS_FAT12 1
#define FS_FAT16 2
#define FS_FAT32 3
/* File attribute bits for directory entry */
#define AM_RDO 0x01 /* Read only */
#define AM_HID 0x02 /* Hidden */
#define AM_SYS 0x04 /* System */
#define AM_VOL 0x08 /* Volume label */
#define AM_LFN 0x0F /* LFN entry */
#define AM_DIR 0x10 /* Directory */
#define AM_ARC 0x20 /* Archive */
#define AM_MASK 0x3F /* Mask of defined bits */
/* Fast seek feature */
#define CREATE_LINKMAP 0xFFFFFFFF
/*--------------------------------*/
/* Multi-byte word access macros */
#if _WORD_ACCESS == 1 /* Enable word access to the FAT structure */
#define LD_WORD(ptr) (WORD)(*(WORD*)(BYTE*)(ptr))
#define LD_DWORD(ptr) (DWORD)(*(DWORD*)(BYTE*)(ptr))
#define ST_WORD(ptr,val) *(WORD*)(BYTE*)(ptr)=(WORD)(val)
#define ST_DWORD(ptr,val) *(DWORD*)(BYTE*)(ptr)=(DWORD)(val)
#else /* Use byte-by-byte access to the FAT structure */
#define LD_WORD(ptr) (WORD)(((WORD)*((BYTE*)(ptr)+1)<<8)|(WORD)*(BYTE*)(ptr))
#define LD_DWORD(ptr) (DWORD)(((DWORD)*((BYTE*)(ptr)+3)<<24)|((DWORD)*((BYTE*)(ptr)+2)<<16)|((WORD)*((BYTE*)(ptr)+1)<<8)|*(BYTE*)(ptr))
#define ST_WORD(ptr,val) *(BYTE*)(ptr)=(BYTE)(val); *((BYTE*)(ptr)+1)=(BYTE)((WORD)(val)>>8)
#define ST_DWORD(ptr,val) *(BYTE*)(ptr)=(BYTE)(val); *((BYTE*)(ptr)+1)=(BYTE)((WORD)(val)>>8); *((BYTE*)(ptr)+2)=(BYTE)((DWORD)(val)>>16); *((BYTE*)(ptr)+3)=(BYTE)((DWORD)(val)>>24)
#endif
#ifdef __cplusplus
}
#endif
#endif /* _FATFS */

View File

@ -0,0 +1,271 @@
/*---------------------------------------------------------------------------/
/ FatFs - FAT file system module configuration file R0.10c (C)ChaN, 2014
/---------------------------------------------------------------------------*/
#include "ch.h"
#define _FFCONF 80376 /* Revision ID */
/*---------------------------------------------------------------------------/
/ Functions and Buffer Configurations
/---------------------------------------------------------------------------*/
#define _FS_TINY 0
/* This option switches tiny buffer configuration. (0:Normal or 1:Tiny)
/ At the tiny configuration, size of the file object (FIL) is reduced _MAX_SS
/ bytes. Instead of private sector buffer eliminated from the file object,
/ common sector buffer in the file system object (FATFS) is used for the file
/ data transfer. */
#define _FS_READONLY 0
/* This option switches read-only configuration. (0:Read/Write or 1:Read-only)
/ Read-only configuration removes basic writing API functions, f_write(),
/ f_sync(), f_unlink(), f_mkdir(), f_chmod(), f_rename(), f_truncate(),
/ f_getfree() and optional writing functions as well. */
#define _FS_MINIMIZE 0
/* This option defines minimization level to remove some API functions.
/
/ 0: All basic functions are enabled.
/ 1: f_stat(), f_getfree(), f_unlink(), f_mkdir(), f_chmod(), f_utime(),
/ f_truncate() and f_rename() function are removed.
/ 2: f_opendir(), f_readdir() and f_closedir() are removed in addition to 1.
/ 3: f_lseek() function is removed in addition to 2. */
#define _USE_STRFUNC 0
/* This option switches string functions, f_gets(), f_putc(), f_puts() and
/ f_printf().
/
/ 0: Disable string functions.
/ 1: Enable without LF-CRLF conversion.
/ 2: Enable with LF-CRLF conversion. */
#define _USE_MKFS 0
/* This option switches f_mkfs() function. (0:Disable or 1:Enable)
/ To enable it, also _FS_READONLY need to be set to 0. */
#define _USE_FASTSEEK 0
/* This option switches fast seek feature. (0:Disable or 1:Enable) */
#define _USE_LABEL 0
/* This option switches volume label functions, f_getlabel() and f_setlabel().
/ (0:Disable or 1:Enable) */
#define _USE_FORWARD 0
/* This option switches f_forward() function. (0:Disable or 1:Enable) */
/* To enable it, also _FS_TINY need to be set to 1. */
/*---------------------------------------------------------------------------/
/ Locale and Namespace Configurations
/---------------------------------------------------------------------------*/
#define _CODE_PAGE 437
/* This option specifies the OEM code page to be used on the target system.
/ Incorrect setting of the code page can cause a file open failure.
/
/ 932 - Japanese Shift_JIS (DBCS, OEM, Windows)
/ 936 - Simplified Chinese GBK (DBCS, OEM, Windows)
/ 949 - Korean (DBCS, OEM, Windows)
/ 950 - Traditional Chinese Big5 (DBCS, OEM, Windows)
/ 1250 - Central Europe (Windows)
/ 1251 - Cyrillic (Windows)
/ 1252 - Latin 1 (Windows)
/ 1253 - Greek (Windows)
/ 1254 - Turkish (Windows)
/ 1255 - Hebrew (Windows)
/ 1256 - Arabic (Windows)
/ 1257 - Baltic (Windows)
/ 1258 - Vietnam (OEM, Windows)
/ 437 - U.S. (OEM)
/ 720 - Arabic (OEM)
/ 737 - Greek (OEM)
/ 775 - Baltic (OEM)
/ 850 - Multilingual Latin 1 (OEM)
/ 858 - Multilingual Latin 1 + Euro (OEM)
/ 852 - Latin 2 (OEM)
/ 855 - Cyrillic (OEM)
/ 866 - Russian (OEM)
/ 857 - Turkish (OEM)
/ 862 - Hebrew (OEM)
/ 874 - Thai (OEM, Windows)
/ 1 - ASCII (No extended character. Valid for only non-LFN configuration.) */
#define _USE_LFN 0
#define _MAX_LFN 255
/* The _USE_LFN option switches the LFN feature.
/
/ 0: Disable LFN feature. _MAX_LFN has no effect.
/ 1: Enable LFN with static working buffer on the BSS. Always NOT thread-safe.
/ 2: Enable LFN with dynamic working buffer on the STACK.
/ 3: Enable LFN with dynamic working buffer on the HEAP.
/
/ When enable the LFN feature, Unicode handling functions (option/unicode.c) must
/ be added to the project. The LFN working buffer occupies (_MAX_LFN + 1) * 2 bytes.
/ When use stack for the working buffer, take care on stack overflow. When use heap
/ memory for the working buffer, memory management functions, ff_memalloc() and
/ ff_memfree(), must be added to the project. */
#define _LFN_UNICODE 0
/* This option switches character encoding on the API. (0:ANSI/OEM or 1:Unicode)
/ To use Unicode string for the path name, enable LFN feature and set _LFN_UNICODE
/ to 1. This option also affects behavior of string I/O functions. */
#define _STRF_ENCODE 3
/* When _LFN_UNICODE is 1, this option selects the character encoding on the file to
/ be read/written via string I/O functions, f_gets(), f_putc(), f_puts and f_printf().
/
/ 0: ANSI/OEM
/ 1: UTF-16LE
/ 2: UTF-16BE
/ 3: UTF-8
/
/ When _LFN_UNICODE is 0, this option has no effect. */
#define _FS_RPATH 0
/* This option configures relative path feature.
/
/ 0: Disable relative path feature and remove related functions.
/ 1: Enable relative path feature. f_chdir() and f_chdrive() are available.
/ 2: f_getcwd() function is available in addition to 1.
/
/ Note that directory items read via f_readdir() are affected by this option. */
/*---------------------------------------------------------------------------/
/ Drive/Volume Configurations
/---------------------------------------------------------------------------*/
#define _VOLUMES 1
/* Number of volumes (logical drives) to be used. */
#define _STR_VOLUME_ID 0
#define _VOLUME_STRS "RAM","NAND","CF","SD1","SD2","USB1","USB2","USB3"
/* _STR_VOLUME_ID option switches string volume ID feature.
/ When _STR_VOLUME_ID is set to 1, also pre-defined strings can be used as drive
/ number in the path name. _VOLUME_STRS defines the drive ID strings for each
/ logical drives. Number of items must be equal to _VOLUMES. Valid characters for
/ the drive ID strings are: A-Z and 0-9. */
#define _MULTI_PARTITION 0
/* This option switches multi-partition feature. By default (0), each logical drive
/ number is bound to the same physical drive number and only an FAT volume found on
/ the physical drive will be mounted. When multi-partition feature is enabled (1),
/ each logical drive number is bound to arbitrary physical drive and partition
/ listed in the VolToPart[]. Also f_fdisk() funciton will be enabled. */
#define _MIN_SS 512
#define _MAX_SS 512
/* These options configure the range of sector size to be supported. (512, 1024,
/ 2048 or 4096) Always set both 512 for most systems, all type of memory cards and
/ harddisk. But a larger value may be required for on-board flash memory and some
/ type of optical media. When _MAX_SS is larger than _MIN_SS, FatFs is configured
/ to variable sector size and GET_SECTOR_SIZE command must be implemented to the
/ disk_ioctl() function. */
#define _USE_TRIM 0
/* This option switches ATA-TRIM feature. (0:Disable or 1:Enable)
/ To enable Trim feature, also CTRL_TRIM command should be implemented to the
/ disk_ioctl() function. */
#define _FS_NOFSINFO 0
/* If you need to know correct free space on the FAT32 volume, set bit 0 of this
/ option, and f_getfree() function at first time after volume mount will force
/ a full FAT scan. Bit 1 controls the use of last allocated cluster number.
/
/ bit0=0: Use free cluster count in the FSINFO if available.
/ bit0=1: Do not trust free cluster count in the FSINFO.
/ bit1=0: Use last allocated cluster number in the FSINFO if available.
/ bit1=1: Do not trust last allocated cluster number in the FSINFO.
*/
/*---------------------------------------------------------------------------/
/ System Configurations
/---------------------------------------------------------------------------*/
#define _FS_NORTC 0
#define _NORTC_MON 11
#define _NORTC_MDAY 9
#define _NORTC_YEAR 2014
/* The _FS_NORTC option switches timestamp feature. If the system does not have
/ an RTC function or valid timestamp is not needed, set _FS_NORTC to 1 to disable
/ the timestamp feature. All objects modified by FatFs will have a fixed timestamp
/ defined by _NORTC_MON, _NORTC_MDAY and _NORTC_YEAR.
/ When timestamp feature is enabled (_FS_NORTC == 0), get_fattime() function need
/ to be added to the project to read current time form RTC. _NORTC_MON,
/ _NORTC_MDAY and _NORTC_YEAR have no effect.
/ These options have no effect at read-only configuration (_FS_READONLY == 1). */
#define _FS_LOCK 0
/* The _FS_LOCK option switches file lock feature to control duplicated file open
/ and illegal operation to open objects. This option must be 0 when _FS_READONLY
/ is 1.
/
/ 0: Disable file lock feature. To avoid volume corruption, application program
/ should avoid illegal open, remove and rename to the open objects.
/ >0: Enable file lock feature. The value defines how many files/sub-directories
/ can be opened simultaneously under file lock control. Note that the file
/ lock feature is independent of re-entrancy. */
#define _FS_REENTRANT 0
#define _FS_TIMEOUT S2ST(10)
typedef semaphore_t * _SYNC_t;
/* The _FS_REENTRANT option switches the re-entrancy (thread safe) of the FatFs
/ module itself. Note that regardless of this option, file access to different
/ volume is always re-entrant and volume control functions, f_mount(), f_mkfs()
/ and f_fdisk() function, are always not re-entrant. Only file/directory access
/ to the same volume is under control of this feature.
/
/ 0: Disable re-entrancy. _FS_TIMEOUT and _SYNC_t have no effect.
/ 1: Enable re-entrancy. Also user provided synchronization handlers,
/ ff_req_grant(), ff_rel_grant(), ff_del_syncobj() and ff_cre_syncobj()
/ function, must be added to the project. Samples are available in
/ option/syscall.c.
/
/ The _FS_TIMEOUT defines timeout period in unit of time tick.
/ The _SYNC_t defines O/S dependent sync object type. e.g. HANDLE, ID, OS_EVENT*,
/ SemaphoreHandle_t and etc.. */
#define _WORD_ACCESS 0
/* The _WORD_ACCESS option is an only platform dependent option. It defines
/ which access method is used to the word data on the FAT volume.
/
/ 0: Byte-by-byte access. Always compatible with all platforms.
/ 1: Word access. Do not choose this unless under both the following conditions.
/
/ * Address misaligned memory access is always allowed to ALL instructions.
/ * Byte order on the memory is little-endian.
/
/ If it is the case, _WORD_ACCESS can also be set to 1 to reduce code size.
/ Following table shows allowable settings of some processor types.
/
/ ARM7TDMI 0 ColdFire 0 V850E 0
/ Cortex-M3 0 Z80 0/1 V850ES 0/1
/ Cortex-M0 0 x86 0/1 TLCS-870 0/1
/ AVR 0/1 RX600(LE) 0/1 TLCS-900 0/1
/ AVR32 0 RL78 0 R32C 0
/ PIC18 0/1 SH-2 0 M16C 0/1
/ PIC24 0 H8S 0 MSP430 0
/ PIC32 0 H8/300H 0 8051 0/1
*/

View File

@ -0,0 +1,343 @@
/*
ChibiOS - Copyright (C) 2006..2015 Giovanni Di Sirio
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.
*/
/**
* @file templates/halconf.h
* @brief HAL configuration header.
* @details HAL configuration file, this file allows to enable or disable the
* various device drivers from your application. You may also use
* this file in order to override the device drivers default settings.
*
* @addtogroup HAL_CONF
* @{
*/
#ifndef _HALCONF_H_
#define _HALCONF_H_
#include "mcuconf.h"
/**
* @brief Enables the PAL subsystem.
*/
#if !defined(HAL_USE_PAL) || defined(__DOXYGEN__)
#define HAL_USE_PAL TRUE
#endif
/**
* @brief Enables the ADC subsystem.
*/
#if !defined(HAL_USE_ADC) || defined(__DOXYGEN__)
#define HAL_USE_ADC FALSE
#endif
/**
* @brief Enables the CAN subsystem.
*/
#if !defined(HAL_USE_CAN) || defined(__DOXYGEN__)
#define HAL_USE_CAN FALSE
#endif
/**
* @brief Enables the DAC subsystem.
*/
#if !defined(HAL_USE_DAC) || defined(__DOXYGEN__)
#define HAL_USE_DAC FALSE
#endif
/**
* @brief Enables the EXT subsystem.
*/
#if !defined(HAL_USE_EXT) || defined(__DOXYGEN__)
#define HAL_USE_EXT FALSE
#endif
/**
* @brief Enables the GPT subsystem.
*/
#if !defined(HAL_USE_GPT) || defined(__DOXYGEN__)
#define HAL_USE_GPT FALSE
#endif
/**
* @brief Enables the I2C subsystem.
*/
#if !defined(HAL_USE_I2C) || defined(__DOXYGEN__)
#define HAL_USE_I2C FALSE
#endif
/**
* @brief Enables the I2S subsystem.
*/
#if !defined(HAL_USE_I2S) || defined(__DOXYGEN__)
#define HAL_USE_I2S FALSE
#endif
/**
* @brief Enables the ICU subsystem.
*/
#if !defined(HAL_USE_ICU) || defined(__DOXYGEN__)
#define HAL_USE_ICU FALSE
#endif
/**
* @brief Enables the MAC subsystem.
*/
#if !defined(HAL_USE_MAC) || defined(__DOXYGEN__)
#define HAL_USE_MAC FALSE
#endif
/**
* @brief Enables the MMC_SPI subsystem.
*/
#if !defined(HAL_USE_MMC_SPI) || defined(__DOXYGEN__)
#define HAL_USE_MMC_SPI FALSE
#endif
/**
* @brief Enables the PWM subsystem.
*/
#if !defined(HAL_USE_PWM) || defined(__DOXYGEN__)
#define HAL_USE_PWM FALSE
#endif
/**
* @brief Enables the RTC subsystem.
*/
#if !defined(HAL_USE_RTC) || defined(__DOXYGEN__)
#define HAL_USE_RTC FALSE
#endif
/**
* @brief Enables the SDC subsystem.
*/
#if !defined(HAL_USE_SDC) || defined(__DOXYGEN__)
#define HAL_USE_SDC FALSE
#endif
/**
* @brief Enables the SERIAL subsystem.
*/
#if !defined(HAL_USE_SERIAL) || defined(__DOXYGEN__)
#define HAL_USE_SERIAL TRUE
#endif
/**
* @brief Enables the SERIAL over USB subsystem.
*/
#if !defined(HAL_USE_SERIAL_USB) || defined(__DOXYGEN__)
#define HAL_USE_SERIAL_USB FALSE
#endif
/**
* @brief Enables the SPI subsystem.
*/
#if !defined(HAL_USE_SPI) || defined(__DOXYGEN__)
#define HAL_USE_SPI FALSE
#endif
/**
* @brief Enables the UART subsystem.
*/
#if !defined(HAL_USE_UART) || defined(__DOXYGEN__)
#define HAL_USE_UART FALSE
#endif
/**
* @brief Enables the USB subsystem.
*/
#if !defined(HAL_USE_USB) || defined(__DOXYGEN__)
#define HAL_USE_USB FALSE
#endif
/**
* @brief Enables the WDG subsystem.
*/
#if !defined(HAL_USE_WDG) || defined(__DOXYGEN__)
#define HAL_USE_WDG FALSE
#endif
/*===========================================================================*/
/* ADC driver related settings. */
/*===========================================================================*/
/**
* @brief Enables synchronous APIs.
* @note Disabling this option saves both code and data space.
*/
#if !defined(ADC_USE_WAIT) || defined(__DOXYGEN__)
#define ADC_USE_WAIT TRUE
#endif
/**
* @brief Enables the @p adcAcquireBus() and @p adcReleaseBus() APIs.
* @note Disabling this option saves both code and data space.
*/
#if !defined(ADC_USE_MUTUAL_EXCLUSION) || defined(__DOXYGEN__)
#define ADC_USE_MUTUAL_EXCLUSION TRUE
#endif
/*===========================================================================*/
/* CAN driver related settings. */
/*===========================================================================*/
/**
* @brief Sleep mode related APIs inclusion switch.
*/
#if !defined(CAN_USE_SLEEP_MODE) || defined(__DOXYGEN__)
#define CAN_USE_SLEEP_MODE TRUE
#endif
/*===========================================================================*/
/* I2C driver related settings. */
/*===========================================================================*/
/**
* @brief Enables the mutual exclusion APIs on the I2C bus.
*/
#if !defined(I2C_USE_MUTUAL_EXCLUSION) || defined(__DOXYGEN__)
#define I2C_USE_MUTUAL_EXCLUSION TRUE
#endif
/*===========================================================================*/
/* MAC driver related settings. */
/*===========================================================================*/
/**
* @brief Enables an event sources for incoming packets.
*/
#if !defined(MAC_USE_ZERO_COPY) || defined(__DOXYGEN__)
#define MAC_USE_ZERO_COPY FALSE
#endif
/**
* @brief Enables an event sources for incoming packets.
*/
#if !defined(MAC_USE_EVENTS) || defined(__DOXYGEN__)
#define MAC_USE_EVENTS TRUE
#endif
/*===========================================================================*/
/* MMC_SPI driver related settings. */
/*===========================================================================*/
/**
* @brief Delays insertions.
* @details If enabled this options inserts delays into the MMC waiting
* routines releasing some extra CPU time for the threads with
* lower priority, this may slow down the driver a bit however.
* This option is recommended also if the SPI driver does not
* use a DMA channel and heavily loads the CPU.
*/
#if !defined(MMC_NICE_WAITING) || defined(__DOXYGEN__)
#define MMC_NICE_WAITING TRUE
#endif
/*===========================================================================*/
/* SDC driver related settings. */
/*===========================================================================*/
/**
* @brief Number of initialization attempts before rejecting the card.
* @note Attempts are performed at 10mS intervals.
*/
#if !defined(SDC_INIT_RETRY) || defined(__DOXYGEN__)
#define SDC_INIT_RETRY 100
#endif
/**
* @brief Include support for MMC cards.
* @note MMC support is not yet implemented so this option must be kept
* at @p FALSE.
*/
#if !defined(SDC_MMC_SUPPORT) || defined(__DOXYGEN__)
#define SDC_MMC_SUPPORT FALSE
#endif
/**
* @brief Delays insertions.
* @details If enabled this options inserts delays into the MMC waiting
* routines releasing some extra CPU time for the threads with
* lower priority, this may slow down the driver a bit however.
*/
#if !defined(SDC_NICE_WAITING) || defined(__DOXYGEN__)
#define SDC_NICE_WAITING TRUE
#endif
/*===========================================================================*/
/* SERIAL driver related settings. */
/*===========================================================================*/
/**
* @brief Default bit rate.
* @details Configuration parameter, this is the baud rate selected for the
* default configuration.
*/
#if !defined(SERIAL_DEFAULT_BITRATE) || defined(__DOXYGEN__)
#define SERIAL_DEFAULT_BITRATE 115200
#endif
/**
* @brief Serial buffers size.
* @details Configuration parameter, you can change the depth of the queue
* buffers depending on the requirements of your application.
* @note The default is 64 bytes for both the transmission and receive
* buffers.
*/
#if !defined(SERIAL_BUFFERS_SIZE) || defined(__DOXYGEN__)
#define SERIAL_BUFFERS_SIZE 64
#endif
/*===========================================================================*/
/* SERIAL_USB driver related setting. */
/*===========================================================================*/
/**
* @brief Serial over USB buffers size.
* @details Configuration parameter, the buffer size must be a multiple of
* the USB data endpoint maximum packet size.
* @note The default is 64 bytes for both the transmission and receive
* buffers.
*/
#if !defined(SERIAL_USB_BUFFERS_SIZE) || defined(__DOXYGEN__)
#define SERIAL_USB_BUFFERS_SIZE 256
#endif
/*===========================================================================*/
/* SPI driver related settings. */
/*===========================================================================*/
/**
* @brief Enables synchronous APIs.
* @note Disabling this option saves both code and data space.
*/
#if !defined(SPI_USE_WAIT) || defined(__DOXYGEN__)
#define SPI_USE_WAIT TRUE
#endif
/**
* @brief Enables the @p spiAcquireBus() and @p spiReleaseBus() APIs.
* @note Disabling this option saves both code and data space.
*/
#if !defined(SPI_USE_MUTUAL_EXCLUSION) || defined(__DOXYGEN__)
#define SPI_USE_MUTUAL_EXCLUSION TRUE
#endif
#include "halconf_community.h"
#endif /* _HALCONF_H_ */
/** @} */

View File

@ -0,0 +1,195 @@
/*
ChibiOS - Copyright (C) 2014 Uladzimir Pylinsky aka barthess
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.
*/
#ifndef _HALCONF_COMMUNITY_H_
#define _HALCONF_COMMUNITY_H_
/**
* @brief Enables the community overlay.
*/
#if !defined(HAL_USE_COMMUNITY) || defined(__DOXYGEN__)
#define HAL_USE_COMMUNITY TRUE
#endif
/**
* @brief Enables the FSMC subsystem.
*/
#if !defined(HAL_USE_FSMC) || defined(__DOXYGEN__)
#define HAL_USE_FSMC FALSE
#endif
/**
* @brief Enables the NAND subsystem.
*/
#if !defined(HAL_USE_NAND) || defined(__DOXYGEN__)
#define HAL_USE_NAND FALSE
#endif
/**
* @brief Enables the 1-wire subsystem.
*/
#if !defined(HAL_USE_ONEWIRE) || defined(__DOXYGEN__)
#define HAL_USE_ONEWIRE FALSE
#endif
/**
* @brief Enables the EICU subsystem.
*/
#if !defined(HAL_USE_EICU) || defined(__DOXYGEN__)
#define HAL_USE_EICU FALSE
#endif
/**
* @brief Enables the CRC subsystem.
*/
#if !defined(HAL_USE_CRC) || defined(__DOXYGEN__)
#define HAL_USE_CRC FALSE
#endif
/**
* @brief Enables the IWDG subsystem.
*/
#if !defined(HAL_USE_IWDG) || defined(__DOXYGEN__)
#define HAL_USE_IWDG FALSE
#endif
/**
* @brief Enables the TIMCAP subsystem.
*/
#if !defined(HAL_USE_TIMCAP) || defined(__DOXYGEN__)
#define HAL_USE_TIMCAP FALSE
#endif
/**
* @brief Enables the USBH subsystem.
*/
#if !defined(HAL_USE_USBH) || defined(__DOXYGEN__)
#define HAL_USE_USBH TRUE
#endif
/*===========================================================================*/
/* USBH driver related settings. */
/*===========================================================================*/
/* main driver */
#define HAL_USBH_PORT_DEBOUNCE_TIME 200
#define HAL_USBH_PORT_RESET_TIMEOUT 500
#define HAL_USBH_DEVICE_ADDRESS_STABILIZATION 20
/* MSD */
#define HAL_USBH_USE_MSD 1
#define HAL_USBHMSD_MAX_LUNS 1
#define HAL_USBHMSD_MAX_INSTANCES 1
/* IAD */
#define HAL_USBH_USE_FTDI 1
#define HAL_USBHFTDI_MAX_PORTS 1
#define HAL_USBHFTDI_MAX_INSTANCES 1
#define HAL_USBHFTDI_DEFAULT_SPEED 9600
#define HAL_USBHFTDI_DEFAULT_FRAMING (USBHFTDI_FRAMING_DATABITS_8 | USBHFTDI_FRAMING_PARITY_NONE | USBHFTDI_FRAMING_STOP_BITS_1)
#define HAL_USBHFTDI_DEFAULT_HANDSHAKE USBHFTDI_HANDSHAKE_NONE
#define HAL_USBHFTDI_DEFAULT_XON 0x11
#define HAL_USBHFTDI_DEFAULT_XOFF 0x13
/* IAD */
#define HAL_USBH_USE_IAD 0
/* UVC */
#define HAL_USBH_USE_UVC 0
#define HAL_USBHUVC_MAX_INSTANCES 1
#define HAL_USBHUVC_MAX_MAILBOX_SZ 70
#define HAL_USBHUVC_WORK_RAM_SIZE 20000
#define HAL_USBHUVC_STATUS_PACKETS_COUNT 10
/* HUB */
#define HAL_USBH_USE_HUB 1
#define HAL_USBHHUB_MAX_INSTANCES 1
#define HAL_USBHHUB_MAX_PORTS 6
/* debug */
#define USBH_DEBUG_ENABLE 1
#define USBH_DEBUG_USBHD USBHD1
#define USBH_DEBUG_SD SD2
#define USBH_DEBUG_BUFFER 25000
#define USBH_DEBUG_ENABLE_TRACE 0
#define USBH_DEBUG_ENABLE_INFO 1
#define USBH_DEBUG_ENABLE_WARNINGS 1
#define USBH_DEBUG_ENABLE_ERRORS 1
#define USBH_LLD_DEBUG_ENABLE_TRACE 0
#define USBH_LLD_DEBUG_ENABLE_INFO 1
#define USBH_LLD_DEBUG_ENABLE_WARNINGS 1
#define USBH_LLD_DEBUG_ENABLE_ERRORS 1
#define USBHHUB_DEBUG_ENABLE_TRACE 0
#define USBHHUB_DEBUG_ENABLE_INFO 1
#define USBHHUB_DEBUG_ENABLE_WARNINGS 1
#define USBHHUB_DEBUG_ENABLE_ERRORS 1
#define USBHMSD_DEBUG_ENABLE_TRACE 0
#define USBHMSD_DEBUG_ENABLE_INFO 1
#define USBHMSD_DEBUG_ENABLE_WARNINGS 1
#define USBHMSD_DEBUG_ENABLE_ERRORS 1
#define USBHUVC_DEBUG_ENABLE_TRACE 0
#define USBHUVC_DEBUG_ENABLE_INFO 1
#define USBHUVC_DEBUG_ENABLE_WARNINGS 1
#define USBHUVC_DEBUG_ENABLE_ERRORS 1
#define USBHFTDI_DEBUG_ENABLE_TRACE 0
#define USBHFTDI_DEBUG_ENABLE_INFO 1
#define USBHFTDI_DEBUG_ENABLE_WARNINGS 1
#define USBHFTDI_DEBUG_ENABLE_ERRORS 1
/*===========================================================================*/
/* FSMCNAND driver related settings. */
/*===========================================================================*/
/**
* @brief Enables the @p nandAcquireBus() and @p nanReleaseBus() APIs.
* @note Disabling this option saves both code and data space.
*/
#if !defined(NAND_USE_MUTUAL_EXCLUSION) || defined(__DOXYGEN__)
#define NAND_USE_MUTUAL_EXCLUSION TRUE
#endif
/*===========================================================================*/
/* 1-wire driver related settings. */
/*===========================================================================*/
/**
* @brief Enables strong pull up feature.
* @note Disabling this option saves both code and data space.
*/
#define ONEWIRE_USE_STRONG_PULLUP FALSE
/**
* @brief Enables search ROM feature.
* @note Disabling this option saves both code and data space.
*/
#define ONEWIRE_USE_SEARCH_ROM TRUE
#endif /* _HALCONF_COMMUNITY_H_ */
/** @} */

View File

@ -0,0 +1,33 @@
/*-------------------------------------------*/
/* Integer type definitions for FatFs module */
/*-------------------------------------------*/
#ifndef _FF_INTEGER
#define _FF_INTEGER
#ifdef _WIN32 /* FatFs development platform */
#include <windows.h>
#include <tchar.h>
#else /* Embedded platform */
/* This type MUST be 8 bit */
typedef unsigned char BYTE;
/* These types MUST be 16 bit */
typedef short SHORT;
typedef unsigned short WORD;
typedef unsigned short WCHAR;
/* These types MUST be 16 bit or 32 bit */
typedef int INT;
typedef unsigned int UINT;
/* These types MUST be 32 bit */
typedef long LONG;
typedef unsigned long DWORD;
#endif
#endif

View File

@ -0,0 +1,488 @@
/*
ChibiOS - Copyright (C) 2006..2015 Giovanni Di Sirio
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.
*/
#include "ch.h"
#include "hal.h"
#include "ff.h"
#include "usbh.h"
#include <string.h>
#if HAL_USBH_USE_FTDI
#include "usbh/dev/ftdi.h"
#include "test.h"
#include "shell.h"
#include "chprintf.h"
static THD_WORKING_AREA(waTestFTDI, 1024);
#define SHELL_WA_SIZE THD_WORKING_AREA_SIZE(2048)
#define TEST_WA_SIZE THD_WORKING_AREA_SIZE(256)
static uint8_t buf[] =
"0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef"
"0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef"
"0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef"
"0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef"
"0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef"
"0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef"
"0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef"
"0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef"
"0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef"
"0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef"
"0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef"
"0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef"
"0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef"
"0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef"
"0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef"
"0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef";
static void cmd_mem(BaseSequentialStream *chp, int argc, char *argv[]) {
size_t n, size;
(void)argv;
if (argc > 0) {
chprintf(chp, "Usage: mem\r\n");
return;
}
n = chHeapStatus(NULL, &size);
chprintf(chp, "core free memory : %u bytes\r\n", chCoreGetStatusX());
chprintf(chp, "heap fragments : %u\r\n", n);
chprintf(chp, "heap free total : %u bytes\r\n", size);
}
static void cmd_threads(BaseSequentialStream *chp, int argc, char *argv[]) {
static const char *states[] = {CH_STATE_NAMES};
thread_t *tp;
(void)argv;
if (argc > 0) {
chprintf(chp, "Usage: threads\r\n");
return;
}
chprintf(chp, " addr stack prio refs state\r\n");
tp = chRegFirstThread();
do {
chprintf(chp, "%08lx %08lx %4lu %4lu %9s\r\n",
(uint32_t)tp, (uint32_t)tp->p_ctx.r13,
(uint32_t)tp->p_prio, (uint32_t)(tp->p_refs - 1),
states[tp->p_state]);
tp = chRegNextThread(tp);
} while (tp != NULL);
}
static void cmd_test(BaseSequentialStream *chp, int argc, char *argv[]) {
thread_t *tp;
(void)argv;
if (argc > 0) {
chprintf(chp, "Usage: test\r\n");
return;
}
tp = chThdCreateFromHeap(NULL, TEST_WA_SIZE, chThdGetPriorityX(),
TestThread, chp);
if (tp == NULL) {
chprintf(chp, "out of memory\r\n");
return;
}
chThdWait(tp);
}
static void cmd_write(BaseSequentialStream *chp, int argc, char *argv[]) {
(void)argv;
if (argc > 0) {
chprintf(chp, "Usage: write\r\n");
return;
}
while (chnGetTimeout((BaseChannel *)chp, TIME_IMMEDIATE) != Q_TIMEOUT) {
//flush
}
while (chnGetTimeout((BaseChannel *)chp, TIME_IMMEDIATE) == Q_TIMEOUT) {
chSequentialStreamWrite(&FTDIPD[0], buf, sizeof buf - 1);
}
chprintf(chp, "\r\n\nstopped\r\n");
}
static const ShellCommand commands[] = {
{"mem", cmd_mem},
{"threads", cmd_threads},
{"test", cmd_test},
{"write", cmd_write},
{NULL, NULL}
};
static const ShellConfig shell_cfg1 = {
(BaseSequentialStream *)&FTDIPD[0],
commands
};
static void ThreadTestFTDI(void *p) {
(void)p;
USBHFTDIPortDriver *const ftdipp = &FTDIPD[0];
shellInit();
start:
while (ftdipp->state != USBHFTDIP_STATE_ACTIVE) {
chThdSleepMilliseconds(100);
}
usbDbgPuts("FTDI: Connected");
USBHFTDIPortConfig config = {
115200,
USBHFTDI_FRAMING_DATABITS_8 | USBHFTDI_FRAMING_PARITY_NONE | USBHFTDI_FRAMING_STOP_BITS_1,
USBHFTDI_HANDSHAKE_NONE,
0,
0
};
usbhftdipStart(ftdipp, &config);
//loopback
if (0) {
for(;;) {
msg_t m = chSequentialStreamGet(ftdipp);
if (m < MSG_OK) {
usbDbgPuts("FTDI: Disconnected");
goto start;
}
chSequentialStreamPut(ftdipp, (uint8_t)m);
if (m == 'q')
break;
}
}
//shell test
if (1) {
thread_t *shelltp = NULL;
for(;;) {
if (ftdipp->state != USBHFTDIP_STATE_READY)
goto start;
if (!shelltp) {
shelltp = shellCreate(&shell_cfg1, SHELL_WA_SIZE, NORMALPRIO);
} else if (chThdTerminatedX(shelltp)) {
chThdRelease(shelltp);
if (ftdipp->state != USBHFTDIP_STATE_READY)
goto start;
break;
}
chThdSleepMilliseconds(100);
}
}
//FTDI uart RX to debug TX bridge
if (0) {
for(;;) {
msg_t m = chSequentialStreamGet(ftdipp);
if (m < MSG_OK) {
usbDbgPuts("FTDI: Disconnected");
goto start;
}
sdPut(&USBH_DEBUG_SD, (uint8_t)m);
if (m == 'q')
break;
}
}
//write speed test
if (1) {
usbhftdipStop(ftdipp);
config.speed = 3000000;
usbhftdipStart(ftdipp, &config);
systime_t st, et;
int i;
for (i = 0; i < 5; i++) {
uint32_t bytes = config.speed / 10;
uint32_t times = bytes / 1024;
st = chVTGetSystemTimeX();
while (times--) {
if (chSequentialStreamWrite(ftdipp, buf, 1024) < 1024) {
usbDbgPuts("FTDI: Disconnected");
goto start;
}
bytes -= 1024;
}
if (bytes) {
if (chSequentialStreamWrite(ftdipp, buf, bytes) < bytes) {
usbDbgPuts("FTDI: Disconnected");
goto start;
}
}
et = chVTGetSystemTimeX();
usbDbgPrintf("\tRate=%uB/s", (config.speed * 100) / (et - st));
}
}
//single character write test (tests the timer)
if (0) {
for (;;) {
if (chSequentialStreamPut(ftdipp, 'A') != MSG_OK) {
usbDbgPuts("FTDI: Disconnected");
goto start;
}
chThdSleepMilliseconds(100);
}
}
usbhftdipStop(ftdipp);
usbDbgPuts("FTDI: Tests done, restarting in 3s");
chThdSleepMilliseconds(3000);
goto start;
}
#endif
#if HAL_USBH_USE_MSD
#include "usbh/dev/msd.h"
#include "ff.h"
static FATFS MSDLUN0FS;
static uint8_t fbuff[10240];
static FIL file;
static FRESULT scan_files(BaseSequentialStream *chp, char *path) {
FRESULT res;
FILINFO fno;
DIR dir;
int i;
char *fn;
#if _USE_LFN
fno.lfname = 0;
fno.lfsize = 0;
#endif
res = f_opendir(&dir, path);
if (res == FR_OK) {
i = strlen(path);
for (;;) {
res = f_readdir(&dir, &fno);
if (res != FR_OK || fno.fname[0] == 0)
break;
if (fno.fname[0] == '.')
continue;
fn = fno.fname;
if (fno.fattrib & AM_DIR) {
path[i++] = '/';
strcpy(&path[i], fn);
res = scan_files(chp, path);
if (res != FR_OK)
break;
path[--i] = 0;
} else {
usbDbgPrintf("FS: %s/%s", path, fn);
}
}
}
return res;
}
static THD_WORKING_AREA(waTestMSD, 1024);
static void ThreadTestMSD(void *p) {
(void)p;
FATFS *fsp;
uint32_t clusters;
FRESULT res;
BaseSequentialStream * const chp = (BaseSequentialStream *)&USBH_DEBUG_SD;
blkstate_t state;
systime_t st, et;
uint32_t j;
start:
for(;;) {
chThdSleepMilliseconds(100);
chSysLock();
state = blkGetDriverState(&MSBLKD[0]);
chSysUnlock();
if (state != BLK_READY)
continue;
//raw read test
if (1) {
#define RAW_READ_SZ_MB 1
#define NBLOCKS (sizeof(fbuff) / 512)
#define NITERATIONS ((RAW_READ_SZ_MB * 1024UL * 1024UL) / sizeof(fbuff))
uint32_t start = 0;
chThdSetPriority(HIGHPRIO);
usbDbgPrintf("BLK: Raw read test (%dMB, %dB blocks)", RAW_READ_SZ_MB, sizeof(fbuff));
st = chVTGetSystemTime();
for (j = 0; j < NITERATIONS; j++) {
blkRead(&MSBLKD[0], start, fbuff, NBLOCKS);
start += NBLOCKS;
}
et = chVTGetSystemTime();
usbDbgPrintf("BLK: Raw read in %d ms, %dkB/s",
et - st,
(RAW_READ_SZ_MB * 1024UL * 1000) / (et - st));
chThdSetPriority(NORMALPRIO);
}
usbDbgPuts("FS: Block driver ready, try mount...");
res = f_mount(&MSDLUN0FS, "0:", 1);
if (res != FR_OK) {
usbDbgPuts("FS: Can't mount. Check file system.");
continue;
}
usbDbgPuts("FS: Mounted.");
res = f_getfree("0:", &clusters, &fsp);
if (res != FR_OK) {
usbDbgPuts("FS: f_getfree() failed");
continue;
}
usbDbgPrintf("FS: %lu free clusters, %lu sectors per cluster, %lu bytes free",
clusters, (uint32_t)MSDLUN0FS.csize,
clusters * (uint32_t)MSDLUN0FS.csize * MSBLKD[0].info.blk_size);
break;
}
//FATFS test
if (1) {
UINT bw;
const uint8_t *src;
const uint8_t *const start = (uint8_t *)0x08000000;
const uint8_t *const top = (uint8_t *)0x08020000;
//write test
if (1) {
usbDbgPuts("FS: Write test (create file /test.dat, 1MB)");
f_open(&file, "/test.dat", FA_CREATE_ALWAYS | FA_WRITE);
src = start;
st = chVTGetSystemTime();
for (j = 0; j < 2048; j++) {
if (f_write(&file, src, 512, &bw) != FR_OK)
goto start;
src += bw;
if (src >= top)
src = start;
}
et = chVTGetSystemTime();
usbDbgPrintf("FS: Written 1MB in %d ms, %dkB/s",
et - st,
(1024UL*1000) / (et - st));
f_close(&file);
}
//read test
if (1) {
usbDbgPuts("FS: Read test (read file /test.dat, 1MB, compare)");
f_open(&file, "/test.dat", FA_READ);
src = start;
st = chVTGetSystemTime();
for (j = 0; j < 2048; j++) {
if (f_read(&file, fbuff, 512, &bw) != FR_OK)
goto start;
if (memcmp(src, fbuff, bw)) {
usbDbgPrintf("Compare error @%08x", (uint32_t)src);
goto start;
}
src += bw;
if (src >= top)
src = start;
}
et = chVTGetSystemTime();
usbDbgPrintf("FS: Read 1MB in %d ms, %dkB/s",
et - st,
(1024UL*1000) / (et - st));
f_close(&file);
}
//scan files test
if (1) {
usbDbgPuts("FS: Scan files test");
fbuff[0] = 0;
scan_files(chp, (char *)fbuff);
}
}
usbDbgPuts("FS: Tests done, restarting in 3s");
chThdSleepMilliseconds(3000);
goto start;
}
#endif
int main(void) {
halInit();
usbhInit();
chSysInit();
//PA2(TX) and PA3(RX) are routed to USART2
sdStart(&SD2, NULL);
palSetPadMode(GPIOA, 2, PAL_MODE_ALTERNATE(7));
palSetPadMode(GPIOA, 3, PAL_MODE_ALTERNATE(7));
#if STM32_USBH_USE_OTG1
//VBUS - configured in board.h
//USB_FS - configured in board.h
#endif
#if STM32_USBH_USE_OTG2
//USB_HS
//TODO: Initialize Pads
#endif
#if HAL_USBH_USE_MSD
usbhmsdObjectInit(&USBHMSD[0]);
usbhmsdLUNObjectInit(&MSBLKD[0]);
chThdCreateStatic(waTestMSD, sizeof(waTestMSD), NORMALPRIO, ThreadTestMSD, 0);
#endif
#if HAL_USBH_USE_FTDI
usbhftdiObjectInit(&USBHFTDID[0]);
usbhftdipObjectInit(&FTDIPD[0]);
chThdCreateStatic(waTestFTDI, sizeof(waTestFTDI), NORMALPRIO, ThreadTestFTDI, 0);
#endif
//turn on USB power
palClearPad(GPIOC, GPIOC_OTG_FS_POWER_ON);
//start
#if STM32_USBH_USE_OTG1
usbhStart(&USBHD1);
#endif
#if STM32_USBH_USE_OTG2
usbhStart(&USBHD2);
#endif
for(;;) {
#if STM32_USBH_USE_OTG1
usbhMainLoop(&USBHD1);
#endif
#if STM32_USBH_USE_OTG2
usbhMainLoop(&USBHD2);
#endif
chThdSleepMilliseconds(100);
}
}

View File

@ -0,0 +1,324 @@
/*
ChibiOS - Copyright (C) 2006..2015 Giovanni Di Sirio
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.
*/
#ifndef _MCUCONF_H_
#define _MCUCONF_H_
/*
* STM32F4xx drivers configuration.
* The following settings override the default settings present in
* the various device driver implementation headers.
* Note that the settings for each driver only have effect if the whole
* driver is enabled in halconf.h.
*
* IRQ priorities:
* 15...0 Lowest...Highest.
*
* DMA priorities:
* 0...3 Lowest...Highest.
*/
#define STM32F4xx_MCUCONF
/*
* HAL driver system settings.
*/
#define STM32_NO_INIT FALSE
#define STM32_HSI_ENABLED TRUE
#define STM32_LSI_ENABLED TRUE
#define STM32_HSE_ENABLED TRUE
#define STM32_LSE_ENABLED FALSE
#define STM32_CLOCK48_REQUIRED TRUE
#define STM32_SW STM32_SW_PLL
#define STM32_PLLSRC STM32_PLLSRC_HSE
#define STM32_PLLM_VALUE 8
#define STM32_PLLN_VALUE 336
#define STM32_PLLP_VALUE 2
#define STM32_PLLQ_VALUE 7
#define STM32_HPRE STM32_HPRE_DIV1
#define STM32_PPRE1 STM32_PPRE1_DIV4
#define STM32_PPRE2 STM32_PPRE2_DIV2
#define STM32_RTCSEL STM32_RTCSEL_LSI
#define STM32_RTCPRE_VALUE 8
#define STM32_MCO1SEL STM32_MCO1SEL_HSI
#define STM32_MCO1PRE STM32_MCO1PRE_DIV1
#define STM32_MCO2SEL STM32_MCO2SEL_SYSCLK
#define STM32_MCO2PRE STM32_MCO2PRE_DIV5
#define STM32_I2SSRC STM32_I2SSRC_CKIN
#define STM32_PLLI2SN_VALUE 192
#define STM32_PLLI2SR_VALUE 5
#define STM32_PVD_ENABLE FALSE
#define STM32_PLS STM32_PLS_LEV0
#define STM32_BKPRAM_ENABLE FALSE
/*
* ADC driver system settings.
*/
#define STM32_ADC_ADCPRE ADC_CCR_ADCPRE_DIV4
#define STM32_ADC_USE_ADC1 FALSE
#define STM32_ADC_USE_ADC2 FALSE
#define STM32_ADC_USE_ADC3 FALSE
#define STM32_ADC_ADC1_DMA_STREAM STM32_DMA_STREAM_ID(2, 4)
#define STM32_ADC_ADC2_DMA_STREAM STM32_DMA_STREAM_ID(2, 2)
#define STM32_ADC_ADC3_DMA_STREAM STM32_DMA_STREAM_ID(2, 1)
#define STM32_ADC_ADC1_DMA_PRIORITY 2
#define STM32_ADC_ADC2_DMA_PRIORITY 2
#define STM32_ADC_ADC3_DMA_PRIORITY 2
#define STM32_ADC_IRQ_PRIORITY 6
#define STM32_ADC_ADC1_DMA_IRQ_PRIORITY 6
#define STM32_ADC_ADC2_DMA_IRQ_PRIORITY 6
#define STM32_ADC_ADC3_DMA_IRQ_PRIORITY 6
/*
* CAN driver system settings.
*/
#define STM32_CAN_USE_CAN1 FALSE
#define STM32_CAN_USE_CAN2 FALSE
#define STM32_CAN_CAN1_IRQ_PRIORITY 11
#define STM32_CAN_CAN2_IRQ_PRIORITY 11
/*
* DAC driver system settings.
*/
#define STM32_DAC_DUAL_MODE FALSE
#define STM32_DAC_USE_DAC1_CH1 FALSE
#define STM32_DAC_USE_DAC1_CH2 FALSE
#define STM32_DAC_DAC1_CH1_IRQ_PRIORITY 10
#define STM32_DAC_DAC1_CH2_IRQ_PRIORITY 10
#define STM32_DAC_DAC1_CH1_DMA_PRIORITY 2
#define STM32_DAC_DAC1_CH2_DMA_PRIORITY 2
#define STM32_DAC_DAC1_CH1_DMA_STREAM STM32_DMA_STREAM_ID(1, 5)
#define STM32_DAC_DAC1_CH2_DMA_STREAM STM32_DMA_STREAM_ID(1, 6)
/*
* EXT driver system settings.
*/
#define STM32_EXT_EXTI0_IRQ_PRIORITY 6
#define STM32_EXT_EXTI1_IRQ_PRIORITY 6
#define STM32_EXT_EXTI2_IRQ_PRIORITY 6
#define STM32_EXT_EXTI3_IRQ_PRIORITY 6
#define STM32_EXT_EXTI4_IRQ_PRIORITY 6
#define STM32_EXT_EXTI5_9_IRQ_PRIORITY 6
#define STM32_EXT_EXTI10_15_IRQ_PRIORITY 6
#define STM32_EXT_EXTI16_IRQ_PRIORITY 6
#define STM32_EXT_EXTI17_IRQ_PRIORITY 15
#define STM32_EXT_EXTI18_IRQ_PRIORITY 6
#define STM32_EXT_EXTI19_IRQ_PRIORITY 6
#define STM32_EXT_EXTI20_IRQ_PRIORITY 6
#define STM32_EXT_EXTI21_IRQ_PRIORITY 15
#define STM32_EXT_EXTI22_IRQ_PRIORITY 15
/*
* GPT driver system settings.
*/
#define STM32_GPT_USE_TIM1 FALSE
#define STM32_GPT_USE_TIM2 FALSE
#define STM32_GPT_USE_TIM3 FALSE
#define STM32_GPT_USE_TIM4 FALSE
#define STM32_GPT_USE_TIM5 FALSE
#define STM32_GPT_USE_TIM6 FALSE
#define STM32_GPT_USE_TIM7 FALSE
#define STM32_GPT_USE_TIM8 FALSE
#define STM32_GPT_USE_TIM9 FALSE
#define STM32_GPT_USE_TIM11 FALSE
#define STM32_GPT_USE_TIM12 FALSE
#define STM32_GPT_USE_TIM14 FALSE
#define STM32_GPT_TIM1_IRQ_PRIORITY 7
#define STM32_GPT_TIM2_IRQ_PRIORITY 7
#define STM32_GPT_TIM3_IRQ_PRIORITY 7
#define STM32_GPT_TIM4_IRQ_PRIORITY 7
#define STM32_GPT_TIM5_IRQ_PRIORITY 7
#define STM32_GPT_TIM6_IRQ_PRIORITY 7
#define STM32_GPT_TIM7_IRQ_PRIORITY 7
#define STM32_GPT_TIM8_IRQ_PRIORITY 7
#define STM32_GPT_TIM9_IRQ_PRIORITY 7
#define STM32_GPT_TIM11_IRQ_PRIORITY 7
#define STM32_GPT_TIM12_IRQ_PRIORITY 7
#define STM32_GPT_TIM14_IRQ_PRIORITY 7
/*
* I2C driver system settings.
*/
#define STM32_I2C_USE_I2C1 FALSE
#define STM32_I2C_USE_I2C2 FALSE
#define STM32_I2C_USE_I2C3 FALSE
#define STM32_I2C_BUSY_TIMEOUT 50
#define STM32_I2C_I2C1_RX_DMA_STREAM STM32_DMA_STREAM_ID(1, 0)
#define STM32_I2C_I2C1_TX_DMA_STREAM STM32_DMA_STREAM_ID(1, 6)
#define STM32_I2C_I2C2_RX_DMA_STREAM STM32_DMA_STREAM_ID(1, 2)
#define STM32_I2C_I2C2_TX_DMA_STREAM STM32_DMA_STREAM_ID(1, 7)
#define STM32_I2C_I2C3_RX_DMA_STREAM STM32_DMA_STREAM_ID(1, 2)
#define STM32_I2C_I2C3_TX_DMA_STREAM STM32_DMA_STREAM_ID(1, 4)
#define STM32_I2C_I2C1_IRQ_PRIORITY 5
#define STM32_I2C_I2C2_IRQ_PRIORITY 5
#define STM32_I2C_I2C3_IRQ_PRIORITY 5
#define STM32_I2C_I2C1_DMA_PRIORITY 3
#define STM32_I2C_I2C2_DMA_PRIORITY 3
#define STM32_I2C_I2C3_DMA_PRIORITY 3
#define STM32_I2C_DMA_ERROR_HOOK(i2cp) osalSysHalt("DMA failure")
/*
* ICU driver system settings.
*/
#define STM32_ICU_USE_TIM1 FALSE
#define STM32_ICU_USE_TIM2 FALSE
#define STM32_ICU_USE_TIM3 FALSE
#define STM32_ICU_USE_TIM4 FALSE
#define STM32_ICU_USE_TIM5 FALSE
#define STM32_ICU_USE_TIM8 FALSE
#define STM32_ICU_USE_TIM9 FALSE
#define STM32_ICU_TIM1_IRQ_PRIORITY 7
#define STM32_ICU_TIM2_IRQ_PRIORITY 7
#define STM32_ICU_TIM3_IRQ_PRIORITY 7
#define STM32_ICU_TIM4_IRQ_PRIORITY 7
#define STM32_ICU_TIM5_IRQ_PRIORITY 7
#define STM32_ICU_TIM8_IRQ_PRIORITY 7
#define STM32_ICU_TIM9_IRQ_PRIORITY 7
/*
* MAC driver system settings.
*/
#define STM32_MAC_TRANSMIT_BUFFERS 2
#define STM32_MAC_RECEIVE_BUFFERS 4
#define STM32_MAC_BUFFERS_SIZE 1522
#define STM32_MAC_PHY_TIMEOUT 100
#define STM32_MAC_ETH1_CHANGE_PHY_STATE TRUE
#define STM32_MAC_ETH1_IRQ_PRIORITY 13
#define STM32_MAC_IP_CHECKSUM_OFFLOAD 0
/*
* PWM driver system settings.
*/
#define STM32_PWM_USE_ADVANCED FALSE
#define STM32_PWM_USE_TIM1 FALSE
#define STM32_PWM_USE_TIM2 FALSE
#define STM32_PWM_USE_TIM3 FALSE
#define STM32_PWM_USE_TIM4 FALSE
#define STM32_PWM_USE_TIM5 FALSE
#define STM32_PWM_USE_TIM8 FALSE
#define STM32_PWM_USE_TIM9 FALSE
#define STM32_PWM_TIM1_IRQ_PRIORITY 7
#define STM32_PWM_TIM2_IRQ_PRIORITY 7
#define STM32_PWM_TIM3_IRQ_PRIORITY 7
#define STM32_PWM_TIM4_IRQ_PRIORITY 7
#define STM32_PWM_TIM5_IRQ_PRIORITY 7
#define STM32_PWM_TIM8_IRQ_PRIORITY 7
#define STM32_PWM_TIM9_IRQ_PRIORITY 7
/*
* SDC driver system settings.
*/
#define STM32_SDC_SDIO_DMA_PRIORITY 3
#define STM32_SDC_SDIO_IRQ_PRIORITY 9
#define STM32_SDC_WRITE_TIMEOUT_MS 250
#define STM32_SDC_READ_TIMEOUT_MS 25
#define STM32_SDC_CLOCK_ACTIVATION_DELAY 10
#define STM32_SDC_SDIO_UNALIGNED_SUPPORT TRUE
#define STM32_SDC_SDIO_DMA_STREAM STM32_DMA_STREAM_ID(2, 3)
/*
* SERIAL driver system settings.
*/
#define STM32_SERIAL_USE_USART1 FALSE
#define STM32_SERIAL_USE_USART2 TRUE
#define STM32_SERIAL_USE_USART3 FALSE
#define STM32_SERIAL_USE_UART4 FALSE
#define STM32_SERIAL_USE_UART5 FALSE
#define STM32_SERIAL_USE_USART6 FALSE
#define STM32_SERIAL_USART1_PRIORITY 12
#define STM32_SERIAL_USART2_PRIORITY 12
#define STM32_SERIAL_USART3_PRIORITY 12
#define STM32_SERIAL_UART4_PRIORITY 12
#define STM32_SERIAL_UART5_PRIORITY 12
#define STM32_SERIAL_USART6_PRIORITY 12
/*
* SPI driver system settings.
*/
#define STM32_SPI_USE_SPI1 FALSE
#define STM32_SPI_USE_SPI2 FALSE
#define STM32_SPI_USE_SPI3 FALSE
#define STM32_SPI_SPI1_RX_DMA_STREAM STM32_DMA_STREAM_ID(2, 0)
#define STM32_SPI_SPI1_TX_DMA_STREAM STM32_DMA_STREAM_ID(2, 3)
#define STM32_SPI_SPI2_RX_DMA_STREAM STM32_DMA_STREAM_ID(1, 3)
#define STM32_SPI_SPI2_TX_DMA_STREAM STM32_DMA_STREAM_ID(1, 4)
#define STM32_SPI_SPI3_RX_DMA_STREAM STM32_DMA_STREAM_ID(1, 0)
#define STM32_SPI_SPI3_TX_DMA_STREAM STM32_DMA_STREAM_ID(1, 7)
#define STM32_SPI_SPI1_DMA_PRIORITY 1
#define STM32_SPI_SPI2_DMA_PRIORITY 1
#define STM32_SPI_SPI3_DMA_PRIORITY 1
#define STM32_SPI_SPI1_IRQ_PRIORITY 10
#define STM32_SPI_SPI2_IRQ_PRIORITY 10
#define STM32_SPI_SPI3_IRQ_PRIORITY 10
#define STM32_SPI_DMA_ERROR_HOOK(spip) osalSysHalt("DMA failure")
/*
* ST driver system settings.
*/
#define STM32_ST_IRQ_PRIORITY 8
#define STM32_ST_USE_TIMER 2
/*
* UART driver system settings.
*/
#define STM32_UART_USE_USART1 FALSE
#define STM32_UART_USE_USART2 FALSE
#define STM32_UART_USE_USART3 FALSE
#define STM32_UART_USE_UART4 FALSE
#define STM32_UART_USE_UART5 FALSE
#define STM32_UART_USE_USART6 FALSE
#define STM32_UART_USART1_RX_DMA_STREAM STM32_DMA_STREAM_ID(2, 5)
#define STM32_UART_USART1_TX_DMA_STREAM STM32_DMA_STREAM_ID(2, 7)
#define STM32_UART_USART2_RX_DMA_STREAM STM32_DMA_STREAM_ID(1, 5)
#define STM32_UART_USART2_TX_DMA_STREAM STM32_DMA_STREAM_ID(1, 6)
#define STM32_UART_USART3_RX_DMA_STREAM STM32_DMA_STREAM_ID(1, 1)
#define STM32_UART_USART3_TX_DMA_STREAM STM32_DMA_STREAM_ID(1, 3)
#define STM32_UART_UART4_RX_DMA_STREAM STM32_DMA_STREAM_ID(1, 2)
#define STM32_UART_UART4_TX_DMA_STREAM STM32_DMA_STREAM_ID(1, 4)
#define STM32_UART_UART5_RX_DMA_STREAM STM32_DMA_STREAM_ID(1, 0)
#define STM32_UART_UART5_TX_DMA_STREAM STM32_DMA_STREAM_ID(1, 7)
#define STM32_UART_USART6_RX_DMA_STREAM STM32_DMA_STREAM_ID(2, 2)
#define STM32_UART_USART6_TX_DMA_STREAM STM32_DMA_STREAM_ID(2, 7)
#define STM32_UART_USART1_IRQ_PRIORITY 12
#define STM32_UART_USART2_IRQ_PRIORITY 12
#define STM32_UART_USART3_IRQ_PRIORITY 12
#define STM32_UART_UART4_IRQ_PRIORITY 12
#define STM32_UART_UART5_IRQ_PRIORITY 12
#define STM32_UART_USART6_IRQ_PRIORITY 12
#define STM32_UART_USART1_DMA_PRIORITY 0
#define STM32_UART_USART2_DMA_PRIORITY 0
#define STM32_UART_USART3_DMA_PRIORITY 0
#define STM32_UART_UART4_DMA_PRIORITY 0
#define STM32_UART_UART5_DMA_PRIORITY 0
#define STM32_UART_USART6_DMA_PRIORITY 0
#define STM32_UART_DMA_ERROR_HOOK(uartp) osalSysHalt("DMA failure")
/*
* USB driver system settings.
*/
#define STM32_USB_USE_OTG1 FALSE
#define STM32_USB_USE_OTG2 FALSE
#define STM32_USB_OTG1_IRQ_PRIORITY 14
#define STM32_USB_OTG2_IRQ_PRIORITY 14
#define STM32_USB_OTG1_RX_FIFO_SIZE 512
#define STM32_USB_OTG2_RX_FIFO_SIZE 1024
#define STM32_USB_OTG_THREAD_PRIO LOWPRIO
#define STM32_USB_OTG_THREAD_STACK_SIZE 128
#define STM32_USB_OTGFIFO_FILL_BASEPRI 0
#include "mcuconf_community.h"
#endif /* _MCUCONF_H_ */

View File

@ -0,0 +1,66 @@
/*
ChibiOS/RT - Copyright (C) 2014 Uladzimir Pylinsky aka barthess
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.
*/
/*
* FSMC driver system settings.
*/
#define STM32_FSMC_USE_FSMC1 FALSE
#define STM32_FSMC_FSMC1_IRQ_PRIORITY 10
/*
* FSMC NAND driver system settings.
*/
#define STM32_NAND_USE_FSMC_NAND1 FALSE
#define STM32_NAND_USE_FSMC_NAND2 FALSE
#define STM32_NAND_USE_EXT_INT FALSE
#define STM32_NAND_DMA_STREAM STM32_DMA_STREAM_ID(2, 7)
#define STM32_NAND_DMA_PRIORITY 0
#define STM32_NAND_DMA_ERROR_HOOK(nandp) osalSysHalt("DMA failure")
/*
* FSMC SRAM driver system settings.
*/
#define STM32_USE_FSMC_SRAM FALSE
#define STM32_SRAM_USE_FSMC_SRAM1 FALSE
#define STM32_SRAM_USE_FSMC_SRAM2 FALSE
#define STM32_SRAM_USE_FSMC_SRAM3 FLASE
#define STM32_SRAM_USE_FSMC_SRAM4 FALSE
/*
* FSMC SDRAM driver system settings.
*/
#define STM32_USE_FSMC_SDRAM FALSE
/*
* USBH driver system settings.
*/
#define STM32_OTG1_CHANNELS_NUMBER 8
#define STM32_OTG2_CHANNELS_NUMBER 12
#define STM32_USBH_USE_OTG1 1
#define STM32_OTG1_RXFIFO_SIZE 1024
#define STM32_OTG1_PTXFIFO_SIZE 128
#define STM32_OTG1_NPTXFIFO_SIZE 128
#define STM32_USBH_USE_OTG2 0
#define STM32_OTG2_RXFIFO_SIZE 2048
#define STM32_OTG2_PTXFIFO_SIZE 1024
#define STM32_OTG2_NPTXFIFO_SIZE 1024
#define STM32_USBH_MIN_QSPACE 4
#define STM32_USBH_CHANNELS_NP 4

View File

@ -0,0 +1,25 @@
*****************************************************************************
** ChibiOS/RT port for ARM-Cortex-M4 STM32F407. **
*****************************************************************************
** TARGET **
The demo runs on an ST STM32F4-Discovery board.
** The Demo **
** Build Procedure **
The demo has been tested by using the free Codesourcery GCC-based toolchain
and YAGARTO. just modify the TRGT line in the makefile in order to use
different GCC toolchains.
** Notes **
Some files used by the demo are not part of ChibiOS/RT but are copyright of
ST Microelectronics and are licensed under a different license.
Also note that not all the files present in the ST library are distributed
with ChibiOS/RT, you can find the whole library on the ST web site:
http://www.st.com