aboutsummaryrefslogtreecommitdiffstats
path: root/ChibiOS_16.1.5/community/testhal/STM32/STM32F4xx/FSMC_NAND/main.c
diff options
context:
space:
mode:
authorClyne Sullivan <tullivan99@gmail.com>2016-11-11 15:15:16 -0500
committerClyne Sullivan <tullivan99@gmail.com>2016-11-11 15:15:16 -0500
commit5a059c8d6ecfe2f98a77570b8b6cf13c500398f7 (patch)
treedb8d337eb96c44feff77d5564eb9da697e8b961b /ChibiOS_16.1.5/community/testhal/STM32/STM32F4xx/FSMC_NAND/main.c
parent7772ea4579a45bcf63ebd5e68be66ba1a9c72dfa (diff)
tar'd chibi
Diffstat (limited to 'ChibiOS_16.1.5/community/testhal/STM32/STM32F4xx/FSMC_NAND/main.c')
-rw-r--r--ChibiOS_16.1.5/community/testhal/STM32/STM32F4xx/FSMC_NAND/main.c650
1 files changed, 0 insertions, 650 deletions
diff --git a/ChibiOS_16.1.5/community/testhal/STM32/STM32F4xx/FSMC_NAND/main.c b/ChibiOS_16.1.5/community/testhal/STM32/STM32F4xx/FSMC_NAND/main.c
deleted file mode 100644
index 2379a12..0000000
--- a/ChibiOS_16.1.5/community/testhal/STM32/STM32F4xx/FSMC_NAND/main.c
+++ /dev/null
@@ -1,650 +0,0 @@
-/*
- ChibiOS/RT - Copyright (C) 2013-2014 Uladzimir Pylinsky aka barthess
-
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
-*/
-
-/*
- * Hardware notes.
- *
- * Use external pullup on ready/busy pin of NAND IC for a speed reason.
- *
- * Chose MCU with 140 (or more) pins package because 100 pins packages
- * has no dedicated interrupt pins for FSMC.
- *
- * If your hardware already done using 100 pin package than you have to:
- * 1) connect ready/busy pin to GPIOD6 (NWAIT in terms of STM32)
- * 2) set GPIOD6 pin as input with pullup and connect it to alternate
- * function0 (not function12)
- * 3) set up EXTI to catch raising edge on GPIOD6 and call NAND driver's
- * isr_handler() function from an EXTI callback.
- *
- * If you use MLC flash memory do NOT use ECC to detect/correct
- * errors because of its weakness. Use Rid-Solomon on BCH code instead.
- * Yes, you have to realize it in sowftware yourself.
- */
-
-/*
- * Software notes.
- *
- * For correct calculation of timing values you need AN2784 document
- * from STMicro.
- */
-
-#include "ch.h"
-#include "hal.h"
-
-#include "bitmap.h"
-
-#include "dma_storm.h"
-#include "string.h"
-#include "stdlib.h"
-
-/*
- ******************************************************************************
- * DEFINES
- ******************************************************************************
- */
-
-#define USE_BAD_MAP TRUE
-
-#define USE_KILL_BLOCK_TEST FALSE
-
-#define FSMCNAND_TIME_SET ((uint32_t) 2) //(8nS)
-#define FSMCNAND_TIME_WAIT ((uint32_t) 6) //(30nS)
-#define FSMCNAND_TIME_HOLD ((uint32_t) 1) //(5nS)
-#define FSMCNAND_TIME_HIZ ((uint32_t) 4) //(20nS)
-
-#define NAND_BLOCKS_COUNT 8192
-#define NAND_PAGE_DATA_SIZE 2048
-#define NAND_PAGE_SPARE_SIZE 64
-#define NAND_PAGE_SIZE (NAND_PAGE_SPARE_SIZE + NAND_PAGE_DATA_SIZE)
-#define NAND_PAGES_PER_BLOCK 64
-#define NAND_ROW_WRITE_CYCLES 3
-#define NAND_COL_WRITE_CYCLES 2
-
-#define NAND_TEST_START_BLOCK 1200
-#define NAND_TEST_END_BLOCK 1220
-
-#if USE_KILL_BLOCK_TEST
-#define NAND_TEST_KILL_BLOCK 8000
-#endif
-
-#if STM32_NAND_USE_FSMC_NAND1
- #define NAND NANDD1
-#elif STM32_NAND_USE_FSMC_NAND2
- #define NAND NANDD2
-#else
-#error "You should enable at least one NAND interface"
-#endif
-
-/*
- ******************************************************************************
- * EXTERNS
- ******************************************************************************
- */
-
-/*
- ******************************************************************************
- * PROTOTYPES
- ******************************************************************************
- */
-#if STM32_NAND_USE_EXT_INT
-static void ready_isr_enable(void);
-static void ready_isr_disable(void);
-static void nand_ready_cb(EXTDriver *extp, expchannel_t channel);
-#endif
-
-/*
- ******************************************************************************
- * GLOBAL VARIABLES
- ******************************************************************************
- */
-/*
- *
- */
-static uint8_t nand_buf[NAND_PAGE_SIZE];
-static uint8_t ref_buf[NAND_PAGE_SIZE];
-
-/*
- *
- */
-static time_measurement_t tmu_erase;
-static time_measurement_t tmu_write_data;
-static time_measurement_t tmu_write_spare;
-static time_measurement_t tmu_read_data;
-static time_measurement_t tmu_read_spare;
-static time_measurement_t tmu_driver_start;
-
-#if USE_BAD_MAP
-#define BAD_MAP_LEN (NAND_BLOCKS_COUNT / (sizeof(bitmap_word_t) * 8))
-static bitmap_word_t badblock_map_array[BAD_MAP_LEN];
-static bitmap_t badblock_map = {
- badblock_map_array,
- BAD_MAP_LEN
-};
-#endif
-
-/*
- *
- */
-static const NANDConfig nandcfg = {
- NAND_BLOCKS_COUNT,
- NAND_PAGE_DATA_SIZE,
- NAND_PAGE_SPARE_SIZE,
- NAND_PAGES_PER_BLOCK,
- NAND_ROW_WRITE_CYCLES,
- NAND_COL_WRITE_CYCLES,
- /* stm32 specific fields */
- ((FSMCNAND_TIME_HIZ << 24) | (FSMCNAND_TIME_HOLD << 16) | \
- (FSMCNAND_TIME_WAIT << 8) | FSMCNAND_TIME_SET),
-#if STM32_NAND_USE_EXT_INT
- ready_isr_enable,
- ready_isr_disable
-#endif
-};
-
-/**
- *
- */
-#if STM32_NAND_USE_EXT_INT
-static const EXTConfig extcfg = {
- {
- {EXT_CH_MODE_DISABLED, NULL}, //0
- {EXT_CH_MODE_DISABLED, NULL},
- {EXT_CH_MODE_DISABLED, NULL},
- {EXT_CH_MODE_DISABLED, NULL},
- {EXT_CH_MODE_DISABLED, NULL}, //4
- {EXT_CH_MODE_DISABLED, NULL},
- {EXT_CH_MODE_RISING_EDGE | EXT_MODE_GPIOD, nand_ready_cb},
- {EXT_CH_MODE_DISABLED, NULL},
- {EXT_CH_MODE_DISABLED, NULL}, //8
- {EXT_CH_MODE_DISABLED, NULL},
- {EXT_CH_MODE_DISABLED, NULL},
- {EXT_CH_MODE_DISABLED, NULL},
- {EXT_CH_MODE_DISABLED, NULL}, //12
- {EXT_CH_MODE_DISABLED, NULL},
- {EXT_CH_MODE_DISABLED, NULL},
- {EXT_CH_MODE_DISABLED, NULL},
- {EXT_CH_MODE_DISABLED, NULL}, //16
- {EXT_CH_MODE_DISABLED, NULL},
- {EXT_CH_MODE_DISABLED, NULL},
- {EXT_CH_MODE_DISABLED, NULL},
- {EXT_CH_MODE_DISABLED, NULL}, //20
- {EXT_CH_MODE_DISABLED, NULL},
- {EXT_CH_MODE_DISABLED, NULL},
- }
-};
-#endif /* STM32_NAND_USE_EXT_INT */
-
-static volatile uint32_t BackgroundThdCnt = 0;
-
-#if USE_KILL_BLOCK_TEST
-static uint32_t KillCycle = 0;
-#endif
-
-/*
- ******************************************************************************
- ******************************************************************************
- * LOCAL FUNCTIONS
- ******************************************************************************
- ******************************************************************************
- */
-static void nand_wp_assert(void) {palClearPad(GPIOB, GPIOB_NAND_WP);}
-static void nand_wp_release(void) {palSetPad(GPIOB, GPIOB_NAND_WP);}
-static void red_led_on(void) {palSetPad(GPIOI, GPIOI_LED_R);}
-static void red_led_off(void) {palClearPad(GPIOI, GPIOI_LED_R);}
-
-#if STM32_NAND_USE_EXT_INT
-static void nand_ready_cb(EXTDriver *extp, expchannel_t channel){
- (void)extp;
- (void)channel;
-
- NAND.isr_handler(&NAND);
-}
-
-static void ready_isr_enable(void) {
- extChannelEnable(&EXTD1, GPIOD_NAND_RB_NWAIT);
-}
-
-static void ready_isr_disable(void) {
- extChannelDisable(&EXTD1, GPIOD_NAND_RB_NWAIT);
-}
-#endif /* STM32_NAND_USE_EXT_INT */
-
-/**
- *
- */
-static THD_WORKING_AREA(BackgroundThreadWA, 128);
-static THD_FUNCTION(BackgroundThread, arg) {
- (void)arg;
-
- while(true){
- BackgroundThdCnt++;
- }
-}
-
-/*
- *
- */
-static bool is_erased(NANDDriver *dp, size_t block){
- uint32_t page = 0;
- size_t i = 0;
-
- for (page=0; page<NAND.config->pages_per_block; page++){
- nandReadPageData(dp, block, page, nand_buf, NAND.config->page_data_size, NULL);
- nandReadPageSpare(dp, block, page, &nand_buf[2048], NAND.config->page_spare_size);
- for (i=0; i<sizeof(nand_buf); i++) {
- if (nand_buf[i] != 0xFF)
- return false;
- }
- }
-
- return true;
-}
-
-/*
- *
- */
-static void pattern_fill(void) {
-
- size_t i;
-
- srand(chSysGetRealtimeCounterX());
-
- for(i=0; i<NAND_PAGE_SIZE; i++){
- ref_buf[i] = rand() & 0xFF;
- }
-
- /* protect bad mark */
- ref_buf[NAND_PAGE_DATA_SIZE] = 0xFF;
- ref_buf[NAND_PAGE_DATA_SIZE + 1] = 0xFF;
- memcpy(nand_buf, ref_buf, NAND_PAGE_SIZE);
-
- /* paranoid mode ON */
- osalDbgCheck(0 == memcmp(ref_buf, nand_buf, NAND_PAGE_SIZE));
-}
-
-/*
- *
- */
-#if USE_KILL_BLOCK_TEST
-static void kill_block(NANDDriver *nandp, uint32_t block){
-
- size_t i = 0;
- size_t page = 0;
- uint8_t op_status;
-
- /* This test requires good block.*/
- osalDbgCheck(!nandIsBad(nandp, block));
-
- while(true){
- op_status = nandErase(&NAND, block);
- if (0 != (op_status & 1)){
- if(!is_erased(nandp, block))
- osalSysHalt("Block successfully killed");
- }
- if(!is_erased(nandp, block))
- osalSysHalt("Block block not erased, but erase operation report success");
-
- for (page=0; page<nandp->config->pages_per_block; page++){
- memset(nand_buf, 0, NAND_PAGE_SIZE);
- op_status = nandWritePageWhole(nandp, block, page, nand_buf, NAND_PAGE_SIZE);
- if (0 != (op_status & 1)){
- nandReadPageWhole(nandp, block, page, nand_buf, NAND_PAGE_SIZE);
- for (i=0; i<NAND_PAGE_SIZE; i++){
- if (nand_buf[i] != 0)
- osalSysHalt("Block successfully killed");
- }
- }
-
- nandReadPageWhole(nandp, block, page, nand_buf, NAND_PAGE_SIZE);
- for (i=0; i<NAND_PAGE_SIZE; i++){
- if (nand_buf[i] != 0)
- osalSysHalt("Page write failed, but write operation report success");
- }
- }
- KillCycle++;
- }
-}
-#endif /* USE_KILL_BLOCK_TEST */
-
-/*
- *
- */
-typedef enum {
- ECC_NO_ERROR = 0,
- ECC_CORRECTABLE_ERROR = 1,
- ECC_UNCORRECTABLE_ERROR = 2,
- ECC_CORRUPTED = 3,
-} ecc_result_t;
-
-/*
- *
- */
-static ecc_result_t parse_ecc(uint32_t ecclen,
- uint32_t ecc1, uint32_t ecc2, uint32_t *corrupted){
-
- size_t i = 0;
- uint32_t corr = 0;
- uint32_t e = 0;
- uint32_t shift = (32 - ecclen);
- uint32_t b0, b1;
-
- ecc1 <<= shift;
- ecc1 >>= shift;
- ecc2 <<= shift;
- ecc2 >>= shift;
- e = ecc1 ^ ecc2;
-
- if (0 == e){
- return ECC_NO_ERROR;
- }
- else if (((e - 1) & e) == 0){
- return ECC_CORRUPTED;
- }
- else {
- for (i=0; i<ecclen/2; i++){
- b0 = e & 1;
- e >>= 1;
- b1 = e & 1;
- e >>= 1;
- if ((b0 + b1) != 1)
- return ECC_UNCORRECTABLE_ERROR;
- corr |= b1 << i;
- }
- *corrupted = corr;
- return ECC_CORRECTABLE_ERROR;
- }
-}
-
-/*
- *
- */
-static void invert_bit(uint8_t *buf, uint32_t byte, uint32_t bit){
- osalDbgCheck((byte < NAND_PAGE_DATA_SIZE) && (bit < 8));
- buf[byte] ^= ((uint8_t)1) << bit;
-}
-
-/*
- *
- */
-static void ecc_test(NANDDriver *nandp, uint32_t block){
-
- uint32_t corrupted;
- uint32_t byte, bit;
- const uint32_t ecclen = 28;
- uint32_t ecc_ref, ecc_broken;
- uint8_t op_status;
- ecc_result_t ecc_result = ECC_NO_ERROR;
-
- /* This test requires good block.*/
- osalDbgCheck(!nandIsBad(nandp, block));
- if (!is_erased(nandp, block))
- nandErase(&NAND, block);
-
- pattern_fill();
-
- /*** Correctable errors ***/
- op_status = nandWritePageData(nandp, block, 0,
- nand_buf, nandp->config->page_data_size, &ecc_ref);
- osalDbgCheck(0 == (op_status & 1)); /* operation failed */
- nandReadPageData(nandp, block, 0,
- nand_buf, nandp->config->page_data_size, &ecc_broken);
- ecc_result = parse_ecc(ecclen, ecc_ref, ecc_broken, &corrupted);
- osalDbgCheck(ECC_NO_ERROR == ecc_result); /* unexpected error */
-
- /**/
- byte = 0;
- bit = 7;
- invert_bit(nand_buf, byte, bit);
- op_status = nandWritePageData(nandp, block, 1,
- nand_buf, nandp->config->page_data_size, &ecc_broken);
- osalDbgCheck(0 == (op_status & 1)); /* operation failed */
- invert_bit(nand_buf, byte, bit);
- ecc_result = parse_ecc(ecclen, ecc_ref, ecc_broken, &corrupted);
- osalDbgCheck(ECC_CORRECTABLE_ERROR == ecc_result); /* this error must be correctable */
- osalDbgCheck(corrupted == (byte * 8 + bit)); /* wrong correction code */
-
- /**/
- byte = 2047;
- bit = 0;
- invert_bit(nand_buf, byte, bit);
- op_status = nandWritePageData(nandp, block, 2,
- nand_buf, nandp->config->page_data_size, &ecc_broken);
- osalDbgCheck(0 == (op_status & 1)); /* operation failed */
- invert_bit(nand_buf, byte, bit);
- ecc_result = parse_ecc(ecclen, ecc_ref, ecc_broken, &corrupted);
- osalDbgCheck(ECC_CORRECTABLE_ERROR == ecc_result); /* this error must be correctable */
- osalDbgCheck(corrupted == (byte * 8 + bit)); /* wrong correction code */
-
- /**/
- byte = 1027;
- bit = 3;
- invert_bit(nand_buf, byte, bit);
- op_status = nandWritePageData(nandp, block, 3,
- nand_buf, nandp->config->page_data_size, &ecc_broken);
- osalDbgCheck(0 == (op_status & 1)); /* operation failed */
- invert_bit(nand_buf, byte, bit);
- ecc_result = parse_ecc(ecclen, ecc_ref, ecc_broken, &corrupted);
- osalDbgCheck(ECC_CORRECTABLE_ERROR == ecc_result); /* this error must be correctable */
- osalDbgCheck(corrupted == (byte * 8 + bit)); /* wrong correction code */
-
- /*** Uncorrectable error ***/
- byte = 1027;
- invert_bit(nand_buf, byte, 3);
- invert_bit(nand_buf, byte, 4);
- op_status = nandWritePageData(nandp, block, 4,
- nand_buf, nandp->config->page_data_size, &ecc_broken);
- osalDbgCheck(0 == (op_status & 1)); /* operation failed */
- invert_bit(nand_buf, byte, 3);
- invert_bit(nand_buf, byte, 4);
- ecc_result = parse_ecc(28, ecc_ref, ecc_broken, &corrupted);
- osalDbgCheck(ECC_UNCORRECTABLE_ERROR == ecc_result); /* This error must be NOT correctable */
-
- /*** make clean ***/
- nandErase(&NAND, block);
-}
-
-/*
- *
- */
-static void general_test (NANDDriver *nandp, size_t first,
- size_t last, size_t read_rounds){
-
- size_t block, page, round;
- bool status;
- uint8_t op_status;
- uint32_t recc, wecc;
-
- red_led_on();
-
- /* initialize time measurement units */
- chTMObjectInit(&tmu_erase);
- chTMObjectInit(&tmu_write_data);
- chTMObjectInit(&tmu_write_spare);
- chTMObjectInit(&tmu_read_data);
- chTMObjectInit(&tmu_read_spare);
-
- /* perform basic checks */
- for (block=first; block<last; block++){
- if (!nandIsBad(nandp, block)){
- if (!is_erased(nandp, block)){
- op_status = nandErase(nandp, block);
- osalDbgCheck(0 == (op_status & 1)); /* operation failed */
- }
- }
- }
-
- /* write block with pattern, read it back and compare */
- for (block=first; block<last; block++){
- if (!nandIsBad(nandp, block)){
- for (page=0; page<nandp->config->pages_per_block; page++){
- pattern_fill();
-
- chTMStartMeasurementX(&tmu_write_data);
- op_status = nandWritePageData(nandp, block, page,
- nand_buf, nandp->config->page_data_size, &wecc);
- chTMStopMeasurementX(&tmu_write_data);
- osalDbgCheck(0 == (op_status & 1)); /* operation failed */
-
- chTMStartMeasurementX(&tmu_write_spare);
- op_status = nandWritePageSpare(nandp, block, page,
- nand_buf + nandp->config->page_data_size,
- nandp->config->page_spare_size);
- chTMStopMeasurementX(&tmu_write_spare);
- osalDbgCheck(0 == (op_status & 1)); /* operation failed */
-
- /* read back and compare */
- for (round=0; round<read_rounds; round++){
- memset(nand_buf, 0, NAND_PAGE_SIZE);
-
- chTMStartMeasurementX(&tmu_read_data);
- nandReadPageData(nandp, block, page,
- nand_buf, nandp->config->page_data_size, &recc);
- chTMStopMeasurementX(&tmu_read_data);
- osalDbgCheck(0 == (recc ^ wecc)); /* ECC error detected */
-
- chTMStartMeasurementX(&tmu_read_spare);
- nandReadPageSpare(nandp, block, page,
- nand_buf + nandp->config->page_data_size,
- nandp->config->page_spare_size);
- chTMStopMeasurementX(&tmu_read_spare);
-
- osalDbgCheck(0 == memcmp(ref_buf, nand_buf, NAND_PAGE_SIZE)); /* Read back failed */
- }
- }
-
- /* make clean */
- chTMStartMeasurementX(&tmu_erase);
- op_status = nandErase(nandp, block);
- chTMStopMeasurementX(&tmu_erase);
- osalDbgCheck(0 == (op_status & 1)); /* operation failed */
-
- status = is_erased(nandp, block);
- osalDbgCheck(true == status); /* blocks was not erased successfully */
- }/* if (!nandIsBad(nandp, block)){ */
- }
- red_led_off();
-}
-
-
-/*
- ******************************************************************************
- * EXPORTED FUNCTIONS
- ******************************************************************************
- */
-
-/*
- * Application entry point.
- */
-int main(void) {
-
- /* performance counters */
- int32_t adc_ints = 0;
- int32_t spi_ints = 0;
- int32_t uart_ints = 0;
- int32_t adc_idle_ints = 0;
- int32_t spi_idle_ints = 0;
- int32_t uart_idle_ints = 0;
- uint32_t background_cnt = 0;
- systime_t T = 0;
-
- /*
- * System initializations.
- * - HAL initialization, this also initializes the configured device drivers
- * and performs the board-specific initializations.
- * - Kernel initialization, the main() function becomes a thread and the
- * RTOS is active.
- */
- halInit();
- chSysInit();
-
-#if STM32_NAND_USE_EXT_INT
- extStart(&EXTD1, &extcfg);
-#endif
- chTMObjectInit(&tmu_driver_start);
- chTMStartMeasurementX(&tmu_driver_start);
-#if USE_BAD_MAP
- nandStart(&NAND, &nandcfg, &badblock_map);
-#else
- nandStart(&NAND, &nandcfg, NULL);
-#endif
- chTMStopMeasurementX(&tmu_driver_start);
-
- chThdSleepMilliseconds(4000);
-
- chThdCreateStatic(BackgroundThreadWA,
- sizeof(BackgroundThreadWA),
- NORMALPRIO - 20,
- BackgroundThread,
- NULL);
-
- nand_wp_release();
-
- /*
- * run NAND test in parallel with DMA load and background thread
- */
- dma_storm_adc_start();
- dma_storm_uart_start();
- dma_storm_spi_start();
- T = chVTGetSystemTimeX();
- general_test(&NAND, NAND_TEST_START_BLOCK, NAND_TEST_END_BLOCK, 1);
- T = chVTGetSystemTimeX() - T;
- adc_ints = dma_storm_adc_stop();
- uart_ints = dma_storm_uart_stop();
- spi_ints = dma_storm_spi_stop();
- chSysLock();
- background_cnt = BackgroundThdCnt;
- BackgroundThdCnt = 0;
- chSysUnlock();
-
- /*
- * run DMA load and background thread _without_ NAND test
- */
- dma_storm_adc_start();
- dma_storm_uart_start();
- dma_storm_spi_start();
- chThdSleep(T);
- adc_idle_ints = dma_storm_adc_stop();
- uart_idle_ints = dma_storm_uart_stop();
- spi_idle_ints = dma_storm_spi_stop();
-
- /*
- * ensure that NAND code have negligible impact on other subsystems
- */
- osalDbgCheck(background_cnt > (BackgroundThdCnt / 4));
- osalDbgCheck(abs(adc_ints - adc_idle_ints) < (adc_idle_ints / 20));
- osalDbgCheck(abs(uart_ints - uart_idle_ints) < (uart_idle_ints / 20));
- osalDbgCheck(abs(spi_ints - spi_idle_ints) < (spi_idle_ints / 10));
-
- /*
- * perform ECC calculation test
- */
- ecc_test(&NAND, NAND_TEST_END_BLOCK);
-
-#if USE_KILL_BLOCK_TEST
- kill_block(&NAND, NAND_TEST_KILL_BLOCK);
-#endif
-
- nand_wp_assert();
-
- /*
- * Normal main() thread activity, in this demo it does nothing.
- */
- while (true) {
- chThdSleepMilliseconds(500);
- }
-}
-
-