SPI debug changes

git-svn-id: svn://svn.code.sf.net/p/nuttx/code/trunk@2953 42af7a65-404d-4744-a932-0658087f49c3
This commit is contained in:
patacongo
2010-09-30 02:39:20 +00:00
parent 8aade43aab
commit 83ac0e8514
4 changed files with 222 additions and 59 deletions
+183 -29
View File
@@ -59,11 +59,24 @@
* Definitions * Definitions
************************************************************************************/ ************************************************************************************/
/* Configuration ********************************************************************/
/* Debug ****************************************************************************/
/* Define the following to enable extremely detailed register debug */
#undef CONFIG_DEBUG_SPIREGS
/* CONFIG_DEBUG must also be defined */
#ifndef CONFIG_DEBUG
# undef CONFIG_DEBUG_SPIREGS
#endif
/* Timing ***************************************************************************/
#define SPI_MAX_DIVIDER 65024 /* = 254 * (255 + 1) */ #define SPI_MAX_DIVIDER 65024 /* = 254 * (255 + 1) */
#define SPI_MIN_DIVIDER 2 #define SPI_MIN_DIVIDER 2
/* Configuration ********************************************************************/
/************************************************************************************ /************************************************************************************
* Private Types * Private Types
************************************************************************************/ ************************************************************************************/
@@ -84,6 +97,16 @@ struct lpc313x_spidev_s
/************************************************************************************ /************************************************************************************
* Private Function Prototypes * Private Function Prototypes
************************************************************************************/ ************************************************************************************/
#ifdef CONFIG_DEBUG_SPIREGS
static bool spi_checkreg(bool wr, uint32_t value, uint32_t address);
static void spi_putreg(uint32_t value, uint32_t address);
static uint32_t spi_getreg(uint32_t address);
#else
# define spi_putreg(v,a) putreg32(v,a)
# define spi_getreg(a) getreg32(a)
#endif
static inline void spi_drive_cs(FAR struct lpc313x_spidev_s *priv, uint8_t slave, uint8_t val); static inline void spi_drive_cs(FAR struct lpc313x_spidev_s *priv, uint8_t slave, uint8_t val);
static inline void spi_select_slave(FAR struct lpc313x_spidev_s *priv, uint8_t slave); static inline void spi_select_slave(FAR struct lpc313x_spidev_s *priv, uint8_t slave);
static inline uint16_t spi_readword(FAR struct lpc313x_spidev_s *priv); static inline uint16_t spi_readword(FAR struct lpc313x_spidev_s *priv);
@@ -133,6 +156,13 @@ static struct lpc313x_spidev_s g_spidev =
.spidev = { &g_spiops }, .spidev = { &g_spiops },
}; };
#ifdef CONFIG_DEBUG_SPIREGS
static bool g_wrlast;
static uint32_t g_addresslast;
static uint32_t g_valuelast;
static int g_ntimes;
#endif
/************************************************************************************ /************************************************************************************
* Public Data * Public Data
************************************************************************************/ ************************************************************************************/
@@ -141,6 +171,98 @@ static struct lpc313x_spidev_s g_spidev =
* Private Functions * Private Functions
************************************************************************************/ ************************************************************************************/
/****************************************************************************
* Name: spi_checkreg
*
* Description:
* Check if the current register access is a duplicate of the preceding.
*
* Input Parameters:
* value - The value to be written
* address - The address of the register to write to
*
* Returned Value:
* true: This is the first register access of this type.
* flase: This is the same as the preceding register access.
*
****************************************************************************/
#ifdef CONFIG_DEBUG_SPIREGS
static bool spi_checkreg(bool wr, uint32_t value, uint32_t address)
{
if (wr == g_wrlast && value == g_valuelast && address == g_addresslast)
{
g_ntimes++;
return false;
}
else
{
if (g_ntimes > 0)
{
lldbg("...[Repeats %d times]...\n", g_ntimes);
}
g_wrlast = wr;
g_valuelast = value;
g_addresslast = address;
g_ntimes = 0;
}
return true;
}
#endif
/****************************************************************************
* Name: spi_putreg
*
* Description:
* Write a 32-bit value to an SPI register
*
* Input Parameters:
* value - The value to be written
* address - The address of the register to write to
*
* Returned Value:
* None
*
****************************************************************************/
#ifdef CONFIG_DEBUG_SPIREGS
static void spi_putreg(uint32_t value, uint32_t address)
{
if (spi_checkreg(true, value, address))
{
lldbg("%08x<-%08x\n", address, value);
}
putreg32(value, address);
}
#endif
/****************************************************************************
* Name: spi_getreg
*
* Description:
* Read a 32-bit value from an SPI register
*
* Input Parameters:
* address - The address of the register to read from
*
* Returned Value:
* The value read from the register
*
****************************************************************************/
#ifdef CONFIG_DEBUG_SPIREGS
static uint32_t spi_getreg(uint32_t address)
{
uint32_t value = getreg32(address);
if (spi_checkreg(false, value, address))
{
lldbg("%08x->%08x\n", address, value);
}
return value;
}
#endif
/**************************************************************************** /****************************************************************************
* Name: spi_drive_cs * Name: spi_drive_cs
* *
@@ -163,26 +285,38 @@ static inline void spi_drive_cs(FAR struct lpc313x_spidev_s *priv, uint8_t slave
{ {
case 0: case 0:
if (val == 0) if (val == 0)
putreg32 (IOCONFIG_SPI_CSOUT0, LPC313X_IOCONFIG_SPI_MODE0RESET); {
spi_putreg(IOCONFIG_SPI_CSOUT0, LPC313X_IOCONFIG_SPI_MODE0RESET);
}
else else
putreg32 (IOCONFIG_SPI_CSOUT0, LPC313X_IOCONFIG_SPI_MODE0SET); {
putreg32 (IOCONFIG_SPI_CSOUT0, LPC313X_IOCONFIG_SPI_MODE1SET); spi_putreg(IOCONFIG_SPI_CSOUT0, LPC313X_IOCONFIG_SPI_MODE0SET);
}
spi_putreg(IOCONFIG_SPI_CSOUT0, LPC313X_IOCONFIG_SPI_MODE1SET);
break; break;
case 1: case 1:
if (val == 0) if (val == 0)
putreg32 (IOCONFIG_EBII2STX0_MUARTCTSN, LPC313X_IOCONFIG_EBII2STX0_MODE0RESET); {
spi_putreg(IOCONFIG_EBII2STX0_MUARTCTSN, LPC313X_IOCONFIG_EBII2STX0_MODE0RESET);
}
else else
putreg32 (IOCONFIG_EBII2STX0_MUARTCTSN, LPC313X_IOCONFIG_EBII2STX0_MODE0SET); {
putreg32 (IOCONFIG_EBII2STX0_MUARTCTSN, LPC313X_IOCONFIG_EBII2STX0_MODE1SET); spi_putreg(IOCONFIG_EBII2STX0_MUARTCTSN, LPC313X_IOCONFIG_EBII2STX0_MODE0SET);
}
spi_putreg(IOCONFIG_EBII2STX0_MUARTCTSN, LPC313X_IOCONFIG_EBII2STX0_MODE1SET);
break; break;
case 2: case 2:
if (val == 0) if (val == 0)
putreg32 (IOCONFIG_EBII2STX0_MUARTRTSN, LPC313X_IOCONFIG_EBII2STX0_MODE0RESET); {
spi_putreg(IOCONFIG_EBII2STX0_MUARTRTSN, LPC313X_IOCONFIG_EBII2STX0_MODE0RESET);
}
else else
putreg32 (IOCONFIG_EBII2STX0_MUARTRTSN, LPC313X_IOCONFIG_EBII2STX0_MODE0SET); {
putreg32 (IOCONFIG_EBII2STX0_MUARTRTSN, LPC313X_IOCONFIG_EBII2STX0_MODE1SET); spi_putreg(IOCONFIG_EBII2STX0_MUARTRTSN, LPC313X_IOCONFIG_EBII2STX0_MODE0SET);
}
spi_putreg(IOCONFIG_EBII2STX0_MUARTRTSN, LPC313X_IOCONFIG_EBII2STX0_MODE1SET);
break; break;
} }
} }
@@ -207,20 +341,21 @@ static inline void spi_select_slave(FAR struct lpc313x_spidev_s *priv, uint8_t s
switch (slave) switch (slave)
{ {
case 0: case 0:
putreg32 (priv->slv1, LPC313X_SPI_SLV0_1); spi_putreg(priv->slv1, LPC313X_SPI_SLV0_1);
putreg32 (priv->slv2, LPC313X_SPI_SLV0_2); spi_putreg(priv->slv2, LPC313X_SPI_SLV0_2);
putreg32 (SPI_SLVENABLE1_ENABLED, LPC313X_SPI_SLVENABLE); spi_putreg(SPI_SLVENABLE1_ENABLED, LPC313X_SPI_SLVENABLE);
break; break;
case 1: case 1:
putreg32 (priv->slv1, LPC313X_SPI_SLV1_1); spi_putreg(priv->slv1, LPC313X_SPI_SLV1_1);
putreg32 (priv->slv2, LPC313X_SPI_SLV1_2); spi_putreg(priv->slv2, LPC313X_SPI_SLV1_2);
putreg32 (SPI_SLVENABLE2_ENABLED, LPC313X_SPI_SLVENABLE); spi_putreg(SPI_SLVENABLE2_ENABLED, LPC313X_SPI_SLVENABLE);
break;
case 2: case 2:
putreg32 (priv->slv1, LPC313X_SPI_SLV2_1); spi_putreg(priv->slv1, LPC313X_SPI_SLV2_1);
putreg32 (priv->slv2, LPC313X_SPI_SLV2_2); spi_putreg(priv->slv2, LPC313X_SPI_SLV2_2);
putreg32 (SPI_SLVENABLE3_ENABLED, LPC313X_SPI_SLVENABLE); spi_putreg(SPI_SLVENABLE3_ENABLED, LPC313X_SPI_SLVENABLE);
break; break;
} }
} }
@@ -243,12 +378,12 @@ static inline uint16_t spi_readword(FAR struct lpc313x_spidev_s *priv)
{ {
/* Wait until the receive buffer is not empty */ /* Wait until the receive buffer is not empty */
while ((getreg32 (LPC313X_SPI_STATUS) & SPI_STATUS_RXFIFOEMPTY) != 0) while ((spi_getreg(LPC313X_SPI_STATUS) & SPI_STATUS_RXFIFOEMPTY) != 0)
; ;
/* Then return the received byte */ /* Then return the received byte */
uint32_t val = getreg32 (LPC313X_SPI_FIFODATA); uint32_t val = spi_getreg(LPC313X_SPI_FIFODATA);
return val; return val;
} }
@@ -272,12 +407,12 @@ static inline void spi_writeword(FAR struct lpc313x_spidev_s *priv, uint16_t wor
{ {
/* Wait until the transmit buffer is not full */ /* Wait until the transmit buffer is not full */
while ((getreg32 (LPC313X_SPI_STATUS) & SPI_STATUS_TXFIFOFULL) != 0) while ((spi_getreg(LPC313X_SPI_STATUS) & SPI_STATUS_TXFIFOFULL) != 0)
; ;
/* Then send the byte */ /* Then send the byte */
putreg32 (word, LPC313X_SPI_FIFODATA); spi_putreg(word, LPC313X_SPI_FIFODATA);
} }
/**************************************************************************** /****************************************************************************
@@ -355,12 +490,15 @@ static void spi_select(FAR struct spi_dev_s *dev, enum spi_dev_e devid, bool sel
case SPIDEV_FLASH: case SPIDEV_FLASH:
slave = 0; slave = 0;
break; break;
case SPIDEV_MMCSD: case SPIDEV_MMCSD:
slave = 1; slave = 1;
break; break;
case SPIDEV_ETHERNET: case SPIDEV_ETHERNET:
slave = 2; slave = 2;
break; break;
default: default:
return; return;
} }
@@ -379,7 +517,7 @@ static void spi_select(FAR struct spi_dev_s *dev, enum spi_dev_e devid, bool sel
/* Enable SPI as master and notify of slave enables change */ /* Enable SPI as master and notify of slave enables change */
putreg32 ((1 << SPI_CONFIG_INTERSLVDELAY_SHIFT) | SPI_CONFIG_UPDENABLE | SPI_CONFIG_SPIENABLE, LPC313X_SPI_CONFIG); spi_putreg((1 << SPI_CONFIG_INTERSLVDELAY_SHIFT) | SPI_CONFIG_UPDENABLE | SPI_CONFIG_SPIENABLE, LPC313X_SPI_CONFIG);
} }
else else
{ {
@@ -387,11 +525,11 @@ static void spi_select(FAR struct spi_dev_s *dev, enum spi_dev_e devid, bool sel
/* Disable all slaves */ /* Disable all slaves */
putreg32 (0, LPC313X_SPI_SLVENABLE); spi_putreg(0, LPC313X_SPI_SLVENABLE);
/* Disable SPI as master */ /* Disable SPI as master */
putreg32 (SPI_CONFIG_UPDENABLE, LPC313X_SPI_CONFIG); spi_putreg(SPI_CONFIG_UPDENABLE, LPC313X_SPI_CONFIG);
} }
} }
@@ -427,9 +565,13 @@ static uint32_t spi_setfrequency(FAR struct spi_dev_s *dev, uint32_t frequency)
div = (spi_clk + frequency / 2) / frequency; div = (spi_clk + frequency / 2) / frequency;
if (div > SPI_MAX_DIVIDER) if (div > SPI_MAX_DIVIDER)
{
div = SPI_MAX_DIVIDER; div = SPI_MAX_DIVIDER;
if (div < SPI_MIN_DIVIDER) }
else if (div < SPI_MIN_DIVIDER)
{
div = SPI_MIN_DIVIDER; div = SPI_MIN_DIVIDER;
}
div2 = (((div-1) / 512) + 2) * 2; div2 = (((div-1) / 512) + 2) * 2;
div1 = ((((div + div2 / 2) / div2) - 1)); div1 = ((((div + div2 / 2) / div2) - 1));
@@ -734,11 +876,23 @@ FAR struct spi_dev_s *up_spiinitialize(int port)
FAR struct lpc313x_spidev_s *priv = &g_spidev; FAR struct lpc313x_spidev_s *priv = &g_spidev;
/* Only the SPI0 interface is supported */ /* Only the SPI0 interface is supported */
if (port != 0) if (port != 0)
{ {
return NULL; return NULL;
} }
/* Configure SPI pins. Nothing needs to be done here because the SPI pins
* default to "driven-by-IP" on reset.
*/
#ifdef CONFIG_DEBUG_SPIREGS
lldbg("PINS: %08x MODE0: %08x MODE1: %08x\n",
spi_getreg(LPC313X_IOCONFIG_SPI_PINS),
spi_getreg(LPC313X_IOCONFIG_SPI_MODE0),
spi_getreg(LPC313X_IOCONFIG_SPI_MODE1));
#endif
/* Enable SPI clocks */ /* Enable SPI clocks */
lpc313x_enableclock(CLKID_SPIPCLK); lpc313x_enableclock(CLKID_SPIPCLK);
@@ -757,7 +911,7 @@ FAR struct spi_dev_s *up_spiinitialize(int port)
/* Reset the SPI block */ /* Reset the SPI block */
putreg32 (SPI_CONFIG_SOFTRST, LPC313X_SPI_CONFIG); spi_putreg(SPI_CONFIG_SOFTRST, LPC313X_SPI_CONFIG);
/* Initialise Slave 0 settings registers */ /* Initialise Slave 0 settings registers */
+2 -2
View File
@@ -1,7 +1,7 @@
/************************************************************************************************ /************************************************************************************************
* arch/arm/src/lpc313x/lpc313x_spi.h * arch/arm/src/lpc313x/lpc313x_spi.h
* *
* Copyright (C) 2009 Gregory Nutt. All rights reserved. * Copyright (C) 2009-2010 Gregory Nutt. All rights reserved.
* Author: Gregory Nutt <spudmonkey@racsa.co.cr> * Author: Gregory Nutt <spudmonkey@racsa.co.cr>
* *
* Redistribution and use in source and binary forms, with or without * Redistribution and use in source and binary forms, with or without
@@ -123,7 +123,7 @@
#define SPI_CONFIG_INTERSLVDELAY_SHIFT (16) /* Bits 16-31: Delay between xfrs to different slaves */ #define SPI_CONFIG_INTERSLVDELAY_SHIFT (16) /* Bits 16-31: Delay between xfrs to different slaves */
#define SPI_CONFIG_NTERSLVDELAY_MASK (0xffff << SPI_CONFIG_INTERSLVDELAY_SHIFT) #define SPI_CONFIG_NTERSLVDELAY_MASK (0xffff << SPI_CONFIG_INTERSLVDELAY_SHIFT)
#define SPI_CONFIG_UPDENABLE (1 << 7) /* Bit 7: 7 W Update enable bit */ #define SPI_CONFIG_UPDENABLE (1 << 7) /* Bit 7: 7 Update enable bit */
#define SPI_CONFIG_SOFTRST (1 << 6) /* Bit 6: 6 Software reset bit */ #define SPI_CONFIG_SOFTRST (1 << 6) /* Bit 6: 6 Software reset bit */
#define SPI_CONFIG_SLVDISABLE (1 << 4) /* Bit 4: 4 Slave output disable (slave mode) */ #define SPI_CONFIG_SLVDISABLE (1 << 4) /* Bit 4: 4 Slave output disable (slave mode) */
#define SPI_CONFIG_XMITMODE (1 << 3) /* Bit 3: 3 Transmit mode */ #define SPI_CONFIG_XMITMODE (1 << 3) /* Bit 3: 3 Transmit mode */
+8
View File
@@ -416,6 +416,14 @@ On-Demand Paging
The references and issues related to this are discussed in (2) The references and issues related to this are discussed in (2)
and (3) above. and (3) above.
Basic support for paging from SPI NOR FLASH can be enabled by adding:
CONFIG_PAGING_AT45DB=y
Or:
CONFIG_PAGING_M25PX=y
Alternative: Alternative:
------------ ------------
+1
View File
@@ -302,6 +302,7 @@ CONFIG_DEBUG=n
CONFIG_DEBUG_VERBOSE=n CONFIG_DEBUG_VERBOSE=n
CONFIG_DEBUG_SYMBOLS=n CONFIG_DEBUG_SYMBOLS=n
CONFIG_DEBUG_PAGING=n CONFIG_DEBUG_PAGING=n
CONFIG_DEBUG_FS=n
CONFIG_MM_REGIONS=1 CONFIG_MM_REGIONS=1
CONFIG_ARCH_LOWPUTC=y CONFIG_ARCH_LOWPUTC=y
CONFIG_RR_INTERVAL=200 CONFIG_RR_INTERVAL=200