source: rtems/c/src/lib/libbsp/arm/lpc32xx/misc/nand-mlc-write-blocks.c @ baa12f26

4.115
Last change on this file since baa12f26 was 3103d4cb, checked in by Sebastian Huber <sebastian.huber@…>, on 06/23/10 at 08:27:57

2010-06-23 Sebastian Huber <sebastian.huber@…>

  • make/custom/lpc32xx_mzx_boot_int.cfg, startup/linkcmds.lpc32xx_mzx_boot_int: Removed files.
  • include/boot.h, include/emc.h, include/i2c.h, include/nand-mlc.h, make/custom/lpc32xx_mzx.cfg, make/custom/lpc32xx_mzx_stage_1.cfg, make/custom/lpc32xx_mzx_stage_2.cfg, misc/boot.c, misc/emc.c, misc/i2c.c, misc/nand-mlc.c, misc/nand-mlc-read-blocks.c, misc/nand-mlc-write-blocks.c, misc/restart.c, startup/linkcmds.lpc32xx, startup/linkcmds.lpc32xx_mzx, startup/linkcmds.lpc32xx_mzx_stage_1, startup/linkcmds.lpc32xx_mzx_stage_2: New files.
  • configure.ac, Makefile.am, preinstall.am: Reflect changes above.
  • include/bsp.h, include/lpc32xx.h, irq/irq.c, rtc/rtc-config.c, startup/bspstart.c, startup/bspstarthooks.c, startup/linkcmds.lpc32xx_phycore: Changes throughout.
  • Property mode set to 100644
File size: 3.5 KB
Line 
1/**
2 * @file
3 *
4 * @ingroup lpc32xx_nand_mlc
5 *
6 * @brief lpc32xx_mlc_write_blocks() implementation.
7 */
8
9/*
10 * Copyright (c) 2010
11 * embedded brains GmbH
12 * Obere Lagerstr. 30
13 * D-82178 Puchheim
14 * Germany
15 * <rtems@embedded-brains.de>
16 *
17 * The license and distribution terms for this file may be
18 * found in the file LICENSE in this distribution or at
19 * http://www.rtems.com/license/LICENSE.
20 */
21
22#include <bsp/nand-mlc.h>
23
24#include <string.h>
25
26#include <bsp.h>
27
28static const uint32_t ones_spare [MLC_LARGE_SPARE_WORD_COUNT] = {
29  0xffffffff,
30  0xffffffff,
31  0xffffffff,
32  0xffffffff,
33  0xffffffff,
34  0xffffffff,
35  0xffffffff,
36  0xffffffff,
37  0xffffffff,
38  0xffffffff,
39  0xffffffff,
40  0xffffffff,
41  0xffffffff,
42  0xffffffff,
43  0xffffffff,
44  0xffffffff
45};
46
47static void zero_block(uint32_t first_page_of_block, uint32_t pages_per_block)
48{
49  uint32_t page = 0;
50
51  for (page = 0; page < pages_per_block; ++page) {
52    lpc32xx_mlc_write_page_with_ecc(
53      first_page_of_block + page,
54      lpc32xx_magic_zero_begin,
55      lpc32xx_magic_zero_begin
56    );
57  }
58}
59
60static bool is_bad_page(
61  uint32_t first_page_of_block,
62  uint32_t page
63)
64{
65  uint32_t spare [MLC_LARGE_SPARE_WORD_COUNT];
66
67  memset(spare, 0, MLC_LARGE_SPARE_SIZE);
68  lpc32xx_mlc_read_page(
69    first_page_of_block + page,
70    lpc32xx_magic_zero_begin,
71    spare
72  );
73  return lpc32xx_mlc_is_bad_page(spare);
74}
75
76static rtems_status_code erase_block(
77  uint32_t block,
78  uint32_t first_page_of_block,
79  uint32_t pages_per_block
80)
81{
82  rtems_status_code sc = RTEMS_SUCCESSFUL;
83
84  if (is_bad_page(first_page_of_block, 0)) {
85    return RTEMS_IO_ERROR;
86  }
87
88  if (is_bad_page(first_page_of_block, 1)) {
89    return RTEMS_IO_ERROR;
90  }
91
92  sc = lpc32xx_mlc_erase_block(block);
93  if (sc != RTEMS_SUCCESSFUL) {
94    zero_block(first_page_of_block, pages_per_block);
95
96    return RTEMS_IO_ERROR;
97  }
98
99  return RTEMS_SUCCESSFUL;
100}
101
102rtems_status_code lpc32xx_mlc_write_blocks(
103  uint32_t block_begin,
104  uint32_t block_end,
105  const void *src,
106  size_t src_size,
107  uint32_t *page_data_buffer
108)
109{
110  rtems_status_code sc = RTEMS_SUCCESSFUL;
111  uint32_t pages_per_block = lpc32xx_mlc_pages_per_block();
112  uint32_t block_count = lpc32xx_mlc_block_count();
113  uint32_t page_size = lpc32xx_mlc_page_size();
114  uint32_t block = 0;
115  const uint8_t *current = src;
116  const uint8_t *last = current;
117  const uint8_t *end = current + src_size;
118
119  if (block_begin > block_end || block_end > block_count) {
120    return RTEMS_INVALID_ID;
121  }
122
123  for (block = block_begin; block != block_end; ++block) {
124    uint32_t first_page_of_block = block * pages_per_block;
125    uint32_t page = 0;
126
127    sc = erase_block(block, first_page_of_block, pages_per_block);
128    if (sc != RTEMS_SUCCESSFUL) {
129      continue;
130    }
131
132    for (page = 0; page < pages_per_block; ++page) {
133      uintptr_t remainder = (uintptr_t) end - (uintptr_t) current;
134      size_t delta = remainder < page_size ? remainder : page_size;
135
136      if (remainder > 0) {
137        memcpy(page_data_buffer, current, delta);
138        sc = lpc32xx_mlc_write_page_with_ecc(
139          first_page_of_block + page,
140          page_data_buffer,
141          ones_spare
142        );
143        if (sc != RTEMS_SUCCESSFUL) {
144          erase_block(block, first_page_of_block, pages_per_block);
145          zero_block(first_page_of_block, pages_per_block);
146          current = last;
147          continue;
148        }
149
150        current += delta;
151      } else {
152        goto done;
153      }
154    }
155
156    last = current;
157  }
158
159done:
160
161  if (current != end) {
162    return RTEMS_IO_ERROR;
163  }
164
165  return RTEMS_SUCCESSFUL;
166}
Note: See TracBrowser for help on using the repository browser.