arch/arm/src/tiva/common/tiva_flash.c: Improve tiva_write() (but needs more work!)

arch/arm/src/tiva/common/tiva_flash.c:  Fix several mistakes in
tiva_write() but note that this function needs more work. (1) Fix wrong
use of && when & was intended. (2) Add compile- time warning directive
because according to this function's interface, it is supposed to
support unaligned writes and/or writes of arbitrary numbers of bytes to
FLASH. However, this function does NOT support that at this time. This
needs to be fixed. (3) Fix wrong preprocessor conditional. Was written
to use the 32-word write buffer only for TM4C1294NCPDT. This buffer is
available on all TM4C123 and TM4C129 parts. Now conditioned upon
CONFIG_ARCH_CHIP_TM4C123 or CONFIG_ARCH_CHIP_TM4C129. (4) Add comments
to document the intent of the above preprocessor logic.
This commit is contained in:
Nathan Hartman 2019-11-06 20:35:35 -06:00 committed by Gregory Nutt
parent 71ce894cab
commit 3869cfc41d

View File

@ -2,7 +2,7 @@
* arch/arm/src/tiva/common/tiva_flash.c * arch/arm/src/tiva/common/tiva_flash.c
* *
* Copyright (c) 2013 Max Holtzberg. All rights reserved. * Copyright (c) 2013 Max Holtzberg. All rights reserved.
* Copyright (C) 2013, 2018 Gregory Nutt. All rights reserved. * Copyright (C) 2013, 2018-2019 Gregory Nutt. All rights reserved.
* *
* Authors: Max Holtzberg <mh@uvc.de> * Authors: Max Holtzberg <mh@uvc.de>
* Gregory Nutt <gnutt@nuttx.org> * Gregory Nutt <gnutt@nuttx.org>
@ -176,7 +176,7 @@ static int tiva_erase(FAR struct mtd_dev_s *dev, off_t startblock,
if (regval != 0) if (regval != 0)
{ {
return -EACCES; return -EACCES;
} }
} }
@ -264,8 +264,16 @@ static ssize_t tiva_read(FAR struct mtd_dev_s *dev, off_t offset,
* Name: tiva_write * Name: tiva_write
* *
* Description: * Description:
* Some FLASH parts have the ability to write an arbitrary number of * Write a block of data to FLASH memory.
* bytes to an arbitrary offset on the device. *
* Input Parameters:
* dev: Device representing Tiva FLASH.
* offset: Destination offset in FLASH memory.
* nbytes: Number of bytes to write.
* buf: Source buffer containing data to be written.
*
* Returned Value:
* Number of bytes written to FLASH.
* *
****************************************************************************/ ****************************************************************************/
@ -273,30 +281,39 @@ static ssize_t tiva_read(FAR struct mtd_dev_s *dev, off_t offset,
static ssize_t tiva_write(FAR struct mtd_dev_s *dev, off_t offset, static ssize_t tiva_write(FAR struct mtd_dev_s *dev, off_t offset,
size_t nbytes, FAR const uint8_t *buf) size_t nbytes, FAR const uint8_t *buf)
{ {
/* WARNING and REVISIT:
* Because this function exports a byte write interface and
* is conditioned upon CONFIG_MTD_BYTE_WRITE, it is supposed
* to support unaligned writes and writes of arbitrary byte
* counts. But it doesn't. This needs to be fixed!
*/
FAR const uint32_t *src = (uint32_t *)((uintptr_t)buf & ~3); FAR const uint32_t *src = (uint32_t *)((uintptr_t)buf & ~3);
ssize_t remaining; ssize_t remaining;
uint32_t regval; uint32_t regval;
DEBUGASSERT(dev != NULL && buf != NULL); DEBUGASSERT(dev != NULL && buf != NULL);
DEBUGASSERT(((uintptr_t)buf & 3) == 0 && (offset & 3) == 0 && DEBUGASSERT(((uintptr_t)buf & 3) == 0 && (offset & 3) == 0 &&
(nbytes && 3) == 0); (nbytes & 3) == 0);
/* Clear the flash access and error interrupts. */ /* Clear the flash access and error interrupts. */
putreg32(FLASH_FCMISC_AMISC | FLASH_FCMISC_VOLTMISC | FLASH_FCMISC_ERMISC, putreg32(FLASH_FCMISC_AMISC | FLASH_FCMISC_VOLTMISC | FLASH_FCMISC_ERMISC,
TIVA_FLASH_FCMISC); TIVA_FLASH_FCMISC);
/* Adjust the offset to the start of the partition. /* Adjust the offset to the start of the partition. */
* REVISIT: If we really wanted to gracefully handle unaligned addresses,
* offsets, and sizes we would have to do a little more than this.
*/
offset &= ~3; offset &= ~3;
offset += TIVA_VIRTUAL_OFFSET; offset += TIVA_VIRTUAL_OFFSET;
nbytes &= ~3; nbytes &= ~3;
remaining = nbytes; remaining = nbytes;
#if defined(CONFIG_ARCH_CHIP_TM4C1294NCPDT) #if defined (CONFIG_ARCH_CHIP_TM4C123) || defined (CONFIG_ARCH_CHIP_TM4C129)
/* TM4C123x and TM4C129x parts have a 32-word FLASH memory write buffer,
* allowing faster writes by writing 32 words in the time it would take
* to write 16.
*/
while (remaining > 0) while (remaining > 0)
{ {
/* Set the address of this block of words. */ /* Set the address of this block of words. */
@ -319,30 +336,34 @@ static ssize_t tiva_write(FAR struct mtd_dev_s *dev, off_t offset,
putreg32(FLASH_FMC_WRKEY | FLASH_FMC2_WRBUF, TIVA_FLASH_FMC2); putreg32(FLASH_FMC_WRKEY | FLASH_FMC2_WRBUF, TIVA_FLASH_FMC2);
/* Wait until the write buffer has been programmed. */ /* Wait until the write buffer has been programmed. */
while (getreg32(TIVA_FLASH_FMC2) & FLASH_FMC2_WRBUF) while (getreg32(TIVA_FLASH_FMC2) & FLASH_FMC2_WRBUF)
{ {
} }
} }
#else #else
/* These parts do not have the 32-word FLASH memory write buffer, so
* we must do the slower 1-word-at-a-time write.
*/
while (remaining > 0) while (remaining > 0)
{ {
/* Program the next word. */ /* Program the next word. */
putreg32(offset, TIVA_FLASH_FMA); putreg32(offset, TIVA_FLASH_FMA);
putreg32(*src, TIVA_FLASH_FMD); putreg32(*src, TIVA_FLASH_FMD);
putreg32(FLASH_FMC_WRKEY | FLASH_FMC_WRITE, TIVA_FLASH_FMC); putreg32(FLASH_FMC_WRKEY | FLASH_FMC_WRITE, TIVA_FLASH_FMC);
/* Wait until the word has been programmed. */ /* Wait until the word has been programmed. */
while (getreg32(TIVA_FLASH_FMC) & FLASH_FMC_WRITE); while (getreg32(TIVA_FLASH_FMC) & FLASH_FMC_WRITE);
/* Increment to the next word. */ /* Increment to the next word. */
src++; src++;
offset += 4; offset += 4;
remaining -= 4; remaining -= 4;
} }
#endif #endif
@ -354,7 +375,7 @@ static ssize_t tiva_write(FAR struct mtd_dev_s *dev, off_t offset,
if (regval != 0) if (regval != 0)
{ {
return -EACCES; return -EACCES;
} }
return nbytes; return nbytes;