Satellite Observers Workbench. NOT yet complete, just published for forum posters to \"cherry pick\" pieces of code as requiered as an example.

Dependencies:   mbed

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers flash_read.c Source File

flash_read.c

00001 /****************************************************************************
00002  *    Copyright 2010 Andy Kirkham, Stellar Technologies Ltd
00003  *    
00004  *    This file is part of the Satellite Observers Workbench (SOWB).
00005  *
00006  *    SOWB is free software: you can redistribute it and/or modify
00007  *    it under the terms of the GNU General Public License as published by
00008  *    the Free Software Foundation, either version 3 of the License, or
00009  *    (at your option) any later version.
00010  *
00011  *    SOWB is distributed in the hope that it will be useful,
00012  *    but WITHOUT ANY WARRANTY; without even the implied warranty of
00013  *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00014  *    GNU General Public License for more details.
00015  *
00016  *    You should have received a copy of the GNU General Public License
00017  *    along with SOWB.  If not, see <http://www.gnu.org/licenses/>.
00018  *
00019  *    $Id: main.cpp 5 2010-07-12 20:51:11Z ajk $
00020  *    
00021  ***************************************************************************/
00022 
00023 #include "sowb.h"
00024 #include "flash.h"
00025 #include "dma.h"
00026 #include "ssp0.h"
00027 #include "gpio.h"
00028 #include "user.h"
00029 #include "debug.h"
00030 
00031 bool page_read_in_progress = false;
00032 
00033 /* Local function prototypes. */
00034 static int _flash_read_page(unsigned int page_address, char *buffer);
00035 
00036 void flash_read_page(unsigned int page_address, char *buffer, bool block) {
00037     _flash_read_page(page_address, buffer);
00038     
00039     if (block) {
00040         while(page_read_in_progress) {
00041             WHILE_WAITING_DO_PROCESS_FUNCTIONS;
00042         }
00043     }
00044 }
00045 
00046 /** flash_read_in_progress
00047  */
00048 bool flash_read_in_progress(void) {
00049     return page_read_in_progress;
00050 }
00051 
00052 /** flash_read_page
00053  * 
00054  * Load the given flash page into the supplied buffer.
00055  *
00056  * @param unsigned int the page to load, between 0 and 4095
00057  * @param char * buffer The RAM buffer to load the page to.
00058  */
00059 static int _flash_read_page(unsigned int page_address, char *buffer) {
00060 
00061     /* We can't read a page while a write or erase is in progress. */    
00062     if (flash_write_in_progress() || flash_sector_erase_in_progress()) {
00063         return 0;
00064     }
00065     
00066     /* Wait for any previous read operation to complete. */
00067     while (page_read_in_progress) WHILE_WAITING_DO_PROCESS_FUNCTIONS;
00068     
00069     /* Mark a read is in operation. */
00070     page_read_in_progress = true; 
00071     
00072     /* Request use of SSP0. */
00073     while(!SSP0_request()) WHILE_WAITING_DO_PROCESS_FUNCTIONS;
00074     
00075     /* Ensure the SSP1 RX FIFO is empty. */
00076     SSP0_FLUSH_RX_FIFO;
00077     
00078     /* Send the command and page read to the flash device. */
00079     FLASH_CS_ASSERT;
00080     FLASH_LONG_COMMAND(FLASH_READ, page_address);
00081     
00082     /* We use two DMA channels to achieve the required results.
00083        The higher priority channel0 is used to drive the SSP0
00084        SCLK0 pin with "don't care" bytes. We do this to flush 
00085        the bytes out of the flash device. We then use Channel1 
00086        to transfer the incoming bytes to RAM. */
00087 
00088     while(!DMA_request_channel(0)) WHILE_WAITING_DO_PROCESS_FUNCTIONS;
00089     while(!DMA_request_channel(1)) WHILE_WAITING_DO_PROCESS_FUNCTIONS;
00090 
00091     LPC_GPDMA->DMACIntTCClear = 0x3;
00092     LPC_GPDMA->DMACSoftSReq   = 0xC;
00093     
00094     /* Prep Channel1 to receive the incoming byte stream. */
00095     LPC_GPDMACH1->DMACCSrcAddr  = (uint32_t)&LPC_SSP0->DR;
00096     LPC_GPDMACH1->DMACCDestAddr = (uint32_t)buffer;
00097     LPC_GPDMACH1->DMACCLLI      = 0;
00098     LPC_GPDMACH1->DMACCControl  = DMA_CHANNEL_TCIE | DMA_CHANNEL_DST_INC | (uint32_t)FLASH_PAGE_SIZE;
00099     
00100     /* Prep Channel0 to send "don't care" bytes in order to clock out the data from the flash device. */
00101     LPC_GPDMACH0->DMACCSrcAddr  = (uint32_t)buffer; /* don't care data. */
00102     LPC_GPDMACH0->DMACCDestAddr = (uint32_t)&LPC_SSP0->DR;
00103     LPC_GPDMACH0->DMACCLLI      = 0;
00104     LPC_GPDMACH0->DMACCControl  = DMA_CHANNEL_TCIE | (uint32_t)FLASH_PAGE_SIZE;
00105     
00106     /* Enable SSP0 DMA. */
00107     LPC_SSP0->DMACR = 0x3;
00108 
00109     /* Enable Channel0 */
00110     LPC_GPDMACH0->DMACCConfig = DMA_CHANNEL_ENABLE | 
00111                                 DMA_CHANNEL_DST_PERIPHERAL_SSP0_TX | 
00112                                 DMA_TRANSFER_TYPE_M2P |
00113                                 DMA_MASK_IE |
00114                                 DMA_MASK_ITC;
00115     
00116     /* Wait until at least one byte has arrived into the RX FIFO
00117        and then start-up the Channel1 DMA to begin transferring them. */
00118     while((LPC_SSP0->SR & (1UL << 2)) == 0);
00119     
00120     /* Enable Channel1 */
00121     LPC_GPDMACH1->DMACCConfig = DMA_CHANNEL_ENABLE | 
00122                                 DMA_CHANNEL_SRC_PERIPHERAL_SSP0_RX | 
00123                                 DMA_TRANSFER_TYPE_P2M |
00124                                 DMA_MASK_IE |
00125                                 DMA_MASK_ITC;
00126                                 
00127     /* SSP0 CS line and "page_read_in_progress" flag are now 
00128        under DMA/SSP0 interrupt control. See the DMA ISR handlers 
00129        and SSP0 ISR handlers for more information. */
00130        
00131     return 1;   
00132 }
00133 
00134 /** flash_read_ssp0_irq
00135  * 
00136  * Called by the SSP0 ISR handler.
00137  */
00138 int flash_read_ssp0_irq(void) {
00139     if (page_read_in_progress) {
00140         if (LPC_SSP0->MIS & (1UL << 3)) {
00141             LPC_SSP0->IMSC &= ~(1UL << 3); 
00142             while(SSP0_IS_BUSY);
00143             FLASH_CS_DEASSERT;
00144             SSP0_release();
00145             page_read_in_progress = false; 
00146             return 1;
00147         }
00148     }
00149     return 0;
00150 }
00151 
00152 /* The following two functions are the DMA ISR handlers. They are
00153    called from dma.c so see that module for more details. */
00154    
00155 /** flash_read_dma0_irq
00156  */
00157 int flash_read_dma0_irq(int channel_number) {
00158     if (page_read_in_progress) {
00159         LPC_GPDMACH0->DMACCConfig = 0;
00160         DMA_release_channel(0);        
00161         return 1;        
00162     }
00163     return 0;
00164 }
00165 
00166 /** flash_read_dma1_irq
00167  */
00168 int flash_read_dma1_irq(int channel_number) {
00169     if (page_read_in_progress) {
00170         LPC_GPDMACH1->DMACCConfig = 0;
00171         DMA_release_channel(1);
00172         LPC_SSP0->IMSC = (1UL << 3);
00173         return 1;        
00174     }
00175     return 0;
00176 }
00177