From: David B. <dbr...@us...> - 2009-11-27 09:00:44
|
This is an automated email from the git hooks/post-receive script. It was generated because a ref change was pushed to the repository containing the project "Main OpenOCD repository". The branch, master has been updated via 2221a037447b61b8a9db500ba997e61dbe874d61 (commit) via 8f3c728273e9b89070259d6120117f6a190dd773 (commit) via 05a5f682c6cff5bba3b54ec7d8bd0ad6b7a72054 (commit) via ffc704fdeb406abff1a61f4f6a0423535db939fd (commit) via 7c9cd4789316a1933f5c1e217d1e01e6d417decb (commit) from fd5f53f035ed7af472b3edfa0afaba9c9af667a0 (commit) Those revisions listed above that are new to this repository have not appeared on any other notification email; so we list those revisions in full, below. - Log ----------------------------------------------------------------- commit 2221a037447b61b8a9db500ba997e61dbe874d61 Author: Dean Glazeski <dn...@gm...> Date: Mon Nov 16 12:47:45 2009 -0600 ARM NAND I/O header documentation update. Fixed the header file to properly specify the doxygen documentation for the items defined in it. Signed-off-by: David Brownell <dbr...@us...> diff --git a/src/flash/arm_nandio.h b/src/flash/arm_nandio.h index fbe1f88..115a13a 100644 --- a/src/flash/arm_nandio.h +++ b/src/flash/arm_nandio.h @@ -1,20 +1,24 @@ #ifndef __ARM_NANDIO_H -#define __ARM_NANDIO_H +#define __ARM_NANDIO_H #include "nand.h" #include "binarybuffer.h" +/** + * The arm_nand_data struct is used for defining NAND I/O operations on an ARM + * core. + */ struct arm_nand_data { - /* target is proxy for some ARM core */ + /** target is proxy for some ARM core */ struct target *target; - /* copy_area holds write-to-NAND loop and data to write */ + /** copy_area holds write-to-NAND loop and data to write */ struct working_area *copy_area; - /* chunk_size == page or ECC unit */ + /** chunk_size == page or ECC unit */ unsigned chunk_size; - /* data == where to write the data */ + /** data == where to write the data */ uint32_t data; /* currently implicit: data width == 8 bits (not 16) */ @@ -23,4 +27,4 @@ struct arm_nand_data { int arm_nandwrite(struct arm_nand_data *nand, uint8_t *data, int size); int arm_nandread(struct arm_nand_data *nand, uint8_t *data, uint32_t size); -#endif /* __ARM_NANDIO_H */ +#endif /* __ARM_NANDIO_H */ commit 8f3c728273e9b89070259d6120117f6a190dd773 Author: Dean Glazeski <dn...@gm...> Date: Mon Nov 16 12:43:39 2009 -0600 ARM NAND I/O documentation update. This updates the functions in the file to all have doxygen comments describing what they do. Signed-off-by: David Brownell <dbr...@us...> diff --git a/src/flash/arm_nandio.c b/src/flash/arm_nandio.c index 990d3a0..f774b61 100644 --- a/src/flash/arm_nandio.c +++ b/src/flash/arm_nandio.c @@ -68,7 +68,7 @@ int arm_code_to_working_area(struct target *target, const uint32_t *code, unsign return retval; } -/* +/** * ARM-specific bulk write from buffer to address of 8-bit wide NAND. * For now this only supports ARMv4 and ARMv5 cores. * @@ -78,6 +78,11 @@ int arm_code_to_working_area(struct target *target, const uint32_t *code, unsign * Different code fragments could handle: * - Thumb2 cores like Cortex-M (needs different byteswapping) * - 16-bit wide data (needs different setup too) + * + * @param nand Pointer to the arm_nand_data struct that defines the I/O + * @param data Pointer to the data to be copied to flash + * @param size Size of the data being copied + * @return Success or failure of the operation */ int arm_nandwrite(struct arm_nand_data *nand, uint8_t *data, int size) { @@ -159,6 +164,7 @@ int arm_nandwrite(struct arm_nand_data *nand, uint8_t *data, int size) * @param nand Pointer to the arm_nand_data struct that defines the I/O * @param data Pointer to the data buffer to store the read data * @param size Amount of data to be stored to the buffer. + * @return Success or failure of the operation */ int arm_nandread(struct arm_nand_data *nand, uint8_t *data, uint32_t size) { commit 05a5f682c6cff5bba3b54ec7d8bd0ad6b7a72054 Author: Dean Glazeski <dn...@gm...> Date: Mon Nov 16 12:26:21 2009 -0600 ARM NAND I/O refactor code copying. Created a function for copying code to the working area on a target. The NAND write and read functions are updated to include use of this function. Signed-off-by: David Brownell <dbr...@us...> diff --git a/src/flash/arm_nandio.c b/src/flash/arm_nandio.c index 20a76f4..990d3a0 100644 --- a/src/flash/arm_nandio.c +++ b/src/flash/arm_nandio.c @@ -28,6 +28,45 @@ #include "armv4_5.h" #include "algorithm.h" +/** + * Copies code to a working area. This will allocate room for the code plus the + * additional amount requested if the working area pointer is null. + * + * @param target Pointer to the target to copy code to + * @param code Pointer to the code area to be copied + * @param code_size Size of the code being copied + * @param additional Size of the additional area to be allocated in addition to + * code + * @param area Pointer to a pointer to a working area to copy code to + * @return Success or failure of the operation + */ +int arm_code_to_working_area(struct target *target, const uint32_t *code, unsigned code_size, + unsigned additional, struct working_area **area) +{ + uint8_t code_buf[code_size]; + unsigned i; + int retval; + unsigned size = code_size + additional; + + /* make sure we have a working area */ + if (NULL == *area) { + retval = target_alloc_working_area(target, size, area); + if (retval != ERROR_OK) { + LOG_DEBUG("%s: no %d byte buffer", __FUNCTION__, (int) size); + return ERROR_NAND_NO_BUFFER; + } + } + + /* buffer code in target endianness */ + for (i = 0; i < code_size / 4; i++) + target_buffer_set_u32(target, code_buf + i * 4, code[i]); + + /* copy code to work area */ + retval = target_write_memory(target, (*area)->address, + 4, code_size / 4, code_buf); + + return retval; +} /* * ARM-specific bulk write from buffer to address of 8-bit wide NAND. @@ -66,29 +105,11 @@ int arm_nandwrite(struct arm_nand_data *nand, uint8_t *data, int size) }; if (!nand->copy_area) { - uint8_t code_buf[sizeof(code)]; - unsigned i; - - /* make sure we have a working area */ - if (target_alloc_working_area(target, - sizeof(code) + nand->chunk_size, - &nand->copy_area) != ERROR_OK) { - LOG_DEBUG("%s: no %d byte buffer", - __FUNCTION__, - (int) sizeof(code) + nand->chunk_size); - return ERROR_NAND_NO_BUFFER; - } - - /* buffer code in target endianness */ - for (i = 0; i < sizeof(code) / 4; i++) - target_buffer_set_u32(target, code_buf + i * 4, code[i]); - - /* copy code to work area */ - retval = target_write_memory(target, - nand->copy_area->address, - 4, sizeof(code) / 4, code_buf); - if (retval != ERROR_OK) + retval = arm_code_to_working_area(target, code, sizeof(code), + nand->chunk_size, &nand->copy_area); + if (retval != ERROR_OK) { return retval; + } } /* copy data to work area */ @@ -139,7 +160,8 @@ int arm_nandwrite(struct arm_nand_data *nand, uint8_t *data, int size) * @param data Pointer to the data buffer to store the read data * @param size Amount of data to be stored to the buffer. */ -int arm_nandread(struct arm_nand_data *nand, uint8_t *data, uint32_t size) { +int arm_nandread(struct arm_nand_data *nand, uint8_t *data, uint32_t size) +{ struct target *target = nand->target; struct armv4_5_algorithm algo; struct arm *armv4_5 = target->arch_info; @@ -165,23 +187,8 @@ int arm_nandread(struct arm_nand_data *nand, uint8_t *data, uint32_t size) { /* create the copy area if not yet available */ if (!nand->copy_area) { - uint8_t code_buf[sizeof(code)]; - unsigned i; - - /* make sure we have a working area */ - retval = target_alloc_working_area(target, sizeof(code) + nand->chunk_size, &nand->copy_area); - if (retval != ERROR_OK) { - LOG_DEBUG("%s: no %d byte buffer", __FUNCTION__, (int) sizeof(code) + nand->chunk_size); - return ERROR_NAND_NO_BUFFER; - } - - /* buffer code in target endianness */ - for (i = 0; i < sizeof(code) / 4; i++) { - target_buffer_set_u32(target, code_buf + i * 4, code[i]); - } - - /* copy code to work area */ - retval = target_write_memory(target, nand->copy_area->address, 4, sizeof(code) / 4, code_buf); + retval = arm_code_to_working_area(target, code, sizeof(code), + nand->chunk_size, &nand->copy_area); if (retval != ERROR_OK) { return retval; } commit ffc704fdeb406abff1a61f4f6a0423535db939fd Author: Dean Glazeski <dn...@gm...> Date: Sun Nov 15 02:32:38 2009 -0600 ARM NAND I/O read function. Implementation of the NAND read function for ARM NAND I/O that includes running a local algorithm on a device to increase the performance of block reads. Signed-off-by: David Brownell <dbr...@us...> diff --git a/src/flash/arm_nandio.c b/src/flash/arm_nandio.c index 81697fa..20a76f4 100644 --- a/src/flash/arm_nandio.c +++ b/src/flash/arm_nandio.c @@ -131,5 +131,94 @@ int arm_nandwrite(struct arm_nand_data *nand, uint8_t *data, int size) return retval; } -/* REVISIT do the same for bulk *read* too ... */ +/** + * Uses an on-chip algorithm for an ARM device to read from a NAND device and + * store the data into the host machine's memory. + * + * @param nand Pointer to the arm_nand_data struct that defines the I/O + * @param data Pointer to the data buffer to store the read data + * @param size Amount of data to be stored to the buffer. + */ +int arm_nandread(struct arm_nand_data *nand, uint8_t *data, uint32_t size) { + struct target *target = nand->target; + struct armv4_5_algorithm algo; + struct arm *armv4_5 = target->arch_info; + struct reg_param reg_params[3]; + uint32_t target_buf; + uint32_t exit = 0; + int retval; + + /* Inputs: + * r0 buffer address + * r1 NAND data address (byte wide) + * r2 buffer length + */ + static const uint32_t code[] = { + 0xe5d13000, /* s: ldrb r3, [r1] */ + 0xe4c03001, /* strb r3, [r0], #1 */ + 0xe2522001, /* subs r2, r2, #1 */ + 0x1afffffb, /* bne s */ + + /* exit: ARMv4 needs hardware breakpoint */ + 0xe1200070, /* e: bkpt #0 */ + }; + + /* create the copy area if not yet available */ + if (!nand->copy_area) { + uint8_t code_buf[sizeof(code)]; + unsigned i; + + /* make sure we have a working area */ + retval = target_alloc_working_area(target, sizeof(code) + nand->chunk_size, &nand->copy_area); + if (retval != ERROR_OK) { + LOG_DEBUG("%s: no %d byte buffer", __FUNCTION__, (int) sizeof(code) + nand->chunk_size); + return ERROR_NAND_NO_BUFFER; + } + + /* buffer code in target endianness */ + for (i = 0; i < sizeof(code) / 4; i++) { + target_buffer_set_u32(target, code_buf + i * 4, code[i]); + } + + /* copy code to work area */ + retval = target_write_memory(target, nand->copy_area->address, 4, sizeof(code) / 4, code_buf); + if (retval != ERROR_OK) { + return retval; + } + } + + target_buf = nand->copy_area->address + sizeof(code); + + /* set up algorithm and parameters */ + algo.common_magic = ARMV4_5_COMMON_MAGIC; + algo.core_mode = ARMV4_5_MODE_SVC; + algo.core_state = ARMV4_5_STATE_ARM; + + init_reg_param(®_params[0], "r0", 32, PARAM_IN); + init_reg_param(®_params[1], "r1", 32, PARAM_IN); + init_reg_param(®_params[2], "r2", 32, PARAM_IN); + + buf_set_u32(reg_params[0].value, 0, 32, target_buf); + buf_set_u32(reg_params[1].value, 0, 32, nand->data); + buf_set_u32(reg_params[2].value, 0, 32, size); + + /* armv4 must exit using a hardware breakpoint */ + if (armv4_5->is_armv4) + exit = nand->copy_area->address + sizeof(code) - 4; + + /* use alg to write data from NAND chip to work area */ + retval = target_run_algorithm(target, 0, NULL, 3, reg_params, + nand->copy_area->address, exit, 1000, &algo); + if (retval != ERROR_OK) + LOG_ERROR("error executing hosted NAND write"); + + destroy_reg_param(®_params[0]); + destroy_reg_param(®_params[1]); + destroy_reg_param(®_params[2]); + + /* read from work area to the host's memory */ + retval = target_read_buffer(target, target_buf, size, data); + + return retval; +} diff --git a/src/flash/arm_nandio.h b/src/flash/arm_nandio.h index a1bed32..fbe1f88 100644 --- a/src/flash/arm_nandio.h +++ b/src/flash/arm_nandio.h @@ -21,5 +21,6 @@ struct arm_nand_data { }; int arm_nandwrite(struct arm_nand_data *nand, uint8_t *data, int size); +int arm_nandread(struct arm_nand_data *nand, uint8_t *data, uint32_t size); #endif /* __ARM_NANDIO_H */ commit 7c9cd4789316a1933f5c1e217d1e01e6d417decb Author: Dean Glazeski <dn...@gm...> Date: Tue Nov 17 14:16:23 2009 -0600 NAND Flash documentation update. Updated doxygen comments for different interface structures for the NAND interface. Signed-off-by: David Brownell <dbr...@us...> diff --git a/src/flash/nand.h b/src/flash/nand.h index b780f28..a30a654 100644 --- a/src/flash/nand.h +++ b/src/flash/nand.h @@ -32,32 +32,78 @@ struct nand_device; #define __NAND_DEVICE_COMMAND(name) \ COMMAND_HELPER(name, struct nand_device *nand) +/** + * Interface for NAND flash controllers. Not all of these functions are + * required for full functionality of the NAND driver, but better performance + * can be achieved by implementing each function. + */ struct nand_flash_controller { + /** Driver name that is used to select it from configuration files. */ char *name; - const struct command_registration *commands; + + const struct command_registration *commands; + + /** NAND device command called when driver is instantiated during configuration. */ __NAND_DEVICE_COMMAND((*nand_device_command)); + + /** Register controller specific commands as a TCL interface to the driver. */ + int (*register_commands)(struct command_context *cmd_ctx); + + /** Initialize the NAND device. */ int (*init)(struct nand_device *nand); + + /** Reset the NAND device. */ int (*reset)(struct nand_device *nand); + + /** Issue a command to the NAND device. */ int (*command)(struct nand_device *nand, uint8_t command); + + /** Write an address to the NAND device. */ int (*address)(struct nand_device *nand, uint8_t address); + + /** Write word of data to the NAND device. */ int (*write_data)(struct nand_device *nand, uint16_t data); + + /** Read word of data from the NAND device. */ int (*read_data)(struct nand_device *nand, void *data); + + /** Write a block of data to the NAND device. */ int (*write_block_data)(struct nand_device *nand, uint8_t *data, int size); + + /** Read a block of data from the NAND device. */ int (*read_block_data)(struct nand_device *nand, uint8_t *data, int size); + + /** Write a page to the NAND device. */ int (*write_page)(struct nand_device *nand, uint32_t page, uint8_t *data, uint32_t data_size, uint8_t *oob, uint32_t oob_size); + + /** Read a page from the NAND device. */ int (*read_page)(struct nand_device *nand, uint32_t page, uint8_t *data, uint32_t data_size, uint8_t *oob, uint32_t oob_size); + + /** Check if the controller is ready for more instructions with timeout. */ int (*controller_ready)(struct nand_device *nand, int timeout); + + /** Check if the NAND device is ready for more instructions with timeout. */ int (*nand_ready)(struct nand_device *nand, int timeout); }; #define NAND_DEVICE_COMMAND_HANDLER(name) static __NAND_DEVICE_COMMAND(name) +/** + * Representation of a single NAND block in a NAND device. + */ struct nand_block { + /** Offset to the block. */ uint32_t offset; + + /** Size of the block. */ uint32_t size; + + /** True if the block has been erased. */ int is_erased; + + /** True if the block is bad. */ int is_bad; }; ----------------------------------------------------------------------- Summary of changes: src/flash/arm_nandio.c | 150 ++++++++++++++++++++++++++++++++++++++++-------- src/flash/arm_nandio.h | 17 ++++-- src/flash/nand.h | 48 +++++++++++++++- 3 files changed, 184 insertions(+), 31 deletions(-) hooks/post-receive -- Main OpenOCD repository |