diff --git a/arch/arm/src/samv7/sam_twihs.c b/arch/arm/src/samv7/sam_twihs.c index 4cbd19d3965..05fa92cd716 100644 --- a/arch/arm/src/samv7/sam_twihs.c +++ b/arch/arm/src/samv7/sam_twihs.c @@ -151,7 +151,7 @@ struct twi_dev_s struct i2c_msg_s *msg; /* Message list */ uint32_t twiclk; /* TWIHS input clock frequency */ uint32_t frequency; /* TWIHS transfer clock frequency */ - bool initd; /* True :device has been initialized */ + int refs; /* Reference count */ uint8_t msgc; /* Number of message in the message list */ sem_t exclsem; /* Only one thread can access at a time */ @@ -1118,6 +1118,10 @@ static int twi_reset(FAR struct i2c_master_s *dev) DEBUGASSERT(priv != NULL); + /* Our caller must own a ref */ + + DEBUGASSERT(priv->refs > 0); + /* Get exclusive access to the TWIHS device */ twi_takesem(&priv->exclsem); @@ -1342,6 +1346,7 @@ struct i2c_master_s *sam_i2cbus_initialize(int bus) { struct twi_dev_s *priv; uint32_t frequency; + const struct twi_attr_s *attr = 0; irqstate_t flags; int ret; @@ -1352,8 +1357,8 @@ struct i2c_master_s *sam_i2cbus_initialize(int bus) { /* Select up TWIHS0 and setup invariant attributes */ - priv = &g_twi0; - priv->attr = &g_twi0attr; + priv = &g_twi0; + attr = &g_twi0attr; /* Select the (initial) TWIHS frequency */ @@ -1366,8 +1371,8 @@ struct i2c_master_s *sam_i2cbus_initialize(int bus) { /* Select up TWIHS1 and setup invariant attributes */ - priv = &g_twi1; - priv->attr = &g_twi1attr; + priv = &g_twi1; + attr = &g_twi1attr; /* Select the (initial) TWIHS frequency */ @@ -1380,8 +1385,8 @@ struct i2c_master_s *sam_i2cbus_initialize(int bus) { /* Select up TWIHS2 and setup invariant attributes */ - priv = &g_twi2; - priv->attr = &g_twi2attr; + priv = &g_twi2; + attr = &g_twi2attr; /* Select the (initial) TWIHS frequency */ @@ -1394,14 +1399,16 @@ struct i2c_master_s *sam_i2cbus_initialize(int bus) return NULL; } - /* Perform one-time TWIHS initialization */ - flags = enter_critical_section(); /* Has the device already been initialized? */ - if (!priv->initd) + if ((volatile int)priv->refs++ == 0) { + /* Perform one-time TWIHS initialization */ + + priv->attr = attr; + /* Allocate a watchdog timer */ priv->timeout = wd_create(); @@ -1438,10 +1445,6 @@ struct i2c_master_s *sam_i2cbus_initialize(int bus) /* Perform repeatable TWIHS hardware initialization */ twi_hw_initialize(priv, frequency); - - /* Now it has been initialized */ - - priv->initd = true; } leave_critical_section(flags); @@ -1452,6 +1455,7 @@ errout_with_wdog: priv->timeout = NULL; errout_with_irq: + priv->refs--; leave_critical_section(flags); return NULL; } @@ -1469,28 +1473,40 @@ int sam_i2cbus_uninitialize(FAR struct i2c_master_s *dev) struct twi_dev_s *priv = (struct twi_dev_s *) dev; irqstate_t flags; - i2cinfo("TWIHS%d Un-initializing\n", priv->attr->twi); + DEBUGASSERT(priv); + + /* Decrement reference count and check for underflow */ + + if (priv->refs == 0) + { + return ERROR; + } + + i2cinfo("TWIHS%d Un-initializing refs:%d\n", priv->attr->twi, priv->refs); /* Disable TWIHS interrupts */ flags = enter_critical_section(); - up_disable_irq(priv->attr->irq); - /* Reset data structures */ + if (--priv->refs == 0) + { + up_disable_irq(priv->attr->irq); - sem_destroy(&priv->exclsem); - sem_destroy(&priv->waitsem); + /* Reset data structures */ - /* Free the watchdog timer */ + sem_destroy(&priv->exclsem); + sem_destroy(&priv->waitsem); - wd_delete(priv->timeout); - priv->timeout = NULL; + /* Free the watchdog timer */ - /* Detach Interrupt Handler */ + wd_delete(priv->timeout); + priv->timeout = NULL; - (void)irq_detach(priv->attr->irq); + /* Detach Interrupt Handler */ + + (void)irq_detach(priv->attr->irq); + } - priv->initd = false; leave_critical_section(flags); return OK; } diff --git a/arch/arm/src/stm32/chip/stm32_flash.h b/arch/arm/src/stm32/chip/stm32_flash.h index 13c966c05c2..2c96c4ddbd3 100644 --- a/arch/arm/src/stm32/chip/stm32_flash.h +++ b/arch/arm/src/stm32/chip/stm32_flash.h @@ -466,4 +466,8 @@ void stm32_flash_lock(void); void stm32_flash_unlock(void); +#ifdef CONFIG_STM32_STM32F40XX +int stm32_flash_writeprotect(size_t page, bool enabled); +#endif + #endif /* __ARCH_ARM_SRC_STM32_CHIP_STM32_FLASH_H */ diff --git a/arch/arm/src/stm32/chip/stm32f40xxx_pinmap.h b/arch/arm/src/stm32/chip/stm32f40xxx_pinmap.h index 1f7b5944ead..d44c664edbf 100644 --- a/arch/arm/src/stm32/chip/stm32f40xxx_pinmap.h +++ b/arch/arm/src/stm32/chip/stm32f40xxx_pinmap.h @@ -615,7 +615,7 @@ #endif #define GPIO_SPI3_MISO_1 (GPIO_ALT|GPIO_AF6|GPIO_SPEED_50MHz|GPIO_PORTB|GPIO_PIN4) -#define GPIO_SPI3_MISO_2 (GPIO_ALT|GPIO_AF6|GPIO_SPEED_50MHz|GPIO_PORTC|GPIO_PIN7) +#define GPIO_SPI3_MISO_2 (GPIO_ALT|GPIO_AF6|GPIO_SPEED_50MHz|GPIO_PORTC|GPIO_PIN11) #define GPIO_SPI3_MOSI_1 (GPIO_ALT|GPIO_AF6|GPIO_SPEED_50MHz|GPIO_PORTB|GPIO_PIN5) #define GPIO_SPI3_MOSI_2 (GPIO_ALT|GPIO_AF6|GPIO_SPEED_50MHz|GPIO_PORTC|GPIO_PIN12) #define GPIO_SPI3_NSS_1 (GPIO_ALT|GPIO_AF6|GPIO_SPEED_50MHz|GPIO_PORTA|GPIO_PIN15) diff --git a/arch/arm/src/stm32/stm32_flash.c b/arch/arm/src/stm32/stm32_flash.c index 1dae18724c5..6291154cc07 100644 --- a/arch/arm/src/stm32/stm32_flash.c +++ b/arch/arm/src/stm32/stm32_flash.c @@ -79,6 +79,8 @@ #else # define FLASH_KEY1 0x45670123 # define FLASH_KEY2 0xCDEF89AB +# define FLASH_OPTKEY1 0x08192A3B +# define FLASH_OPTKEY2 0x4C5D6E7F #endif #if defined(CONFIG_STM32_STM32F10XX) || defined(CONFIG_STM32_STM32F30XX) @@ -384,6 +386,87 @@ ssize_t stm32_eeprom_erase(size_t addr, size_t eraselen) #endif /* defined(CONFIG_STM32_STM32L15XX) */ +/************************************************************************************ + * Name: stm32_flash_writeprotect + * + * Description: + * Enable or disable the write protection of a flash sector. + * + ************************************************************************************/ + +#ifdef CONFIG_STM32_STM32F40XX +int stm32_flash_writeprotect(size_t page, bool enabled) +{ + uint32_t reg; + uint32_t val; + +#ifdef CONFIG_STM32_STM32F40XX + if (page >= STM32_FLASH_NPAGES) + { + return -EFAULT; + } +#else +# warning missing logic in stm32_flash_writeprotect +#endif + + /* Select the register that contains the bit to be changed */ + + if (page < 12) + { + reg = STM32_FLASH_OPTCR; + } +#if defined(CONFIG_STM32_FLASH_CONFIG_I) && defined(CONFIG_STM32_STM32F40XX) + else + { + reg = STM32_FLASH_OPTCR1; + page -= 12; + } +#else + else + { + return -EFAULT; + } +#endif + + /* Read the option status */ + + val = getreg32(reg); + + /* Set or clear the protection */ + + if (enabled) + { + val &= ~(1 << (16+page) ); + } + else + { + val |= (1 << (16+page) ); + } + + /* Unlock options */ + + putreg32(FLASH_OPTKEY1, STM32_FLASH_OPTKEYR); + putreg32(FLASH_OPTKEY2, STM32_FLASH_OPTKEYR); + + /* Write options */ + + putreg32(val, reg); + + /* Trigger programmation */ + + modifyreg32(STM32_FLASH_OPTCR, 0, FLASH_OPTCR_OPTSTRT); + + /* Wait for completion */ + + while(getreg32(STM32_FLASH_SR) & FLASH_SR_BSY) up_waste(); + + /* Relock options */ + + modifyreg32(STM32_FLASH_OPTCR, 0, FLASH_OPTCR_OPTLOCK); + return 0; +} +#endif + #if defined(CONFIG_STM32_STM32F10XX) || defined(CONFIG_STM32_STM32F30XX) size_t up_progmem_pagesize(size_t page) { diff --git a/arch/arm/src/stm32/stm32_i2s.c b/arch/arm/src/stm32/stm32_i2s.c index 0f246f57634..1f5d348384c 100644 --- a/arch/arm/src/stm32/stm32_i2s.c +++ b/arch/arm/src/stm32/stm32_i2s.c @@ -2333,7 +2333,7 @@ static int i2s_dma_allocate(struct stm32_i2s_s *priv) { /* Allocate an RX DMA channel */ - priv->rx.dma = stm32_dmachannel(DMAMAP_SPI3_RX_2); + priv->rx.dma = stm32_dmachannel(DMACHAN_I2S3_RX); if (!priv->rx.dma) { i2serr("ERROR: Failed to allocate the RX DMA channel\n"); @@ -2356,7 +2356,7 @@ static int i2s_dma_allocate(struct stm32_i2s_s *priv) { /* Allocate a TX DMA channel */ - priv->tx.dma = stm32_dmachannel(DMAMAP_SPI3_TX_2); + priv->tx.dma = stm32_dmachannel(DMACHAN_I2S3_TX); if (!priv->tx.dma) { i2serr("ERROR: Failed to allocate the TX DMA channel\n"); diff --git a/configs/stm32f4discovery/include/board.h b/configs/stm32f4discovery/include/board.h index 91077e674fc..273c8945b2d 100644 --- a/configs/stm32f4discovery/include/board.h +++ b/configs/stm32f4discovery/include/board.h @@ -310,21 +310,14 @@ #define GPIO_SPI2_MOSI GPIO_SPI2_MOSI_1 #define GPIO_SPI2_SCK GPIO_SPI2_SCK_1 -/* SPI3 - Onboard devices use SPI3 */ - -#define GPIO_SPI3_MISO GPIO_SPI3_MISO_2 -#define GPIO_SPI3_MOSI GPIO_SPI3_MOSI_2 -#define GPIO_SPI3_SCK GPIO_SPI3_SCK_2 -#define GPIO_SPI3_NSS GPIO_SPI3_NSS_2 - -/* I2S3 - Onboard devices use I2S3 */ +/* I2S3 - CS43L22 configuration uses I2S3 */ #define GPIO_I2S3_SD GPIO_I2S3_SD_2 #define GPIO_I2S3_CK GPIO_I2S3_CK_2 #define GPIO_I2S3_WS GPIO_I2S3_WS_1 -#define DMACHAN_SPI3_RX DMAMAP_SPI3_RX_2 -#define DMACHAN_SPI3_TX DMAMAP_SPI3_TX_2 +#define DMACHAN_I2S3_RX DMAMAP_SPI3_RX_2 +#define DMACHAN_I2S3_TX DMAMAP_SPI3_TX_2 /* I2C config to use with Nunchuk PB7 (SDA) and PB8 (SCL) */