mirror of
https://github.com/apache/nuttx.git
synced 2026-06-07 09:18:00 +08:00
Merge remote-tracking branch 'upstream/master'
This commit is contained in:
+128
-89
File diff suppressed because it is too large
Load Diff
@@ -667,6 +667,24 @@ endif # LPC54_EMC_DYNAMIC
|
||||
|
||||
endmenu # EMC Configuration
|
||||
|
||||
menu "SPI Master configuration"
|
||||
depends on LPC54_HAVE_SPI_MASTER
|
||||
|
||||
config LPC54_SPI_WIDEDATA
|
||||
bool "Enable wide data"
|
||||
default n
|
||||
---help---
|
||||
The LPC54xxx SPI supports data widths from 4 through 16 bits. For
|
||||
data from 4 through 8 bits; the receive and transmit data is
|
||||
represented with a uint8_t type. For the wider data, data is
|
||||
represented with a uint16_t. There is duplication of logic for this
|
||||
different widths. By default, SPI wide data is disabled since that
|
||||
is the less frequently used data type and disabling wide data can
|
||||
result in some size reduction. Select this option if you need wide
|
||||
SPI data.
|
||||
|
||||
endmenu # SPI Master configuration
|
||||
|
||||
menu "Ethernet configuration"
|
||||
depends on LPC54_ETHERNET
|
||||
|
||||
|
||||
@@ -260,38 +260,146 @@
|
||||
/* Register bit definitions *************************************************************************/
|
||||
|
||||
/* SPI Configuration register */
|
||||
#define SPI_CFG_
|
||||
|
||||
#define SPI_CFG_ENABLE (1 << 0) /* Bit 0: SPI enable */
|
||||
#define SPI_CFG_MASTER (1 << 2) /* Bit 2: Master mode select */
|
||||
#define SPI_CFG_LSBF (1 << 3) /* Bit 3: LSB First mode enable */
|
||||
#define SPI_CFG_CPHA (1 << 4) /* Bit 4: Clock Phase select */
|
||||
#define SPI_CFG_CPOL (1 << 5) /* Bit 5: Clock Polarity select */
|
||||
#define SPI_CFG_LOOP (1 << 7) /* Bit 7: Loopback mode enable */
|
||||
#define SPI_CFG_SPOL0 (1 << 8) /* Bit 8: SSEL0 Polarity select */
|
||||
#define SPI_CFG_SPOL1 (1 << 9) /* Bit 9: SSEL1 Polarity select */
|
||||
#define SPI_CFG_SPOL2 (1 << 10) /* Bit 10: SSEL2 Polarity select */
|
||||
#define SPI_CFG_SPOL3 (1 << 11) /* Bit 11: SSEL3 Polarity select */
|
||||
|
||||
/* SPI Delay register */
|
||||
#define SPI_DLY_
|
||||
|
||||
#define SPI_DLY_PRE_DELAY_SHIFT (0) /* Bits 0-3: Time between SSEL assertion and data transfer */
|
||||
#define SPI_DLY_PRE_DELAY_MASK (15 << SPI_DLY_PRE_DELAY_SHIFT)
|
||||
# define SPI_DLY_PRE_DELAY(n) ((uint32_t)(n) << SPI_DLY_PRE_DELAY_SHIFT)
|
||||
#define SPI_DLY_POST_DELAY_SHIFT (4) /* Bits 4-7: Time between tdata transfer and SSEL deassertion */
|
||||
#define SPI_DLY_POST_DELAY_MASK (15 << SPI_DLY_POST_DELAY_SHIFT)
|
||||
# define SPI_DLY_POST_DELAY(n) ((uint32_t)(n) << SPI_DLY_POST_DELAY_SHIFT)
|
||||
#define SPI_DLY_FRAME_DELAY_SHIFT (8) /* Bits 8-11: Minimum amount of time between frames */
|
||||
#define SPI_DLY_FRAME_DELAY_MASK (15 << SPI_DLY_FRAME_DELAY_SHIFT)
|
||||
# define SPI_DLY_FRAME_DELAY(n) ((uint32_t)(n) << SPI_DLY_FRAME_DELAY_SHIFT)
|
||||
#define SPI_DLY_TRANSFER_DELAY_SHIFT (12) /* Bits 12-15: Time SSEL deasserted between transfers */
|
||||
#define SPI_DLY_TRANSFER_DELAY_MASK (15 << SPI_DLY_TRANSFER_DELAY_SHIFT)
|
||||
# define SPI_DLY_TRANSFER_DELAY(n) ((uint32_t)(n) << SPI_DLY_TRANSFER_DELAY_SHIFT)
|
||||
|
||||
/* SPI Status register */
|
||||
#define SPI_STAT_
|
||||
/* SPI Interrupt Enable read and set */
|
||||
#define SPI_INTENSET_
|
||||
/* SPI Interrupt Enable Clear */
|
||||
#define SPI_INTENCLR_
|
||||
|
||||
#define SPI_STAT_SSA (1 << 4) /* Bit 4: Slave Select Assert */
|
||||
#define SPI_STAT_SSD (1 << 5) /* Bit 5: Slave Select Deassert */
|
||||
#define SPI_STAT_STALLED (1 << 6) /* Bit 6: Stalled status flag */
|
||||
#define SPI_STAT_ENDTRANSFER (1 << 7) /* Bit 7: End Transfer control bit */
|
||||
#define SPI_STAT_MSTIDLE (1 << 8) /* Bit 8: Master idle status flag */
|
||||
|
||||
/* SPI Interrupt Enable read and set, SPI Interrupt Enable Clear, and SPI Interrupt Status */
|
||||
|
||||
#define SPI_INT_SSA (1 << 4) /* Bit 4: Slave select assert interrupt */
|
||||
#define SPI_INT_SSD (1 << 5) /* Bit 5: Slave select deassert interrupt */
|
||||
#define SPI_INT_MSTIDLE (1 << 8) /* Bit 8: Master idle interrupt */
|
||||
|
||||
/* SPI clock Divider */
|
||||
#define SPI_DIV_
|
||||
/* SPI Interrupt Status */
|
||||
#define SPI_INTSTAT_
|
||||
|
||||
#define SPI_DIV_SHIFT (0) /* Bits 0-15: Rate divider value */
|
||||
#define SPI_DIV_MASK (0xffff << SPI_DIV_SHIFT)
|
||||
# define SPI_DIV(n) ((uint32_t)((n)-1) << SPI_DIV_SHIFT)
|
||||
|
||||
/* FIFO configuration and enable register */
|
||||
#define SPI_FIFOCFG_
|
||||
|
||||
#define SPI_FIFOCFG_ENABLETX (1 << 0) /* Bit 0: Enable the transmit FIFO) */
|
||||
#define SPI_FIFOCFG_ENABLERX (1 << 1) /* Bit 1: Enable the receive FIFO) */
|
||||
#define SPI_FIFOCFG_SIZE_SHIFT (4) /* Bits 4-5: FIFO size configuration (read-only) */
|
||||
#define SPI_FIFOCFG_SIZE_MASK (3 << SPI_FIFOCFG_SIZE_SHIFT)
|
||||
# define SPI_FIFOCFG_SIZE_8x16 (1 << SPI_FIFOCFG_SIZE_SHIFT) /* FIFO is configured as 8 entries of 16 bits */
|
||||
#define SPI_FIFOCFG_DMATX (1 << 12) /* Bit 12: DMA configuration for transmit */
|
||||
#define SPI_FIFOCFG_DMARX (1 << 13) /* Bit 13: DMA configuration for receive */
|
||||
#define SPI_FIFOCFG_WAKETX (1 << 14) /* Bit 14: Wake-up for transmit FIFO level */
|
||||
#define SPI_FIFOCFG_WAKERX (1 << 15) /* Bit 15: Wake-up for receive FIFO level */
|
||||
#define SPI_FIFOCFG_EMPTYTX (1 << 16) /* Bit 16: Empty command for the transmit FIFO) */
|
||||
#define SPI_FIFOCFG_EMPTYRX (1 << 17) /* Bit 17: Empty command for the receive FIFO) */
|
||||
|
||||
/* FIFO status register */
|
||||
#define SPI_FIFOSTAT_
|
||||
|
||||
#define SPI_FIFOSTAT_TXERR (1 << 0) /* Bit 0: TX FIFO error */
|
||||
#define SPI_FIFOSTAT_RXERR (1 << 1) /* Bit 1: RX FIFO error */
|
||||
#define SPI_FIFOSTAT_PERINT (1 << 3) /* Bit 3: Peripheral interrupt */
|
||||
#define SPI_FIFOSTAT_TXEMPTY (1 << 4) /* Bit 4: Transmit FIFO empty */
|
||||
#define SPI_FIFOSTAT_TXNOTFULL (1 << 5) /* Bit 5: Transmit FIFO not full */
|
||||
#define SPI_FIFOSTAT_RXNOTEMPTY (1 << 6) /* Bit 6: Receive FIFO not empty */
|
||||
#define SPI_FIFOSTAT_RXFULL (1 << 7) /* Bit 7: Receive FIFO full */
|
||||
#define SPI_FIFOSTAT_TXLVL_SHIFT (8) /* Bits 8-12: Transmit FIFO current level */
|
||||
#define SPI_FIFOSTAT_TXLVL_MASK (31 << SPI_FIFOSTAT_TXLVL_SHIFT)
|
||||
#define SPI_FIFOSTAT_RXLVL_SHIFT (16) /* Bits 16-20: Receive FIFO current level */
|
||||
#define SPI_FIFOSTAT_RXLVL_MASK (31 << SPI_FIFOSTAT_RXLVL_SHIFT)
|
||||
|
||||
/* FIFO trigger level settings for interrupt and DMA request */
|
||||
#define SPI_FIFOTRIG_
|
||||
/* FIFO interrupt enable set (enable) and read register */
|
||||
#define SPI_FIFOINTENSET_
|
||||
/* FIFO interrupt enable clear (disable) and read register */
|
||||
#define SPI_FIFOINTENCLR_
|
||||
/* FIFO interrupt status register */
|
||||
#define SPI_FIFOINTSTAT_
|
||||
|
||||
#define SPI_FIFOTRIG_TXLVLENA (1 << 0) /* Bit 0: Transmit FIFO level trigger enable */
|
||||
#define SPI_FIFOTRIG_RXLVLENA (1 << 1) /* Bit 1: Receive FIFO level trigger enable */
|
||||
#define SPI_FIFOTRIG_TXLVL_SHIFT (8) /* Bits 8-11: Transmit FIFO level trigger point */
|
||||
#define SPI_FIFOTRIG_TXLVL_MASK (15 << SPI_FIFOTRIG_TXLVL_SHIFT)
|
||||
# define SPI_FIFOTRIG_TXLVL(n) ((uint32_t)(n) << SPI_FIFOTRIG_TXLVL_SHIFT)
|
||||
# define SPI_FIFOTRIG_TXLVL_EMPTY (0 << SPI_FIFOTRIG_TXLVL_SHIFT)
|
||||
# define SPI_FIFOTRIG_TXLVL_NOTFULL (7 << SPI_FIFOTRIG_TXLVL_SHIFT)
|
||||
#define SPI_FIFOTRIG_RXLVL_SHIFT (16) /* Bits 16-19: Receive FIFO level trigger point */
|
||||
#define SPI_FIFOTRIG_RXLVL_MASK (15 << SPI_FIFOTRIG_RXLVL_SHIFT)
|
||||
# define SPI_FIFOTRIG_RXLVL(n) ((uint32_t)((n)-1) << SPI_FIFOTRIG_RXLVL_SHIFT)
|
||||
# define SPI_FIFOTRIG_RXLVL_NOTEMPTY (0 << SPI_FIFOTRIG_RXLVL_SHIFT)
|
||||
# define SPI_FIFOTRIG_RXLVL_FULL (7 << SPI_FIFOTRIG_RXLVL_SHIFT)
|
||||
|
||||
/* FIFO interrupt enable set (enable) and read register, FIFO interrupt enable clear (disable)
|
||||
* and read register, and FIFO interrupt status register
|
||||
*/
|
||||
|
||||
#define SPI_FIFOINT_TXERR (1 << 0) /* Bit 0: Transmit error interrupt */
|
||||
#define SPI_FIFOINT_RXERR (1 << 1) /* Bit 1: Receive error interrupt */
|
||||
#define SPI_FIFOINT_TXLVL (1 << 2) /* Bit 2: Tx FIFO level reached interrupt */
|
||||
#define SPI_FIFOINT_RXLVL (1 << 3) /* Bit 3: Rx FIFO level reached interrupt */
|
||||
#define SPI_FIFOINTSTAT_PERINT (1 << 4) /* Bit 4: Peripheral interrupt (status only) */
|
||||
|
||||
/* FIFO write data */
|
||||
#define SPI_FIFOWR_
|
||||
/* FIFO read data */
|
||||
#define SPI_FIFORD_
|
||||
/* FIFO data read with no FIFO pop */
|
||||
#define SPI_FIFORDNOPOP_
|
||||
|
||||
#define SPI_FIFOWR_TXDATA_SHIFT (0) /* Bits 0-15: Transmit data to the FIFO */
|
||||
#define SPI_FIFOWR_TXDATA_MASK (0xffff << SPI_FIFOWR_TXDATA_SHIFT)
|
||||
# define SPI_FIFOWR_TXDATA(n) ((uint32_t)(n) << SPI_FIFOWR_TXDATA_SHIFT)
|
||||
#define SPI_FIFOWR_TXSSELN_SHIFT (16) /* Bits 16-19: Transmit Slave Selects */
|
||||
#define SPI_FIFOWR_TXSSELN_MASK (15 << SPI_FIFOWR_TXSSELN_SHIFT)
|
||||
# define SPI_FIFOWR_TXSSELN_ALL (15 << SPI_FIFOWR_TXSSELN_SHIFT)
|
||||
# define SPI_FIFOWR_TXSSEL0N (1 << 16) /* Bit 16: Transmit Slave Select */
|
||||
# define SPI_FIFOWR_TXSSEL1N (1 << 17) /* Bit 17: Transmit Slave Select */
|
||||
# define SPI_FIFOWR_TXSSEL2N (1 << 18) /* Bit 18: Transmit Slave Select */
|
||||
# define SPI_FIFOWR_TXSSEL3N (1 << 19) /* Bit 19: Transmit Slave Select */
|
||||
#define SPI_FIFOWR_EOT (1 << 20) /* Bit 20: End of Transfer */
|
||||
#define SPI_FIFOWR_EOF (1 << 21) /* Bit 21: End of Frame */
|
||||
#define SPI_FIFOWR_RXIGNORE (1 << 22) /* Bit 22: Receive Ignore */
|
||||
#define SPI_FIFOWR_LEN_SHIFT (24) /* Bits 24-27: Data Length */
|
||||
#define SPI_FIFOWR_LEN_MASK (15 << SPI_FIFOWR_LEN_SHIFT)
|
||||
# define SPI_FIFOWR_LEN(n) ((uint32_t)((n)-1) << SPI_FIFOWR_LEN_SHIFT)
|
||||
|
||||
/* FIFO read data and FIFO data read with no FIFO pop */
|
||||
|
||||
#define SPI_FIFORD_RXDATA_SHIFT (0) /* Bits 0-15: Received data from the FIFO */
|
||||
#define SPI_FIFORD_RXDATA_MASK (0xffff << SPI_FIFORD_RXDATA_SHIFT)
|
||||
#define SPI_FIFORD_RXSSELN_SHIFT (16) /* Bits 16-19: Slave Selects for receive */
|
||||
#define SPI_FIFORD_RXSSELN_MASK (15 << SPI_FIFORD_RXSSELN_SHIFT)
|
||||
# define SPI_FIFORD_RXSSEL0N (1 << 16) /* Bit 16: Slave Select for receive */
|
||||
# define SPI_FIFORD_RXSSEL1N (1 << 17) /* Bit 17: Slave Select for receive */
|
||||
# define SPI_FIFORD_RXSSEL2N (1 << 18) /* Bit 18: Slave Select for receive */
|
||||
# define SPI_FIFORD_RXSSEL3N (1 << 19) /* Bit 19: Slave Select for receive */
|
||||
#define SPI_FIFORD_SOT (1 << 20) /* Bit 20: Start of Transfer flag */
|
||||
|
||||
/* SPI module Identification */
|
||||
#define SPI_ID_
|
||||
|
||||
#define SPI_ID_APERTURE_SHIFT (0) /* Bits 0-7: Aperture encoded as (aperture size/4K) -1 */
|
||||
#define SPI_ID_APERTURE_MASK (0xff << SPI_ID_APERTURE_SHIFT)
|
||||
#define SPI_ID_MINORREV_SHIFT (8) /* Bits 8-11: Minor revision of module implementation */
|
||||
#define SPI_ID_MINORREV_MASK (15 << SPI_ID_MINORREV_SHIFT)
|
||||
#define SPI_ID_MAJORREV_SHIFT (12) /* Bits 12-15: Major revision of module implementation */
|
||||
#define SPI_ID_MAJORREV_MASK (15 << SPI_ID_MAJORREV_SHIFT)
|
||||
#define SPI_ID_ID_SHIFT (15) /* Bits 16-31: Unique module identifier for this IP block */
|
||||
#define SPI_ID_ID_MASK (0xffff << SPI_ID_ID_SHIFT)
|
||||
|
||||
#endif /* __ARCH_ARM_SRC_LPC54XX_CHIP_LPC54_SPI_H */
|
||||
|
||||
+1303
-242
File diff suppressed because it is too large
Load Diff
@@ -109,45 +109,111 @@ extern "C"
|
||||
FAR struct spi_dev_s *lpc54_spibus_initialize(int port);
|
||||
|
||||
/************************************************************************************
|
||||
* Name: lpc54_spiselect, lpc54_spistatus, and lpc54_spicmddata
|
||||
* Name: lpc54_spiN_select, lpc54_spiN_status, and lpc54_spiN_cmddata
|
||||
*
|
||||
* Description:
|
||||
* These functions must be provided in your board-specific logic. The
|
||||
* lpc54_spiselect function will perform chip selection and the lpc54_spistatus
|
||||
* lpc54_spiN_select function will perform chip selection and the lpc54_spiN_status
|
||||
* will perform status operations using GPIOs in the way your board is configured.
|
||||
*
|
||||
* If CONFIG_SPI_CMDDATA is defined in the NuttX configuration, then
|
||||
* lpc54_spicmddata must also be provided. This functions performs cmd/data
|
||||
* lpc54_spiN_cmddata must also be provided. This functions performs cmd/data
|
||||
* selection operations using GPIOs in the way your board is configured.
|
||||
*
|
||||
************************************************************************************/
|
||||
|
||||
void lpc54_spiselect(FAR struct spi_dev_s *dev, uint32_t devid, bool selected);
|
||||
uint8_t lpc54_spistatus(FAR struct spi_dev_s *dev, uint32_t devid);
|
||||
#ifdef CONFIG_LPC54_SPI0_MASTER
|
||||
void lpc54_spi0_select(FAR struct spi_dev_s *dev, uint32_t devid, bool selected);
|
||||
uint8_t lpc54_spi0_status(FAR struct spi_dev_s *dev, uint32_t devid);
|
||||
|
||||
#ifdef CONFIG_SPI_CMDDATA
|
||||
int lpc54_spicmddata(FAR struct spi_dev_s *dev, uint32_t devid, bool cmd);
|
||||
int lpc54_spi0_cmddata(FAR struct spi_dev_s *dev, uint32_t devid, bool cmd);
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_LPC54_SPI1_MASTER
|
||||
void lpc54_spi1_select(FAR struct spi_dev_s *dev, uint32_t devid, bool selected);
|
||||
uint8_t lpc54_spi1_status(FAR struct spi_dev_s *dev, uint32_t devid);
|
||||
|
||||
#ifdef CONFIG_SPI_CMDDATA
|
||||
int lpc54_spi1_cmddata(FAR struct spi_dev_s *dev, uint32_t devid, bool cmd);
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_LPC54_SPI2_MASTER
|
||||
void lpc54_spi2_select(FAR struct spi_dev_s *dev, uint32_t devid, bool selected);
|
||||
uint8_t lpc54_spi2_status(FAR struct spi_dev_s *dev, uint32_t devid);
|
||||
|
||||
#ifdef CONFIG_SPI_CMDDATA
|
||||
int lpc54_spi2_cmddata(FAR struct spi_dev_s *dev, uint32_t devid, bool cmd);
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_LPC54_SPI3_MASTER
|
||||
void lpc54_spi3_select(FAR struct spi_dev_s *dev, uint32_t devid, bool selected);
|
||||
uint8_t lpc54_spi3_status(FAR struct spi_dev_s *dev, uint32_t devid);
|
||||
|
||||
#ifdef CONFIG_SPI_CMDDATA
|
||||
int lpc54_spi3_cmddata(FAR struct spi_dev_s *dev, uint32_t devid, bool cmd);
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_LPC54_SPI4_MASTER
|
||||
void lpc54_spi4_select(FAR struct spi_dev_s *dev, uint32_t devid, bool selected);
|
||||
uint8_t lpc54_spi4_status(FAR struct spi_dev_s *dev, uint32_t devid);
|
||||
|
||||
#ifdef CONFIG_SPI_CMDDATA
|
||||
int lpc54_spi4_cmddata(FAR struct spi_dev_s *dev, uint32_t devid, bool cmd);
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_LPC54_SPI5_MASTER
|
||||
void lpc54_spi5_select(FAR struct spi_dev_s *dev, uint32_t devid, bool selected);
|
||||
uint8_t lpc54_spi5_status(FAR struct spi_dev_s *dev, uint32_t devid);
|
||||
|
||||
#ifdef CONFIG_SPI_CMDDATA
|
||||
int lpc54_spi5_cmddata(FAR struct spi_dev_s *dev, uint32_t devid, bool cmd);
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_LPC54_SPI6_MASTER
|
||||
void lpc54_spi6_select(FAR struct spi_dev_s *dev, uint32_t devid, bool selected);
|
||||
uint8_t lpc54_spi6_status(FAR struct spi_dev_s *dev, uint32_t devid);
|
||||
|
||||
#ifdef CONFIG_SPI_CMDDATA
|
||||
int lpc54_spi6_cmddata(FAR struct spi_dev_s *dev, uint32_t devid, bool cmd);
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_LPC54_SPI7_MASTER
|
||||
void lpc54_spi7_select(FAR struct spi_dev_s *dev, uint32_t devid, bool selected);
|
||||
uint8_t lpc54_spi7_status(FAR struct spi_dev_s *dev, uint32_t devid);
|
||||
|
||||
#ifdef CONFIG_SPI_CMDDATA
|
||||
int lpc54_spi7_cmddata(FAR struct spi_dev_s *dev, uint32_t devid, bool cmd);
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_LPC54_SPI8_MASTER
|
||||
void lpc54_spi8_select(FAR struct spi_dev_s *dev, uint32_t devid, bool selected);
|
||||
uint8_t lpc54_spi8_status(FAR struct spi_dev_s *dev, uint32_t devid);
|
||||
|
||||
#ifdef CONFIG_SPI_CMDDATA
|
||||
int lpc54_spi8_cmddata(FAR struct spi_dev_s *dev, uint32_t devid, bool cmd);
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_LPC54_SPI9_MASTER
|
||||
void lpc54_spi9_select(FAR struct spi_dev_s *dev, uint32_t devid, bool selected);
|
||||
uint8_t lpc54_spi9_status(FAR struct spi_dev_s *dev, uint32_t devid);
|
||||
|
||||
#ifdef CONFIG_SPI_CMDDATA
|
||||
int lpc54_spi9_cmddata(FAR struct spi_dev_s *dev, uint32_t devid, bool cmd);
|
||||
#endif
|
||||
#endif
|
||||
|
||||
/************************************************************************************
|
||||
* Name: spi_flush
|
||||
*
|
||||
* Description:
|
||||
* Flush and discard any words left in the RX fifo. This can be called from
|
||||
* spiselect after a device is deselected (if you worry about such things).
|
||||
*
|
||||
* Input Parameters:
|
||||
* dev - Device-specific state data
|
||||
*
|
||||
* Returned Value:
|
||||
* None
|
||||
*
|
||||
************************************************************************************/
|
||||
|
||||
void spi_flush(FAR struct spi_dev_s *dev);
|
||||
|
||||
/************************************************************************************
|
||||
* Name: lpc54_spi/spiregister
|
||||
* Name: lpc54_spiN_register
|
||||
*
|
||||
* Description:
|
||||
* If the board supports a card detect callback to inform the SPI-based MMC/SD
|
||||
@@ -167,8 +233,37 @@ void spi_flush(FAR struct spi_dev_s *dev);
|
||||
************************************************************************************/
|
||||
|
||||
#ifdef CONFIG_SPI_CALLBACK
|
||||
int lpc54_spiregister(FAR struct spi_dev_s *dev, spi_mediachange_t callback, void *arg);
|
||||
#ifdef CONFIG_LPC54_SPI0_MASTER
|
||||
int lpc54_spi0_register(FAR struct spi_dev_s *dev, spi_mediachange_t callback, void *arg);
|
||||
#endif
|
||||
#ifdef CONFIG_LPC54_SPI1_MASTER
|
||||
int lpc54_spi1_register(FAR struct spi_dev_s *dev, spi_mediachange_t callback, void *arg);
|
||||
#endif
|
||||
#ifdef CONFIG_LPC54_SPI2_MASTER
|
||||
int lpc54_spi2_register(FAR struct spi_dev_s *dev, spi_mediachange_t callback, void *arg);
|
||||
#endif
|
||||
#ifdef CONFIG_LPC54_SPI3_MASTER
|
||||
int lpc54_spi3_register(FAR struct spi_dev_s *dev, spi_mediachange_t callback, void *arg);
|
||||
#endif
|
||||
#ifdef CONFIG_LPC54_SPI4_MASTER
|
||||
int lpc54_spi4_register(FAR struct spi_dev_s *dev, spi_mediachange_t callback, void *arg);
|
||||
#endif
|
||||
#ifdef CONFIG_LPC54_SPI5_MASTER
|
||||
int lpc54_spi5_register(FAR struct spi_dev_s *dev, spi_mediachange_t callback, void *arg);
|
||||
#endif
|
||||
#ifdef CONFIG_LPC54_SPI6_MASTER
|
||||
int lpc54_spi6_register(FAR struct spi_dev_s *dev, spi_mediachange_t callback, void *arg);
|
||||
#endif
|
||||
#ifdef CONFIG_LPC54_SPI7_MASTER
|
||||
int lpc54_spi7_register(FAR struct spi_dev_s *dev, spi_mediachange_t callback, void *arg);
|
||||
#endif
|
||||
#ifdef CONFIG_LPC54_SPI8_MASTER
|
||||
int lpc54_spi8_register(FAR struct spi_dev_s *dev, spi_mediachange_t callback, void *arg);
|
||||
#endif
|
||||
#ifdef CONFIG_LPC54_SPI9_MASTER
|
||||
int lpc54_spi9_register(FAR struct spi_dev_s *dev, spi_mediachange_t callback, void *arg);
|
||||
#endif
|
||||
#endif /* CONFIG_SPI_CALLBACK */
|
||||
|
||||
#undef EXTERN
|
||||
#if defined(__cplusplus)
|
||||
|
||||
@@ -447,8 +447,8 @@
|
||||
# define HRTIM_TIMDT_DTPRSC_110 (6 << HRTIM_TIMDT_DTPRSC_SHIFT)
|
||||
# define HRTIM_TIMDT_DTPRSC_111 (7 << HRTIM_TIMDT_DTPRSC_SHIFT)
|
||||
#define HRTIM_TIMDT_DTRSLK (1 << 14) /* Bit 14: Deadtime Rising Sign Lock */
|
||||
#define HRTIM_TIMDT_DTRLK (1 << 14) /* Bit 15: Deadtime Rising Lock */
|
||||
#define HRTIM_TIMDT_DTF_SHIFT 0 /* Bits 16-24: Deadtime Falling Value */
|
||||
#define HRTIM_TIMDT_DTRLK (1 << 15) /* Bit 15: Deadtime Rising Lock */
|
||||
#define HRTIM_TIMDT_DTF_SHIFT 16 /* Bits 16-24: Deadtime Falling Value */
|
||||
#define HRTIM_TIMDT_DTF_MASK (0x1ff << HRTIM_TIMDT_DTF_SHIFT)
|
||||
#define HRTIM_TIMDT_SDTF (1 << 25) /* Bit 25: Sign Deadtime Falling Value */
|
||||
#define HRTIM_TIMDT_DTFSLK (1 << 30) /* Bit 30: Deadtime Falling Sign Lock */
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -208,10 +208,12 @@
|
||||
(hrtim)->hd_ops->cmp_update(hrtim, tim, index, cmp)
|
||||
#define HRTIM_PER_SET(hrtim, tim, per) \
|
||||
(hrtim)->hd_ops->per_update(hrtim, tim, per)
|
||||
#define HRTIM_OUTPUTS_ENABLE(hrtim, tim, state) \
|
||||
(hrtim)->hd_ops->outputs_enable(hrtim, tim, state)
|
||||
#define HRTIM_OUTPUTS_ENABLE(hrtim, tim, state) \
|
||||
(hrtim)->hd_ops->outputs_enable(hrtim, tim, state)
|
||||
#define HRTIM_OUTPUTS_ENABLE(hrtim, outputs, state) \
|
||||
(hrtim)->hd_ops->outputs_enable(hrtim, outputs, state)
|
||||
#define HRTIM_OUTPUT_SET_SET(hrtim, output, set) \
|
||||
(hrtim)->hd_ops->output_set_set(hrtim, output, set)
|
||||
#define HRTIM_OUTPUT_RST_SET(hrtim, output, rst) \
|
||||
(hrtim)->hd_ops->output_rst_set(hrtim, output, rst)
|
||||
#define HRTIM_BURST_CMP_SET(hrtim, cmp) \
|
||||
(hrtim)->hd_ops->burst_cmp_set(hrtim, cmp)
|
||||
#define HRTIM_BURST_PER_SET(hrtim, per) \
|
||||
@@ -220,6 +222,8 @@
|
||||
(hrtim)->hd_ops->burst_pre_set(hrtim, pre)
|
||||
#define HRTIM_BURST_ENABLE(hrtim, state) \
|
||||
(hrtim)->hd_ops->burst_enable(hrtim, state)
|
||||
#define HRTIM_DEADTIME_UPDATE(hrtim, tim, dt, val) \
|
||||
(hrtim)->hd_ops->deadtime_update(hrtim, tim, dt, val)
|
||||
|
||||
/************************************************************************************
|
||||
* Public Types
|
||||
@@ -229,23 +233,23 @@
|
||||
|
||||
enum stm32_hrtim_tim_e
|
||||
{
|
||||
HRTIM_TIMER_MASTER = 0,
|
||||
HRTIM_TIMER_MASTER = (1<<0),
|
||||
#ifdef CONFIG_STM32_HRTIM_TIMA
|
||||
HRTIM_TIMER_TIMA = 1,
|
||||
HRTIM_TIMER_TIMA = (1<<1),
|
||||
#endif
|
||||
#ifdef CONFIG_STM32_HRTIM_TIMB
|
||||
HRTIM_TIMER_TIMB = 2,
|
||||
HRTIM_TIMER_TIMB = (1<<2),
|
||||
#endif
|
||||
#ifdef CONFIG_STM32_HRTIM_TIMC
|
||||
HRTIM_TIMER_TIMC = 3,
|
||||
HRTIM_TIMER_TIMC = (1<<3),
|
||||
#endif
|
||||
#ifdef CONFIG_STM32_HRTIM_TIMD
|
||||
HRTIM_TIMER_TIMD = 4,
|
||||
HRTIM_TIMER_TIMD = (1<<4),
|
||||
#endif
|
||||
#ifdef CONFIG_STM32_HRTIM_TIME
|
||||
HRTIM_TIMER_TIME = 5,
|
||||
HRTIM_TIMER_TIME = (1<<5),
|
||||
#endif
|
||||
HRTIM_TIMER_COMMON = 6
|
||||
HRTIM_TIMER_COMMON = (1<<6)
|
||||
};
|
||||
|
||||
/* Source which can force the Tx1/Tx2 output to its inactive state */
|
||||
@@ -571,7 +575,7 @@ enum stm32_outputs_e
|
||||
enum stm32_hrtim_deadtime_sign_e
|
||||
{
|
||||
HRTIM_DT_SIGN_POSITIVE = 0,
|
||||
HRTIM_DT_DIGN_NEGATIVE = 1
|
||||
HRTIM_DT_SIGN_NEGATIVE = 1
|
||||
};
|
||||
|
||||
/* HRTIM Deadtime types */
|
||||
@@ -973,6 +977,10 @@ struct stm32_hrtim_ops_s
|
||||
#ifdef CONFIG_STM32_HRTIM_PWM
|
||||
int (*outputs_enable)(FAR struct hrtim_dev_s *dev, uint16_t outputs,
|
||||
bool state);
|
||||
int (*output_set_set)(FAR struct hrtim_dev_s *dev, uint16_t output,
|
||||
uint32_t set);
|
||||
int (*output_rst_set)(FAR struct hrtim_dev_s *dev, uint16_t output,
|
||||
uint32_t rst);
|
||||
#endif
|
||||
#ifdef CONFIG_STM32_HRTIM_BURST
|
||||
int (*burst_enable)(FAR struct hrtim_dev_s *dev, bool state);
|
||||
@@ -988,8 +996,10 @@ struct stm32_hrtim_ops_s
|
||||
uint8_t chan, bool state);
|
||||
#endif
|
||||
#ifdef CONFIG_STM32_HRTIM_DEADTIME
|
||||
int (*deadtime_update)(FAR struct hrtim_dev_s *dev, uint8_t dt, uint16_t value);
|
||||
uint16_t (*deadtime_get)(FAR struct hrtim_dev_s *dev, uint8_t dt);
|
||||
int (*deadtime_update)(FAR struct hrtim_dev_s *dev, uint8_t timer,
|
||||
uint8_t dt, uint16_t value);
|
||||
uint16_t (*deadtime_get)(FAR struct hrtim_dev_s *dev, uint8_t timer,
|
||||
uint8_t dt);
|
||||
#endif
|
||||
#ifdef CONFIG_STM32_HRTIM_CAPTURE
|
||||
uint16_t (*capture_get)(FAR struct hrtim_dev_s *dev, uint8_t timer,
|
||||
|
||||
@@ -1430,6 +1430,7 @@ config STM32F7_SDMMC1
|
||||
select ARCH_HAVE_SDIO
|
||||
select ARCH_HAVE_SDIOWAIT_WRCOMPLETE
|
||||
select SDIO_PREFLIGHT
|
||||
select SDIO_BLOCKSETUP
|
||||
|
||||
config STM32F7_SDMMC2
|
||||
bool "SDMMC2"
|
||||
@@ -1439,6 +1440,7 @@ config STM32F7_SDMMC2
|
||||
select ARCH_HAVE_SDIO
|
||||
select ARCH_HAVE_SDIOWAIT_WRCOMPLETE
|
||||
select SDIO_PREFLIGHT
|
||||
select SDIO_BLOCKSETUP
|
||||
|
||||
config STM32F7_SPDIFRX
|
||||
bool "SPDIFRX"
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
/****************************************************************************
|
||||
* arch/arm/src/stm32f7/stm32_sdmmc.c
|
||||
*
|
||||
* Copyright (C) 2009, 2011-2017 Gregory Nutt. All rights reserved.
|
||||
* Copyright (C) 2009, 2011-2018 Gregory Nutt. All rights reserved.
|
||||
* Authors: Gregory Nutt <gnutt@nuttx.org>
|
||||
* David Sidrane <david_s5@nscdg.com>
|
||||
*
|
||||
@@ -388,6 +388,10 @@ struct stm32_dev_s
|
||||
bool dmamode; /* true: DMA mode transfer */
|
||||
DMA_HANDLE dma; /* Handle for DMA channel */
|
||||
#endif
|
||||
|
||||
/* Misc */
|
||||
|
||||
uint32_t blocksize; /* Current block size */
|
||||
};
|
||||
|
||||
/* Register logging support */
|
||||
@@ -421,8 +425,8 @@ struct stm32_sampleregs_s
|
||||
|
||||
/* Low-level helpers ********************************************************/
|
||||
|
||||
static inline void sdmmc_putreg32(struct stm32_dev_s *priv, uint32_t value,\
|
||||
int offset);
|
||||
static inline void sdmmc_putreg32(struct stm32_dev_s *priv, uint32_t value,
|
||||
int offset);
|
||||
static inline uint32_t sdmmc_getreg32(struct stm32_dev_s *priv, int offset);
|
||||
static void stm32_takesem(struct stm32_dev_s *priv);
|
||||
#define stm32_givesem(priv) (nxsem_post(&priv->waitsem))
|
||||
@@ -438,7 +442,7 @@ static inline uint32_t stm32_getpwrctrl(struct stm32_dev_s *priv);
|
||||
#ifdef CONFIG_STM32F7_SDMMC_XFRDEBUG
|
||||
static void stm32_sampleinit(void);
|
||||
static void stm32_sdiosample(struct stm32_dev_s *priv,
|
||||
struct stm32_sdioregs_s *regs);
|
||||
struct stm32_sdioregs_s *regs);
|
||||
static void stm32_sample(struct stm32_dev_s *priv, int index);
|
||||
static void stm32_sdiodump(struct stm32_sdioregs_s *regs, const char *msg);
|
||||
static void stm32_dumpsample(struct stm32_dev_s *priv,
|
||||
@@ -458,13 +462,15 @@ static void stm32_dmacallback(DMA_HANDLE handle, uint8_t status, void *arg);
|
||||
|
||||
static uint8_t stm32_log2(uint16_t value);
|
||||
static void stm32_dataconfig(struct stm32_dev_s *priv, uint32_t timeout,
|
||||
uint32_t dlen, uint32_t dctrl);
|
||||
uint32_t dlen, uint32_t dctrl);
|
||||
static void stm32_datadisable(struct stm32_dev_s *priv);
|
||||
static void stm32_sendfifo(struct stm32_dev_s *priv);
|
||||
static void stm32_recvfifo(struct stm32_dev_s *priv);
|
||||
static void stm32_eventtimeout(int argc, uint32_t arg);
|
||||
static void stm32_endwait(struct stm32_dev_s *priv, sdio_eventset_t wkupevent);
|
||||
static void stm32_endtransfer(struct stm32_dev_s *priv, sdio_eventset_t wkupevent);
|
||||
static void stm32_endwait(struct stm32_dev_s *priv,
|
||||
sdio_eventset_t wkupevent);
|
||||
static void stm32_endtransfer(struct stm32_dev_s *priv,
|
||||
sdio_eventset_t wkupevent);
|
||||
|
||||
/* Interrupt Handling *******************************************************/
|
||||
|
||||
@@ -495,6 +501,8 @@ static int stm32_attach(FAR struct sdio_dev_s *dev);
|
||||
|
||||
static int stm32_sendcmd(FAR struct sdio_dev_s *dev, uint32_t cmd,
|
||||
uint32_t arg);
|
||||
static void stm32_blocksetup(FAR struct sdio_dev_s *dev,
|
||||
unsigned int blocksize, unsigned int nblocks);
|
||||
static int stm32_recvsetup(FAR struct sdio_dev_s *dev, FAR uint8_t *buffer,
|
||||
size_t nbytes);
|
||||
static int stm32_sendsetup(FAR struct sdio_dev_s *dev,
|
||||
@@ -543,6 +551,7 @@ static void stm32_default(struct stm32_dev_s *priv);
|
||||
/****************************************************************************
|
||||
* Private Data
|
||||
****************************************************************************/
|
||||
|
||||
#ifdef CONFIG_STM32F7_SDMMC1
|
||||
struct stm32_dev_s g_sdmmcdev1 =
|
||||
{
|
||||
@@ -558,9 +567,7 @@ struct stm32_dev_s g_sdmmcdev1 =
|
||||
.clock = stm32_clock,
|
||||
.attach = stm32_attach,
|
||||
.sendcmd = stm32_sendcmd,
|
||||
#ifdef CONFIG_SDIO_BLOCKSETUP
|
||||
.blocksetup = stm32_blocksetup, /* Not implemented yet */
|
||||
#endif
|
||||
.blocksetup = stm32_blocksetup,
|
||||
.recvsetup = stm32_recvsetup,
|
||||
.sendsetup = stm32_sendsetup,
|
||||
.cancel = stm32_cancel,
|
||||
@@ -620,9 +627,7 @@ struct stm32_dev_s g_sdmmcdev2 =
|
||||
.clock = stm32_clock,
|
||||
.attach = stm32_attach,
|
||||
.sendcmd = stm32_sendcmd,
|
||||
#ifdef CONFIG_SDIO_BLOCKSETUP
|
||||
.blocksetup = stm32_blocksetup, /* Not implemented yet */
|
||||
#endif
|
||||
.blocksetup = stm32_blocksetup,
|
||||
.recvsetup = stm32_recvsetup,
|
||||
.sendsetup = stm32_sendsetup,
|
||||
.cancel = stm32_cancel,
|
||||
@@ -1433,6 +1438,19 @@ static void stm32_endwait(struct stm32_dev_s *priv, sdio_eventset_t wkupevent)
|
||||
static void stm32_endtransfer(struct stm32_dev_s *priv,
|
||||
sdio_eventset_t wkupevent)
|
||||
{
|
||||
/* Disable the DTEN bit (it should not be left set after previous read when
|
||||
* the next write initialization starts).
|
||||
*/
|
||||
|
||||
#if 1
|
||||
sdmmc_putreg32(priv,
|
||||
sdmmc_getreg32(priv, STM32_SDMMC_DCTRL_OFFSET) &
|
||||
~STM32_SDMMC_DCTRL_DTEN,
|
||||
STM32_SDMMC_DCTRL_OFFSET);
|
||||
#else
|
||||
stm32_datadisable(priv);
|
||||
#endif
|
||||
|
||||
/* Disable all transfer related interrupts */
|
||||
|
||||
stm32_configxfrints(priv, 0);
|
||||
@@ -2057,6 +2075,30 @@ static int stm32_sendcmd(FAR struct sdio_dev_s *dev, uint32_t cmd, uint32_t arg)
|
||||
return OK;
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Name: stm32_blocksetup
|
||||
*
|
||||
* Description:
|
||||
* Configure block size and the number of blocks for next transfer.
|
||||
*
|
||||
* Input Parameters:
|
||||
* dev - An instance of the SDIO device interface.
|
||||
* blocksize - The selected block size.
|
||||
* nblocks - The number of blocks to transfer.
|
||||
*
|
||||
* Returned Value:
|
||||
* None
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
static void stm32_blocksetup(FAR struct sdio_dev_s *dev, unsigned int blocksize,
|
||||
unsigned int nblocks)
|
||||
{
|
||||
struct stm32_dev_s *priv = (struct stm32_dev_s *)dev;
|
||||
|
||||
priv->blocksize = blocksize;
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Name: stm32_recvsetup
|
||||
*
|
||||
@@ -2103,7 +2145,7 @@ static int stm32_recvsetup(FAR struct sdio_dev_s *dev, FAR uint8_t *buffer,
|
||||
|
||||
/* Then set up the SDIO data path */
|
||||
|
||||
dblocksize = stm32_log2(nbytes) << STM32_SDMMC_DCTRL_DBLOCKSIZE_SHIFT;
|
||||
dblocksize = stm32_log2(priv->blocksize) << STM32_SDMMC_DCTRL_DBLOCKSIZE_SHIFT;
|
||||
stm32_dataconfig(priv, SDMMC_DTIMER_DATATIMEOUT, nbytes, dblocksize |
|
||||
STM32_SDMMC_DCTRL_DTDIR);
|
||||
|
||||
@@ -2158,7 +2200,7 @@ static int stm32_sendsetup(FAR struct sdio_dev_s *dev, FAR const
|
||||
|
||||
/* Then set up the SDIO data path */
|
||||
|
||||
dblocksize = stm32_log2(nbytes) << STM32_SDMMC_DCTRL_DBLOCKSIZE_SHIFT;
|
||||
dblocksize = stm32_log2(priv->blocksize) << STM32_SDMMC_DCTRL_DBLOCKSIZE_SHIFT;
|
||||
stm32_dataconfig(priv, SDMMC_DTIMER_DATATIMEOUT, nbytes, dblocksize);
|
||||
|
||||
/* Enable TX interrupts */
|
||||
@@ -2882,7 +2924,7 @@ static int stm32_dmarecvsetup(FAR struct sdio_dev_s *dev, FAR uint8_t *buffer,
|
||||
|
||||
/* Then set up the SDIO data path */
|
||||
|
||||
dblocksize = stm32_log2(buflen) << STM32_SDMMC_DCTRL_DBLOCKSIZE_SHIFT;
|
||||
dblocksize = stm32_log2(priv->blocksize) << STM32_SDMMC_DCTRL_DBLOCKSIZE_SHIFT;
|
||||
stm32_dataconfig(priv, SDMMC_DTIMER_DATATIMEOUT, buflen, dblocksize |
|
||||
STM32_SDMMC_DCTRL_DTDIR);
|
||||
|
||||
@@ -2975,7 +3017,7 @@ static int stm32_dmasendsetup(FAR struct sdio_dev_s *dev,
|
||||
|
||||
/* Then set up the SDIO data path */
|
||||
|
||||
dblocksize = stm32_log2(buflen) << STM32_SDMMC_DCTRL_DBLOCKSIZE_SHIFT;
|
||||
dblocksize = stm32_log2(priv->blocksize) << STM32_SDMMC_DCTRL_DBLOCKSIZE_SHIFT;
|
||||
stm32_dataconfig(priv, SDMMC_DTIMER_DATATIMEOUT, buflen, dblocksize);
|
||||
|
||||
/* Configure the TX DMA */
|
||||
|
||||
@@ -24,6 +24,12 @@ README
|
||||
device functionality
|
||||
- 10/100Mbps Ethernet (RJ45 connector)
|
||||
|
||||
CONTENTS
|
||||
========
|
||||
|
||||
- STATUS
|
||||
- Configurations
|
||||
|
||||
STATUS
|
||||
======
|
||||
|
||||
@@ -86,20 +92,13 @@ STATUS
|
||||
of this writing. Also added the netnsh configuration will, eventually,
|
||||
be used to test the Ethernet driver.
|
||||
2018-01-01: There Ethernet driver appears to be fully functional although
|
||||
more testing is certainly needed. I believe that there is a memory
|
||||
corruption issue in the current configuration that cause problems
|
||||
occasionally. For example, after a longer Telnet session, I sometimes
|
||||
see the following DEBUGASSERT after exiting the session from the host:
|
||||
more testing is certainly needed.
|
||||
2018-01-14: The basic SPI driver is code complete but still untested. It
|
||||
is "basic" in the sense that it supports only polled mode (no DMA).
|
||||
|
||||
up_assert: Assertion failed at file:mm_heap/mm_free.c line: 129
|
||||
|
||||
which is a clear indication heap corruption. Increasing the size of some
|
||||
stacks might correct this problem, but I have not yet experimented with
|
||||
that. I have not seen the problem in any other context.
|
||||
|
||||
There is still no support for the Accelerometer, SPIFI, or USB. There is a
|
||||
complete but not-yet-functional SD card. There is a partial SPI driver,
|
||||
but no on-board SPI devices to test it.
|
||||
There is still no support for the Accelerometer, SPIFI, or USB. There are
|
||||
complete but not-yet-functional SD card and SPI drivers. There are no
|
||||
on-board devices to support SPI testing.
|
||||
|
||||
Configurations
|
||||
==============
|
||||
|
||||
@@ -64,7 +64,7 @@ CONFIG_PREALLOC_MQ_MSGS=4
|
||||
CONFIG_PREALLOC_TIMERS=4
|
||||
CONFIG_PREALLOC_WDOGS=4
|
||||
CONFIG_RAM_SIZE=163840
|
||||
CONFIG_RAM_START=0x10000000
|
||||
CONFIG_RAM_START=0x20000000
|
||||
CONFIG_RAW_BINARY=y
|
||||
CONFIG_RR_INTERVAL=200
|
||||
CONFIG_SCHED_HPWORK=y
|
||||
|
||||
@@ -306,7 +306,7 @@
|
||||
/* Pin Disambiguation *******************************************************/
|
||||
/* Flexcomm0/USART0
|
||||
*
|
||||
* USART0 connects to the serial bridge on LPC4322JET100 and is typlical used
|
||||
* USART0 connects to the serial bridge on LPC4322JET100 and is typically used
|
||||
* for the serial console.
|
||||
*
|
||||
* BRIDGE_UART_RXD -> P0_29-ISP_FC0_RXD -> P0.29 GPIO_FC0_RXD_SDA_MOSI_2
|
||||
@@ -316,6 +316,18 @@
|
||||
#define GPIO_USART0_RXD (GPIO_FC0_RXD_SDA_MOSI_2 | GPIO_FILTER_OFF)
|
||||
#define GPIO_USART0_TXD (GPIO_FC0_TXD_SCL_MISO_2 | GPIO_FILTER_OFF)
|
||||
|
||||
/* An alternative for the serial console is a Arduino Uno compatible serial
|
||||
* shield:
|
||||
*
|
||||
* Arduino Uno J13 Board Signal
|
||||
* ----------- ------ ----------------
|
||||
* D0 RX Pin 15 P3_26-FC4_RXD
|
||||
* D1 TX Pin 13 P3_27-FC4_TXD
|
||||
*/
|
||||
|
||||
#define GPIO_USART4_RXD (GPIO_FC4_RXD_SDA_MOSI_2 | GPIO_FILTER_OFF)
|
||||
#define GPIO_USART4_TXD (GPIO_FC4_TXD_SCL_MISO_2 | GPIO_FILTER_OFF)
|
||||
|
||||
/* Flexcomm2/I2C
|
||||
*
|
||||
* For I2C:
|
||||
@@ -329,8 +341,14 @@
|
||||
* Type I pins need for high speed I2C need:
|
||||
* GPIO_FILTER_OFF + GPIO_I2C_FILTER_OFF + GPIO_I2CDRIVE_HIGH
|
||||
*
|
||||
* The touchscreen controller is on I2C2: SCL P3.24, SDA P3.23. These are
|
||||
* both Type D/I pins.
|
||||
* There are several on-board devices using I2C2:
|
||||
*
|
||||
* Codec I2C address: 0x1a
|
||||
* Accel I2C address: 0x1d
|
||||
* Touch panel I2C address: 0x38
|
||||
*
|
||||
* In addition, these same I2C2 pins are brought out through D14 and D15 of
|
||||
* the Arduino Uno connector.
|
||||
*/
|
||||
|
||||
#if defined(CONFIG_LPC54_I2C_FAST)
|
||||
@@ -351,6 +369,35 @@
|
||||
GPIO_FILTER_OFF | _I2CFILTER | \
|
||||
_I2CDRIVE)
|
||||
|
||||
/* Flexcomm2/SPI
|
||||
*
|
||||
* There are no SPI devices on board the LPCXpresso-LPC54628. SPI is
|
||||
* available on the Arduino Uno compatible connector, however:
|
||||
*
|
||||
* Arduino Uno J9 Board Signal Pin Type
|
||||
* ----------- ------ ---------------- ---------
|
||||
* D10 SSEL Pin 15 P3_20-FC9_SCK Type D
|
||||
* D11 MOSI Pin 13 P3_21-FC9_MOSI Type A
|
||||
* D12 MISO Pin 11 P3_22-FC9_MISO Type A
|
||||
* D13 SCK Pin 9 P3_30-FC9_SSELn0 Type D
|
||||
*
|
||||
* For SPI:
|
||||
* Type A & D pins need:
|
||||
* GPIO_PUSHPULL (on outputs) + GPIO_SLEW_STANDARD (Type D) +
|
||||
* GPIO_FILTER_OFF
|
||||
* GPIO_SLEW_FAST is optional for high data rates (Type D).
|
||||
* Type I need:
|
||||
* GPIO_I2C_FILTER_OFF + GPIO_I2CDRIVE_LOW + GPIO_FILTER_OFF +
|
||||
* GPIO_I2CSLEW_GPIO
|
||||
*/
|
||||
|
||||
#define GPIO_FC9_RXD_SDA_MOSI (GPIO_FC9_RXD_SDA_MOSI_1 | \
|
||||
GPIO_PUSHPULL | GPIO_FILTER_OFF)
|
||||
#define GPIO_FC9_TXD_SCL_MISO (GPIO_FC9_TXD_SCL_MISO_1 | \
|
||||
GPIO_FILTER_OFF)
|
||||
#define GPIO_FC9_SCK (GPIO_FC9_SCK_1 | GPIO_PUSHPULL | \
|
||||
GPIO_SLEW_STANDARD | GPIO_FILTER_OFF)
|
||||
|
||||
/* SD/MMC
|
||||
*
|
||||
* P2_10-SD_CDn
|
||||
@@ -412,7 +459,6 @@
|
||||
* feature.
|
||||
*/
|
||||
|
||||
|
||||
#define GPIO_ENET_MDIO GPIO_ENET_MDIO_2 /* P4.16 */
|
||||
#define GPIO_ENET_MDC GPIO_ENET_MDC_2 /* P4.15 */
|
||||
|
||||
|
||||
@@ -55,7 +55,7 @@ CONFIG_PREALLOC_MQ_MSGS=4
|
||||
CONFIG_PREALLOC_TIMERS=4
|
||||
CONFIG_PREALLOC_WDOGS=4
|
||||
CONFIG_RAM_SIZE=163840
|
||||
CONFIG_RAM_START=0x10000000
|
||||
CONFIG_RAM_START=0x20000000
|
||||
CONFIG_RAW_BINARY=y
|
||||
CONFIG_RR_INTERVAL=200
|
||||
CONFIG_SCHED_HPWORK=y
|
||||
|
||||
@@ -42,7 +42,7 @@ CONFIG_PREALLOC_MQ_MSGS=4
|
||||
CONFIG_PREALLOC_TIMERS=4
|
||||
CONFIG_PREALLOC_WDOGS=4
|
||||
CONFIG_RAM_SIZE=163840
|
||||
CONFIG_RAM_START=0x10000000
|
||||
CONFIG_RAM_START=0x20000000
|
||||
CONFIG_RAW_BINARY=y
|
||||
CONFIG_RR_INTERVAL=200
|
||||
CONFIG_RTC_ALARM=y
|
||||
|
||||
@@ -87,7 +87,7 @@ CONFIG_NXWM=y
|
||||
CONFIG_PREALLOC_TIMERS=4
|
||||
CONFIG_PREALLOC_WDOGS=8
|
||||
CONFIG_RAM_SIZE=163840
|
||||
CONFIG_RAM_START=0x10000000
|
||||
CONFIG_RAM_START=0x20000000
|
||||
CONFIG_RAW_BINARY=y
|
||||
CONFIG_RR_INTERVAL=200
|
||||
CONFIG_SCHED_HPWORK=y
|
||||
|
||||
@@ -33,7 +33,7 @@
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
/* The LPC54628 on the LPCXPressio has 512Kb of FLASH at address 0x0000:0000.
|
||||
/* The LPC54628 on the LPCXPresso has 512Kb of FLASH at address 0x0000:0000.
|
||||
* The Main SRAM is comprised of up to a total 160 KB of contiguous, on-chip
|
||||
* static RAM memory beginning at address 0x2000:0000 (this is in addition
|
||||
* to SRAMX aso the total device SRAM can be up to 200 KB).
|
||||
|
||||
@@ -181,9 +181,9 @@ void board_userled_initialize(void)
|
||||
|
||||
void board_userled(int led, bool ledon)
|
||||
{
|
||||
if (led == 1)
|
||||
if (led == BOARD_LD2)
|
||||
{
|
||||
stm32f0_gpiowrite(GPIO_LD2, ldeon);
|
||||
stm32f0_gpiowrite(GPIO_LD2, ledon);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -193,10 +193,7 @@ void board_userled(int led, bool ledon)
|
||||
|
||||
void board_userled_all(uint8_t ledset)
|
||||
{
|
||||
if (led == 1)
|
||||
{
|
||||
stm32f0_gpiowrite(GPIO_LD2, (ledset & BOARD_LD2_BIT) != 0);
|
||||
}
|
||||
stm32f0_gpiowrite(GPIO_LD2, (ledset & BOARD_LD2_BIT) != 0);
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
|
||||
@@ -181,9 +181,9 @@ void board_userled_initialize(void)
|
||||
|
||||
void board_userled(int led, bool ledon)
|
||||
{
|
||||
if (led == 1)
|
||||
if (led == BOARD_LD2)
|
||||
{
|
||||
stm32f0_gpiowrite(GPIO_LD2, ldeon);
|
||||
stm32f0_gpiowrite(GPIO_LD2, ledon);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -193,10 +193,7 @@ void board_userled(int led, bool ledon)
|
||||
|
||||
void board_userled_all(uint8_t ledset)
|
||||
{
|
||||
if (led == 1)
|
||||
{
|
||||
stm32f0_gpiowrite(GPIO_LD2, (ledset & BOARD_LD2_BIT) != 0);
|
||||
}
|
||||
stm32f0_gpiowrite(GPIO_LD2, (ledset & BOARD_LD2_BIT) != 0);
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
|
||||
@@ -181,9 +181,9 @@ void board_userled_initialize(void)
|
||||
|
||||
void board_userled(int led, bool ledon)
|
||||
{
|
||||
if (led == 1)
|
||||
if (led == BOARD_LD2)
|
||||
{
|
||||
stm32_gpiowrite(GPIO_LD2, ldeon);
|
||||
stm32_gpiowrite(GPIO_LD2, ledon);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -193,10 +193,7 @@ void board_userled(int led, bool ledon)
|
||||
|
||||
void board_userled_all(uint8_t ledset)
|
||||
{
|
||||
if (led == 1)
|
||||
{
|
||||
stm32_gpiowrite(GPIO_LD2, (ledset & BOARD_LD2_BIT) != 0);
|
||||
}
|
||||
stm32_gpiowrite(GPIO_LD2, (ledset & BOARD_LD2_BIT) != 0);
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
|
||||
@@ -181,7 +181,7 @@ void board_userled_initialize(void)
|
||||
|
||||
void board_userled(int led, bool ledon)
|
||||
{
|
||||
if (led == 1)
|
||||
if (led == BOARD_LD2)
|
||||
{
|
||||
stm32l4_gpiowrite(GPIO_LD2, ledon);
|
||||
}
|
||||
@@ -193,10 +193,7 @@ void board_userled(int led, bool ledon)
|
||||
|
||||
void board_userled_all(uint8_t ledset)
|
||||
{
|
||||
if (led == 1)
|
||||
{
|
||||
stm32l4_gpiowrite(GPIO_LD2, (ledset & BOARD_LD2_BIT) != 0);
|
||||
}
|
||||
stm32l4_gpiowrite(GPIO_LD2, (ledset & BOARD_LD2_BIT) != 0);
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
|
||||
@@ -181,9 +181,9 @@ void board_userled_initialize(void)
|
||||
|
||||
void board_userled(int led, bool ledon)
|
||||
{
|
||||
if (led == 1)
|
||||
if (led == BOARD_LD2)
|
||||
{
|
||||
stm32l4_gpiowrite(GPIO_LD2, ldeon);
|
||||
stm32l4_gpiowrite(GPIO_LD2, ledon);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -193,10 +193,7 @@ void board_userled(int led, bool ledon)
|
||||
|
||||
void board_userled_all(uint8_t ledset)
|
||||
{
|
||||
if (led == 1)
|
||||
{
|
||||
stm32l4_gpiowrite(GPIO_LD2, (ledset & BOARD_LD2_BIT) != 0);
|
||||
}
|
||||
stm32l4_gpiowrite(GPIO_LD2, (ledset & BOARD_LD2_BIT) != 0);
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
|
||||
@@ -172,7 +172,7 @@ void board_userled_initialize(void)
|
||||
{
|
||||
/* Configure LD2 GPIO for output */
|
||||
|
||||
stm32_configgpio(GPIO_LD2);
|
||||
stm32l4_configgpio(GPIO_LD2);
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
@@ -181,9 +181,9 @@ void board_userled_initialize(void)
|
||||
|
||||
void board_userled(int led, bool ledon)
|
||||
{
|
||||
if (led == 1)
|
||||
if (led == BOARD_LD2)
|
||||
{
|
||||
stm32_gpiowrite(GPIO_LD2, ldeon);
|
||||
stm32l4_gpiowrite(GPIO_LD2, ledon);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -193,10 +193,7 @@ void board_userled(int led, bool ledon)
|
||||
|
||||
void board_userled_all(uint8_t ledset)
|
||||
{
|
||||
if (led == 1)
|
||||
{
|
||||
stm32_gpiowrite(GPIO_LD2, (ledset & BOARD_LD2_BIT) != 0);
|
||||
}
|
||||
stm32l4_gpiowrite(GPIO_LD2, (ledset & BOARD_LD2_BIT) != 0);
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
|
||||
@@ -192,11 +192,11 @@ void board_userled(int led, bool ledon)
|
||||
switch (led)
|
||||
{
|
||||
case BOARD_LED_RED:
|
||||
stm32l4_gpiowrite(GPIO_LED_RED, ldeon);
|
||||
stm32l4_gpiowrite(GPIO_LED_RED, ledon);
|
||||
break;
|
||||
|
||||
case BOARD_LED_GRN:
|
||||
stm32l4_gpiowrite(GPIO_LED_GRN, ldeon);
|
||||
stm32l4_gpiowrite(GPIO_LED_GRN, ledon);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -440,7 +440,7 @@ int losetup(FAR const char *devname, FAR const char *filename,
|
||||
{
|
||||
/* If that fails, then try to open the device read-only */
|
||||
|
||||
fd = open(filename, O_RDWR);
|
||||
fd = open(filename, O_RDONLY);
|
||||
if (fd < 0)
|
||||
{
|
||||
ret = -get_errno();
|
||||
|
||||
+35
-10
@@ -1895,6 +1895,25 @@ static ssize_t mmcsd_writemultiple(FAR struct mmcsd_state_s *priv,
|
||||
}
|
||||
}
|
||||
|
||||
/* If Controller does not need DMA setup before the write then send CMD25
|
||||
* now.
|
||||
*/
|
||||
|
||||
if ((priv->caps & SDIO_CAPS_DMABEFOREWRITE) == 0)
|
||||
{
|
||||
/* Send CMD25, WRITE_MULTIPLE_BLOCK, and verify that good R1 status
|
||||
* is returned
|
||||
*/
|
||||
|
||||
mmcsd_sendcmdpoll(priv, MMCSD_CMD25, offset);
|
||||
ret = mmcsd_recvR1(priv, MMCSD_CMD25);
|
||||
if (ret != OK)
|
||||
{
|
||||
ferr("ERROR: mmcsd_recvR1 for CMD25 failed: %d\n", ret);
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
|
||||
/* Configure SDIO controller hardware for the write transfer */
|
||||
|
||||
SDIO_BLOCKSETUP(priv->dev, priv->blocksize, nblocks);
|
||||
@@ -1923,24 +1942,30 @@ static ssize_t mmcsd_writemultiple(FAR struct mmcsd_state_s *priv,
|
||||
|
||||
priv->wrbusy = true;
|
||||
|
||||
/* Send CMD25, WRITE_MULTIPLE_BLOCK, and verify that good R1 status
|
||||
* is returned
|
||||
*/
|
||||
/* If Controller needs DMA setup before write then only send CMD25 now. */
|
||||
|
||||
mmcsd_sendcmdpoll(priv, MMCSD_CMD25, offset);
|
||||
ret = mmcsd_recvR1(priv, MMCSD_CMD25);
|
||||
if (ret != OK)
|
||||
if ((priv->caps & SDIO_CAPS_DMABEFOREWRITE) != 0)
|
||||
{
|
||||
ferr("ERROR: mmcsd_recvR1 for CMD25 failed: %d\n", ret);
|
||||
return ret;
|
||||
/* Send CMD25, WRITE_MULTIPLE_BLOCK, and verify that good R1 status
|
||||
* is returned
|
||||
*/
|
||||
|
||||
mmcsd_sendcmdpoll(priv, MMCSD_CMD25, offset);
|
||||
ret = mmcsd_recvR1(priv, MMCSD_CMD25);
|
||||
if (ret != OK)
|
||||
{
|
||||
ferr("ERROR: mmcsd_recvR1 for CMD25 failed: %d\n", ret);
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
|
||||
/* Wait for the transfer to complete */
|
||||
|
||||
ret = mmcsd_eventwait(priv, SDIOWAIT_TIMEOUT | SDIOWAIT_ERROR, nblocks * MMCSD_BLOCK_WDATADELAY);
|
||||
ret = mmcsd_eventwait(priv, SDIOWAIT_TIMEOUT | SDIOWAIT_ERROR,
|
||||
nblocks * MMCSD_BLOCK_WDATADELAY);
|
||||
if (ret != OK)
|
||||
{
|
||||
ferr("ERROR: CMD18 transfer failed: %d\n", ret);
|
||||
ferr("ERROR: CMD25 transfer failed: %d\n", ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
@@ -77,6 +77,7 @@
|
||||
****************************************************************************/
|
||||
|
||||
extern const struct procfs_operations proc_operations;
|
||||
extern const struct procfs_operations irq_operations;
|
||||
extern const struct procfs_operations cpuload_operations;
|
||||
extern const struct procfs_operations meminfo_operations;
|
||||
extern const struct procfs_operations module_operations;
|
||||
@@ -124,8 +125,12 @@ static const struct procfs_entry_s g_procfs_entries[] =
|
||||
{ "cpuload", &cpuload_operations, PROCFS_FILE_TYPE },
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_SCHED_IRQMONITOR
|
||||
{ "irqs", &irq_operations, PROCFS_FILE_TYPE },
|
||||
#endif
|
||||
|
||||
#ifndef CONFIG_FS_PROCFS_EXCLUDE_MEMINFO
|
||||
{ "meminfo", &meminfo_operations, PROCFS_FILE_TYPE },
|
||||
{ "meminfo", &meminfo_operations, PROCFS_FILE_TYPE },
|
||||
#endif
|
||||
|
||||
#if defined(CONFIG_MODULE) && !defined(CONFIG_FS_PROCFS_EXCLUDE_MODULE)
|
||||
@@ -133,15 +138,15 @@ static const struct procfs_entry_s g_procfs_entries[] =
|
||||
#endif
|
||||
|
||||
#ifndef CONFIG_FS_PROCFS_EXCLUDE_BLOCKS
|
||||
{ "fs/blocks", &mount_procfsoperations, PROCFS_FILE_TYPE },
|
||||
{ "fs/blocks", &mount_procfsoperations, PROCFS_FILE_TYPE },
|
||||
#endif
|
||||
|
||||
#ifndef CONFIG_FS_PROCFS_EXCLUDE_MOUNT
|
||||
{ "fs/mount", &mount_procfsoperations, PROCFS_FILE_TYPE },
|
||||
{ "fs/mount", &mount_procfsoperations, PROCFS_FILE_TYPE },
|
||||
#endif
|
||||
|
||||
#ifndef CONFIG_FS_PROCFS_EXCLUDE_USAGE
|
||||
{ "fs/usage", &mount_procfsoperations, PROCFS_FILE_TYPE },
|
||||
{ "fs/usage", &mount_procfsoperations, PROCFS_FILE_TYPE },
|
||||
#endif
|
||||
|
||||
#if defined(CONFIG_FS_SMARTFS) && !defined(CONFIG_FS_PROCFS_EXCLUDE_SMARTFS)
|
||||
|
||||
@@ -124,7 +124,7 @@ size_t procfs_memcpy(FAR const char *src, size_t srclen,
|
||||
/* Handle the remaining offset */
|
||||
|
||||
srclen -= lnoffset;
|
||||
dest += lnoffset;
|
||||
src += lnoffset;
|
||||
*offset = 0;
|
||||
|
||||
/* Copy the line into the user destination buffer */
|
||||
|
||||
@@ -2072,7 +2072,7 @@ int smartfs_extendfile(FAR struct smartfs_mountpt_s *fs,
|
||||
ret = OK;
|
||||
|
||||
errout_with_buffer:
|
||||
#ifdef CONFIG_SMARTFS_USE_SECTOR_BUFFER
|
||||
#ifndef CONFIG_SMARTFS_USE_SECTOR_BUFFER
|
||||
/* Release the allocated buffer */
|
||||
|
||||
kmm_free(buffer);
|
||||
|
||||
+2
-2
@@ -114,8 +114,8 @@ typedef uint32_t irq_mapped_t;
|
||||
|
||||
/* This struct defines the form of an interrupt service routine */
|
||||
|
||||
typedef int (*xcpt_t)(int irq, FAR void *context, FAR void *arg);
|
||||
#endif
|
||||
typedef CODE int (*xcpt_t)(int irq, FAR void *context, FAR void *arg);
|
||||
#endif /* __ASSEMBLY__ */
|
||||
|
||||
/* Now include architecture-specific types */
|
||||
|
||||
|
||||
@@ -70,8 +70,8 @@
|
||||
* Name: SPI_LOCK
|
||||
*
|
||||
* Description:
|
||||
* On SPI busses where there are multiple devices, it will be necessary to
|
||||
* lock SPI to have exclusive access to the busses for a sequence of
|
||||
* On SPI buses where there are multiple devices, it will be necessary to
|
||||
* lock SPI to have exclusive access to the buses for a sequence of
|
||||
* transfers. The bus should be locked before the chip is selected. After
|
||||
* locking the SPI bus, the caller should then also call the setfrequency,
|
||||
* setbits, and setmode methods to make sure that the SPI is properly
|
||||
|
||||
@@ -623,6 +623,15 @@ endmenu # Pthread Options
|
||||
|
||||
menu "Performance Monitoring"
|
||||
|
||||
config SCHED_IRQMONITOR
|
||||
bool "Enable IRQ monitoring"
|
||||
default n
|
||||
depends on FS_PROCFS
|
||||
---help---
|
||||
Enabling counting of interrupts from all interrupt sources. These
|
||||
counts will be available in the mounted procfs file systems at the
|
||||
top-level file, "irqs".
|
||||
|
||||
config SCHED_CPULOAD
|
||||
bool "Enable CPU load monitoring"
|
||||
default n
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
/****************************************************************************
|
||||
* sched/clock/clock_systimer.c
|
||||
*
|
||||
* Copyright (C) 2011, 2014-2016 Gregory Nutt. All rights reserved.
|
||||
* Copyright (C) 2011, 2014-2016, 2018 Gregory Nutt. All rights reserved.
|
||||
* Author: Gregory Nutt <gnutt@nuttx.org>
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
@@ -50,10 +50,15 @@
|
||||
/****************************************************************************
|
||||
* Pre-processor Definitions
|
||||
****************************************************************************/
|
||||
|
||||
/* See nuttx/clock.h */
|
||||
|
||||
#undef clock_systimer
|
||||
|
||||
/* 32-bit mask for 64-bit timer values */
|
||||
|
||||
#define TIMER_MASK32 0x00000000ffffffff
|
||||
|
||||
/****************************************************************************
|
||||
* Public Functions
|
||||
****************************************************************************/
|
||||
@@ -109,20 +114,34 @@ systime_t clock_systimer(void)
|
||||
/* Convert to a 64- then a 32-bit value */
|
||||
|
||||
tmp = USEC2TICK(1000000 * (uint64_t)ts.tv_sec + (uint64_t)ts.tv_nsec / 1000);
|
||||
return (systime_t)(tmp & 0x00000000ffffffff);
|
||||
return (systime_t)(tmp & TIMER_MASK32);
|
||||
|
||||
# endif /* CONFIG_SYSTEM_TIME64 */
|
||||
#else /* CONFIG_SCHED_TICKLESS */
|
||||
# ifdef CONFIG_SYSTEM_TIME64
|
||||
|
||||
irqstate_t flags;
|
||||
systime_t sample;
|
||||
systime_t verify;
|
||||
|
||||
/* 64-bit accesses are not atomic on most architectures. */
|
||||
/* 64-bit accesses are not atomic on most architectures. The following
|
||||
* loop samples the 64-bit timer twice and loops in the rare event that
|
||||
* there was 32-bit rollover between samples.
|
||||
*
|
||||
* If there is no 32-bit rollover, then:
|
||||
*
|
||||
* - The MS 32-bits of each sample will be the same, and
|
||||
* - The LS 32-bits of the second sample will be greater than or equal to
|
||||
* the LS 32-bits for the first sample.
|
||||
*/
|
||||
|
||||
do
|
||||
{
|
||||
verify = g_system_timer;
|
||||
sample = g_system_timer;
|
||||
}
|
||||
while ((sample & TIMER_MASK32) < (verify & TIMER_MASK32) ||
|
||||
(sample & ~TIMER_MASK32) != (verify & ~TIMER_MASK32));
|
||||
|
||||
flags = enter_critical_section();
|
||||
sample = g_system_timer;
|
||||
leave_critical_section(flags);
|
||||
return sample;
|
||||
|
||||
# else /* CONFIG_SYSTEM_TIME64 */
|
||||
|
||||
@@ -115,7 +115,7 @@ volatile dq_queue_t g_readytorun;
|
||||
* and
|
||||
* - Tasks/threads that have not been assigned to a CPU.
|
||||
*
|
||||
* Otherwise, the TCB will be reatined in an assigned task list,
|
||||
* Otherwise, the TCB will be retained in an assigned task list,
|
||||
* g_assignedtasks. As its name suggests, on 'g_assignedtasks queue for CPU
|
||||
* 'n' would contain only tasks/threads that are assigned to CPU 'n'. Tasks/
|
||||
* threads would be assigned a particular CPU by one of two mechanisms:
|
||||
@@ -187,7 +187,7 @@ volatile dq_queue_t g_waitingforfill;
|
||||
|
||||
volatile dq_queue_t g_inactivetasks;
|
||||
|
||||
/* These are lists of dayed memory deallocations that need to be handled
|
||||
/* These are lists of delayed memory deallocations that need to be handled
|
||||
* within the IDLE loop or worker thread. These deallocations get queued
|
||||
* by sched_kufree and sched_kfree() if the OS needs to deallocate memory
|
||||
* while it is within an interrupt handler.
|
||||
@@ -229,7 +229,7 @@ struct pidhash_s g_pidhash[CONFIG_MAX_TASKS];
|
||||
/* This is a table of task lists. This table is indexed by the task stat
|
||||
* enumeration type (tstate_t) and provides a pointer to the associated
|
||||
* static task list (if there is one) as well as a a set of attribute flags
|
||||
* indicating properities of the list, for example, if the list is an
|
||||
* indicating properties of the list, for example, if the list is an
|
||||
* ordered list or not.
|
||||
*/
|
||||
|
||||
@@ -311,7 +311,7 @@ uint8_t g_os_initstate; /* See enum os_initstate_e */
|
||||
/****************************************************************************
|
||||
* Private Data
|
||||
****************************************************************************/
|
||||
/* This is an arry of task control block (TCB) for the IDLE thread of each
|
||||
/* This is an array of task control block (TCB) for the IDLE thread of each
|
||||
* CPU. For the non-SMP case, this is a a single TCB; For the SMP case,
|
||||
* there is one TCB per CPU. NOTE: The system boots on CPU0 into the IDLE
|
||||
* task. The IDLE task later starts the other CPUs and spawns the user
|
||||
|
||||
+8
-1
@@ -1,7 +1,7 @@
|
||||
############################################################################
|
||||
# sched/irq/Make.defs
|
||||
#
|
||||
# Copyright (C) 2014, 2016 Gregory Nutt. All rights reserved.
|
||||
# Copyright (C) 2014, 2016, 2018 Gregory Nutt. All rights reserved.
|
||||
# Author: Gregory Nutt <gnutt@nuttx.org>
|
||||
#
|
||||
# Redistribution and use in source and binary forms, with or without
|
||||
@@ -44,6 +44,13 @@ else ifeq ($(CONFIG_SCHED_INSTRUMENTATION_CSECTION),y)
|
||||
CSRCS += irq_csection.c
|
||||
endif
|
||||
|
||||
ifeq ($(CONFIG_SCHED_IRQMONITOR),y)
|
||||
CSRCS += irq_foreach.c
|
||||
ifeq ($(CONFIG_FS_PROCFS),y)
|
||||
CSRCS += irq_procfs.c
|
||||
endif
|
||||
endif
|
||||
|
||||
# Include irq build support
|
||||
|
||||
DEPPATH += --dep-path irq
|
||||
|
||||
+50
-3
@@ -1,7 +1,8 @@
|
||||
/****************************************************************************
|
||||
* sched/irq/irq.h
|
||||
*
|
||||
* Copyright (C) 2007, 2008, 2013-2014, 2017 Gregory Nutt. All rights reserved.
|
||||
* Copyright (C) 2007, 2008, 2013-2014, 2017-2018 Gregory Nutt. All rights
|
||||
* reserved.
|
||||
* Author: Gregory Nutt <gnutt@nuttx.org>
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
@@ -71,10 +72,26 @@
|
||||
|
||||
struct irq_info_s
|
||||
{
|
||||
xcpt_t handler; /* Address of the interrupt handler */
|
||||
FAR void *arg; /* The argument provided to the interrupt handler. */
|
||||
xcpt_t handler; /* Address of the interrupt handler */
|
||||
FAR void *arg; /* The argument provided to the interrupt handler. */
|
||||
#ifdef CONFIG_SCHED_IRQMONITOR
|
||||
systime_t start; /* Time interrupt attached */
|
||||
#ifdef CONFIG_HAVE_LONG_LONG
|
||||
uint64_t count; /* Number of interrupts on this IRQ */
|
||||
#else
|
||||
uint32_t mscount; /* Number of interrupts on this IRQ (MS) */
|
||||
uint32_t lscount; /* Number of interrupts on this IRQ (LS) */
|
||||
#endif
|
||||
#endif
|
||||
};
|
||||
|
||||
#ifdef CONFIG_SCHED_IRQMONITOR
|
||||
/* This is the type of the callback from irq_foreach(). */
|
||||
|
||||
typedef CODE int (*irq_foreach_t)(int irq, FAR struct irq_info_s *info,
|
||||
FAR void *arg);
|
||||
#endif
|
||||
|
||||
/****************************************************************************
|
||||
* Public Data
|
||||
****************************************************************************/
|
||||
@@ -180,6 +197,36 @@ int irq_unexpected_isr(int irq, FAR void *context, FAR void *arg);
|
||||
bool irq_cpu_locked(int cpu);
|
||||
#endif
|
||||
|
||||
/****************************************************************************
|
||||
* Name: irq_foreach
|
||||
*
|
||||
* Description:
|
||||
* This function traverses the internal list of interrupts and provides
|
||||
* information about each attached interrupt.
|
||||
*
|
||||
* Some caution may be necessary: If interrupts are disabled then the
|
||||
* counts may change during the traversal. If pre-emption is enabled, then
|
||||
* the traversed sequence may be widely separated in time.
|
||||
*
|
||||
* Input Parameters:
|
||||
* callback - This function will be called for each attached interrupt
|
||||
* along with the IRQ number, an instance of struct irq_info_s,
|
||||
* and the caller provided argument
|
||||
* args - This is an opaque argument provided with each call to the
|
||||
* callback function.
|
||||
*
|
||||
* Returned Value:
|
||||
* Zero (OK) is returned after callback has been invoked for all of
|
||||
* the attached interrupts. The callback function may terminate the
|
||||
* traversal at any time by returning a non-zero value. In that case,
|
||||
* irq_foreach will return that non-zero value.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
#ifdef CONFIG_SCHED_IRQMONITOR
|
||||
int irq_foreach(irq_foreach_t callback, FAR void *arg);
|
||||
#endif
|
||||
|
||||
#undef EXTERN
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
|
||||
+11
-1
@@ -1,7 +1,8 @@
|
||||
/****************************************************************************
|
||||
* sched/irq/irq_attach.c
|
||||
*
|
||||
* Copyright (C) 2007-2008, 2010, 2012, 2017 Gregory Nutt. All rights reserved.
|
||||
* Copyright (C) 2007-2008, 2010, 2012, 2017-2018 Gregory Nutt. All rights
|
||||
* reserved.
|
||||
* Author: Gregory Nutt <gnutt@nuttx.org>
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
@@ -115,6 +116,15 @@ int irq_attach(int irq, xcpt_t isr, FAR void *arg)
|
||||
|
||||
g_irqvector[ndx].handler = isr;
|
||||
g_irqvector[ndx].arg = arg;
|
||||
#ifdef CONFIG_SCHED_IRQMONITOR
|
||||
g_irqvector[ndx].start = clock_systimer();
|
||||
#ifdef CONFIG_HAVE_LONG_LONG
|
||||
g_irqvector[ndx].count = 0;
|
||||
#else
|
||||
g_irqvector[ndx].mscount = 0;
|
||||
g_irqvector[ndx].lscount = 0;
|
||||
#endif
|
||||
#endif
|
||||
|
||||
leave_critical_section(flags);
|
||||
ret = OK;
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
/****************************************************************************
|
||||
* sched/irq/irq_dispatch.c
|
||||
*
|
||||
* Copyright (C) 2007, 2008, 2017 Gregory Nutt. All rights reserved.
|
||||
* Copyright (C) 2007, 2008, 2017-2018 Gregory Nutt. All rights reserved.
|
||||
* Author: Gregory Nutt <gnutt@nuttx.org>
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
@@ -46,6 +46,33 @@
|
||||
|
||||
#include "irq/irq.h"
|
||||
|
||||
/****************************************************************************
|
||||
* Pre-processor Definitions
|
||||
****************************************************************************/
|
||||
|
||||
#ifdef CONFIG_SCHED_IRQMONITOR
|
||||
# ifdef CONFIG_HAVE_LONG_LONG
|
||||
# define INCR_COUNT(ndx) \
|
||||
do \
|
||||
{ \
|
||||
g_irqvector[ndx].count++; \
|
||||
} \
|
||||
while (0)
|
||||
# else
|
||||
# define INCR_COUNT(ndx) \
|
||||
do \
|
||||
{ \
|
||||
if (++g_irqvector[ndx].lscount == 0) \
|
||||
{ \
|
||||
g_irqvector[ndx].mscount++; \
|
||||
} \
|
||||
} \
|
||||
while (0)
|
||||
# endif
|
||||
#else
|
||||
# define INCR_COUNT(ndx)
|
||||
#endif
|
||||
|
||||
/****************************************************************************
|
||||
* Public Functions
|
||||
****************************************************************************/
|
||||
@@ -86,13 +113,14 @@ void irq_dispatch(int irq, FAR void *context)
|
||||
{
|
||||
vector = g_irqvector[ndx].handler;
|
||||
arg = g_irqvector[ndx].arg;
|
||||
INCR_COUNT(ndx);
|
||||
}
|
||||
#else
|
||||
vector = g_irqvector[irq].handler;
|
||||
arg = g_irqvector[irq].arg;
|
||||
INCR_COUNT(irq);
|
||||
#endif
|
||||
}
|
||||
|
||||
#else
|
||||
vector = irq_unexpected_isr;
|
||||
arg = NULL;
|
||||
|
||||
@@ -0,0 +1,118 @@
|
||||
/****************************************************************************
|
||||
* sched/irq/irq_foreach.c
|
||||
*
|
||||
* Copyright (C) 2018 Gregory Nutt. All rights reserved.
|
||||
* Author: Gregory Nutt <gnutt@nuttx.org>
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in
|
||||
* the documentation and/or other materials provided with the
|
||||
* distribution.
|
||||
* 3. Neither the name NuttX nor the names of its contributors may be
|
||||
* used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
|
||||
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
|
||||
* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
|
||||
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
|
||||
* OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
|
||||
* AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
|
||||
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
/****************************************************************************
|
||||
* Included Files
|
||||
****************************************************************************/
|
||||
|
||||
#include <nuttx/config.h>
|
||||
|
||||
#include <assert.h>
|
||||
#include <debug.h>
|
||||
|
||||
#include <nuttx/irq.h>
|
||||
|
||||
#include "irq/irq.h"
|
||||
|
||||
#ifdef CONFIG_SCHED_IRQMONITOR
|
||||
|
||||
/****************************************************************************
|
||||
* Pre-processor Definitions
|
||||
****************************************************************************/
|
||||
|
||||
/* This is the number of entries in the interrupt vector table */
|
||||
|
||||
#ifdef CONFIG_ARCH_MINIMAL_VECTORTABLE
|
||||
# define TAB_SIZE CONFIG_ARCH_NUSER_INTERRUPTS
|
||||
#else
|
||||
# define TAB_SIZE NR_IRQS
|
||||
#endif
|
||||
|
||||
/****************************************************************************
|
||||
* Public Functions
|
||||
****************************************************************************/
|
||||
|
||||
/****************************************************************************
|
||||
* Name: irq_foreach
|
||||
*
|
||||
* Description:
|
||||
* This function traverses the internal list of interrupts and provides
|
||||
* information about each attached interrupt.
|
||||
*
|
||||
* Some caution may be necessary: If interrupts are disabled then the
|
||||
* counts may change during the traversal. If pre-emption is enabled, then
|
||||
* the traversed sequence may be widely separated in time.
|
||||
*
|
||||
* Input Parameters:
|
||||
* callback - This function will be called for each attached interrupt
|
||||
* along with the IRQ number, an instance of struct irq_info_s,
|
||||
* and the caller provided argument
|
||||
* args - This is an opaque argument provided with each call to the
|
||||
* callback function.
|
||||
*
|
||||
* Returned Value:
|
||||
* Zero (OK) is returned after callback has been invoked for all of
|
||||
* the attached interrupts. The callback function may terminate the
|
||||
* traversal at any time by returning a non-zero value. In that case,
|
||||
* irq_foreach will return that non-zero value.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
int irq_foreach(irq_foreach_t callback, FAR void *arg)
|
||||
{
|
||||
int irq;
|
||||
int ret;
|
||||
|
||||
DEBUGASSERT(callback != NULL);
|
||||
|
||||
/* Visit each interrupt in the interrupt table */
|
||||
|
||||
for (irq = 0; irq < TAB_SIZE; irq++)
|
||||
{
|
||||
if (g_irqvector[irq].handler != NULL &&
|
||||
g_irqvector[irq].handler != irq_unexpected_isr)
|
||||
{
|
||||
ret = callback(irq, &g_irqvector[irq], arg);
|
||||
if (ret != 0)
|
||||
{
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return OK;
|
||||
}
|
||||
|
||||
#endif /* CONFIG_SCHED_IRQMONITOR */
|
||||
@@ -1,7 +1,7 @@
|
||||
/****************************************************************************
|
||||
* sched/irq/irq_initialize.c
|
||||
*
|
||||
* Copyright (C) 2007-2008, 2010 Gregory Nutt. All rights reserved.
|
||||
* Copyright (C) 2007-2008, 2010, 2018 Gregory Nutt. All rights reserved.
|
||||
* Author: Gregory Nutt <gnutt@nuttx.org>
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
@@ -89,5 +89,14 @@ void irq_initialize(void)
|
||||
{
|
||||
g_irqvector[i].handler = irq_unexpected_isr;
|
||||
g_irqvector[i].arg = NULL;
|
||||
#ifdef CONFIG_SCHED_IRQMONITOR
|
||||
g_irqvector[i].start = 0;
|
||||
#ifdef CONFIG_HAVE_LONG_LONG
|
||||
g_irqvector[i].count = 0;
|
||||
#else
|
||||
g_irqvector[i].mscount = 0;
|
||||
g_irqvector[i].lscount = 0;
|
||||
#endif
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,443 @@
|
||||
/****************************************************************************
|
||||
* sched/irq/irq_procfs.c
|
||||
*
|
||||
* Copyright (C) 2018 Gregory Nutt. All rights reserved.
|
||||
* Author: Gregory Nutt <gnutt@nuttx.org>
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in
|
||||
* the documentation and/or other materials provided with the
|
||||
* distribution.
|
||||
* 3. Neither the name NuttX nor the names of its contributors may be
|
||||
* used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
|
||||
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
|
||||
* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
|
||||
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
|
||||
* OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
|
||||
* AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
|
||||
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
/****************************************************************************
|
||||
* Included Files
|
||||
****************************************************************************/
|
||||
|
||||
#include <nuttx/config.h>
|
||||
|
||||
#include <sys/stat.h>
|
||||
#include <stdio.h>
|
||||
#include <fcntl.h>
|
||||
#include <string.h>
|
||||
#include <assert.h>
|
||||
#include <errno.h>
|
||||
|
||||
#include <nuttx/kmalloc.h>
|
||||
#include <nuttx/fs/fs.h>
|
||||
#include <nuttx/fs/procfs.h>
|
||||
|
||||
#include "irq/irq.h"
|
||||
|
||||
#if !defined(CONFIG_DISABLE_MOUNTPOINT) && defined(CONFIG_FS_PROCFS)
|
||||
#ifdef CONFIG_SCHED_IRQMONITOR
|
||||
|
||||
/****************************************************************************
|
||||
* Pre-processor Definitions
|
||||
****************************************************************************/
|
||||
/* Output format:
|
||||
*
|
||||
* 11111111112222222222333333333344
|
||||
* 12345678901234567890123456789012345678901
|
||||
*
|
||||
* IRQ HANDLER ARGUMENT COUNT RATE
|
||||
* DDD XXXXXXXX XXXXXXXX DDDDDDDDDD DDDD.DDD
|
||||
*
|
||||
* NOTE: This assumes that an address can be represented in 32-bits. In
|
||||
* the typical configuration where CONFIG_HAVE_LONG_LONG=y, the COUNT field
|
||||
* may not be wide enough.
|
||||
*/
|
||||
|
||||
#define HDR_FMT "IRQ HANDLER ARGUMENT COUNT RATE\n"
|
||||
#define IRQ_FMT "%3u %08lx %08lx %10lu %4lu.%03lu\n"
|
||||
|
||||
/* Determines the size of an intermediate buffer that must be large enough
|
||||
* to handle the longest line generated by this logic (plus a couple of
|
||||
* bytes).
|
||||
*/
|
||||
|
||||
#define IRQ_LINELEN 44
|
||||
|
||||
/****************************************************************************
|
||||
* Private Types
|
||||
****************************************************************************/
|
||||
|
||||
/* This structure describes one open "file" */
|
||||
|
||||
struct irq_file_s
|
||||
{
|
||||
struct procfs_file_s base; /* Base open file structure */
|
||||
FAR char *buffer; /* User provided buffer */
|
||||
size_t remaining; /* Number of available characters in buffer */
|
||||
size_t ncopied; /* Number of characters in buffer */
|
||||
off_t offset; /* Current file offset */
|
||||
char line[IRQ_LINELEN]; /* Pre-allocated buffer for formatted lines */
|
||||
};
|
||||
|
||||
/****************************************************************************
|
||||
* Private Function Prototypes
|
||||
****************************************************************************/
|
||||
|
||||
/* irq_foreach() callback function */
|
||||
|
||||
static int irq_callback(int irq, FAR struct irq_info_s *info,
|
||||
FAR void *arg);
|
||||
|
||||
/* File system methods */
|
||||
|
||||
static int irq_open(FAR struct file *filep, FAR const char *relpath,
|
||||
int oflags, mode_t mode);
|
||||
static int irq_close(FAR struct file *filep);
|
||||
static ssize_t irq_read(FAR struct file *filep, FAR char *buffer,
|
||||
size_t buflen);
|
||||
static int irq_dup(FAR const struct file *oldp,
|
||||
FAR struct file *newp);
|
||||
static int irq_stat(FAR const char *relpath, FAR struct stat *buf);
|
||||
|
||||
/****************************************************************************
|
||||
* Public Data
|
||||
****************************************************************************/
|
||||
|
||||
/* See fs_mount.c -- this structure is explicitly extern'ed there.
|
||||
* We use the old-fashioned kind of initializers so that this will compile
|
||||
* with any compiler.
|
||||
*/
|
||||
|
||||
const struct procfs_operations irq_operations =
|
||||
{
|
||||
irq_open, /* open */
|
||||
irq_close, /* close */
|
||||
irq_read, /* read */
|
||||
NULL, /* write */
|
||||
|
||||
irq_dup, /* dup */
|
||||
|
||||
NULL, /* opendir */
|
||||
NULL, /* closedir */
|
||||
NULL, /* readdir */
|
||||
NULL, /* rewinddir */
|
||||
|
||||
irq_stat /* stat */
|
||||
};
|
||||
|
||||
/****************************************************************************
|
||||
* Private Functions
|
||||
****************************************************************************/
|
||||
|
||||
/****************************************************************************
|
||||
* Name: irq_callback
|
||||
****************************************************************************/
|
||||
|
||||
static int irq_callback(int irq, FAR struct irq_info_s *info,
|
||||
FAR void *arg)
|
||||
{
|
||||
FAR struct irq_file_s *irqfile = (FAR struct irq_file_s *)arg;
|
||||
struct irq_info_s copy;
|
||||
irqstate_t flags;
|
||||
systime_t elapsed;
|
||||
systime_t now;
|
||||
size_t linesize;
|
||||
size_t copysize;
|
||||
unsigned long intpart;
|
||||
unsigned long fracpart;
|
||||
unsigned long count;
|
||||
|
||||
DEBUGASSERT(irqfile != NULL);
|
||||
|
||||
/* Take a snapshot and reset the counts */
|
||||
|
||||
flags = enter_critical_section();
|
||||
memcpy(©, info, sizeof(struct irq_info_s));
|
||||
now = clock_systimer();
|
||||
info->start = now;
|
||||
#ifdef CONFIG_HAVE_LONG_LONG
|
||||
info->count = 0;
|
||||
#else
|
||||
info->mscount = 0;
|
||||
info->lscount = 0;
|
||||
#endif
|
||||
leave_critical_section(flags);
|
||||
|
||||
/* Don't bother if count == 0 */
|
||||
|
||||
if (copy.count == 0)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Calculate the interrupt rate from the interrupt count and the elapsed
|
||||
* time.
|
||||
*
|
||||
* REVISIT: If these counts have not been samples and reset in a long time
|
||||
* then the following will likely overflow.
|
||||
*/
|
||||
|
||||
elapsed = now - copy.start;
|
||||
|
||||
#ifdef CONFIG_HAVE_LONG_LONG
|
||||
/* elapsed = <current-time> - <start-time>, units=clock ticks
|
||||
* rate = <interrupt-count> * TICKS_PER_SEC / elapsed
|
||||
*/
|
||||
|
||||
intpart = (unsigned int)((copy.count * TICK_PER_SEC) / elapsed);
|
||||
if (intpart >= 10000)
|
||||
{
|
||||
intpart = 9999;
|
||||
fracpart = 999;
|
||||
}
|
||||
else
|
||||
{
|
||||
uint64_t intcount = (uint64_t)intpart * elapsed / TICK_PER_SEC;
|
||||
fracpart = (unsigned int)
|
||||
(((copy.count - intcount) * TICK_PER_SEC * 1000) / elapsed);
|
||||
}
|
||||
|
||||
/* Make sure that the count is representable with snprintf format */
|
||||
|
||||
if (copy.count > ULONG_MAX)
|
||||
{
|
||||
count = ULONG_MAX;
|
||||
}
|
||||
else
|
||||
{
|
||||
count = (unsigned long)copy.count;
|
||||
}
|
||||
|
||||
#else
|
||||
# error Missing logic
|
||||
#endif
|
||||
|
||||
/* Output information about this interrupt */
|
||||
|
||||
linesize = snprintf(irqfile->line, IRQ_LINELEN, IRQ_FMT,
|
||||
(unsigned int)irq,
|
||||
(unsigned long)((uintptr_t)copy.handler),
|
||||
(unsigned long)((uintptr_t)copy.arg),
|
||||
count, intpart, fracpart);
|
||||
|
||||
copysize = procfs_memcpy(irqfile->line, linesize, irqfile->buffer,
|
||||
irqfile->remaining, &irqfile->offset);
|
||||
|
||||
irqfile->ncopied += copysize;
|
||||
irqfile->buffer += copysize;
|
||||
irqfile->remaining -= copysize;
|
||||
|
||||
/* Return a non-zero value to stop the traversal if the user-provided
|
||||
* buffer is full.
|
||||
*/
|
||||
|
||||
if (irqfile->remaining > 0)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Name: irq_open
|
||||
****************************************************************************/
|
||||
|
||||
static int irq_open(FAR struct file *filep, FAR const char *relpath,
|
||||
int oflags, mode_t mode)
|
||||
{
|
||||
FAR struct irq_file_s *irqfile;
|
||||
|
||||
finfo("Open '%s'\n", relpath);
|
||||
|
||||
/* PROCFS is read-only. Any attempt to open with any kind of write
|
||||
* access is not permitted.
|
||||
*
|
||||
* REVISIT: Write-able proc files could be quite useful.
|
||||
*/
|
||||
|
||||
if ((oflags & O_WRONLY) != 0 || (oflags & O_RDONLY) == 0)
|
||||
{
|
||||
ferr("ERROR: Only O_RDONLY supported\n");
|
||||
return -EACCES;
|
||||
}
|
||||
|
||||
/* "irqs" is the only acceptable value for the relpath */
|
||||
|
||||
if (strcmp(relpath, "irqs") != 0)
|
||||
{
|
||||
ferr("ERROR: relpath is '%s'\n", relpath);
|
||||
return -ENOENT;
|
||||
}
|
||||
|
||||
/* Allocate a container to hold the file attributes */
|
||||
|
||||
irqfile = (FAR struct irq_file_s *)kmm_zalloc(sizeof(struct irq_file_s));
|
||||
if (!irqfile)
|
||||
{
|
||||
ferr("ERROR: Failed to allocate file attributes\n");
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
/* Save the attributes as the open-specific state in filep->f_priv */
|
||||
|
||||
filep->f_priv = (FAR void *)irqfile;
|
||||
return OK;
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Name: irq_close
|
||||
****************************************************************************/
|
||||
|
||||
static int irq_close(FAR struct file *filep)
|
||||
{
|
||||
FAR struct irq_file_s *irqfile;
|
||||
|
||||
/* Recover our private data from the struct file instance */
|
||||
|
||||
irqfile = (FAR struct irq_file_s *)filep->f_priv;
|
||||
DEBUGASSERT(irqfile);
|
||||
|
||||
/* Release the file attributes structure */
|
||||
|
||||
kmm_free(irqfile);
|
||||
filep->f_priv = NULL;
|
||||
return OK;
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Name: irq_read
|
||||
****************************************************************************/
|
||||
|
||||
static ssize_t irq_read(FAR struct file *filep, FAR char *buffer,
|
||||
size_t buflen)
|
||||
{
|
||||
FAR struct irq_file_s *irqfile;
|
||||
size_t linesize;
|
||||
size_t copysize;
|
||||
|
||||
finfo("buffer=%p buflen=%d\n", buffer, (int)buflen);
|
||||
|
||||
/* Recover our private data from the struct file instance */
|
||||
|
||||
irqfile = (FAR struct irq_file_s *)filep->f_priv;
|
||||
DEBUGASSERT(irqfile);
|
||||
|
||||
/* Save the file offset and the user buffer information */
|
||||
|
||||
irqfile->offset = filep->f_pos;
|
||||
irqfile->buffer = buffer;
|
||||
irqfile->remaining = buflen;
|
||||
|
||||
/* The first line to output is the header */
|
||||
|
||||
linesize = snprintf(irqfile->line, IRQ_LINELEN, HDR_FMT);
|
||||
|
||||
copysize = procfs_memcpy(irqfile->line, linesize, irqfile->buffer,
|
||||
irqfile->remaining, &irqfile->offset);
|
||||
|
||||
irqfile->ncopied = copysize;
|
||||
irqfile->buffer += copysize;
|
||||
irqfile->remaining -= copysize;
|
||||
|
||||
/* Now traverse the list of attached interrupts, generating output for
|
||||
* each.
|
||||
*/
|
||||
|
||||
(void)irq_foreach(irq_callback, (FAR void *)irqfile);
|
||||
|
||||
/* Update the file position */
|
||||
|
||||
filep->f_pos += irqfile->ncopied;
|
||||
return irqfile->ncopied;
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Name: irq_dup
|
||||
*
|
||||
* Description:
|
||||
* Duplicate open file data in the new file structure.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
static int irq_dup(FAR const struct file *oldp, FAR struct file *newp)
|
||||
{
|
||||
FAR struct irq_file_s *oldattr;
|
||||
FAR struct irq_file_s *newattr;
|
||||
|
||||
finfo("Dup %p->%p\n", oldp, newp);
|
||||
|
||||
/* Recover our private data from the old struct file instance */
|
||||
|
||||
oldattr = (FAR struct irq_file_s *)oldp->f_priv;
|
||||
DEBUGASSERT(oldattr);
|
||||
|
||||
/* Allocate a new container to hold the task and attribute selection */
|
||||
|
||||
newattr = (FAR struct irq_file_s *)kmm_malloc(sizeof(struct irq_file_s));
|
||||
if (!newattr)
|
||||
{
|
||||
ferr("ERROR: Failed to allocate file attributes\n");
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
/* The copy the file attributes from the old attributes to the new */
|
||||
|
||||
memcpy(newattr, oldattr, sizeof(struct irq_file_s));
|
||||
|
||||
/* Save the new attributes in the new file structure */
|
||||
|
||||
newp->f_priv = (FAR void *)newattr;
|
||||
return OK;
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Name: irq_stat
|
||||
*
|
||||
* Description: Return information about a file or directory
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
static int irq_stat(const char *relpath, struct stat *buf)
|
||||
{
|
||||
/* "irqs" is the only acceptable value for the relpath */
|
||||
|
||||
if (strcmp(relpath, "irqs") != 0)
|
||||
{
|
||||
ferr("ERROR: relpath is '%s'\n", relpath);
|
||||
return -ENOENT;
|
||||
}
|
||||
|
||||
/* "irqs" is the name for a read-only file */
|
||||
|
||||
memset(buf, 0, sizeof(struct stat));
|
||||
buf->st_mode = S_IFREG | S_IROTH | S_IRGRP | S_IRUSR;
|
||||
return OK;
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Public Functions
|
||||
****************************************************************************/
|
||||
|
||||
#endif /* CONFIG_SCHED_IRQMONITOR */
|
||||
#endif /* !CONFIG_DISABLE_MOUNTPOINT && CONFIG_FS_PROCFS */
|
||||
@@ -1,7 +1,8 @@
|
||||
/****************************************************************************
|
||||
* sched/pthread/pthread_setschedparam.c
|
||||
*
|
||||
* Copyright (C) 2007, 2008, 2012, 2015 Gregory Nutt. All rights reserved.
|
||||
* Copyright (C) 2007, 2008, 2012, 2015, 2018 Gregory Nutt. All rights
|
||||
* reserved.
|
||||
* Author: Gregory Nutt <gnutt@nuttx.org>
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
@@ -105,10 +106,6 @@ int pthread_setschedparam(pthread_t thread, int policy,
|
||||
|
||||
sinfo("thread ID=%d policy=%d param=0x%p\n", thread, policy, param);
|
||||
|
||||
/* Set the errno to some non-zero value (failsafe) */
|
||||
|
||||
set_errno(EINVAL);
|
||||
|
||||
/* Let sched_setscheduler do all of the work */
|
||||
|
||||
ret = sched_setscheduler((pid_t)thread, policy, param);
|
||||
|
||||
+5
-1
@@ -1,7 +1,7 @@
|
||||
/****************************************************************************
|
||||
* sched/sched/sched.h
|
||||
*
|
||||
* Copyright (C) 2007-2014, 2016 Gregory Nutt. All rights reserved.
|
||||
* Copyright (C) 2007-2014, 2016, 2018 Gregory Nutt. All rights reserved.
|
||||
* Author: Gregory Nutt <gnutt@nuttx.org>
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
@@ -63,6 +63,10 @@
|
||||
* tasks built into the design).
|
||||
*/
|
||||
|
||||
#if CONFIG_MAX_TASKS & (CONFIG_MAX_TASKS - 1)
|
||||
# error CONFIG_MAX_TASKS must be power of 2
|
||||
#endif
|
||||
|
||||
#define MAX_TASKS_MASK (CONFIG_MAX_TASKS-1)
|
||||
#define PIDHASH(pid) ((pid) & MAX_TASKS_MASK)
|
||||
|
||||
|
||||
@@ -105,7 +105,7 @@ void nxsem_recover(FAR struct tcb_s *tcb)
|
||||
nxsem_canceled(tcb, sem);
|
||||
|
||||
/* And increment the count on the semaphore. This releases the count
|
||||
* that was taken by sem_post(). This count decremented the semaphore
|
||||
* that was taken by sem_wait(). This count decremented the semaphore
|
||||
* count to negative and caused the thread to be blocked in the first
|
||||
* place.
|
||||
*/
|
||||
|
||||
@@ -103,11 +103,11 @@ static int thread_create(FAR const char *name, uint8_t ttype, int priority,
|
||||
goto errout;
|
||||
}
|
||||
|
||||
#ifdef HAVE_TASK_GROUP
|
||||
/* Allocate a new task group with privileges appropriate for the parent
|
||||
* thread type.
|
||||
*/
|
||||
|
||||
#ifdef HAVE_TASK_GROUP
|
||||
ret = group_allocate(tcb, ttype);
|
||||
if (ret < 0)
|
||||
{
|
||||
@@ -157,9 +157,9 @@ static int thread_create(FAR const char *name, uint8_t ttype, int priority,
|
||||
|
||||
(void)task_argsetup(tcb, name, argv);
|
||||
|
||||
#ifdef HAVE_TASK_GROUP
|
||||
/* Now we have enough in place that we can join the group */
|
||||
|
||||
#ifdef HAVE_TASK_GROUP
|
||||
ret = group_initialize(tcb);
|
||||
if (ret < 0)
|
||||
{
|
||||
|
||||
@@ -52,7 +52,7 @@
|
||||
****************************************************************************/
|
||||
|
||||
/****************************************************************************
|
||||
* Name: task_setcancelstate
|
||||
* Name: task_setcanceltype
|
||||
*
|
||||
* Description:
|
||||
* The task_setcanceltype() function atomically both sets the calling
|
||||
|
||||
+10
-4
@@ -1,7 +1,8 @@
|
||||
/****************************************************************************
|
||||
* sched/wdog/wd_delete.c
|
||||
*
|
||||
* Copyright (C) 2007-2009, 2014, 2016 Gregory Nutt. All rights reserved.
|
||||
* Copyright (C) 2007-2009, 2014, 2016, 2018 Gregory Nutt. All rights
|
||||
* reserved.
|
||||
* Author: Gregory Nutt <gnutt@nuttx.org>
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
@@ -113,9 +114,7 @@ int wd_delete(WDOG_ID wdog)
|
||||
sched_kfree(wdog);
|
||||
}
|
||||
|
||||
/* This was a pre-allocated timer. This function should not be called for
|
||||
* statically allocated timers.
|
||||
*/
|
||||
/* Check if this is pre-allocated timer. */
|
||||
|
||||
else if (!WDOG_ISSTATIC(wdog))
|
||||
{
|
||||
@@ -129,6 +128,13 @@ int wd_delete(WDOG_ID wdog)
|
||||
leave_critical_section(flags);
|
||||
}
|
||||
|
||||
/* This function should not be called for statically allocated timers. */
|
||||
|
||||
else
|
||||
{
|
||||
leave_critical_section(flags);
|
||||
}
|
||||
|
||||
/* Return success */
|
||||
|
||||
return OK;
|
||||
|
||||
Reference in New Issue
Block a user