aboutsummaryrefslogtreecommitdiffstats
path: root/os/hal/ports/STM32/LLD/emcnand_lld.c
diff options
context:
space:
mode:
Diffstat (limited to 'os/hal/ports/STM32/LLD/emcnand_lld.c')
-rw-r--r--os/hal/ports/STM32/LLD/emcnand_lld.c545
1 files changed, 0 insertions, 545 deletions
diff --git a/os/hal/ports/STM32/LLD/emcnand_lld.c b/os/hal/ports/STM32/LLD/emcnand_lld.c
deleted file mode 100644
index 9ed6db9bd..000000000
--- a/os/hal/ports/STM32/LLD/emcnand_lld.c
+++ /dev/null
@@ -1,545 +0,0 @@
-/*
- ChibiOS/HAL - Copyright (C) 2006-2014 Giovanni Di Sirio
-
- 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.
-*/
-/*
- Concepts and parts of this file have been contributed by Uladzimir Pylinsky
- aka barthess.
- */
-
-/**
- * @file emcnand_lld.c
- * @brief EMCNAND Driver subsystem low level driver source template.
- *
- * @addtogroup EMCNAND
- * @{
- */
-
-#include "hal.h"
-
-#if HAL_USE_EMCNAND || defined(__DOXYGEN__)
-
-/*===========================================================================*/
-/* Driver local definitions. */
-/*===========================================================================*/
-#define EMCNAND_DMA_CHANNEL \
- STM32_DMA_GETCHANNEL(STM32_EMCNAND_EMCNAND1_DMA_STREAM, \
- STM32_EMC_DMA_CHN)
-
-/*===========================================================================*/
-/* Driver exported variables. */
-/*===========================================================================*/
-
-/**
- * @brief EMCNAND1 driver identifier.
- */
-#if STM32_EMCNAND_USE_EMCNAND1 || defined(__DOXYGEN__)
-EMCNANDDriver EMCNANDD1;
-#endif
-
-/**
- * @brief EMCNAND2 driver identifier.
- */
-#if STM32_EMCNAND_USE_EMCNAND2 || defined(__DOXYGEN__)
-EMCNANDDriver EMCNANDD2;
-#endif
-
-/*===========================================================================*/
-/* Driver local types. */
-/*===========================================================================*/
-
-/*===========================================================================*/
-/* Driver local variables and types. */
-/*===========================================================================*/
-
-/*===========================================================================*/
-/* Driver local functions. */
-/*===========================================================================*/
-/**
- * @brief Wakes up the waiting thread.
- *
- * @param[in] emcnandp pointer to the @p EMCNANDDriver object
- * @param[in] msg wakeup message
- *
- * @notapi
- */
-static void wakeup_isr(EMCNANDDriver *emcnandp){
-
- osalDbgCheck(emcnandp->thread != NULL);
- osalThreadResumeI(&emcnandp->thread, MSG_OK);
-}
-
-/**
- * @brief Put calling thread in suspend and switch driver state
- *
- * @param[in] emcnandp pointer to the @p EMCNANDDriver object
- */
-static void emcnand_lld_suspend_thread(EMCNANDDriver *emcnandp) {
-
- //emcnandp->thread = chThdGetSelfX();
- osalThreadSuspendS(&emcnandp->thread);
-}
-
-/**
- * @brief Caclulate ECCPS register value
- *
- * @param[in] emcnandp pointer to the @p EMCNANDDriver object
- */
-static uint32_t calc_eccps(EMCNANDDriver *emcnandp){
-
- uint32_t i = 0;
- uint32_t eccps = emcnandp->config->page_data_size;
-
- eccps = eccps >> 9;
- while (eccps > 0){
- i++;
- eccps >>= 1;
- }
-
- return i << 17;
-}
-
-/*===========================================================================*/
-/* Driver interrupt handlers. */
-/*===========================================================================*/
-
-#if STM32_EMC_USE_INT
-/**
- * @brief Enable interrupts from FSMC
- *
- * @param[in] emcnandp pointer to the @p EMCNANDDriver object
- *
- * @notapi
- */
-static void emcnand_ready_isr_enable(EMCNANDDriver *emcnandp) {
- emcnandp->nand->SR |= FSMC_SR_IREN;
- osalSysHalt("Function untested");
-}
-
-/**
- * @brief Disable interrupts from FSMC
- *
- * @param[in] emcnandp pointer to the @p EMCNANDDriver object
- *
- * @notapi
- */
-static void emcnand_ready_isr_disable(EMCNANDDriver *emcnandp) {
- emcnandp->nand->SR &= ~FSMC_SR_IREN;
- osalSysHalt("Function untested");
-}
-
-/**
- * @brief Ready interrupt handler
- *
- * @param[in] emcnandp pointer to the @p EMCNANDDriver object
- * @param[in] flags flags passed from FSMC intrrupt handler
- *
- * @notapi
- */
-static void emcnand_isr_handler (EMCNANDDriver *emcnandp,
- emcnandflags_t flags){
- (void)emcnandp;
- (void)flags;
-
- osalSysHalt("Unrealized");
-}
-#else /* STM32_EMC_USE_INT */
-/**
- * @brief Disable interrupts from EXTI
- *
- * @param[in] emcnandp pointer to the @p EMCNANDDriver object
- *
- * @notapi
- */
-static void emcnand_ready_isr_enable(EMCNANDDriver *emcnandp) {
- emcnandp->config->ext_isr_enable();
-}
-
-/**
- * @brief Enable interrupts from EXTI
- *
- * @param[in] emcnandp pointer to the @p EMCNANDDriver object
- *
- * @notapi
- */
-static void emcnand_ready_isr_disable(EMCNANDDriver *emcnandp) {
- emcnandp->config->ext_isr_disable();
-}
-
-/**
- * @brief Ready pin interrupt handler.
- *
- * @param[in] emcnandp pointer to the @p EMCNANDDriver object
- *
- * @notapi
- */
-static void emcnand_isr_handler(EMCNANDDriver *emcnandp){
-
- osalSysLockFromISR();
-
- switch (emcnandp->state){
- case EMCNAND_READ:
- emcnandp->state = EMCNAND_DMA_RX;
- dmaStartMemCopy(emcnandp->dma, emcnandp->dmamode,
- emcnandp->map_data, emcnandp->rxdata, emcnandp->datalen);
- /* thread will be woked up from DMA ISR */
- break;
-
- case EMCNAND_ERASE:
- /* NAND reports about erase finish */
- emcnandp->state = EMCNAND_READY;
- wakeup_isr(emcnandp);
- break;
-
- case EMCNAND_PROGRAM:
- /* NAND reports about page programming finish */
- emcnandp->state = EMCNAND_READY;
- wakeup_isr(emcnandp);
- break;
-
- default:
- osalSysHalt("Unhandled case");
- break;
- }
-
- osalSysUnlockFromISR();
-}
-#endif /* STM32_EMC_USE_INT */
-
-/**
- * @brief DMA RX end IRQ handler.
- *
- * @param[in] emcnandp pointer to the @p EMCNANDDriver object
- * @param[in] flags pre-shifted content of the ISR register
- *
- * @notapi
- */
-static void emcnand_lld_serve_transfer_end_irq(EMCNANDDriver *emcnandp,
- uint32_t flags) {
- /* DMA errors handling.*/
-#if defined(STM32_EMCNAND_DMA_ERROR_HOOK)
- if ((flags & (STM32_DMA_ISR_TEIF | STM32_DMA_ISR_DMEIF)) != 0) {
- STM32_EMCNAND_DMA_ERROR_HOOK(emcnandp);
- }
-#else
- (void)flags;
-#endif
-
- osalSysLockFromISR();
-
- dmaStreamDisable(emcnandp->dma);
-
- switch (emcnandp->state){
- case EMCNAND_DMA_TX:
- emcnandp->state = EMCNAND_PROGRAM;
- emcnandp->map_cmd[0] = NAND_CMD_PAGEPROG;
- /* thread will be woken from ready_isr() */
- break;
-
- case EMCNAND_DMA_RX:
- emcnandp->state = EMCNAND_READY;
- emcnandp->rxdata = NULL;
- emcnandp->datalen = 0;
- wakeup_isr(emcnandp);
- break;
-
- default:
- osalSysHalt("Unhandled case");
- break;
- }
-
- osalSysUnlockFromISR();
-}
-
-/*===========================================================================*/
-/* Driver exported functions. */
-/*===========================================================================*/
-
-/**
- * @brief Low level EMCNAND driver initialization.
- *
- * @notapi
- */
-void emcnand_lld_init(void) {
-
-#if STM32_EMCNAND_USE_EMCNAND1
- /* Driver initialization.*/
- emcnandObjectInit(&EMCNANDD1);
- EMCNANDD1.rxdata = NULL;
- EMCNANDD1.datalen = 0;
- EMCNANDD1.thread = NULL;
- EMCNANDD1.dma = STM32_DMA_STREAM(STM32_EMCNAND_EMCNAND1_DMA_STREAM);
- EMCNANDD1.nand = (FSMC_NAND_TypeDef *)FSMC_Bank2_R_BASE;
- EMCNANDD1.map_data = (uint8_t*)FSMC_Bank2_MAP_COMMON_DATA;
- EMCNANDD1.map_cmd = (uint8_t*)FSMC_Bank2_MAP_COMMON_CMD;
- EMCNANDD1.map_addr = (uint8_t*)FSMC_Bank2_MAP_COMMON_ADDR;
-#endif /* STM32_EMCNAND_USE_EMCNAND1 */
-
-#if STM32_EMCNAND_USE_EMCNAND2
- /* Driver initialization.*/
- #warning "Untested"
- emcnandObjectInit(&EMCNANDD1);
- EMCNANDD2.rxdata = NULL;
- EMCNANDD2.datalen = 0;
- EMCNANDD2.thread = NULL;
- EMCNANDD2.dma = STM32_DMA_STREAM(STM32_EMCNAND_EMCNAND2_DMA_STREAM);
- EMCNANDD2.nand = (FSMC_NAND_TypeDef *)FSMC_Bank3_R_BASE;
- EMCNANDD2.map_data = (uint8_t*)FSMC_Bank3_MAP_COMMON_DATA;
- EMCNANDD2.map_cmd = (uint8_t*)FSMC_Bank3_MAP_COMMON_CMD;
- EMCNANDD2.map_addr = (uint8_t*)FSMC_Bank3_MAP_COMMON_ADDR;
-#endif /* STM32_EMCNAND_USE_EMCNAND2 */
-}
-
-/**
- * @brief Configures and activates the EMCNAND peripheral.
- *
- * @param[in] emcnandp pointer to the @p EMCNANDDriver object
- *
- * @notapi
- */
-void emcnand_lld_start(EMCNANDDriver *emcnandp) {
-
- bool_t b;
-
- if (emcnandp->state == EMCNAND_STOP) {
- b = dmaStreamAllocate(emcnandp->dma,
- STM32_EMC_FSMC1_IRQ_PRIORITY,
- (stm32_dmaisr_t)emcnand_lld_serve_transfer_end_irq,
- (void *)emcnandp);
- osalDbgAssert(!b, "stream already allocated");
- emcnandp->dmamode = STM32_DMA_CR_CHSEL(EMCNAND_DMA_CHANNEL) |
- STM32_DMA_CR_PL(STM32_EMCNAND_EMCNAND1_DMA_PRIORITY) |
- STM32_DMA_CR_PSIZE_BYTE | STM32_DMA_CR_MSIZE_BYTE |
- STM32_DMA_CR_DMEIE | STM32_DMA_CR_TEIE |
- STM32_DMA_CR_TCIE;
- /* dmaStreamSetFIFO(emcnandp->dma,
- STM32_DMA_FCR_DMDIS | EMCNAND_STM32_DMA_FCR_FTH_LVL); */
- emcnandp->nand->PCR = calc_eccps(emcnandp) | FSMC_PCR_PTYP | FSMC_PCR_PBKEN;
- emcnandp->nand->PMEM = emcnandp->config->pmem;
- emcnandp->nand->PATT = emcnandp->config->pmem;
- emcnandp->isr_handler = emcnand_isr_handler;
- emcnand_ready_isr_enable(emcnandp);
- }
-}
-
-/**
- * @brief Deactivates the EMCNAND peripheral.
- *
- * @param[in] emcnandp pointer to the @p EMCNANDDriver object
- *
- * @notapi
- */
-void emcnand_lld_stop(EMCNANDDriver *emcnandp) {
-
- if (emcnandp->state == EMCNAND_READY) {
- dmaStreamRelease(emcnandp->dma);
- emcnandp->nand->PCR &= ~FSMC_PCR_PBKEN;
- emcnand_ready_isr_disable(emcnandp);
- emcnandp->isr_handler = NULL;
- }
-}
-
-/**
- * @brief Read data from NAND.
- *
- * @param[in] emcnandp pointer to the @p EMCNANDDriver object
- * @param[out] data pointer to data buffer
- * @param[in] datalen size of data buffer
- * @param[in] addr pointer to address buffer
- * @param[in] addrlen length of address
- * @param[out] ecc pointer to store computed ECC. Ignored when NULL.
- *
- * @notapi
- */
-void emcnand_lld_read_data(EMCNANDDriver *emcnandp, uint8_t *data,
- size_t datalen, uint8_t *addr, size_t addrlen, uint32_t *ecc){
-
- emcnandp->state = EMCNAND_READ;
- emcnandp->rxdata = data;
- emcnandp->datalen = datalen;
-
- emcnand_lld_write_cmd (emcnandp, NAND_CMD_READ0);
- emcnand_lld_write_addr(emcnandp, addr, addrlen);
- osalSysLock();
- emcnand_lld_write_cmd (emcnandp, NAND_CMD_READ0_CONFIRM);
-
- /* Here NAND asserts busy signal and starts transferring from memory
- array to page buffer. After the end of transmission ready_isr functions
- starts DMA transfer from page buffer to MCU's RAM.*/
- osalDbgAssert((emcnandp->nand->PCR & FSMC_PCR_ECCEN) == 0,
- "State machine broken. ECCEN must be previously disabled.");
-
- if (NULL != ecc){
- emcnandp->nand->PCR |= FSMC_PCR_ECCEN;
- }
-
- emcnand_lld_suspend_thread(emcnandp);
- osalSysUnlock();
-
- /* thread was woken up from DMA ISR */
- if (NULL != ecc){
- while (! (emcnandp->nand->SR & FSMC_SR_FEMPT))
- ;
- *ecc = emcnandp->nand->ECCR;
- emcnandp->nand->PCR &= ~FSMC_PCR_ECCEN;
- }
-}
-
-/**
- * @brief Write data to NAND.
- *
- * @param[in] emcnandp pointer to the @p EMCNANDDriver object
- * @param[in] data buffer with data to be written
- * @param[in] datalen size of data buffer
- * @param[in] addr pointer to address buffer
- * @param[in] addrlen length of address
- * @param[out] ecc pointer to store computed ECC. Ignored when NULL.
- *
- * @return The operation status reported by NAND IC (0x70 command).
- *
- * @notapi
- */
-uint8_t emcnand_lld_write_data(EMCNANDDriver *emcnandp, const uint8_t *data,
- size_t datalen, uint8_t *addr, size_t addrlen, uint32_t *ecc){
-
- emcnandp->state = EMCNAND_WRITE;
-
- emcnand_lld_write_cmd (emcnandp, NAND_CMD_WRITE);
- osalSysLock();
- emcnand_lld_write_addr(emcnandp, addr, addrlen);
-
- /* Now start DMA transfer to NAND buffer and put thread in sleep state.
- Tread will we woken up from ready ISR. */
- emcnandp->state = EMCNAND_DMA_TX;
- osalDbgAssert((emcnandp->nand->PCR & FSMC_PCR_ECCEN) == 0,
- "State machine broken. ECCEN must be previously disabled.");
-
- if (NULL != ecc){
- emcnandp->nand->PCR |= FSMC_PCR_ECCEN;
- }
-
- dmaStartMemCopy(emcnandp->dma, emcnandp->dmamode,
- data, emcnandp->map_data, datalen);
-
- emcnand_lld_suspend_thread(emcnandp);
- osalSysUnlock();
-
- if (NULL != ecc){
- while (! (emcnandp->nand->SR & FSMC_SR_FEMPT))
- ;
- *ecc = emcnandp->nand->ECCR;
- emcnandp->nand->PCR &= ~FSMC_PCR_ECCEN;
- }
-
- return emcnand_lld_read_status(emcnandp);
-}
-
-/**
- * @brief Erase block.
- *
- * @param[in] emcnandp pointer to the @p EMCNANDDriver object
- * @param[in] addr pointer to address buffer
- * @param[in] addrlen length of address
- *
- * @return The operation status reported by NAND IC (0x70 command).
- *
- * @notapi
- */
-uint8_t emcnand_lld_erase(EMCNANDDriver *emcnandp,
- uint8_t *addr, size_t addrlen){
-
- emcnandp->state = EMCNAND_ERASE;
-
- emcnand_lld_write_cmd (emcnandp, NAND_CMD_ERASE);
- emcnand_lld_write_addr(emcnandp, addr, addrlen);
- osalSysLock();
- emcnand_lld_write_cmd (emcnandp, NAND_CMD_ERASE_CONFIRM);
- emcnand_lld_suspend_thread(emcnandp);
- osalSysUnlock();
-
- return emcnand_lld_read_status(emcnandp);
-}
-
-/**
- * @brief Read data from NAND using polling approach.
- *
- * @detatils Use this function to read data when no waiting expected. For
- * Example read status word after 0x70 command
- *
- * @param[in] emcnandp pointer to the @p EMCNANDDriver object
- * @param[out] data pointer to output buffer
- * @param[in] len length of data to be read
- *
- * @notapi
- */
-void emcnand_lld_polled_read_data(EMCNANDDriver *emcnandp,
- uint8_t *data, size_t len){
- size_t i = 0;
-
- for (i=0; i<len; i++)
- data[i] = emcnandp->map_data[i];
-}
-
-/**
- * @brief Send addres to NAND.
- *
- * @param[in] emcnandp pointer to the @p EMCNANDDriver object
- * @param[in] len length of address array
- * @param[in] addr pointer to address array
- *
- * @notapi
- */
-void emcnand_lld_write_addr(EMCNANDDriver *emcnandp,
- const uint8_t *addr, size_t len){
- size_t i = 0;
-
- for (i=0; i<len; i++)
- emcnandp->map_addr[i] = addr[i];
-}
-
-/**
- * @brief Send command to NAND.
- *
- * @param[in] emcnandp pointer to the @p EMCNANDDriver object
- * @param[in] cmd command value
- *
- * @notapi
- */
-void emcnand_lld_write_cmd(EMCNANDDriver *emcnandp, uint8_t cmd){
- emcnandp->map_cmd[0] = cmd;
-}
-
-/**
- * @brief Read status byte from NAND.
- *
- * @param[in] emcnandp pointer to the @p EMCNANDDriver object
- *
- * @return Status byte.
- *
- * @notapi
- */
-uint8_t emcnand_lld_read_status(EMCNANDDriver *emcnandp) {
-
- uint8_t status[1] = {0x01}; /* presume worse */
-
- emcnand_lld_write_cmd(emcnandp, NAND_CMD_STATUS);
- emcnand_lld_polled_read_data(emcnandp, status, 1);
-
- return status[0];
-}
-
-#endif /* HAL_USE_EMCNAND */
-
-/** @} */
-