aboutsummaryrefslogtreecommitdiffstats
path: root/os/hal
diff options
context:
space:
mode:
Diffstat (limited to 'os/hal')
-rw-r--r--os/hal/boards/EXP430FR5969/board.c6
-rw-r--r--os/hal/boards/EXP430FR5969/board.h6
-rw-r--r--os/hal/boards/EXP430FR6989/board.c12
-rw-r--r--os/hal/boards/EXP430FR6989/board.h14
-rw-r--r--os/hal/boards/NONSTANDARD_STM32F4_BARTHESS2/board.h18
-rw-r--r--os/hal/hal.mk3
-rw-r--r--os/hal/include/hal_community.h5
-rw-r--r--os/hal/include/hal_crc.h6
-rw-r--r--os/hal/include/hal_ee24xx.h6
-rw-r--r--os/hal/include/hal_ee25xx.h6
-rw-r--r--os/hal/include/hal_eeprom.h6
-rw-r--r--os/hal/include/hal_eicu.h6
-rw-r--r--os/hal/include/hal_nand.h6
-rw-r--r--os/hal/include/hal_onewire.h13
-rw-r--r--os/hal/include/hal_rng.h6
-rw-r--r--os/hal/include/hal_timcap.h8
-rw-r--r--os/hal/include/hal_usb_msd.h192
-rw-r--r--os/hal/include/hal_usbh.h6
-rw-r--r--os/hal/ports/MSP430X/hal_adc_lld.c354
-rw-r--r--os/hal/ports/MSP430X/hal_adc_lld.h516
-rw-r--r--os/hal/ports/MSP430X/hal_dma_lld.c235
-rw-r--r--os/hal/ports/MSP430X/hal_dma_lld.h4
-rw-r--r--os/hal/ports/MSP430X/hal_lld.c4
-rw-r--r--os/hal/ports/MSP430X/hal_lld.h2
-rw-r--r--os/hal/ports/MSP430X/hal_serial_lld.c16
-rw-r--r--os/hal/ports/MSP430X/hal_spi_lld.c34
-rw-r--r--os/hal/ports/MSP430X/hal_spi_lld.h4
-rw-r--r--os/hal/ports/MSP430X/platform.mk3
-rw-r--r--os/hal/ports/STM32/LLD/CRCv1/hal_crc_lld.c2
-rw-r--r--os/hal/ports/STM32/LLD/CRCv1/hal_crc_lld.h8
-rw-r--r--os/hal/ports/STM32/LLD/DMA2Dv1/hal_stm32_dma2d.c2
-rw-r--r--os/hal/ports/STM32/LLD/DMA2Dv1/hal_stm32_dma2d.h8
-rw-r--r--os/hal/ports/STM32/LLD/FSMCv1/hal_fsmc.c8
-rw-r--r--os/hal/ports/STM32/LLD/FSMCv1/hal_fsmc.h17
-rw-r--r--os/hal/ports/STM32/LLD/FSMCv1/hal_fsmc_sdram.c2
-rw-r--r--os/hal/ports/STM32/LLD/FSMCv1/hal_fsmc_sdram.h8
-rw-r--r--os/hal/ports/STM32/LLD/FSMCv1/hal_fsmc_sram.c2
-rw-r--r--os/hal/ports/STM32/LLD/FSMCv1/hal_fsmc_sram.h8
-rw-r--r--os/hal/ports/STM32/LLD/FSMCv1/hal_nand_lld.c23
-rw-r--r--os/hal/ports/STM32/LLD/FSMCv1/hal_nand_lld.h38
-rw-r--r--os/hal/ports/STM32/LLD/LTDCv1/hal_stm32_ltdc.c2
-rw-r--r--os/hal/ports/STM32/LLD/LTDCv1/hal_stm32_ltdc.h8
-rw-r--r--os/hal/ports/STM32/LLD/TIMv1/hal_eicu_lld.h6
-rw-r--r--os/hal/ports/STM32/LLD/TIMv1/hal_timcap_lld.c2
-rw-r--r--os/hal/ports/STM32/LLD/TIMv1/hal_timcap_lld.h4
-rw-r--r--os/hal/ports/STM32/LLD/USBHv1/hal_stm32_otg.h6
-rw-r--r--os/hal/ports/STM32/LLD/USBHv1/hal_usbh_lld.h6
-rw-r--r--os/hal/src/hal_nand.c28
-rw-r--r--os/hal/src/hal_onewire.c11
-rw-r--r--os/hal/src/hal_timcap.c2
-rw-r--r--os/hal/src/hal_usb_msd.c408
51 files changed, 1746 insertions, 360 deletions
diff --git a/os/hal/boards/EXP430FR5969/board.c b/os/hal/boards/EXP430FR5969/board.c
index ac48ba0..0643cce 100644
--- a/os/hal/boards/EXP430FR5969/board.c
+++ b/os/hal/boards/EXP430FR5969/board.c
@@ -25,11 +25,11 @@
const PALConfig pal_default_config =
{
{VAL_IOPORT1_OUT, VAL_IOPORT1_DIR, VAL_IOPORT1_REN, VAL_IOPORT1_SEL0,
- VAL_IOPORT1_SEL1, VAL_IOPORT1_IES, VAL_IOPORT1_IE},
+ VAL_IOPORT1_SEL1},
{VAL_IOPORT2_OUT, VAL_IOPORT2_DIR, VAL_IOPORT2_REN, VAL_IOPORT2_SEL0,
- VAL_IOPORT2_SEL1, VAL_IOPORT2_IES, VAL_IOPORT2_IE},
+ VAL_IOPORT2_SEL1},
{VAL_IOPORT0_OUT, VAL_IOPORT0_DIR, VAL_IOPORT0_REN, VAL_IOPORT0_SEL0,
- VAL_IOPORT0_SEL1, VAL_IOPORT0_IES, VAL_IOPORT0_IE}
+ VAL_IOPORT0_SEL1}
}; /* Set UART TX pin correctly */
#endif /* HAL_USE_PAL */
diff --git a/os/hal/boards/EXP430FR5969/board.h b/os/hal/boards/EXP430FR5969/board.h
index 97103d3..3abe1cc 100644
--- a/os/hal/boards/EXP430FR5969/board.h
+++ b/os/hal/boards/EXP430FR5969/board.h
@@ -65,8 +65,6 @@
#define VAL_IOPORT1_REN 0xFCFE
#define VAL_IOPORT1_SEL0 0x0000
#define VAL_IOPORT1_SEL1 0x0300
-#define VAL_IOPORT1_IES 0x0000
-#define VAL_IOPORT1_IE 0x0000
/*
* Port B setup:
@@ -93,8 +91,6 @@
#define VAL_IOPORT2_REN 0xBDFF
#define VAL_IOPORT2_SEL0 0x0000
#define VAL_IOPORT2_SEL1 0x0000
-#define VAL_IOPORT2_IES 0x0000
-#define VAL_IOPORT2_IE 0x0000
/*
* Port J setup:
@@ -113,8 +109,6 @@
#define VAL_IOPORT0_REN 0x00CF
#define VAL_IOPORT0_SEL0 0x0030
#define VAL_IOPORT0_SEL1 0x0000
-#define VAL_IOPORT0_IES 0x0000
-#define VAL_IOPORT0_IE 0x0000
#if !defined(_FROM_ASM_)
#ifdef __cplusplus
diff --git a/os/hal/boards/EXP430FR6989/board.c b/os/hal/boards/EXP430FR6989/board.c
index a6836cf..475a2ea 100644
--- a/os/hal/boards/EXP430FR6989/board.c
+++ b/os/hal/boards/EXP430FR6989/board.c
@@ -25,17 +25,17 @@
const PALConfig pal_default_config =
{
{VAL_IOPORT1_OUT, VAL_IOPORT1_DIR, VAL_IOPORT1_REN, VAL_IOPORT1_SEL0,
- VAL_IOPORT1_SEL1, VAL_IOPORT1_IES, VAL_IOPORT1_IE},
+ VAL_IOPORT1_SEL1},
{VAL_IOPORT2_OUT, VAL_IOPORT2_DIR, VAL_IOPORT2_REN, VAL_IOPORT2_SEL0,
- VAL_IOPORT2_SEL1, VAL_IOPORT2_IES, VAL_IOPORT2_IE},
+ VAL_IOPORT2_SEL1},
{VAL_IOPORT3_OUT, VAL_IOPORT3_DIR, VAL_IOPORT3_REN, VAL_IOPORT3_SEL0,
- VAL_IOPORT3_SEL1, VAL_IOPORT3_IES, VAL_IOPORT3_IE},
+ VAL_IOPORT3_SEL1},
{VAL_IOPORT4_OUT, VAL_IOPORT4_DIR, VAL_IOPORT4_REN, VAL_IOPORT4_SEL0,
- VAL_IOPORT4_SEL1, VAL_IOPORT4_IES, VAL_IOPORT4_IE},
+ VAL_IOPORT4_SEL1},
{VAL_IOPORT5_OUT, VAL_IOPORT5_DIR, VAL_IOPORT5_REN, VAL_IOPORT5_SEL0,
- VAL_IOPORT5_SEL1, VAL_IOPORT5_IES, VAL_IOPORT5_IE},
+ VAL_IOPORT5_SEL1},
{VAL_IOPORT0_OUT, VAL_IOPORT0_DIR, VAL_IOPORT0_REN, VAL_IOPORT0_SEL0,
- VAL_IOPORT0_SEL1, VAL_IOPORT0_IES, VAL_IOPORT0_IE}
+ VAL_IOPORT0_SEL1}
}; /* Set UART TX pin correctly */
#endif /* HAL_USE_PAL */
diff --git a/os/hal/boards/EXP430FR6989/board.h b/os/hal/boards/EXP430FR6989/board.h
index 83b8fbb..d5afe29 100644
--- a/os/hal/boards/EXP430FR6989/board.h
+++ b/os/hal/boards/EXP430FR6989/board.h
@@ -69,8 +69,6 @@
#define VAL_IOPORT1_REN 0xFFFE
#define VAL_IOPORT1_SEL0 0x0000
#define VAL_IOPORT1_SEL1 0x0000
-#define VAL_IOPORT1_IES 0x0006
-#define VAL_IOPORT1_IE 0x0006
/*
* Port B setup:
@@ -97,8 +95,6 @@
#define VAL_IOPORT2_REN 0xFFCF
#define VAL_IOPORT2_SEL0 0x0030
#define VAL_IOPORT2_SEL1 0x0000
-#define VAL_IOPORT2_IES 0x0000
-#define VAL_IOPORT2_IE 0x0000
/*
* Port C setup:
@@ -125,8 +121,6 @@
#define VAL_IOPORT3_REN 0xFFFF
#define VAL_IOPORT3_SEL0 0x0000
#define VAL_IOPORT3_SEL1 0x0000
-#define VAL_IOPORT3_IES 0x0000
-#define VAL_IOPORT3_IE 0x0000
/*
* Port D setup:
@@ -153,11 +147,9 @@
#define VAL_IOPORT4_REN 0xFFFF
#define VAL_IOPORT4_SEL0 0x0000
#define VAL_IOPORT4_SEL1 0x0000
-#define VAL_IOPORT4_IES 0x0000
-#define VAL_IOPORT4_IE 0x0000
/*
- * Port D setup:
+ * Port E setup:
*
* P9.0 - BoosterPack BP27 (input pullup)
* P9.1 - BoosterPack BP28 (input pullup)
@@ -181,8 +173,6 @@
#define VAL_IOPORT5_REN 0xFF7F
#define VAL_IOPORT5_SEL0 0x0000
#define VAL_IOPORT5_SEL1 0x0000
-#define VAL_IOPORT5_IES 0x0000
-#define VAL_IOPORT5_IE 0x0000
/*
* Port J setup:
@@ -201,8 +191,6 @@
#define VAL_IOPORT0_REN 0x00CF
#define VAL_IOPORT0_SEL0 0x0030
#define VAL_IOPORT0_SEL1 0x0000
-#define VAL_IOPORT0_IES 0x0000
-#define VAL_IOPORT0_IE 0x0000
#if !defined(_FROM_ASM_)
#ifdef __cplusplus
diff --git a/os/hal/boards/NONSTANDARD_STM32F4_BARTHESS2/board.h b/os/hal/boards/NONSTANDARD_STM32F4_BARTHESS2/board.h
index 05aeceb..0788eb7 100644
--- a/os/hal/boards/NONSTANDARD_STM32F4_BARTHESS2/board.h
+++ b/os/hal/boards/NONSTANDARD_STM32F4_BARTHESS2/board.h
@@ -587,19 +587,14 @@
PIN_OSPEED_100M(GPIOD_MEM_D0) | \
PIN_OSPEED_100M(GPIOD_MEM_D1))
-#if STM32_NAND_USE_EXT_INT
-#define NAND_RB_NWAIT_PUPDR(pin) (PIN_PUPDR_PULLUP(pin))
-#else
-#define NAND_RB_NWAIT_PUPDR(pin) (PIN_PUPDR_FLOATING(pin))
-#endif
#define VAL_GPIOD_PUPDR (PIN_PUPDR_FLOATING(GPIOD_MEM_D2) | \
PIN_PUPDR_FLOATING(GPIOD_MEM_D3) | \
PIN_PUPDR_FLOATING(GPIOD_PIN2) | \
PIN_PUPDR_FLOATING(GPIOD_PIN3) | \
PIN_PUPDR_FLOATING(GPIOD_MEM_OE) | \
PIN_PUPDR_FLOATING(GPIOD_MEM_WE) | \
- NAND_RB_NWAIT_PUPDR(GPIOD_NAND_RB_NWAIT) | \
- PIN_PUPDR_PULLUP(GPIOD_NAND_CE1) | \
+ PIN_PUPDR_FLOATING(GPIOD_NAND_RB_NWAIT) |\
+ PIN_PUPDR_PULLUP(GPIOD_NAND_CE1) | \
PIN_PUPDR_FLOATING(GPIOD_MEM_D13) | \
PIN_PUPDR_FLOATING(GPIOD_MEM_D14) | \
PIN_PUPDR_FLOATING(GPIOD_MEM_D15) | \
@@ -893,21 +888,16 @@
PIN_OSPEED_100M(GPIOG_PIN14) | \
PIN_OSPEED_100M(GPIOG_PIN15))
-#if STM32_NAND_USE_EXT_INT
-#define NAND_RB1_PUPDR(pin) (PIN_PUPDR_FLOATING(pin))
-#else
-#define NAND_RB1_PUPDR(pin) (PIN_PUPDR_PULLUP(pin))
-#endif
#define VAL_GPIOG_PUPDR (PIN_PUPDR_FLOATING(GPIOG_MEM_A10) | \
PIN_PUPDR_FLOATING(GPIOG_MEM_A11) | \
PIN_PUPDR_FLOATING(GPIOG_MEM_A12) | \
PIN_PUPDR_FLOATING(GPIOG_MEM_A13) | \
PIN_PUPDR_FLOATING(GPIOG_MEM_A14) | \
PIN_PUPDR_FLOATING(GPIOG_MEM_A15) | \
- NAND_RB1_PUPDR(GPIOG_NAND_RB1) | \
+ PIN_PUPDR_PULLUP(GPIOG_NAND_RB1) | \
PIN_PUPDR_FLOATING(GPIOG_NAND_RB2) | \
PIN_PUPDR_FLOATING(GPIOG_PIN8) | \
- PIN_PUPDR_PULLUP(GPIOG_NAND_CE2) | \
+ PIN_PUPDR_PULLUP(GPIOG_NAND_CE2) | \
PIN_PUPDR_FLOATING(GPIOG_PIN10) | \
PIN_PUPDR_FLOATING(GPIOG_PIN11) | \
PIN_PUPDR_FLOATING(GPIOG_SRAM_CS1) | \
diff --git a/os/hal/hal.mk b/os/hal/hal.mk
index ce74620..f05ddbc 100644
--- a/os/hal/hal.mk
+++ b/os/hal/hal.mk
@@ -18,6 +18,7 @@ HALSRC += ${CHIBIOS_CONTRIB}/os/hal/src/hal_community.c \
${CHIBIOS_CONTRIB}/os/hal/src/hal_eeprom.c \
${CHIBIOS_CONTRIB}/os/hal/src/hal_timcap.c \
${CHIBIOS_CONTRIB}/os/hal/src/hal_qei.c \
- ${CHIBIOS_CONTRIB}/os/hal/src/hal_usb_hid.c
+ ${CHIBIOS_CONTRIB}/os/hal/src/hal_usb_hid.c \
+ ${CHIBIOS_CONTRIB}/os/hal/src/hal_usb_msd.c
HALINC += ${CHIBIOS_CONTRIB}/os/hal/include
diff --git a/os/hal/include/hal_community.h b/os/hal/include/hal_community.h
index 1518c7e..430df7c 100644
--- a/os/hal/include/hal_community.h
+++ b/os/hal/include/hal_community.h
@@ -67,6 +67,10 @@
#define HAL_USE_USB_HID FALSE
#endif
+#if !defined(HAL_USE_USB_MSD)
+#define HAL_USE_USB_MSD FALSE
+#endif
+
/* Abstract interfaces.*/
/* Shared headers.*/
@@ -84,6 +88,7 @@
#include "hal_crc.h"
#include "hal_eeprom.h"
#include "hal_usb_hid.h"
+#include "hal_usb_msd.h"
/*===========================================================================*/
/* Driver constants. */
diff --git a/os/hal/include/hal_crc.h b/os/hal/include/hal_crc.h
index 8c4c895..d7ef10f 100644
--- a/os/hal/include/hal_crc.h
+++ b/os/hal/include/hal_crc.h
@@ -14,8 +14,8 @@
limitations under the License.
*/
-#ifndef _CRC_H_
-#define _CRC_H_
+#ifndef HAL_CRC_H_
+#define HAL_CRC_H_
#if (HAL_USE_CRC == TRUE) || defined(__DOXYGEN__)
@@ -153,6 +153,6 @@ extern "C" {
#endif /* HAL_USE_CRC */
-#endif /* _CRC_H_ */
+#endif /* HAL_CRC_H_ */
/** @} */
diff --git a/os/hal/include/hal_ee24xx.h b/os/hal/include/hal_ee24xx.h
index ab12fd1..00cdc95 100644
--- a/os/hal/include/hal_ee24xx.h
+++ b/os/hal/include/hal_ee24xx.h
@@ -4,8 +4,8 @@
The work is provided "as is" without warranty of any kind, neither express nor implied.
*/
-#ifndef EE24XX_H
-#define EE24XX_H
+#ifndef HAL_EE24XX_H
+#define HAL_EE24XX_H
#include "hal.h"
@@ -61,4 +61,4 @@ typedef struct {
#endif /* #if defined(EEPROM_USE_EE24XX) && EEPROM_USE_EE24XX */
-#endif // EE24XX_H
+#endif // HAL_EE24XX_H
diff --git a/os/hal/include/hal_ee25xx.h b/os/hal/include/hal_ee25xx.h
index fc2ad6f..e520bd6 100644
--- a/os/hal/include/hal_ee25xx.h
+++ b/os/hal/include/hal_ee25xx.h
@@ -4,8 +4,8 @@
The work is provided "as is" without warranty of any kind, neither express nor implied.
*/
-#ifndef EE25XX_H
-#define EE25XX_H
+#ifndef HAL_EE25XX_H
+#define HAL_EE25XX_H
#include "hal.h"
@@ -60,4 +60,4 @@ EepromFileStream *SPIEepromFileOpen(SPIEepromFileStream *efs,
#endif /* #if defined(EEPROM_USE_EE25XX) && EEPROM_USE_EE25XX */
-#endif // EE25XX_H
+#endif // HAL_EE25XX_H
diff --git a/os/hal/include/hal_eeprom.h b/os/hal/include/hal_eeprom.h
index cd05e14..6f53fb9 100644
--- a/os/hal/include/hal_eeprom.h
+++ b/os/hal/include/hal_eeprom.h
@@ -26,8 +26,8 @@
The work is provided "as is" without warranty of any kind, neither express nor implied.
*/
-#ifndef __EEPROM_H__
-#define __EEPROM_H__
+#ifndef HAL_EEPROM_H_
+#define HAL_EEPROM_H_
#include "ch.h"
#include "hal.h"
@@ -140,4 +140,4 @@ msg_t eepfs_get(void *ip);
#include "hal_ee25xx.h"
#endif /* #if defined(HAL_USE_EEPROM) && HAL_USE_EEPROM */
-#endif /* __EEPROM_H__ */
+#endif /* HAL_EEPROM_H_ */
diff --git a/os/hal/include/hal_eicu.h b/os/hal/include/hal_eicu.h
index d4b0ed2..8b4b07d 100644
--- a/os/hal/include/hal_eicu.h
+++ b/os/hal/include/hal_eicu.h
@@ -22,8 +22,8 @@
32-bit timers and timers with single capture/compare channels.
*/
-#ifndef _EICU_H_
-#define _EICU_H_
+#ifndef HAL_EICU_H_
+#define HAL_EICU_H_
#if (HAL_USE_EICU == TRUE) || defined(__DOXYGEN__)
@@ -186,6 +186,6 @@ extern "C" {
#endif /* HAL_USE_EICU */
-#endif /* _EICU_H_ */
+#endif /* HAL_EICU_H_ */
/** @} */
diff --git a/os/hal/include/hal_nand.h b/os/hal/include/hal_nand.h
index d5a1c04..ace3e5d 100644
--- a/os/hal/include/hal_nand.h
+++ b/os/hal/include/hal_nand.h
@@ -15,15 +15,15 @@
*/
/**
- * @file nand.h
+ * @file hal_nand.h
* @brief NAND Driver macros and structures.
*
* @addtogroup NAND
* @{
*/
-#ifndef _NAND_H_
-#define _NAND_H_
+#ifndef HAL_NAND_H_
+#define HAL_NAND_H_
#if (HAL_USE_NAND == TRUE) || defined(__DOXYGEN__)
diff --git a/os/hal/include/hal_onewire.h b/os/hal/include/hal_onewire.h
index 9fb5be2..bbaf77b 100644
--- a/os/hal/include/hal_onewire.h
+++ b/os/hal/include/hal_onewire.h
@@ -15,15 +15,15 @@
*/
/**
- * @file onewire.h
+ * @file hal_onewire.h
* @brief 1-wire Driver macros and structures.
*
* @addtogroup onewire
* @{
*/
-#ifndef _ONEWIRE_H_
-#define _ONEWIRE_H_
+#ifndef HAL_ONEWIRE_H_
+#define HAL_ONEWIRE_H_
#if (HAL_USE_ONEWIRE == TRUE) || defined(__DOXYGEN__)
@@ -59,11 +59,13 @@
/*===========================================================================*/
/* Driver pre-compile time settings. */
/*===========================================================================*/
+#if ONEWIRE_SYNTH_SEARCH_TEST && !ONEWIRE_USE_SEARCH_ROM
+#error "Synthetic search rom test needs ONEWIRE_USE_SEARCH_ROM"
+#endif
/*===========================================================================*/
/* Derived constants and error checks. */
/*===========================================================================*/
-
#if !HAL_USE_PWM
#error "1-wire Driver requires HAL_USE_PWM"
#endif
@@ -328,7 +330,6 @@ extern onewireDriver OWD1;
#ifdef __cplusplus
extern "C" {
#endif
- void onewireInit(void);
void onewireObjectInit(onewireDriver *owp);
void onewireStart(onewireDriver *owp, const onewireConfig *config);
void onewireStop(onewireDriver *owp);
@@ -352,7 +353,7 @@ extern "C" {
#endif /* HAL_USE_ONEWIRE */
-#endif /* _ONEWIRE_H_ */
+#endif /* HAL_ONEWIRE_H_ */
/** @} */
diff --git a/os/hal/include/hal_rng.h b/os/hal/include/hal_rng.h
index 0e3c484..dc146c7 100644
--- a/os/hal/include/hal_rng.h
+++ b/os/hal/include/hal_rng.h
@@ -14,8 +14,8 @@
limitations under the License.
*/
-#ifndef _RNG_H_
-#define _RNG_H_
+#ifndef HAL_RNG_H_
+#define HAL_RNG_H_
#if (HAL_USE_RNG == TRUE) || defined(__DOXYGEN__)
@@ -131,6 +131,6 @@ extern "C" {
#endif /* HAL_USE_RNG */
-#endif /* _RNG_H_ */
+#endif /* HAL_RNG_H_ */
/** @} */
diff --git a/os/hal/include/hal_timcap.h b/os/hal/include/hal_timcap.h
index bd43dd1..61c7fc5 100644
--- a/os/hal/include/hal_timcap.h
+++ b/os/hal/include/hal_timcap.h
@@ -19,15 +19,15 @@
*/
/**
- * @file timcap.h
+ * @file hal_timcap.h
* @brief TIMCAP Driver macros and structures.
*
* @addtogroup TIMCAP
* @{
*/
-#ifndef _TIMCAP_H_
-#define _TIMCAP_H_
+#ifndef HAL_TIMCAP_H_
+#define HAL_TIMCAP_H_
#include "ch.h"
#include "hal.h"
@@ -201,6 +201,6 @@ extern "C" {
#endif /* HAL_USE_TIMCAP */
-#endif /* _TIMCAP_H_ */
+#endif /* HAL_TIMCAP_H_ */
/** @} */
diff --git a/os/hal/include/hal_usb_msd.h b/os/hal/include/hal_usb_msd.h
new file mode 100644
index 0000000..08241df
--- /dev/null
+++ b/os/hal/include/hal_usb_msd.h
@@ -0,0 +1,192 @@
+/*
+ ChibiOS/HAL - Copyright (C) 2016 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.
+*/
+
+/**
+ * @file hal_usb_msd.h
+ * @brief USM mass storage device driver macros and structures.
+ *
+ * @addtogroup usb_msd
+ * @{
+ */
+
+#ifndef HAL_USB_MSD_H
+#define HAL_USB_MSD_H
+
+#if (HAL_USE_USB_MSD == TRUE) || defined(__DOXYGEN__)
+
+#include "lib_scsi.h"
+
+/*===========================================================================*/
+/* Driver constants. */
+/*===========================================================================*/
+
+#define USB_MSD_DATA_EP 0x01
+#define USB_MSD_EP_SIZE 0x40
+
+/*===========================================================================*/
+/* Driver pre-compile time settings. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Derived constants and error checks. */
+/*===========================================================================*/
+
+#if !HAL_USE_USB
+#error "Mass storage Driver requires HAL_USE_USB"
+#endif
+
+/*===========================================================================*/
+/* Driver data structures and types. */
+/*===========================================================================*/
+
+/**
+ * @brief Type of a structure representing an USB mass storage driver.
+ */
+typedef struct USBMassStorageDriver USBMassStorageDriver;
+
+/**
+ * @brief Type of a driver state machine possible states.
+ */
+typedef enum {
+ USB_MSD_UNINIT = 0,
+ USB_MSD_STOP,
+ USB_MSD_READY,
+} usbmsdstate_t;
+
+/**
+ * @brief Represents command block wrapper structure.
+ * @details See USB Mass Storage Class Specification.
+ */
+typedef struct PACKED_VAR {
+ uint32_t signature;
+ uint32_t tag;
+ uint32_t data_len;
+ uint8_t flags;
+ uint8_t lun;
+ uint8_t cmd_len;
+ uint8_t cmd_data[16];
+} msd_cbw_t;
+
+/**
+ * @brief Represents command status wrapper structure.
+ * @details See USB Mass Storage Class Specification.
+ */
+typedef struct PACKED_VAR {
+ uint32_t signature;
+ uint32_t tag;
+ uint32_t data_residue;
+ uint8_t status;
+} msd_csw_t;
+
+/**
+ * @brief Transport handler passed to SCSI layer.
+ */
+typedef struct {
+ /**
+ * @brief Pointer to the @p USBDriver object.
+ */
+ USBDriver *usbp;
+ /**
+ * @brief USB endpoint number.
+ */
+ usbep_t ep;
+} usb_scsi_transport_handler_t;
+
+
+/**
+ * @brief Structure representing an USB mass storage driver.
+ */
+struct USBMassStorageDriver {
+ /**
+ * @brief Pointer to the @p USBDriver object.
+ */
+ USBDriver *usbp;
+ /**
+ * @brief Driver state.
+ */
+ usbmsdstate_t state;
+ /**
+ * @brief CBW structure.
+ */
+ msd_cbw_t cbw;
+ /**
+ * @brief CSW structure.
+ */
+ msd_csw_t csw;
+ /**
+ * @brief Thread working area.
+ */
+ THD_WORKING_AREA( waMSDWorker, 512);
+ /**
+ * @brief Worker thread handler.
+ */
+ thread_reference_t worker;
+ /**
+ * @brief SCSI target driver structure.
+ */
+ SCSITarget scsi_target;
+ /**
+ * @brief SCSI target configuration structure.
+ */
+ SCSITargetConfig scsi_config;
+ /**
+ * @brief SCSI transport structure.
+ */
+ SCSITransport scsi_transport;
+ /**
+ * @brief SCSI over USB transport handler structure.
+ */
+ usb_scsi_transport_handler_t usb_scsi_transport_handler;
+};
+
+
+/*===========================================================================*/
+/* Driver macros. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* External declarations. */
+/*===========================================================================*/
+
+extern USBMassStorageDriver USBMSD1;
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+ void msdObjectInit(USBMassStorageDriver *msdp);
+ void msdStart(USBMassStorageDriver *msdp, USBDriver *usbp,
+ BaseBlockDevice *blkdev, uint8_t *blkbuf,
+ const scsi_inquiry_response_t *scsi_inquiry_response);
+ void msdStop(USBMassStorageDriver *msdp);
+ bool msd_request_hook(USBDriver *usbp);
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* HAL_USE_USB_MSD */
+
+#endif /* HAL_USB_MSD_H */
+
+/** @} */
+
+
+
+
+
+
+
+
+
diff --git a/os/hal/include/hal_usbh.h b/os/hal/include/hal_usbh.h
index 5fd0047..63be93e 100644
--- a/os/hal/include/hal_usbh.h
+++ b/os/hal/include/hal_usbh.h
@@ -15,8 +15,8 @@
limitations under the License.
*/
-#ifndef USBH_H_
-#define USBH_H_
+#ifndef HAL_USBH_H_
+#define HAL_USBH_H_
#include "hal.h"
@@ -433,4 +433,4 @@ struct usbh_baseclassdriver {
#endif
-#endif /* USBH_H_ */
+#endif /* HAL_USBH_H_ */
diff --git a/os/hal/ports/MSP430X/hal_adc_lld.c b/os/hal/ports/MSP430X/hal_adc_lld.c
new file mode 100644
index 0000000..42d3cbe
--- /dev/null
+++ b/os/hal/ports/MSP430X/hal_adc_lld.c
@@ -0,0 +1,354 @@
+/*
+ ChibiOS - Copyright (C) 2016 Andrew Wygle aka awygle
+
+ 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 hal_adc_lld.c
+ * @brief MSP430X ADC subsystem low level driver source.
+ *
+ * @addtogroup ADC
+ * @{
+ */
+
+#include "hal.h"
+
+#if (HAL_USE_ADC == TRUE) || defined(__DOXYGEN__)
+
+/*===========================================================================*/
+/* Driver local definitions. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Driver exported variables. */
+/*===========================================================================*/
+
+/**
+ * @brief ADC1 driver identifier.
+ */
+#if (MSP430X_ADC_USE_ADC1 == TRUE) || defined(__DOXYGEN__)
+ADCDriver ADCD1;
+#endif
+
+/*===========================================================================*/
+/* Driver local variables and types. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Driver local functions. */
+/*===========================================================================*/
+
+static void restart_dma(ADCDriver * adcp) {
+ /* TODO timeouts? */
+ /* Restart DMA transfer */
+ if (adcp->dma.registers == NULL) {
+ /* Acquire a DMA stream because dmaTransfer can be called from ISRs */
+ osalSysLockFromISR();
+ dmaAcquireI(&(adcp->dma), adcp->dma.index);
+ osalSysUnlockFromISR();
+ dmaTransfer(&(adcp->dma), &(adcp->req));
+ }
+ else {
+ dmaTransfer(&(adcp->dma), &(adcp->req));
+ }
+}
+
+static void dma_callback(void * args) {
+ ADCDriver * adcp = (ADCDriver *)args;
+
+ if (adcp->grpp == NULL)
+ return;
+
+ adcp->count++;
+
+ if (adcp->count == adcp->depth / 2) {
+ /* half-full interrupt */
+ _adc_isr_half_code(adcp);
+ }
+
+ if (adcp->count == adcp->depth) {
+ /* full interrupt */
+
+ /* adc_lld_stop_conversion is called automatically here if needed */
+ _adc_isr_full_code(adcp);
+ /* after isr_full, adcp->grpp is only non-NULL if it's a circular group */
+ if (adcp->grpp) {
+ /* Reset the buffer pointer */
+ adcp->req.dest_addr = adcp->samples;
+
+ restart_dma(adcp);
+
+ /* Reset the count */
+ adcp->count = 0;
+
+ /* Start next sequence */
+ adcp->regs->ctl[0] |= ADC12SC;
+ }
+ }
+ else {
+ /* Advance the buffer pointer */
+ adcp->req.dest_addr = adcp->samples + (adcp->req.size * adcp->count);
+
+ restart_dma(adcp);
+
+ /* Start next sequence */
+ adcp->regs->ctl[0] |= ADC12SC;
+ }
+}
+
+static void populate_tlv(ADCDriver * adcp) {
+ uint8_t * tlv_addr = (uint8_t *)TLV_START;
+
+ while (*tlv_addr != TLV_TAGEND && tlv_addr < (uint8_t *)TLV_END) {
+ if (*tlv_addr == TLV_ADC12CAL) {
+ adcp->adc_cal = (msp430x_adc_cal_t *)(tlv_addr + 2);
+ }
+ else if (*tlv_addr == TLV_REFCAL) {
+ adcp->ref_cal = (msp430x_ref_cal_t *)(tlv_addr + 2);
+ }
+ tlv_addr += (tlv_addr[1] + 2);
+ }
+}
+
+/*===========================================================================*/
+/* Driver interrupt handlers. */
+/*===========================================================================*/
+
+PORT_IRQ_HANDLER(ADC12_VECTOR) {
+
+ OSAL_IRQ_PROLOGUE();
+
+ switch (__even_in_range(ADC12IV, ADC12IV_ADC12TOVIFG)) {
+
+ case ADC12IV_ADC12OVIFG: {
+ if (ADCD1.grpp == NULL)
+ break;
+ _adc_isr_error_code(&ADCD1, ADC_ERR_OVERFLOW);
+ break;
+ }
+ case ADC12IV_ADC12TOVIFG: {
+ if (ADCD1.grpp == NULL)
+ break;
+ _adc_isr_error_code(&ADCD1, ADC_ERR_AWD);
+ break;
+ }
+ default:
+ osalDbgAssert(false, "unhandled ADC exception");
+ _adc_isr_error_code(&ADCD1, ADC_ERR_UNKNOWN);
+ }
+
+ OSAL_IRQ_EPILOGUE();
+}
+
+/*===========================================================================*/
+/* Driver exported functions. */
+/*===========================================================================*/
+
+/**
+ * @brief Low level ADC driver initialization.
+ *
+ * @notapi
+ */
+void adc_lld_init(void) {
+
+#if MSP430X_ADC_USE_ADC1 == TRUE
+ /* Driver initialization.*/
+ adcObjectInit(&ADCD1);
+ ADCD1.regs = (msp430x_adc_reg_t *)(&ADC12CTL0);
+ populate_tlv(&ADCD1);
+#endif
+}
+
+/**
+ * @brief Configures and activates the ADC peripheral.
+ *
+ * @param[in] adcp pointer to the @p ADCDriver object
+ *
+ * @notapi
+ */
+void adc_lld_start(ADCDriver * adcp) {
+
+ if (adcp->state == ADC_STOP) {
+ /* Enables the peripheral.*/
+ adcp->regs->ctl[0] = ADC12ON | ADC12MSC;
+ adcp->regs->ctl[1] =
+ MSP430X_ADC1_PDIV | MSP430X_ADC1_DIV | MSP430X_ADC1_SSEL | ADC12SHP;
+ adcp->regs->ctl[3] = ADC12ICH3MAP | ADC12ICH2MAP | ADC12ICH1MAP |
+ ADC12ICH0MAP | ADC12TCMAP | ADC12BATMAP;
+ adcp->regs->ier[2] = ADC12TOVIE | ADC12OVIE;
+ adcp->req.trigger = DMA_TRIGGER_MNEM(ADC12IFG);
+#if MSP430X_ADC_COMPACT_SAMPLES == TRUE
+ adcp->req.data_mode = MSP430X_DMA_SRCWORD | MSP430X_DMA_DSTBYTE;
+#else
+ adcp->req.data_mode = MSP430X_DMA_SRCWORD | MSP430X_DMA_DSTWORD;
+#endif
+ adcp->req.addr_mode = MSP430X_DMA_SRCINCR | MSP430X_DMA_DSTINCR;
+ adcp->req.transfer_mode = MSP430X_DMA_SINGLE;
+ adcp->req.callback.callback = dma_callback;
+ adcp->req.callback.args = adcp;
+
+#if MSP430X_ADC_EXCLUSIVE_DMA == TRUE
+ bool b;
+ if (adcp->config->dma_index < MSP430X_DMA_CHANNELS) {
+ b = dmaAcquireI(&adcp->dma, adcp->config->dma_index);
+ osalDbgAssert(!b, "stream already allocated");
+ }
+ else {
+#endif
+ adcp->dma.registers = NULL;
+#if MSP430X_ADC_EXCLUSIVE_DMA == TRUE
+ }
+#endif
+ }
+ /* Configures the peripheral.*/
+}
+
+/**
+ * @brief Deactivates the ADC peripheral.
+ *
+ * @param[in] adcp pointer to the @p ADCDriver object
+ *
+ * @notapi
+ */
+void adc_lld_stop(ADCDriver * adcp) {
+
+ if (adcp->state == ADC_READY) {
+/* Resets the peripheral.*/
+
+/* Disables the peripheral.*/
+#if MSP430X_ADC_EXCLUSIVE_DMA == TRUE
+ if (adcp->config->dma_index < MSP430X_DMA_CHANNELS) {
+ dmaRelease(&(adcp->dma));
+ }
+#endif
+ adcp->regs->ctl[0] = 0;
+ }
+}
+
+/**
+ * @brief Starts an ADC conversion.
+ *
+ * @param[in] adcp pointer to the @p ADCDriver object
+ *
+ * @notapi
+ */
+void adc_lld_start_conversion(ADCDriver * adcp) {
+
+ /* always use sequential transfer mode - this is fine */
+ adcp->regs->ctl[1] |= ADC12CONSEQ0;
+
+ /* set resolution */
+ adcp->regs->ctl[2] |= adcp->grpp->res;
+ /* start from MEM0 */
+ adcp->regs->ctl[3] &= ~(ADC12CSTARTADD_31);
+
+ /* Configure voltage reference */
+ while (REFCTL0 & REFGENBUSY)
+ ;
+ REFCTL0 = adcp->grpp->vref_src;
+
+ for (int i = 0; i < adcp->grpp->num_channels; i++) {
+ osalDbgAssert(adcp->grpp->channels[i] < 32, "invalid channel number");
+ adcp->regs->mctl[i] = adcp->grpp->ref | adcp->grpp->channels[i];
+ }
+
+ adcp->regs->mctl[adcp->grpp->num_channels - 1] |= ADC12EOS;
+
+ adcp->req.source_addr = adcp->regs->mem;
+ adcp->req.dest_addr = adcp->samples;
+ adcp->req.size = adcp->grpp->num_channels;
+ adcp->count = 0;
+
+/* TODO timeouts? */
+#if MSP430X_ADC_EXCLUSIVE_DMA == TRUE
+ if (adcp->config->dma_index >= MSP430X_DMA_CHANNELS) {
+ adcp->dma.index = dmaRequestS(&(adcp->req), TIME_INFINITE);
+ }
+ else {
+ dmaTransfer(&(adcp->dma), &(adcp->req));
+ }
+#else
+ adcp->dma.index = dmaRequestS(&(adcp->req), TIME_INFINITE);
+#endif
+
+ adcp->regs->ctl[0] |= adcp->grpp->rate | ADC12MSC | ADC12ENC | ADC12SC;
+}
+
+/**
+ * @brief Stops an ongoing conversion.
+ *
+ * @param[in] adcp pointer to the @p ADCDriver object
+ *
+ * @notapi
+ */
+void adc_lld_stop_conversion(ADCDriver * adcp) {
+
+ /* TODO stop DMA transfers here */
+ adcp->regs->ctl[0] &= ~(ADC12ENC | ADC12SC);
+
+#if MSP430X_ADC_EXCLUSIVE_DMA == TRUE
+ if (adcp->config->dma_index >= MSP430X_DMA_CHANNELS) {
+#endif
+ if (adcp->dma.registers != NULL) {
+ dmaRelease(&(adcp->dma));
+ adcp->dma.registers = NULL;
+ }
+#if MSP430X_ADC_EXCLUSIVE_DMA == TRUE
+ }
+#endif
+}
+
+adcsample_t adcMSP430XAdjustResult(ADCConversionGroup * grpp,
+ adcsample_t sample) {
+ uint32_t tmp;
+ uint16_t fact;
+ if (grpp->ref == MSP430X_ADC_VSS_VREF_BUF ||
+ grpp->ref == MSP430X_ADC_VEREF_P_VREF_BUF ||
+ grpp->ref == MSP430X_ADC_VREF_BUF_VCC ||
+ grpp->ref == MSP430X_ADC_VREF_BUF_VEREF_P ||
+ grpp->ref == MSP430X_ADC_VEREF_N_VREF_BUF) {
+ /* Retrieve proper reference correction factor from TLV */
+ fact = (&(ADCD1.ref_cal->CAL_ADC_12VREF_FACTOR))[grpp->vref_src >> 4];
+ /* Calculate corrected value */
+ tmp = (uint32_t)(sample << 1) * (uint32_t)fact;
+ sample = tmp >> 16;
+ }
+
+ /* Gain correction */
+ fact = ADCD1.adc_cal->CAL_ADC_GAIN_FACTOR;
+ tmp = (uint32_t)(sample << 1) * (uint32_t)fact;
+ sample = tmp >> 16;
+
+ /* Offset correction */
+ sample += ADCD1.adc_cal->CAL_ADC_OFFSET;
+
+ return sample;
+}
+
+adcsample_t adcMSP430XAdjustTemp(ADCConversionGroup * grpp,
+ adcsample_t sample) {
+ uint16_t t30;
+ uint16_t t85;
+
+ /* Retrieve proper T = 30 correction value from TLV */
+ t30 = (&(ADCD1.adc_cal->CAL_ADC_12T30))[grpp->vref_src >> 3];
+ /* Retrieve proper T = 85 correction value from TLV */
+ t85 = (&(ADCD1.adc_cal->CAL_ADC_12T30))[(grpp->vref_src >> 3) + 1];
+
+ return ((((int32_t)sample - (int32_t)t30) * (85 - 30)) / (t85 - t30)) + 30;
+}
+
+#endif /* HAL_USE_ADC == TRUE */
+
+/** @} */
diff --git a/os/hal/ports/MSP430X/hal_adc_lld.h b/os/hal/ports/MSP430X/hal_adc_lld.h
new file mode 100644
index 0000000..1cca36b
--- /dev/null
+++ b/os/hal/ports/MSP430X/hal_adc_lld.h
@@ -0,0 +1,516 @@
+/*
+ ChibiOS - Copyright (C) 2016 Andrew Wygle aka awygle
+
+ 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 hal_adc_lld.h
+ * @brief MSP430X ADC subsystem low level driver header.
+ *
+ * @addtogroup ADC
+ * @{
+ */
+
+#ifndef HAL_ADC_LLD_H
+#define HAL_ADC_LLD_H
+
+#if (HAL_USE_ADC == TRUE) || defined(__DOXYGEN__)
+
+/*===========================================================================*/
+/* Driver constants. */
+/*===========================================================================*/
+
+/**
+ * @name Sampling rates
+ * @{
+ */
+typedef enum {
+ MSP430X_ADC_SHT_4 = 0x0000,
+ MSP430X_ADC_SHT_8 = 0x1100,
+ MSP430X_ADC_SHT_16 = 0x2200,
+ MSP430X_ADC_SHT_32 = 0x3300,
+ MSP430X_ADC_SHT_64 = 0x4400,
+ MSP430X_ADC_SHT_96 = 0x5500,
+ MSP430X_ADC_SHT_128 = 0x6600,
+ MSP430X_ADC_SHT_192 = 0x7700,
+ MSP430X_ADC_SHT_256 = 0x8800,
+ MSP430X_ADC_SHT_384 = 0x9900,
+ MSP430X_ADC_SHT_512 = 0xAA00
+} MSP430XADCSampleRates;
+/** @} */
+
+/**
+ * @name Resolution
+ * @{
+ */
+typedef enum {
+ MSP430X_ADC_RES_8BIT = 0x0000,
+ MSP430X_ADC_RES_10BIT = 0x0010,
+ MSP430X_ADC_RES_12BIT = 0x0020
+} MSP430XADCResolution;
+/** @} */
+
+/**
+ * @name References
+ * @{
+ */
+typedef enum {
+ MSP430X_ADC_VSS_VCC = 0x0000,
+ MSP430X_ADC_VSS_VREF_BUF = 0x0100,
+ MSP430X_ADC_VSS_VEREF_N = 0x0200,
+ MSP430X_ADC_VSS_VEREF_P_BUF = 0x0300,
+ MSP430X_ADC_VSS_VEREF_P = 0x0400,
+ MSP430X_ADC_VEREF_P_BUF_VCC = 0x0500,
+ MSP430X_ADC_VEREF_P_VCC = 0x0600,
+ MSP430X_ADC_VEREF_P_VREF_BUF = 0x0700,
+ MSP430X_ADC_VREF_BUF_VCC = 0x0900,
+ MSP430X_ADC_VREF_BUF_VEREF_P = 0x0B00,
+ MSP430X_ADC_VEREF_N_VCC = 0x0C00,
+ MSP430X_ADC_VEREF_N_VREF_BUF = 0x0D00,
+ MSP430X_ADC_VEREF_N_VEREF_P = 0x0E00,
+ MSP430X_ADC_VEREF_N_VEREF_P_BUF = 0x0F00
+} MSP430XADCReferences;
+
+typedef enum {
+ MSP430X_REF_1V2 = 0x0000,
+ MSP430X_REF_2V0 = 0x0010,
+ MSP430X_REF_2V5 = 0x0020,
+ MSP430X_REF_1V2_EXT = 0x0002,
+ MSP430X_REF_2V0_EXT = 0x0012,
+ MSP430X_REF_2V5_EXT = 0x0022
+} MSP430XREFSources;
+
+#define MSP430X_REF_NONE MSP430X_REF_1V2
+
+/** @} */
+
+/*===========================================================================*/
+/* Driver pre-compile time settings. */
+/*===========================================================================*/
+
+/**
+ * @name MSP430X configuration options
+ * @{
+ */
+/**
+ * @brief Stores ADC samples in an 8 bit integer.
+ * @note 10 and 12 bit sampling modes must not be used when this option is
+ * enabled.
+ */
+#if !defined(MSP430X_ADC_COMPACT_SAMPLES) || defined(__DOXYGEN__)
+#define MSP430X_ADC_COMPACT_SAMPLES FALSE
+#endif
+
+/**
+ * @brief ADC1 driver enable switch.
+ * @details If set to @p TRUE the support for ADC1 is included.
+ * @note The default is @p TRUE.
+ */
+#if !defined(MSP430X_ADC_USE_ADC1) || defined(__DOXYGEN__)
+#define MSP430X_ADC_USE_ADC1 TRUE
+#endif
+
+/**]
+ * @brief Exclusive DMA enable switch.
+ * @details If set to @p TRUE the support for exclusive DMA is included.
+ * @note This increases the size of the compiled executable somewhat.
+ * @note The default is @p FALSE.
+ */
+#if !defined(MSP430X_ADC_EXCLUSIVE_DMA) || defined(__DOXYGEN__)
+#define MSP430X_ADC_EXCLUSIVE_DMA FALSE
+#endif
+
+#if MSP430X_ADC_USE_ADC1
+
+/**
+ * @brief ADC1 clock source configuration
+ */
+#if !defined(MSP430X_ADC1_CLK_SRC)
+#define MSP430X_ADC1_CLK_SRC MSP430X_MODCLK
+#endif
+
+#endif
+/** @} */
+
+/*===========================================================================*/
+/* Derived constants and error checks. */
+/*===========================================================================*/
+
+#if MSP430X_ADC_USE_ADC1
+
+#if !defined(__MSP430_HAS_ADC12_B__)
+#error "No ADC present or ADC version not supported"
+#endif
+
+#if (MSP430X_ADC1_CLK_SRC == MSP430X_MODCLK)
+#define MSP430X_ADC1_CLK_FREQ MSP430X_MODCLK_FREQ
+#define MSP430X_ADC1_SSEL ADC12SSEL_0
+#elif (MSP430X_ADC1_CLK_SRC == MSP430X_ACLK)
+#define MSP430X_ADC1_CLK_FREQ MSP430X_ACLK_FREQ
+#define MSP430X_ADC1_SSEL ADC12SSEL_1
+#elif (MSP430X_ADC1_CLK_SRC == MSP430X_MCLK)
+#define MSP$30X_ADC1_CLK_FREQ MSP430X_MCLK_FREQ
+#define MSP430X_ADC1_SSEL ADC12SSEL_2
+#elif (MSP430X_ADC1_CLK_SRC == MSP430SMCLK)
+#define MSP430X_ADC1_CLK_FREQ MSP430X_SMCLK_FREQ
+#define MSP430X_ADC1_SSEL ADC12SSEL_3
+#else
+#error "Invalid ADC1 clock source requested!"
+#endif
+
+#if !defined(MSP430X_ADC1_FREQ)
+#warning "ADC clock frequency not defined - assuming 1 for all dividers"
+#define MSP430X_ADC1_DIV_CALC(x) (x == 1)
+#else
+#define MSP430X_ADC1_DIV_CALC(x) \
+ ((MSP430X_ADC1_CLK_FREQ / x) == MSP430X_ADC1_FREQ)
+#endif
+
+/**
+ * @brief ADC1 prescaler calculations
+ */
+#if MSP430X_ADC1_DIV_CALC(1)
+#define MSP430X_ADC1_PDIV ADC12PDIV__1
+#define MSP430X_ADC1_DIV ADC12DIV_0
+#elif MSP430X_ADC1_DIV_CALC(2)
+#define MSP430X_ADC1_PDIV ADC12PDIV__1
+#define MSP430X_ADC1_DIV ADC12DIV_1
+#elif MSP430X_ADC1_DIV_CALC(3)
+#define MSP430X_ADC1_PDIV ADC12PDIV__1
+#define MSP430X_ADC1_DIV ADC12DIV_2
+#elif MSP430X_ADC1_DIV_CALC(4)
+#define MSP430X_ADC1_PDIV ADC12PDIV__4
+#define MSP430X_ADC1_DIV ADC12DIV_0
+#elif MSP430X_ADC1_DIV_CALC(5)
+#define MSP430X_ADC1_PDIV ADC12PDIV__1
+#define MSP430X_ADC1_DIV ADC12DIV_4
+#elif MSP430X_ADC1_DIV_CALC(6)
+#define MSP430X_ADC1_PDIV ADC12PDIV__1
+#define MSP430X_ADC1_DIV ADC12DIV_5
+#elif MSP430X_ADC1_DIV_CALC(7)
+#define MSP430X_ADC1_PDIV ADC12PDIV__1
+#define MSP430X_ADC1_DIV ADC12DIV_6
+#elif MSP430X_ADC1_DIV_CALC(8)
+#define MSP430X_ADC1_PDIV ADC12PDIV__4
+#define MSP430X_ADC1_DIV ADC12DIV_2
+#elif MSP430X_ADC1_DIV_CALC(12)
+#define MSP430X_ADC1_PDIV ADC12PDIV__4
+#define MSP430X_ADC1_DIV ADC12DIV_2
+#elif MSP430X_ADC1_DIV_CALC(16)
+#define MSP430X_ADC1_PDIV ADC12PDIV__4
+#define MSP430X_ADC1_DIV ADC12DIV_3
+#elif MSP430X_ADC1_DIV_CALC(20)
+#define MSP430X_ADC1_PDIV ADC12PDIV__4
+#define MSP430X_ADC1_DIV ADC12DIV_4
+#elif MSP430X_ADC1_DIV_CALC(24)
+#define MSP430X_ADC1_PDIV ADC12PDIV__4
+#define MSP430X_ADC1_DIV ADC12DIV_5
+#elif MSP430X_ADC1_DIV_CALC(28)
+#define MSP430X_ADC1_PDIV ADC12PDIV__4
+#define MSP430X_ADC1_DIV ADC12DIV_6
+#elif MSP430X_ADC1_DIV_CALC(32)
+#define MSP430X_ADC1_PDIV ADC12PDIV__32
+#define MSP430X_ADC1_DIV ADC12DIV_0
+#elif MSP430X_ADC1_DIV_CALC(64)
+#define MSP430X_ADC1_PDIV ADC12PDIV__64
+#define MSP430X_ADC1_DIV ADC12DIV_0
+#elif MSP430X_ADC1_DIV_CALC(96)
+#define MSP430X_ADC1_PDIV ADC12PDIV__32
+#define MSP430X_ADC1_DIV ADC12DIV_2
+#elif MSP430X_ADC1_DIV_CALC(128)
+#define MSP430X_ADC1_PDIV ADC12PDIV__64
+#define MSP430X_ADC1_DIV ADC12DIV_1
+#elif MSP430X_ADC1_DIV_CALC(160)
+#define MSP430X_ADC1_PDIV ADC12PDIV__32
+#define MSP430X_ADC1_DIV ADC12DIV_4
+#elif MSP430X_ADC1_DIV_CALC(192)
+#define MSP430X_ADC1_PDIV ADC12PDIV__64
+#define MSP430X_ADC1_DIV ADC12DIV_2
+#elif MSP430X_ADC1_DIV_CALC(224)
+#define MSP430X_ADC1_PDIV ADC12PDIV__32
+#define MSP430X_ADC1_DIV ADC12DIV_6
+#elif MSP430X_ADC1_DIV_CALC(256)
+#define MSP430X_ADC1_PDIV ADC12PDIV__64
+#define MSP430X_ADC1_DIV ADC12DIV_3
+#elif MSP430X_ADC1_DIV_CALC(320)
+#define MSP430X_ADC1_PDIV ADC12PDIV__64
+#define MSP430X_ADC1_DIV ADC12DIV_4
+#elif MSP430X_ADC1_DIV_CALC(384)
+#define MSP430X_ADC1_PDIV ADC12PDIV__64
+#define MSP430X_ADC1_DIV ADC12DIV_5
+#elif MSP430X_ADC1_DIV_CALC(448)
+#define MSP430X_ADC1_PDIV ADC12PDIV__64
+#define MSP430X_ADC1_DIV ADC12DIV_6
+#elif MSP430X_ADC1_DIV_CALC(512)
+#define MSP430X_ADC1_PDIV ADC12PDIV__64
+#define MSP430X_ADC1_DIV ADC12DIV_7
+#else
+#error "MSP430X_ADC1_FREQ not achievable with MSP430X_ADC1_CLK_SRC"
+#endif
+
+#endif /* MSP430X_ADC_USE_ADC1 */
+
+/*===========================================================================*/
+/* Driver data structures and types. */
+/*===========================================================================*/
+
+/**
+ * @brief ADC sample data type.
+ */
+#if !MSP430X_ADC_COMPACT_SAMPLES || defined(__DOXYGEN__)
+typedef uint16_t adcsample_t;
+#else
+typedef uint8_t adcsample_t;
+#endif
+
+/**
+ * @brief Channels number in a conversion group.
+ */
+typedef uint8_t adc_channels_num_t;
+
+/**
+ * @brief Possible ADC failure causes.
+ * @note Error codes are architecture dependent and should not relied
+ * upon.
+ */
+typedef enum {
+ ADC_ERR_UNKNOWN = 0, /**< Unknown error has occurred */
+ ADC_ERR_OVERFLOW = 1, /**< ADC overflow condition. */
+ ADC_ERR_AWD = 2 /**< Analog watchdog triggered. */
+} adcerror_t;
+
+/**
+ * @brief Type of a structure representing an ADC driver.
+ */
+typedef struct ADCDriver ADCDriver;
+
+/**
+ * @brief ADC notification callback type.
+ *
+ * @param[in] adcp pointer to the @p ADCDriver object triggering the
+ * callback
+ * @param[in] buffer pointer to the most recent samples data
+ * @param[in] n number of buffer rows available starting from @p buffer
+ */
+typedef void (*adccallback_t)(ADCDriver * adcp, adcsample_t * buffer, size_t n);
+
+/**
+ * @brief ADC error callback type.
+ *
+ * @param[in] adcp pointer to the @p ADCDriver object triggering the
+ * callback
+ * @param[in] err ADC error code
+ */
+typedef void (*adcerrorcallback_t)(ADCDriver * adcp, adcerror_t err);
+
+/**
+ * @brief MSP430X ADC register structure.
+ */
+typedef struct {
+ uint16_t ctl[4];
+ uint16_t lo;
+ uint16_t hi;
+ uint16_t ifgr[3];
+ uint16_t ier[3];
+ uint16_t iv;
+ uint16_t padding[3];
+ uint16_t mctl[32];
+ uint16_t mem[32];
+} msp430x_adc_reg_t;
+
+/**
+ * @brief MSP430X ADC calibration structure.
+ */
+typedef struct {
+ uint16_t CAL_ADC_GAIN_FACTOR;
+ uint16_t CAL_ADC_OFFSET;
+ uint16_t CAL_ADC_12T30;
+ uint16_t CAL_ADC_12T85;
+ uint16_t CAL_ADC_20T30;
+ uint16_t CAL_ADC_20T85;
+ uint16_t CAL_ADC_25T30;
+ uint16_t CAL_ADC_25T85;
+} msp430x_adc_cal_t;
+
+/**
+ * @brief MSP430X REF calibration structure.
+ */
+typedef struct {
+ uint16_t CAL_ADC_12VREF_FACTOR;
+ uint16_t CAL_ADC_20VREF_FACTOR;
+ uint16_t CAL_ADC_25VREF_FACTOR;
+} msp430x_ref_cal_t;
+
+/**
+ * @brief Conversion group configuration structure.
+ * @details This implementation-dependent structure describes a conversion
+ * operation.
+ * @note The use of this configuration structure requires knowledge of
+ * MSP430X ADC cell registers interface, please refer to the MSP430X
+ * reference manual for details.
+ */
+typedef struct {
+ /**
+ * @brief Enables the circular buffer mode for the group.
+ */
+ bool circular;
+ /**
+ * @brief Number of the analog channels belonging to the conversion group.
+ */
+ adc_channels_num_t num_channels;
+ /**
+ * @brief Callback function associated to the group or @p NULL.
+ */
+ adccallback_t end_cb;
+ /**
+ * @brief Error callback or @p NULL.
+ */
+ adcerrorcallback_t error_cb;
+ /* End of the mandatory fields.*/
+ /**
+ * @brief Sequence of analog channels belonging to the conversion group.
+ * @note Only the first num_channels are valid.
+ */
+ uint8_t channels[32];
+ /**
+ * @brief Sample resolution
+ */
+ MSP430XADCResolution res;
+ /**
+ * @brief Sampling time in clock cycles
+ */
+ MSP430XADCSampleRates rate;
+ /**
+ * @brief Voltage references to use
+ */
+ MSP430XADCReferences ref;
+ /**
+ * @brief VREF source
+ */
+ MSP430XREFSources vref_src;
+} ADCConversionGroup;
+
+/**
+ * @brief Driver configuration structure.
+ * @note It could be empty on some architectures.
+ */
+typedef struct {
+#if MSP430X_ADC_EXCLUSIVE_DMA == TRUE || defined(__DOXYGEN__)
+ /**
+ * @brief The index of the DMA channel.
+ * @note This may be >MSP430X_DMA_CHANNELS to indicate that exclusive DMA
+ * is not used.
+ */
+ uint8_t dma_index;
+#endif
+} ADCConfig;
+
+/**
+ * @brief Structure representing an ADC driver.
+ */
+struct ADCDriver {
+ /**
+ * @brief Driver state.
+ */
+ adcstate_t state;
+ /**
+ * @brief Current configuration data.
+ */
+ const ADCConfig * config;
+ /**
+ * @brief Current samples buffer pointer or @p NULL.
+ */
+ adcsample_t * samples;
+ /**
+ * @brief Current samples buffer depth or @p 0.
+ */
+ size_t depth;
+ /**
+ * @brief Current conversion group pointer or @p NULL.
+ */
+ const ADCConversionGroup * grpp;
+#if (ADC_USE_WAIT == TRUE) || defined(__DOXYGEN__)
+ /**
+ * @brief Waiting thread.
+ */
+ thread_reference_t thread;
+#endif
+#if (ADC_USE_MUTUAL_EXCLUSION == TRUE) || defined(__DOXYGEN__)
+ /**
+ * @brief Mutex protecting the peripheral.
+ */
+ mutex_t mutex;
+#endif
+#if defined(ADC_DRIVER_EXT_FIELDS)
+ ADC_DRIVER_EXT_FIELDS
+#endif
+ /* End of the mandatory fields.*/
+ /**
+ * @brief Base address of ADC12_B registers
+ */
+ msp430x_adc_reg_t * regs;
+ /**
+ * @brief DMA request structure
+ */
+ msp430x_dma_req_t req;
+ /**
+ * @brief ADC calibration structure from TLV
+ */
+ msp430x_adc_cal_t * adc_cal;
+ /**
+ * @brief REF calibration structure from TLV
+ */
+ msp430x_ref_cal_t * ref_cal;
+ /**
+ * @brief Count of times DMA callback has been called
+ */
+ uint8_t count;
+ /**
+ * @brief DMA stream
+ */
+ msp430x_dma_ch_t dma;
+};
+
+/*===========================================================================*/
+/* Driver macros. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* External declarations. */
+/*===========================================================================*/
+
+#if (MSP430X_ADC_USE_ADC1 == TRUE) && !defined(__DOXYGEN__)
+extern ADCDriver ADCD1;
+#endif
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+void adc_lld_init(void);
+void adc_lld_start(ADCDriver * adcp);
+void adc_lld_stop(ADCDriver * adcp);
+void adc_lld_start_conversion(ADCDriver * adcp);
+void adc_lld_stop_conversion(ADCDriver * adcp);
+adcsample_t adcMSP430XAdjustResult(ADCConversionGroup * grpp,
+ adcsample_t sample);
+adcsample_t adcMSP430XAdjustTemp(ADCConversionGroup * grpp, adcsample_t sample);
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* HAL_USE_ADC == TRUE */
+
+#endif /* HAL_ADC_LLD_H */
+
+/** @} */
diff --git a/os/hal/ports/MSP430X/hal_dma_lld.c b/os/hal/ports/MSP430X/hal_dma_lld.c
index 43e1d6c..82bf39f 100644
--- a/os/hal/ports/MSP430X/hal_dma_lld.c
+++ b/os/hal/ports/MSP430X/hal_dma_lld.c
@@ -44,9 +44,8 @@ static msp430x_dma_ch_reg_t * const dma_channels =
(msp430x_dma_ch_reg_t *)&DMA0CTL;
static msp430x_dma_cb_t callbacks[MSP430X_DMA_CHANNELS];
-#if CH_CFG_USE_SEMAPHORES
-static semaphore_t dma_lock;
-#endif
+static threads_queue_t dma_queue;
+static unsigned int queue_length;
/*===========================================================================*/
/* Driver local functions. */
@@ -88,9 +87,9 @@ PORT_IRQ_HANDLER(DMA_VECTOR) {
index = (DMAIV >> 1) - 1;
if (index < MSP430X_DMA_CHANNELS) {
-#if CH_CFG_USE_SEMAPHORES
- chSemSignalI(&dma_lock);
-#endif
+ osalSysLockFromISR();
+ osalThreadDequeueNextI(&dma_queue, MSG_OK);
+ osalSysUnlockFromISR();
msp430x_dma_cb_t * cb = &callbacks[index];
@@ -113,9 +112,7 @@ PORT_IRQ_HANDLER(DMA_VECTOR) {
* @init
*/
void dmaInit(void) {
-#if CH_CFG_USE_SEMAPHORES
- chSemObjectInit(&dma_lock, MSP430X_DMA_CHANNELS);
-#endif
+ osalThreadQueueObjectInit(&dma_queue);
}
/**
@@ -125,134 +122,124 @@ void dmaInit(void) {
* semaphores are enabled, the calling thread will sleep until a
* channel is available or the request times out. If semaphores are
* disabled, the calling thread will busy-wait instead of sleeping.
+ *
+ * @sclass
*/
-bool dmaRequest(msp430x_dma_req_t * request, systime_t timeout) {
-/* Check if a DMA channel is available */
-#if CH_CFG_USE_SEMAPHORES
- msg_t semresult = chSemWaitTimeout(&dma_lock, timeout);
- if (semresult != MSG_OK)
- return true;
-#endif
-
-#if !(CH_CFG_USE_SEMAPHORES)
- systime_t start = chVTGetSystemTimeX();
-
- do {
-#endif
- /* Grab the correct DMA channel to use */
- int i = 0;
- for (i = 0; i < MSP430X_DMA_CHANNELS; i++) {
- if (!(dma_channels[i].ctl & DMAEN)) {
- break;
- }
- }
-#if !(CH_CFG_USE_SEMAPHORES)
- while (chVTTimeElapsedSinceX(start) < timeout)
- ;
-#endif
-
-#if !(CH_CFG_USE_SEMAPHORES)
- if (i == MSP430X_DMA_CHANNELS) {
- return true;
+int dmaRequestS(msp430x_dma_req_t * request, systime_t timeout) {
+
+ osalDbgCheckClassS();
+
+ /* Check if a DMA channel is available */
+ if (queue_length >= MSP430X_DMA_CHANNELS) {
+ msg_t queueresult = osalThreadEnqueueTimeoutS(&dma_queue, timeout);
+ if (queueresult != MSG_OK)
+ return -1;
+ }
+
+ /* Grab the correct DMA channel to use */
+ int i = 0;
+ for (i = 0; i < MSP430X_DMA_CHANNELS; i++) {
+ if (!(dma_channels[i].ctl & DMAEN)) {
+ break;
}
-#endif
+ }
+
+ /* Make the request */
+ init_request(request, i);
+
+ return i;
+}
- /* Make the request */
- init_request(request, i);
+/**
+ * @brief Acquires exclusive control of a DMA channel.
+ * @pre The channel must not be already acquired or an error is returned.
+ * @note If the channel is in use by the DMA engine, blocks until acquired.
+ * @post This channel must be interacted with using only the functions
+ * defined in this module.
+ *
+ * @param[out] channel The channel handle. Must be pre-allocated.
+ * @param[in] index The index of the channel (< MSP430X_DMA_CHANNELS).
+ * @return The operation status.
+ * @retval false no error, channel acquired.
+ * @retval true error, channel already acquired.
+ *
+ * @iclass
+ */
+bool dmaAcquireI(msp430x_dma_ch_t * channel, uint8_t index) {
+
+ osalDbgCheckClassI();
- return false;
+ /* Is the channel already acquired? */
+ osalDbgAssert(index < MSP430X_DMA_CHANNELS, "invalid channel index");
+ if (dma_channels[index].ctl & DMADT_4) {
+ return true;
}
- /**
- * @brief Acquires exclusive control of a DMA channel.
- * @pre The channel must not be already acquired or an error is returned.
- * @note If the channel is in use by the DMA engine, blocks until acquired.
- * @post This channel must be interacted with using only the functions
- * defined in this module.
- *
- * @param[out] channel The channel handle. Must be pre-allocated.
- * @param[in] index The index of the channel (< MSP430X_DMA_CHANNELS).
- * @return The operation status.
- * @retval false no error, channel acquired.
- * @retval true error, channel already acquired.
- */
- bool dmaAcquire(msp430x_dma_ch_t * channel, uint8_t index) {
- /* Acquire the channel in an idle mode */
-
- /* Is the channel already acquired? */
- osalDbgAssert(index < MSP430X_DMA_CHANNELS, "invalid channel index");
- if (dma_channels[index].ctl & DMADT_4) {
- return true;
- }
+ /* Increment the DMA counter */
+ queue_length++;
-/* Increment the DMA counter */
-#if CH_CFG_USE_SEMAPHORES
- msg_t semresult = chSemWait(&dma_lock);
- if (semresult != MSG_OK)
- return true;
-#endif
+ while (dma_channels[index].ctl & DMAEN)
+ ;
- while (dma_channels[index].ctl & DMAEN)
- ;
+ /* Acquire the channel in an idle mode */
+ dma_trigger_set(index, DMA_TRIGGER_MNEM(DMAREQ));
+ dma_channels[index].sz = 0;
+ dma_channels[index].ctl = DMAEN | DMAABORT | DMADT_4;
- dma_trigger_set(index, DMA_TRIGGER_MNEM(DMAREQ));
- dma_channels[index].sz = 0;
- dma_channels[index].ctl = DMAEN | DMAABORT | DMADT_4;
+ channel->registers = dma_channels + index;
+ channel->index = index;
+ channel->cb = callbacks + index;
+
+ return false;
+}
- channel->registers = dma_channels + index;
- channel->index = index;
- channel->cb = callbacks + index;
+/**
+ * @brief Initiates a DMA transfer operation using an acquired channel.
+ * @pre The channel must have been acquired using @p dmaAcquire().
+ *
+ * @param[in] channel pointer to a DMA channel from @p dmaAcquire().
+ * @param[in] request pointer to a DMA request object.
+ */
+void dmaTransfer(msp430x_dma_ch_t * channel, msp430x_dma_req_t * request) {
- return false;
- }
+ dma_trigger_set(channel->index, request->trigger);
+ /**(channel->ctl) = request->trigger;*/
- /**
- * @brief Initiates a DMA transfer operation using an acquired channel.
- * @pre The channel must have been acquired using @p dmaAcquire().
- *
- * @param[in] channel pointer to a DMA channel from @p dmaAcquire().
- * @param[in] request pointer to a DMA request object.
- */
- void dmaTransfer(msp430x_dma_ch_t * channel, msp430x_dma_req_t * request) {
-
- dma_trigger_set(channel->index, request->trigger);
- /**(channel->ctl) = request->trigger;*/
-
- channel->cb->callback = request->callback.callback;
- channel->cb->args = request->callback.args;
-
- chSysLock();
- channel->registers->ctl &= (~DMAEN);
- channel->registers->sa = (uintptr_t)request->source_addr;
- channel->registers->da = (uintptr_t)request->dest_addr;
- channel->registers->sz = request->size;
- channel->registers->ctl = DMAIE | request->data_mode | request->addr_mode |
- request->transfer_mode | DMADT_4 | DMAEN |
- DMAREQ; /* repeated transfers */
- chSysUnlock();
- }
+ channel->cb->callback = request->callback.callback;
+ channel->cb->args = request->callback.args;
- /**
- * @brief Releases exclusive control of a DMA channel.
- * @details The channel is released from control and returned to the DMA
- * engine
- * pool. Trying to release an unallocated channel is an illegal
- * operation and is trapped if assertions are enabled.
- * @pre The channel must have been acquired using @p dmaAcquire().
- * @post The channel is returned to the DMA engine pool.
- */
- void dmaRelease(msp430x_dma_ch_t * channel) {
-
- osalDbgCheck(channel != NULL);
-
- /* Release the channel in an idle mode */
- channel->registers->ctl = DMAABORT;
-
-/* release the DMA counter */
-#if CH_CFG_USE_SEMAPHORES
- chSemSignal(&dma_lock);
-#endif
- }
+ channel->registers->ctl &= (~DMAEN);
+ channel->registers->sa = (uintptr_t)request->source_addr;
+ channel->registers->da = (uintptr_t)request->dest_addr;
+ channel->registers->sz = request->size;
+ channel->registers->ctl = DMAIE | request->data_mode | request->addr_mode |
+ request->transfer_mode | DMADT_4 | DMAEN |
+ DMAREQ; /* repeated transfers */
+}
+
+/**
+ * @brief Releases exclusive control of a DMA channel.
+ * @details The channel is released from control and returned to the DMA
+ * engine
+ * pool. Trying to release an unallocated channel is an illegal
+ * operation and is trapped if assertions are enabled.
+ * @pre The channel must have been acquired using @p dmaAcquire().
+ * @post The channel is returned to the DMA engine pool.
+ */
+void dmaRelease(msp430x_dma_ch_t * channel) {
+ syssts_t sts;
+
+ sts = osalSysGetStatusAndLockX();
+ osalDbgCheck(channel != NULL);
+
+ /* Release the channel in an idle mode */
+ channel->registers->ctl = DMAABORT;
+
+ /* release the DMA counter */
+ osalThreadDequeueAllI(&dma_queue, MSG_RESET);
+ queue_length = 0;
+ osalSysRestoreStatusX(sts);
+}
#endif /* HAL_USE_DMA == TRUE */
diff --git a/os/hal/ports/MSP430X/hal_dma_lld.h b/os/hal/ports/MSP430X/hal_dma_lld.h
index d1495d2..f558e78 100644
--- a/os/hal/ports/MSP430X/hal_dma_lld.h
+++ b/os/hal/ports/MSP430X/hal_dma_lld.h
@@ -159,8 +159,8 @@ typedef struct {
extern "C" {
#endif
void dmaInit(void);
-bool dmaRequest(msp430x_dma_req_t * request, systime_t timeout);
-bool dmaAcquire(msp430x_dma_ch_t * channel, uint8_t index);
+int dmaRequestS(msp430x_dma_req_t * request, systime_t timeout);
+bool dmaAcquireI(msp430x_dma_ch_t * channel, uint8_t index);
void dmaTransfer(msp430x_dma_ch_t * channel, msp430x_dma_req_t * request);
void dmaRelease(msp430x_dma_ch_t * channel);
diff --git a/os/hal/ports/MSP430X/hal_lld.c b/os/hal/ports/MSP430X/hal_lld.c
index 872fe97..812a0cf 100644
--- a/os/hal/ports/MSP430X/hal_lld.c
+++ b/os/hal/ports/MSP430X/hal_lld.c
@@ -82,6 +82,10 @@ void hal_lld_init(void) {
} while (SFRIFG1 & OFIFG);
#endif
CSCTL0_H = 0xFF; /* Lock clock system */
+
+#if (HAL_USE_DMA == TRUE)
+ dmaInit();
+#endif
}
/** @} */
diff --git a/os/hal/ports/MSP430X/hal_lld.h b/os/hal/ports/MSP430X/hal_lld.h
index 9549453..62f07e9 100644
--- a/os/hal/ports/MSP430X/hal_lld.h
+++ b/os/hal/ports/MSP430X/hal_lld.h
@@ -25,6 +25,8 @@
#ifndef _HAL_LLD_H_
#define _HAL_LLD_H_
+#include "hal_dma_lld.h"
+
/*===========================================================================*/
/* Driver constants. */
/*===========================================================================*/
diff --git a/os/hal/ports/MSP430X/hal_serial_lld.c b/os/hal/ports/MSP430X/hal_serial_lld.c
index 0d9aa1c..feb00ac 100644
--- a/os/hal/ports/MSP430X/hal_serial_lld.c
+++ b/os/hal/ports/MSP430X/hal_serial_lld.c
@@ -374,11 +374,11 @@ PORT_IRQ_HANDLER(USCI_A0_VECTOR) {
if (oqIsEmptyI(&SD0.oqueue))
chnAddFlagsI(&SD0, CHN_TRANSMISSION_END);
UCA0IE &= ~UCTXCPTIE;
+ osalSysUnlockFromISR();
break;
default: /* other interrupts */
- while (1)
- ;
+ osalDbgAssert(false, "unhandled serial interrupt");
break;
}
@@ -432,11 +432,11 @@ PORT_IRQ_HANDLER(USCI_A1_VECTOR) {
if (oqIsEmptyI(&SD1.oqueue))
chnAddFlagsI(&SD1, CHN_TRANSMISSION_END);
UCA1IE &= ~UCTXCPTIE;
+ osalSysUnlockFromISR();
break;
default: /* other interrupts */
- while (1)
- ;
+ osalDbgAssert(false, "unhandled serial interrupt");
break;
}
@@ -490,11 +490,11 @@ PORT_IRQ_HANDLER(USCI_A2_VECTOR) {
if (oqIsEmptyI(&SD2.oqueue))
chnAddFlagsI(&SD2, CHN_TRANSMISSION_END);
UCA2IE &= ~UCTXCPTIE;
+ osalSysUnlockFromISR();
break;
default: /* other interrupts */
- while (1)
- ;
+ osalDbgAssert(false, "unhandled serial interrupt");
break;
}
@@ -548,11 +548,11 @@ PORT_IRQ_HANDLER(USCI_A3_VECTOR) {
if (oqIsEmptyI(&SD3.oqueue))
chnAddFlagsI(&SD3, CHN_TRANSMISSION_END);
UCA3IE &= ~UCTXCPTIE;
+ osalSysUnlockFromISR();
break;
default: /* other interrupts */
- while (1)
- ;
+ osalDbgAssert(false, "unhandled serial interrupt");
break;
}
diff --git a/os/hal/ports/MSP430X/hal_spi_lld.c b/os/hal/ports/MSP430X/hal_spi_lld.c
index 70a357e..3a54b1e 100644
--- a/os/hal/ports/MSP430X/hal_spi_lld.c
+++ b/os/hal/ports/MSP430X/hal_spi_lld.c
@@ -104,21 +104,21 @@ static uint16_t dummyrx;
static void init_transfer(SPIDriver * spip) {
#if MSP430X_SPI_EXCLUSIVE_DMA == TRUE || defined(__DOXYGEN__)
- if (spip->config->dmarx_index > MSP430X_DMA_CHANNELS) {
- dmaRequest(&(spip->rx_req), TIME_INFINITE);
+ if (spip->config->dmarx_index >= MSP430X_DMA_CHANNELS) {
+ dmaRequestS(&(spip->rx_req), TIME_INFINITE);
}
else {
dmaTransfer(&(spip->dmarx), &(spip->rx_req));
}
- if (spip->config->dmatx_index > MSP430X_DMA_CHANNELS) {
- dmaRequest(&(spip->tx_req), TIME_INFINITE);
+ if (spip->config->dmatx_index >= MSP430X_DMA_CHANNELS) {
+ dmaRequestS(&(spip->tx_req), TIME_INFINITE);
}
else {
dmaTransfer(&(spip->dmatx), &(spip->tx_req));
}
#else
- dmaRequest(&(spip->rx_req), TIME_INFINITE);
- dmaRequest(&(spip->tx_req), TIME_INFINITE);
+ dmaRequestS(&(spip->rx_req), TIME_INFINITE);
+ dmaRequestS(&(spip->tx_req), TIME_INFINITE);
#endif
*(spip->ifg) |= UCTXIFG;
@@ -325,11 +325,11 @@ void spi_lld_start(SPIDriver * spip) {
/* Claim DMA streams here */
bool b;
if (spip->config->dmatx_index < MSP430X_DMA_CHANNELS) {
- b = dmaAcquire(&(spip->dmatx), spip->config->dmatx_index);
+ b = dmaAcquireI(&(spip->dmatx), spip->config->dmatx_index);
osalDbgAssert(!b, "stream already allocated");
}
if (spip->config->dmarx_index < MSP430X_DMA_CHANNELS) {
- b = dmaAcquire(&(spip->dmarx), spip->config->dmarx_index);
+ b = dmaAcquireI(&(spip->dmarx), spip->config->dmarx_index);
osalDbgAssert(!b, "stream already allocated");
}
#endif /* MSP430X_SPI_EXCLUSIVE_DMA */
@@ -388,10 +388,11 @@ void spi_lld_start(SPIDriver * spip) {
spip->regs->ctlw0 = UCSWRST;
spip->regs->brw = brw;
spip->regs->ctlw0 =
- (spip->config->spi_mode << 14) | (spip->config->bit_order << 13) |
+ ((spip->config->spi_mode ^ 0x02) << 14) | (spip->config->bit_order << 13) |
(spip->config->data_size << 12) | (UCMST) |
((spip->config->ss_line ? 0 : 2) << 9) | (UCSYNC) | (ssel) | (UCSTEM);
*(spip->ifg) = 0;
+ spi_lld_unselect(spip);
}
/**
@@ -406,8 +407,12 @@ void spi_lld_stop(SPIDriver * spip) {
if (spip->state == SPI_READY) {
/* Disables the peripheral.*/
#if MSP430X_SPI_EXCLUSIVE_DMA == TRUE
- dmaRelease(&(spip->dmatx));
- dmaRelease(&(spip->dmarx));
+ if (spip->config->dmatx_index < MSP430X_DMA_CHANNELS) {
+ dmaRelease(&(spip->dmatx));
+ }
+ if (spip->config->dmarx_index < MSP430X_DMA_CHANNELS) {
+ dmaRelease(&(spip->dmarx));
+ }
#endif
spip->regs->ctlw0 = UCSWRST;
}
@@ -561,15 +566,12 @@ void spi_lld_receive(SPIDriver * spip, size_t n, void * rxbuf) {
* @param[in] frame the data frame to send over the SPI bus
* @return The received data frame from the SPI bus.
*/
-uint16_t spi_lld_polled_exchange(SPIDriver * spip, uint16_t frame) {
-
- osalDbgAssert(!(frame & 0xFF00U), "16-bit transfers not supported");
+uint8_t spi_lld_polled_exchange(SPIDriver * spip, uint8_t frame) {
- while (!(*(spip->ifg) & UCTXIFG))
- ;
spip->regs->txbuf = frame;
while (!(*(spip->ifg) & UCRXIFG))
;
+ *(spip->ifg) &= ~(UCRXIFG | UCTXIFG);
return spip->regs->rxbuf;
}
diff --git a/os/hal/ports/MSP430X/hal_spi_lld.h b/os/hal/ports/MSP430X/hal_spi_lld.h
index ebf14c8..949a8a0 100644
--- a/os/hal/ports/MSP430X/hal_spi_lld.h
+++ b/os/hal/ports/MSP430X/hal_spi_lld.h
@@ -118,7 +118,7 @@
* @note This increases the size of the compiled executable somewhat.
* @note The default is @p FALSE.
*/
-#if !defined(MSP430X_SPI_EXCLUSIVE_DMA) | defined(__DOXYGEN__)
+#if !defined(MSP430X_SPI_EXCLUSIVE_DMA) || defined(__DOXYGEN__)
#define MSP430X_SPI_EXCLUSIVE_DMA FALSE
#endif
@@ -630,7 +630,7 @@ extern "C" {
const void *txbuf, void *rxbuf);
void spi_lld_send(SPIDriver *spip, size_t n, const void *txbuf);
void spi_lld_receive(SPIDriver *spip, size_t n, void *rxbuf);
- uint16_t spi_lld_polled_exchange(SPIDriver *spip, uint16_t frame);
+ uint8_t spi_lld_polled_exchange(SPIDriver *spip, uint8_t frame);
#ifdef __cplusplus
}
#endif
diff --git a/os/hal/ports/MSP430X/platform.mk b/os/hal/ports/MSP430X/platform.mk
index 832814b..627a2f0 100644
--- a/os/hal/ports/MSP430X/platform.mk
+++ b/os/hal/ports/MSP430X/platform.mk
@@ -4,7 +4,8 @@ PLATFORMSRC = ${CHIBIOS_CONTRIB}/os/hal/ports/MSP430X/hal_lld.c \
${CHIBIOS_CONTRIB}/os/hal/ports/MSP430X/hal_serial_lld.c \
${CHIBIOS_CONTRIB}/os/hal/ports/MSP430X/hal_pal_lld.c \
${CHIBIOS_CONTRIB}/os/hal/ports/MSP430X/hal_dma_lld.c \
- ${CHIBIOS_CONTRIB}/os/hal/ports/MSP430X/hal_spi_lld.c
+ ${CHIBIOS_CONTRIB}/os/hal/ports/MSP430X/hal_spi_lld.c \
+ ${CHIBIOS_CONTRIB}/os/hal/ports/MSP430X/hal_adc_lld.c
# Required include directories
PLATFORMINC = ${CHIBIOS_CONTRIB}/os/hal/ports/MSP430X
diff --git a/os/hal/ports/STM32/LLD/CRCv1/hal_crc_lld.c b/os/hal/ports/STM32/LLD/CRCv1/hal_crc_lld.c
index 601deca..f8178f1 100644
--- a/os/hal/ports/STM32/LLD/CRCv1/hal_crc_lld.c
+++ b/os/hal/ports/STM32/LLD/CRCv1/hal_crc_lld.c
@@ -15,7 +15,7 @@
*/
/**
- * @file STM32/CRCv1/crc_lld.c
+ * @file STM32/CRCv1/hal_crc_lld.c
* @brief STM32 CRC subsystem low level driver source.
*
* @addtogroup CRC
diff --git a/os/hal/ports/STM32/LLD/CRCv1/hal_crc_lld.h b/os/hal/ports/STM32/LLD/CRCv1/hal_crc_lld.h
index ecdaf81..213d346 100644
--- a/os/hal/ports/STM32/LLD/CRCv1/hal_crc_lld.h
+++ b/os/hal/ports/STM32/LLD/CRCv1/hal_crc_lld.h
@@ -15,15 +15,15 @@
*/
/**
- * @file STM32/CRCv1/crc_lld.h
+ * @file STM32/CRCv1/hal_crc_lld.h
* @brief STM32 CRC subsystem low level driver header.
*
* @addtogroup CRC
* @{
*/
-#ifndef _CRC_LLD_H_
-#define _CRC_LLD_H_
+#ifndef HAL_CRC_LLD_H_
+#define HAL_CRC_LLD_H_
#if (HAL_USE_CRC == TRUE) || defined(__DOXYGEN__)
@@ -244,6 +244,6 @@ extern "C" {
#endif /* HAL_USE_CRC */
-#endif /* _CRC_LLD_H_ */
+#endif /* HAL_CRC_LLD_H_ */
/** @} */
diff --git a/os/hal/ports/STM32/LLD/DMA2Dv1/hal_stm32_dma2d.c b/os/hal/ports/STM32/LLD/DMA2Dv1/hal_stm32_dma2d.c
index aba029f..6751202 100644
--- a/os/hal/ports/STM32/LLD/DMA2Dv1/hal_stm32_dma2d.c
+++ b/os/hal/ports/STM32/LLD/DMA2Dv1/hal_stm32_dma2d.c
@@ -15,7 +15,7 @@
*/
/**
- * @file stm32_dma2d.c
+ * @file hal_stm32_dma2d.c
* @brief DMA2D/Chrom-ART driver.
*/
diff --git a/os/hal/ports/STM32/LLD/DMA2Dv1/hal_stm32_dma2d.h b/os/hal/ports/STM32/LLD/DMA2Dv1/hal_stm32_dma2d.h
index 01f0941..c06ab62 100644
--- a/os/hal/ports/STM32/LLD/DMA2Dv1/hal_stm32_dma2d.h
+++ b/os/hal/ports/STM32/LLD/DMA2Dv1/hal_stm32_dma2d.h
@@ -15,15 +15,15 @@
*/
/**
- * @file stm32_dma2d.h
+ * @file hal_stm32_dma2d.h
* @brief DMA2D/Chrom-ART driver.
*
* @addtogroup dma2d
* @{
*/
-#ifndef _STM32_DMA2D_H_
-#define _STM32_DMA2D_H_
+#ifndef HAL_STM32_DMA2D_H_
+#define HAL_STM32_DMA2D_H_
/**
* @brief Using the DMA2D driver.
@@ -659,6 +659,6 @@ extern "C" {
#endif /* STM32_DMA2D_USE_DMA2D */
-#endif /* _STM32_DMA2D_H_ */
+#endif /* HAL_STM32_DMA2D_H_ */
/** @} */
diff --git a/os/hal/ports/STM32/LLD/FSMCv1/hal_fsmc.c b/os/hal/ports/STM32/LLD/FSMCv1/hal_fsmc.c
index 40ad05c..b4c2938 100644
--- a/os/hal/ports/STM32/LLD/FSMCv1/hal_fsmc.c
+++ b/os/hal/ports/STM32/LLD/FSMCv1/hal_fsmc.c
@@ -15,7 +15,7 @@
*/
/**
- * @file fsmc.c
+ * @file hal_fsmc.c
* @brief FSMC Driver subsystem low level driver source template.
*
* @addtogroup FSMC
@@ -125,7 +125,7 @@ void fsmc_start(FSMCDriver *fsmcp) {
rccResetFSMC();
#endif
rccEnableFSMC(FALSE);
-#if (!STM32_NAND_USE_EXT_INT && HAL_USE_NAND)
+#if HAL_USE_NAND
nvicEnableVector(STM32_FSMC_NUMBER, STM32_FSMC_FSMC1_IRQ_PRIORITY);
#endif
}
@@ -153,7 +153,7 @@ void fsmc_stop(FSMCDriver *fsmcp) {
/* Disables the peripheral.*/
#if STM32_FSMC_USE_FSMC1
if (&FSMCD1 == fsmcp) {
-#if (!STM32_NAND_USE_EXT_INT && HAL_USE_NAND)
+#if HAL_USE_NAND
nvicDisableVector(STM32_FSMC_NUMBER);
#endif
rccDisableFSMC(FALSE);
@@ -164,7 +164,6 @@ void fsmc_stop(FSMCDriver *fsmcp) {
}
}
-#if !STM32_NAND_USE_EXT_INT
/**
* @brief FSMC shared interrupt handler.
*
@@ -185,7 +184,6 @@ CH_IRQ_HANDLER(STM32_FSMC_HANDLER) {
#endif
CH_IRQ_EPILOGUE();
}
-#endif /* !STM32_NAND_USE_EXT_INT */
#endif /* HAL_USE_FSMC */
diff --git a/os/hal/ports/STM32/LLD/FSMCv1/hal_fsmc.h b/os/hal/ports/STM32/LLD/FSMCv1/hal_fsmc.h
index f9d8a60..f0d4c65 100644
--- a/os/hal/ports/STM32/LLD/FSMCv1/hal_fsmc.h
+++ b/os/hal/ports/STM32/LLD/FSMCv1/hal_fsmc.h
@@ -15,15 +15,15 @@
*/
/**
- * @file fsmc.h
+ * @file hal_fsmc.h
* @brief FSMC Driver subsystem low level driver header.
*
* @addtogroup FSMC
* @{
*/
-#ifndef _FSMC_H_
-#define _FSMC_H_
+#ifndef HAL_FSMC_H_
+#define HAL_FSMC_H_
#if (HAL_USE_FSMC == TRUE) || defined(__DOXYGEN__)
@@ -247,15 +247,6 @@ typedef struct {
#define STM32_FSMC_USE_FSMC1 FALSE
#endif
-/**
- * @brief Internal FSMC interrupt enable switch
- * @details MCUs in 100-pin package has no dedicated interrupt pin for FSMC.
- * You have to use EXTI module instead to workaround this issue.
- */
-#if !defined(STM32_NAND_USE_EXT_INT) || defined(__DOXYGEN__)
-#define STM32_NAND_USE_EXT_INT FALSE
-#endif
-
/** @} */
/*===========================================================================*/
@@ -344,6 +335,6 @@ extern "C" {
#endif /* HAL_USE_FSMC */
-#endif /* _FSMC_H_ */
+#endif /* HAL_FSMC_H_ */
/** @} */
diff --git a/os/hal/ports/STM32/LLD/FSMCv1/hal_fsmc_sdram.c b/os/hal/ports/STM32/LLD/FSMCv1/hal_fsmc_sdram.c
index 95f47d5..ac83477 100644
--- a/os/hal/ports/STM32/LLD/FSMCv1/hal_fsmc_sdram.c
+++ b/os/hal/ports/STM32/LLD/FSMCv1/hal_fsmc_sdram.c
@@ -18,7 +18,7 @@
*/
/**
- * @file fsmc_sdram.c
+ * @file hal_fsmc_sdram.c
* @brief SDRAM Driver subsystem low level driver source.
*
* @addtogroup SDRAM
diff --git a/os/hal/ports/STM32/LLD/FSMCv1/hal_fsmc_sdram.h b/os/hal/ports/STM32/LLD/FSMCv1/hal_fsmc_sdram.h
index cef6772..b419168 100644
--- a/os/hal/ports/STM32/LLD/FSMCv1/hal_fsmc_sdram.h
+++ b/os/hal/ports/STM32/LLD/FSMCv1/hal_fsmc_sdram.h
@@ -18,15 +18,15 @@
*/
/**
- * @file fsmc_sdram.h
+ * @file hal_fsmc_sdram.h
* @brief SDRAM Driver subsystem low level driver header.
*
* @addtogroup SDRAM
* @{
*/
-#ifndef _FMC_SDRAM_H_
-#define _FMC_SDRAM_H_
+#ifndef HAL_FMC_SDRAM_H_
+#define HAL_FMC_SDRAM_H_
#if (defined(STM32F427xx) || defined(STM32F437xx) || \
defined(STM32F429xx) || defined(STM32F439xx))
@@ -166,6 +166,6 @@ extern "C" {
#endif /* STM32F427xx / STM32F429xx / STM32F437xx / STM32F439xx */
-#endif /* _FMC_SDRAM_H_ */
+#endif /* HAL_FMC_SDRAM_H_ */
/** @} */
diff --git a/os/hal/ports/STM32/LLD/FSMCv1/hal_fsmc_sram.c b/os/hal/ports/STM32/LLD/FSMCv1/hal_fsmc_sram.c
index 6f710d4..333362f 100644
--- a/os/hal/ports/STM32/LLD/FSMCv1/hal_fsmc_sram.c
+++ b/os/hal/ports/STM32/LLD/FSMCv1/hal_fsmc_sram.c
@@ -15,7 +15,7 @@
*/
/**
- * @file fsmc_sram.c
+ * @file hal_fsmc_sram.c
* @brief SRAM Driver subsystem low level driver source.
*
* @addtogroup SRAM
diff --git a/os/hal/ports/STM32/LLD/FSMCv1/hal_fsmc_sram.h b/os/hal/ports/STM32/LLD/FSMCv1/hal_fsmc_sram.h
index 529bdc7..5e749a8 100644
--- a/os/hal/ports/STM32/LLD/FSMCv1/hal_fsmc_sram.h
+++ b/os/hal/ports/STM32/LLD/FSMCv1/hal_fsmc_sram.h
@@ -15,15 +15,15 @@
*/
/**
- * @file fsmc_sram.h
+ * @file hal_fsmc_sram.h
* @brief SRAM Driver subsystem low level driver header.
*
* @addtogroup SRAM
* @{
*/
-#ifndef _FSMC_SRAM_H_
-#define _FSMC_SRAM_H_
+#ifndef HAL_FSMC_SRAM_H_
+#define HAL_FSMC_SRAM_H_
#include "hal_fsmc.h"
@@ -167,6 +167,6 @@ extern "C" {
#endif /* STM32_USE_FSMC_SRAM */
-#endif /* _FSMC_SRAM_H_ */
+#endif /* HAL_FSMC_SRAM_H_ */
/** @} */
diff --git a/os/hal/ports/STM32/LLD/FSMCv1/hal_nand_lld.c b/os/hal/ports/STM32/LLD/FSMCv1/hal_nand_lld.c
index b37c026..f39ff35 100644
--- a/os/hal/ports/STM32/LLD/FSMCv1/hal_nand_lld.c
+++ b/os/hal/ports/STM32/LLD/FSMCv1/hal_nand_lld.c
@@ -15,7 +15,7 @@
*/
/**
- * @file nand_lld.c
+ * @file hal_nand_lld.c
* @brief NAND Driver subsystem low level driver source.
*
* @addtogroup NAND
@@ -117,13 +117,10 @@ static uint32_t calc_eccps(NANDDriver *nandp) {
* @notapi
*/
static void nand_ready_isr_enable(NANDDriver *nandp) {
-#if STM32_NAND_USE_EXT_INT
- nandp->config->ext_nand_isr_enable();
-#else
+
nandp->nand->SR &= ~(FSMC_SR_IRS | FSMC_SR_ILS | FSMC_SR_IFS |
- FSMC_SR_ILEN | FSMC_SR_IFEN);
+ FSMC_SR_ILEN | FSMC_SR_IFEN);
nandp->nand->SR |= FSMC_SR_IREN;
-#endif
}
/**
@@ -134,11 +131,8 @@ static void nand_ready_isr_enable(NANDDriver *nandp) {
* @notapi
*/
static void nand_ready_isr_disable(NANDDriver *nandp) {
-#if STM32_NAND_USE_EXT_INT
- nandp->config->ext_nand_isr_disable();
-#else
+
nandp->nand->SR &= ~FSMC_SR_IREN;
-#endif
}
/**
@@ -152,10 +146,8 @@ static void nand_isr_handler (NANDDriver *nandp) {
osalSysLockFromISR();
-#if !STM32_NAND_USE_EXT_INT
osalDbgCheck(nandp->nand->SR & FSMC_SR_IRS); /* spurious interrupt happened */
nandp->nand->SR &= ~FSMC_SR_IRS;
-#endif
switch (nandp->state){
case NAND_READ:
@@ -501,12 +493,13 @@ void nand_lld_write_cmd(NANDDriver *nandp, uint8_t cmd) {
*/
uint8_t nand_lld_read_status(NANDDriver *nandp) {
- uint8_t status[1] = {0x01}; /* presume worse */
+ uint8_t status;
+ status = 1; /* presume worse */
nand_lld_write_cmd(nandp, NAND_CMD_STATUS);
- nand_lld_polled_read_data(nandp, status, 1);
+ nand_lld_polled_read_data(nandp, &status, 1);
- return status[0];
+ return status;
}
#endif /* HAL_USE_NAND */
diff --git a/os/hal/ports/STM32/LLD/FSMCv1/hal_nand_lld.h b/os/hal/ports/STM32/LLD/FSMCv1/hal_nand_lld.h
index 8dca42f..de7a0c4 100644
--- a/os/hal/ports/STM32/LLD/FSMCv1/hal_nand_lld.h
+++ b/os/hal/ports/STM32/LLD/FSMCv1/hal_nand_lld.h
@@ -15,15 +15,15 @@
*/
/**
- * @file nand_lld.h
+ * @file hal_nand_lld.h
* @brief NAND Driver subsystem low level driver header.
*
* @addtogroup NAND
* @{
*/
-#ifndef _NAND_LLD_H_
-#define _NAND_LLD_H_
+#ifndef HAL_NAND_LLD_H_
+#define HAL_NAND_LLD_H_
#include "hal_fsmc.h"
#include "bitmap.h"
@@ -120,10 +120,6 @@
#error "FSMC not present in the selected device"
#endif
-#if STM32_NAND_USE_EXT_INT && !HAL_USE_EXT
-#error "External interrupt controller must be enabled to use this feature"
-#endif
-
#if !defined(STM32_DMA_REQUIRED)
#define STM32_DMA_REQUIRED
#endif
@@ -133,11 +129,6 @@
/*===========================================================================*/
/**
- * @brief NAND driver condition flags type.
- */
-typedef uint32_t nandflags_t;
-
-/**
* @brief Type of a structure representing an NAND driver.
*/
typedef struct NANDDriver NANDDriver;
@@ -147,23 +138,12 @@ typedef struct NANDDriver NANDDriver;
*/
typedef void (*nandisrhandler_t)(NANDDriver *nandp);
-#if STM32_NAND_USE_EXT_INT
-/**
- * @brief Type of function switching external interrupts on and off.
- */
-typedef void (*nandisrswitch_t)(void);
-#endif /* STM32_NAND_USE_EXT_INT */
-
/**
* @brief Driver configuration structure.
* @note It could be empty on some architectures.
*/
typedef struct {
/**
- * @brief Pointer to lower level driver.
- */
- //const FSMCDriver *fsmcp;
- /**
* @brief Number of erase blocks in NAND device.
*/
uint32_t blocks;
@@ -197,16 +177,6 @@ typedef struct {
* from STMicroelectronics.
*/
uint32_t pmem;
-#if STM32_NAND_USE_EXT_INT
- /**
- * @brief Function enabling interrupts from EXTI
- */
- nandisrswitch_t ext_nand_isr_enable;
- /**
- * @brief Function disabling interrupts from EXTI
- */
- nandisrswitch_t ext_nand_isr_disable;
-#endif /* STM32_NAND_USE_EXT_INT */
} NANDConfig;
/**
@@ -319,6 +289,6 @@ extern "C" {
#endif /* HAL_USE_NAND */
-#endif /* _NAND_LLD_H_ */
+#endif /* HAL_NAND_LLD_H_ */
/** @} */
diff --git a/os/hal/ports/STM32/LLD/LTDCv1/hal_stm32_ltdc.c b/os/hal/ports/STM32/LLD/LTDCv1/hal_stm32_ltdc.c
index e5f9a09..f0fd289 100644
--- a/os/hal/ports/STM32/LLD/LTDCv1/hal_stm32_ltdc.c
+++ b/os/hal/ports/STM32/LLD/LTDCv1/hal_stm32_ltdc.c
@@ -15,7 +15,7 @@
*/
/**
- * @file stm32_ltdc.c
+ * @file hal_stm32_ltdc.c
* @brief LCD-TFT Controller Driver.
*/
diff --git a/os/hal/ports/STM32/LLD/LTDCv1/hal_stm32_ltdc.h b/os/hal/ports/STM32/LLD/LTDCv1/hal_stm32_ltdc.h
index 16b38ca..5db89e2 100644
--- a/os/hal/ports/STM32/LLD/LTDCv1/hal_stm32_ltdc.h
+++ b/os/hal/ports/STM32/LLD/LTDCv1/hal_stm32_ltdc.h
@@ -15,15 +15,15 @@
*/
/**
- * @file stm32_ltdc.h
+ * @file hal_stm32_ltdc.h
* @brief LCD-TFT Controller Driver.
*
* @addtogroup ltdc
* @{
*/
-#ifndef _STM32_LTDC_H_
-#define _STM32_LTDC_H_
+#ifndef HAL_STM32_LTDC_H_
+#define HAL_STM32_LTDC_H_
/**
* @brief Using the LTDC driver.
@@ -731,6 +731,6 @@ extern "C" {
#endif /* STM32_LTDC_USE_LTDC */
-#endif /* _STM32_LTDC_H_ */
+#endif /* HAL_STM32_LTDC_H_ */
/** @} */
diff --git a/os/hal/ports/STM32/LLD/TIMv1/hal_eicu_lld.h b/os/hal/ports/STM32/LLD/TIMv1/hal_eicu_lld.h
index 927eb6f..e72098e 100644
--- a/os/hal/ports/STM32/LLD/TIMv1/hal_eicu_lld.h
+++ b/os/hal/ports/STM32/LLD/TIMv1/hal_eicu_lld.h
@@ -22,8 +22,8 @@
32-bit timers and timers with single capture/compare channels.
*/
-#ifndef __EICU_LLD_H
-#define __EICU_LLD_H
+#ifndef HAL_EICU_LLD_H
+#define HAL_EICU_LLD_H
#include "stm32_tim.h"
@@ -551,4 +551,4 @@ extern "C" {
#endif /* HAL_USE_EICU */
-#endif /* __EICU_LLD_H */
+#endif /* HAL_EICU_LLD_H */
diff --git a/os/hal/ports/STM32/LLD/TIMv1/hal_timcap_lld.c b/os/hal/ports/STM32/LLD/TIMv1/hal_timcap_lld.c
index 8ab6176..c55fae2 100644
--- a/os/hal/ports/STM32/LLD/TIMv1/hal_timcap_lld.c
+++ b/os/hal/ports/STM32/LLD/TIMv1/hal_timcap_lld.c
@@ -24,7 +24,7 @@
/**
- * @file STM32/timcap_lld.c
+ * @file STM32/hal_timcap_lld.c
* @brief STM32 TIMCAP subsystem low level driver header.
*
* @addtogroup TIMCAP
diff --git a/os/hal/ports/STM32/LLD/TIMv1/hal_timcap_lld.h b/os/hal/ports/STM32/LLD/TIMv1/hal_timcap_lld.h
index d39c438..643798a 100644
--- a/os/hal/ports/STM32/LLD/TIMv1/hal_timcap_lld.h
+++ b/os/hal/ports/STM32/LLD/TIMv1/hal_timcap_lld.h
@@ -22,8 +22,8 @@
* @{
*/
-#ifndef _TIMCAP_LLD_H_
-#define _TIMCAP_LLD_H_
+#ifndef HAL_TIMCAP_LLD_H_
+#define HAL_TIMCAP_LLD_H_
#include "ch.h"
#include "hal.h"
diff --git a/os/hal/ports/STM32/LLD/USBHv1/hal_stm32_otg.h b/os/hal/ports/STM32/LLD/USBHv1/hal_stm32_otg.h
index ca2dc49..b88e620 100644
--- a/os/hal/ports/STM32/LLD/USBHv1/hal_stm32_otg.h
+++ b/os/hal/ports/STM32/LLD/USBHv1/hal_stm32_otg.h
@@ -15,7 +15,7 @@
*/
/**
- * @file stm32_otg.h
+ * @file hal_stm32_otg.h
* @brief STM32 OTG registers layout header.
*
* @addtogroup USB
@@ -23,8 +23,8 @@
*/
-#ifndef _STM32_OTG_H_
-#define _STM32_OTG_H_
+#ifndef HAL_STM32_OTG_H_
+#define HAL_STM32_OTG_H_
/**
* @brief Number of the implemented endpoints in OTG_FS.
diff --git a/os/hal/ports/STM32/LLD/USBHv1/hal_usbh_lld.h b/os/hal/ports/STM32/LLD/USBHv1/hal_usbh_lld.h
index e8df749..5c0ac40 100644
--- a/os/hal/ports/STM32/LLD/USBHv1/hal_usbh_lld.h
+++ b/os/hal/ports/STM32/LLD/USBHv1/hal_usbh_lld.h
@@ -15,8 +15,8 @@
limitations under the License.
*/
-#ifndef USBH_LLD_H_
-#define USBH_LLD_H_
+#ifndef HAL_USBH_LLD_H_
+#define HAL_USBH_LLD_H_
#include "hal.h"
@@ -150,4 +150,4 @@ uint8_t usbh_lld_roothub_get_statuschange_bitmap(USBHDriver *usbh);
#endif
-#endif /* USBH_LLD_H_ */
+#endif /* HAL_USBH_LLD_H_ */
diff --git a/os/hal/src/hal_nand.c b/os/hal/src/hal_nand.c
index 24dd6de..e1b298a 100644
--- a/os/hal/src/hal_nand.c
+++ b/os/hal/src/hal_nand.c
@@ -80,16 +80,13 @@ static void pagesize_check(size_t page_data_size) {
*/
static void calc_addr(const NANDConfig *cfg, uint32_t block, uint32_t page,
uint32_t page_offset, uint8_t *addr, size_t addr_len) {
- size_t i = 0;
- uint32_t row = 0;
+ size_t i;
+ uint32_t row;
- /* Incorrect buffer length.*/
osalDbgCheck(cfg->rowcycles + cfg->colcycles == addr_len);
osalDbgCheck((block < cfg->blocks) && (page < cfg->pages_per_block) &&
(page_offset < cfg->page_data_size + cfg->page_spare_size));
- /* convert address to NAND specific */
- memset(addr, 0, addr_len);
row = (block * cfg->pages_per_block) + page;
for (i=0; i<cfg->colcycles; i++){
addr[i] = page_offset & 0xFF;
@@ -115,17 +112,14 @@ static void calc_addr(const NANDConfig *cfg, uint32_t block, uint32_t page,
*/
static void calc_blk_addr(const NANDConfig *cfg, uint32_t block,
uint8_t *addr, size_t addr_len) {
- size_t i = 0;
- uint32_t row = 0;
+ size_t i;
+ uint32_t row;
- /* Incorrect buffer length.*/
- osalDbgCheck(cfg->rowcycles == addr_len);
- osalDbgCheck((block < cfg->blocks));
+ osalDbgCheck(cfg->rowcycles == addr_len); /* Incorrect buffer length */
+ osalDbgCheck(block < cfg->blocks); /* Overflow */
- /* convert address to NAND specific */
- memset(addr, 0, addr_len);
row = block * cfg->pages_per_block;
- for (i=0; i<addr_len; i++){
+ for (i=0; i<addr_len; i++) {
addr[i] = row & 0xFF;
row = row >> 8;
}
@@ -415,7 +409,6 @@ void nandReadPageSpare(NANDDriver *nandp, uint32_t block, uint32_t page,
uint8_t nandWritePageSpare(NANDDriver *nandp, uint32_t block, uint32_t page,
const uint8_t *spare, size_t sparelen) {
- uint8_t retVal;
const NANDConfig *cfg = nandp->config;
uint8_t addr[8];
size_t addrlen = cfg->rowcycles + cfg->colcycles;
@@ -425,8 +418,7 @@ uint8_t nandWritePageSpare(NANDDriver *nandp, uint32_t block, uint32_t page,
osalDbgAssert(nandp->state == NAND_READY, "invalid state");
calc_addr(cfg, block, page, cfg->page_data_size, addr, addrlen);
- retVal = nand_lld_write_data(nandp, spare, sparelen, addr, addrlen, NULL);
- return retVal;
+ return nand_lld_write_data(nandp, spare, sparelen, addr, addrlen, NULL);
}
/**
@@ -478,7 +470,6 @@ uint8_t nandReadBadMark(NANDDriver *nandp, uint32_t block, uint32_t page) {
*/
uint8_t nandErase(NANDDriver *nandp, uint32_t block) {
- uint8_t retVal;
const NANDConfig *cfg = nandp->config;
uint8_t addr[4];
size_t addrlen = cfg->rowcycles;
@@ -487,8 +478,7 @@ uint8_t nandErase(NANDDriver *nandp, uint32_t block) {
osalDbgAssert(nandp->state == NAND_READY, "invalid state");
calc_blk_addr(cfg, block, addr, addrlen);
- retVal = nand_lld_erase(nandp, addr, addrlen);
- return retVal;
+ return nand_lld_erase(nandp, addr, addrlen);
}
/**
diff --git a/os/hal/src/hal_onewire.c b/os/hal/src/hal_onewire.c
index a93eec0..4e80807 100644
--- a/os/hal/src/hal_onewire.c
+++ b/os/hal/src/hal_onewire.c
@@ -46,7 +46,7 @@ on every timer overflow event.
*/
/**
- * @file onewire.c
+ * @file hal_onewire.c
* @brief 1-wire Driver code.
*
* @addtogroup onewire
@@ -251,7 +251,6 @@ static void ow_write_bit_I(onewireDriver *owp, ioline_t bit) {
static void ow_reset_cb(PWMDriver *pwmp, onewireDriver *owp) {
owp->reg.slave_present = (PAL_LOW == ow_read_bit(owp));
-
osalSysLockFromISR();
pwmDisableChannelI(pwmp, owp->config->sample_channel);
osalThreadResumeI(&owp->thread, MSG_OK);
@@ -661,7 +660,7 @@ bool onewireReset(onewireDriver *owp) {
pwmcfg->channels[mch].callback = NULL;
pwmcfg->channels[mch].mode = owp->config->pwmmode;
pwmcfg->channels[sch].callback = pwm_reset_cb;
- pwmcfg->channels[sch].mode = PWM_OUTPUT_ACTIVE_LOW;
+ pwmcfg->channels[sch].mode = PWM_OUTPUT_DISABLED;
ow_bus_active(owp);
@@ -714,7 +713,7 @@ void onewireRead(onewireDriver *owp, uint8_t *rxbuf, size_t rxbytes) {
pwmcfg->channels[mch].callback = NULL;
pwmcfg->channels[mch].mode = owp->config->pwmmode;
pwmcfg->channels[sch].callback = pwm_read_bit_cb;
- pwmcfg->channels[sch].mode = PWM_OUTPUT_ACTIVE_LOW;
+ pwmcfg->channels[sch].mode = PWM_OUTPUT_DISABLED;
ow_bus_active(owp);
osalSysLock();
@@ -848,7 +847,7 @@ size_t onewireSearchRom(onewireDriver *owp, uint8_t *result,
pwmcfg->channels[mch].callback = NULL;
pwmcfg->channels[mch].mode = owp->config->pwmmode;
pwmcfg->channels[sch].callback = pwm_search_rom_cb;
- pwmcfg->channels[sch].mode = PWM_OUTPUT_ACTIVE_LOW;
+ pwmcfg->channels[sch].mode = PWM_OUTPUT_DISABLED;
ow_bus_active(owp);
osalSysLock();
@@ -882,7 +881,7 @@ size_t onewireSearchRom(onewireDriver *owp, uint8_t *result,
* Include test code (if enabled).
*/
#if ONEWIRE_SYNTH_SEARCH_TEST
-#include "search_rom_synth.c"
+#include "synth_searchrom.c"
#endif
#endif /* HAL_USE_ONEWIRE */
diff --git a/os/hal/src/hal_timcap.c b/os/hal/src/hal_timcap.c
index a352490..309c147 100644
--- a/os/hal/src/hal_timcap.c
+++ b/os/hal/src/hal_timcap.c
@@ -19,7 +19,7 @@
*/
/**
- * @file timcap.c
+ * @file hal_timcap.c
* @brief TIMCAP Driver code.
*
* @addtogroup TIMCAP
diff --git a/os/hal/src/hal_usb_msd.c b/os/hal/src/hal_usb_msd.c
new file mode 100644
index 0000000..068d698
--- /dev/null
+++ b/os/hal/src/hal_usb_msd.c
@@ -0,0 +1,408 @@
+/*
+ ChibiOS/HAL - Copyright (C) 2016 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.
+*/
+
+/**
+ * @file hal_usb_msd.c
+ * @brief USM mass storage device code.
+ *
+ * @addtogroup usb_msd
+ * @{
+ */
+
+#include "hal.h"
+
+#if (HAL_USE_USB_MSD == TRUE) || defined(__DOXYGEN__)
+
+#include <string.h>
+
+/*===========================================================================*/
+/* Driver local definitions. */
+/*===========================================================================*/
+
+#define MSD_REQ_RESET 0xFF
+#define MSD_GET_MAX_LUN 0xFE
+
+#define MSD_CBW_SIGNATURE 0x43425355
+#define MSD_CSW_SIGNATURE 0x53425355
+
+#define MSD_THD_PRIO NORMALPRIO
+
+#define CBW_FLAGS_RESERVED_MASK 0b01111111
+#define CBW_LUN_RESERVED_MASK 0b11110000
+#define CBW_CMD_LEN_RESERVED_MASK 0b11000000
+
+#define CSW_STATUS_PASSED 0x00
+#define CSW_STATUS_FAILED 0x01
+#define CSW_STATUS_PHASE_ERROR 0x02
+
+#define MSD_SETUP_WORD(setup, index) (uint16_t)(((uint16_t)setup[index+1] << 8)\
+ | (setup[index] & 0x00FF))
+
+#define MSD_SETUP_VALUE(setup) MSD_SETUP_WORD(setup, 2)
+#define MSD_SETUP_INDEX(setup) MSD_SETUP_WORD(setup, 4)
+#define MSD_SETUP_LENGTH(setup) MSD_SETUP_WORD(setup, 6)
+
+/*===========================================================================*/
+/* Driver exported variables. */
+/*===========================================================================*/
+/**
+ * @brief USB mass storage driver identifier.
+ */
+USBMassStorageDriver USBMSD1;
+
+/*===========================================================================*/
+/* Driver local variables and types. */
+/*===========================================================================*/
+
+/**
+ * @brief Hardcoded default SCSI inquiry response structure.
+ */
+static const scsi_inquiry_response_t default_scsi_inquiry_response = {
+ 0x00, /* direct access block device */
+ 0x80, /* removable */
+ 0x04, /* SPC-2 */
+ 0x02, /* response data format */
+ 0x20, /* response has 0x20 + 4 bytes */
+ 0x00,
+ 0x00,
+ 0x00,
+ "Chibios",
+ "Mass Storage",
+ {'v',CH_KERNEL_MAJOR+'0','.',CH_KERNEL_MINOR+'0'}
+};
+
+/*===========================================================================*/
+/* Driver local functions. */
+/*===========================================================================*/
+
+/**
+ * @brief Checks validity of CBW content.
+ * @details The device shall consider the CBW valid when:
+ * • The CBW was received after the device had sent a CSW or after a reset,
+ * • the CBW is 31 (1Fh) bytes in length,
+ * • and the dCBWSignature is equal to 43425355h.
+ *
+ * @param[in] cbw pointer to the @p msd_cbw_t object
+ * @param[in] recvd number of received bytes
+ *
+ * @return Operation status.
+ * @retval true CBW is meaningful.
+ * @retval false CBW is bad.
+ *
+ * @notapi
+ */
+static bool cbw_valid(const msd_cbw_t *cbw, msg_t recvd) {
+ if ((sizeof(msd_cbw_t) != recvd) || (cbw->signature != MSD_CBW_SIGNATURE)) {
+ return false;
+ }
+ else {
+ return true;
+ }
+}
+
+/**
+ * @brief Checks meaningfulness of CBW content.
+ * @details The device shall consider the contents of a valid CBW meaningful when:
+ * • no reserved bits are set,
+ * • the bCBWLUN contains a valid LUN supported by the device,
+ * • and both bCBWCBLength and the content of the CBWCB are in
+ * accordance with bInterfaceSubClass.
+ *
+ * @param[in] cbw pointer to the @p msd_cbw_t object
+ *
+ * @return Operation status.
+ * @retval true CBW is meaningful.
+ * @retval false CBW is bad.
+ *
+ * @notapi
+ */
+static bool cbw_meaningful(const msd_cbw_t *cbw) {
+ if (((cbw->cmd_len & CBW_CMD_LEN_RESERVED_MASK) != 0)
+ || ((cbw->flags & CBW_FLAGS_RESERVED_MASK) != 0)
+ || (cbw->lun != 0)) {
+ return false;
+ }
+ else {
+ return true;
+ }
+}
+
+/**
+ * @brief SCSI transport transmit function.
+ *
+ * @param[in] transport pointer to the @p SCSITransport object
+ * @param[in] data payload
+ * @param[in] len number of bytes to be transmitted
+ *
+ * @return Number of successfully transmitted bytes.
+
+ * @notapi
+ */
+static uint32_t scsi_transport_transmit(const SCSITransport *transport,
+ const uint8_t *data, size_t len) {
+
+ usb_scsi_transport_handler_t *trp = transport->handler;
+ msg_t status = usbTransmit(trp->usbp, trp->ep, data, len);
+ if (MSG_OK == status)
+ return len;
+ else
+ return 0;
+}
+
+/**
+ * @brief SCSI transport receive function.
+ *
+ * @param[in] transport pointer to the @p SCSITransport object
+ * @param[in] data payload
+ * @param[in] len number bytes to be received
+ *
+ * @return Number of successfully received bytes.
+
+ * @notapi
+ */
+static uint32_t scsi_transport_receive(const SCSITransport *transport,
+ uint8_t *data, size_t len) {
+
+ usb_scsi_transport_handler_t *trp = transport->handler;
+ msg_t status = usbReceive(trp->usbp, trp->ep, data, len);
+ if (MSG_RESET != status)
+ return status;
+ else
+ return 0;
+}
+
+/**
+ * @brief Fills and sends CSW message.
+ *
+ * @param[in] msdp pointer to the @p USBMassStorageDriver object
+ * @param[in] status status returned by SCSI layer
+ * @param[in] residue number of residue bytes in case of failed transaction
+ *
+ * @notapi
+ */
+static void send_csw(USBMassStorageDriver *msdp, uint8_t status,
+ uint32_t residue) {
+
+ msdp->csw.signature = MSD_CSW_SIGNATURE;
+ msdp->csw.data_residue = residue;
+ msdp->csw.tag = msdp->cbw.tag;
+ msdp->csw.status = status;
+
+ usbTransmit(msdp->usbp, USB_MSD_DATA_EP, (uint8_t *)&msdp->csw,
+ sizeof(msd_csw_t));
+}
+
+/**
+ * @brief Mass storage worker thread.
+ *
+ * @param[in] arg pointer to the @p USBMassStorageDriver object
+ *
+ * @notapi
+ */
+static THD_FUNCTION(usb_msd_worker, arg) {
+ USBMassStorageDriver *msdp = arg;
+
+ while(! chThdShouldTerminateX()) {
+ const msg_t status = usbReceive(msdp->usbp, USB_MSD_DATA_EP,
+ (uint8_t *)&msdp->cbw, sizeof(msd_cbw_t));
+ if (MSG_RESET == status) {
+ osalThreadSleepMilliseconds(50);
+ }
+ else if (cbw_valid(&msdp->cbw, status) && cbw_meaningful(&msdp->cbw)) {
+ if (SCSI_SUCCESS == scsiExecCmd(&msdp->scsi_target, msdp->cbw.cmd_data)) {
+ send_csw(msdp, CSW_STATUS_PASSED, 0);
+ }
+ else {
+ send_csw(msdp, CSW_STATUS_FAILED, scsiResidue(&msdp->scsi_target));
+ }
+ }
+ else {
+ ; /* do NOT send CSW here. Incorrect CBW must be silently ignored */
+ }
+ }
+
+ chThdExit(MSG_OK);
+}
+
+/*===========================================================================*/
+/* Driver exported functions. */
+/*===========================================================================*/
+
+/**
+ * @brief Mass storage specific request hook for USB.
+ *
+ * @param[in] usbp pointer to the @p USBDriver object
+ *
+ * @notapi
+ */
+bool msd_request_hook(USBDriver *usbp) {
+
+ if (((usbp->setup[0] & USB_RTYPE_TYPE_MASK) == USB_RTYPE_TYPE_CLASS) &&
+ ((usbp->setup[0] & USB_RTYPE_RECIPIENT_MASK) == USB_RTYPE_RECIPIENT_INTERFACE)) {
+ /* check that the request is for interface 0.*/
+ if (MSD_SETUP_INDEX(usbp->setup) != 0)
+ return false;
+
+ /* act depending on bRequest = setup[1] */
+ switch(usbp->setup[1]) {
+ case MSD_REQ_RESET:
+ /* check that it is a HOST2DEV request */
+ if (((usbp->setup[0] & USB_RTYPE_DIR_MASK) != USB_RTYPE_DIR_HOST2DEV) ||
+ (MSD_SETUP_LENGTH(usbp->setup) != 0) ||
+ (MSD_SETUP_VALUE(usbp->setup) != 0)) {
+ return false;
+ }
+
+ /*
+ As required by the BOT specification, the Bulk-only mass storage reset request (classspecific
+ request) is implemented. This request is used to reset the mass storage device and
+ its associated interface. This class-specific request should prepare the device for the next
+ CBW from the host.
+ To generate the BOT Mass Storage Reset, the host must send a device request on the
+ default pipe of:
+ • bmRequestType: Class, interface, host to device
+ • bRequest field set to 255 (FFh)
+ • wValue field set to ‘0’
+ • wIndex field set to the interface number
+ • wLength field set to ‘0’
+ */
+ chSysLockFromISR();
+
+ /* release and abandon current transmission */
+ usbStallReceiveI(usbp, 1);
+ usbStallTransmitI(usbp, 1);
+ /* The device shall NAK the status stage of the device request until
+ * the Bulk-Only Mass Storage Reset is complete.
+ * NAK EP1 in and out */
+ usbp->otg->ie[1].DIEPCTL = DIEPCTL_SNAK;
+ usbp->otg->oe[1].DOEPCTL = DOEPCTL_SNAK;
+
+ chSysUnlockFromISR();
+
+ /* response to this request using EP0 */
+ usbSetupTransfer(usbp, 0, 0, NULL);
+ return true;
+
+ case MSD_GET_MAX_LUN:
+ /* check that it is a DEV2HOST request */
+ if (((usbp->setup[0] & USB_RTYPE_DIR_MASK) != USB_RTYPE_DIR_DEV2HOST) ||
+ (MSD_SETUP_LENGTH(usbp->setup) != 1) ||
+ (MSD_SETUP_VALUE(usbp->setup) != 0)) {
+ return false;
+ }
+
+ /* stall to indicate that we don't support LUN */
+ osalSysLockFromISR();
+ usbStallTransmitI(usbp, 0);
+ osalSysUnlockFromISR();
+ return true;
+
+ default:
+ return false;
+ break;
+ }
+ }
+ return false;
+}
+
+/**
+ * @brief Initializes the standard part of a @p USBMassStorageDriver structure.
+ *
+ * @param[out] msdp pointer to the @p USBMassStorageDriver object
+ *
+ * @init
+ */
+void msdObjectInit(USBMassStorageDriver *msdp) {
+
+ memset(msdp, 0x55, sizeof(USBMassStorageDriver));
+ msdp->state = USB_MSD_STOP;
+ msdp->usbp = NULL;
+ msdp->worker = NULL;
+
+ scsiObjectInit(&msdp->scsi_target);
+}
+
+/**
+ * @brief Stops the USB mass storage driver.
+ *
+ * @param[in] msdp pointer to the @p USBMassStorageDriver object
+ *
+ * @api
+ */
+void msdStop(USBMassStorageDriver *msdp) {
+
+ osalDbgCheck(msdp != NULL);
+ osalDbgAssert((msdp->state == USB_MSD_READY), "invalid state");
+
+ chThdTerminate(msdp->worker);
+ chThdWait(msdp->worker);
+
+ scsiStop(&msdp->scsi_target);
+
+ msdp->worker = NULL;
+ msdp->state = USB_MSD_STOP;
+ msdp->usbp = NULL;
+}
+
+/**
+ * @brief Configures and activates the USB mass storage driver.
+ *
+ * @param[in] msdp pointer to the @p USBMassStorageDriver object
+ * @param[in] usbp pointer to the @p USBDriver object
+ * @param[in] blkdev pointer to the @p BaseBlockDevice object
+ * @param[in] blkbuf pointer to the working area buffer, must be allocated
+ * by user, must be big enough to store 1 data block
+ * @param[in] inquiry pointer to the SCSI inquiry response structure,
+ * set it to @p NULL to use default hardcoded value.
+ *
+ * @api
+ */
+void msdStart(USBMassStorageDriver *msdp, USBDriver *usbp,
+ BaseBlockDevice *blkdev, uint8_t *blkbuf,
+ const scsi_inquiry_response_t *inquiry) {
+
+ osalDbgCheck((msdp != NULL) && (usbp != NULL)
+ && (blkdev != NULL) && (blkbuf != NULL));
+ osalDbgAssert((msdp->state == USB_MSD_STOP), "invalid state");
+
+ msdp->usbp = usbp;
+
+ msdp->usb_scsi_transport_handler.usbp = msdp->usbp;
+ msdp->usb_scsi_transport_handler.ep = USB_MSD_DATA_EP;
+ msdp->scsi_transport.handler = &msdp->usb_scsi_transport_handler;
+ msdp->scsi_transport.transmit = scsi_transport_transmit;
+ msdp->scsi_transport.receive = scsi_transport_receive;
+
+ if (NULL == inquiry) {
+ msdp->scsi_config.inquiry_response = &default_scsi_inquiry_response;
+ }
+ else {
+ msdp->scsi_config.inquiry_response = inquiry;
+ }
+ msdp->scsi_config.blkbuf = blkbuf;
+ msdp->scsi_config.blkdev = blkdev;
+ msdp->scsi_config.transport = &msdp->scsi_transport;
+
+ scsiStart(&msdp->scsi_target, &msdp->scsi_config);
+
+ msdp->state = USB_MSD_READY;
+ msdp->worker = chThdCreateStatic(msdp->waMSDWorker, sizeof(msdp->waMSDWorker),
+ MSD_THD_PRIO, usb_msd_worker, msdp);
+}
+
+#endif /* HAL_USE_USB_MSD */
+
+/** @} */