Satellite Observers Workbench. NOT yet complete, just published for forum posters to \"cherry pick\" pieces of code as requiered as an example.
flash/flash_read.c@0:0a841b89d614, 2010-10-11 (annotated)
- Committer:
- AjK
- Date:
- Mon Oct 11 10:34:55 2010 +0000
- Revision:
- 0:0a841b89d614
Totally Alpha quality as this project isn\t completed. Just publishing it as it answers many questions asked in the forums
Who changed what in which revision?
User | Revision | Line number | New contents of line |
---|---|---|---|
AjK | 0:0a841b89d614 | 1 | /**************************************************************************** |
AjK | 0:0a841b89d614 | 2 | * Copyright 2010 Andy Kirkham, Stellar Technologies Ltd |
AjK | 0:0a841b89d614 | 3 | * |
AjK | 0:0a841b89d614 | 4 | * This file is part of the Satellite Observers Workbench (SOWB). |
AjK | 0:0a841b89d614 | 5 | * |
AjK | 0:0a841b89d614 | 6 | * SOWB is free software: you can redistribute it and/or modify |
AjK | 0:0a841b89d614 | 7 | * it under the terms of the GNU General Public License as published by |
AjK | 0:0a841b89d614 | 8 | * the Free Software Foundation, either version 3 of the License, or |
AjK | 0:0a841b89d614 | 9 | * (at your option) any later version. |
AjK | 0:0a841b89d614 | 10 | * |
AjK | 0:0a841b89d614 | 11 | * SOWB is distributed in the hope that it will be useful, |
AjK | 0:0a841b89d614 | 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of |
AjK | 0:0a841b89d614 | 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
AjK | 0:0a841b89d614 | 14 | * GNU General Public License for more details. |
AjK | 0:0a841b89d614 | 15 | * |
AjK | 0:0a841b89d614 | 16 | * You should have received a copy of the GNU General Public License |
AjK | 0:0a841b89d614 | 17 | * along with SOWB. If not, see <http://www.gnu.org/licenses/>. |
AjK | 0:0a841b89d614 | 18 | * |
AjK | 0:0a841b89d614 | 19 | * $Id: main.cpp 5 2010-07-12 20:51:11Z ajk $ |
AjK | 0:0a841b89d614 | 20 | * |
AjK | 0:0a841b89d614 | 21 | ***************************************************************************/ |
AjK | 0:0a841b89d614 | 22 | |
AjK | 0:0a841b89d614 | 23 | #include "sowb.h" |
AjK | 0:0a841b89d614 | 24 | #include "flash.h" |
AjK | 0:0a841b89d614 | 25 | #include "dma.h" |
AjK | 0:0a841b89d614 | 26 | #include "ssp0.h" |
AjK | 0:0a841b89d614 | 27 | #include "gpio.h" |
AjK | 0:0a841b89d614 | 28 | #include "user.h" |
AjK | 0:0a841b89d614 | 29 | #include "debug.h" |
AjK | 0:0a841b89d614 | 30 | |
AjK | 0:0a841b89d614 | 31 | bool page_read_in_progress = false; |
AjK | 0:0a841b89d614 | 32 | |
AjK | 0:0a841b89d614 | 33 | /* Local function prototypes. */ |
AjK | 0:0a841b89d614 | 34 | static int _flash_read_page(unsigned int page_address, char *buffer); |
AjK | 0:0a841b89d614 | 35 | |
AjK | 0:0a841b89d614 | 36 | void flash_read_page(unsigned int page_address, char *buffer, bool block) { |
AjK | 0:0a841b89d614 | 37 | _flash_read_page(page_address, buffer); |
AjK | 0:0a841b89d614 | 38 | |
AjK | 0:0a841b89d614 | 39 | if (block) { |
AjK | 0:0a841b89d614 | 40 | while(page_read_in_progress) { |
AjK | 0:0a841b89d614 | 41 | WHILE_WAITING_DO_PROCESS_FUNCTIONS; |
AjK | 0:0a841b89d614 | 42 | } |
AjK | 0:0a841b89d614 | 43 | } |
AjK | 0:0a841b89d614 | 44 | } |
AjK | 0:0a841b89d614 | 45 | |
AjK | 0:0a841b89d614 | 46 | /** flash_read_in_progress |
AjK | 0:0a841b89d614 | 47 | */ |
AjK | 0:0a841b89d614 | 48 | bool flash_read_in_progress(void) { |
AjK | 0:0a841b89d614 | 49 | return page_read_in_progress; |
AjK | 0:0a841b89d614 | 50 | } |
AjK | 0:0a841b89d614 | 51 | |
AjK | 0:0a841b89d614 | 52 | /** flash_read_page |
AjK | 0:0a841b89d614 | 53 | * |
AjK | 0:0a841b89d614 | 54 | * Load the given flash page into the supplied buffer. |
AjK | 0:0a841b89d614 | 55 | * |
AjK | 0:0a841b89d614 | 56 | * @param unsigned int the page to load, between 0 and 4095 |
AjK | 0:0a841b89d614 | 57 | * @param char * buffer The RAM buffer to load the page to. |
AjK | 0:0a841b89d614 | 58 | */ |
AjK | 0:0a841b89d614 | 59 | static int _flash_read_page(unsigned int page_address, char *buffer) { |
AjK | 0:0a841b89d614 | 60 | |
AjK | 0:0a841b89d614 | 61 | /* We can't read a page while a write or erase is in progress. */ |
AjK | 0:0a841b89d614 | 62 | if (flash_write_in_progress() || flash_sector_erase_in_progress()) { |
AjK | 0:0a841b89d614 | 63 | return 0; |
AjK | 0:0a841b89d614 | 64 | } |
AjK | 0:0a841b89d614 | 65 | |
AjK | 0:0a841b89d614 | 66 | /* Wait for any previous read operation to complete. */ |
AjK | 0:0a841b89d614 | 67 | while (page_read_in_progress) WHILE_WAITING_DO_PROCESS_FUNCTIONS; |
AjK | 0:0a841b89d614 | 68 | |
AjK | 0:0a841b89d614 | 69 | /* Mark a read is in operation. */ |
AjK | 0:0a841b89d614 | 70 | page_read_in_progress = true; |
AjK | 0:0a841b89d614 | 71 | |
AjK | 0:0a841b89d614 | 72 | /* Request use of SSP0. */ |
AjK | 0:0a841b89d614 | 73 | while(!SSP0_request()) WHILE_WAITING_DO_PROCESS_FUNCTIONS; |
AjK | 0:0a841b89d614 | 74 | |
AjK | 0:0a841b89d614 | 75 | /* Ensure the SSP1 RX FIFO is empty. */ |
AjK | 0:0a841b89d614 | 76 | SSP0_FLUSH_RX_FIFO; |
AjK | 0:0a841b89d614 | 77 | |
AjK | 0:0a841b89d614 | 78 | /* Send the command and page read to the flash device. */ |
AjK | 0:0a841b89d614 | 79 | FLASH_CS_ASSERT; |
AjK | 0:0a841b89d614 | 80 | FLASH_LONG_COMMAND(FLASH_READ, page_address); |
AjK | 0:0a841b89d614 | 81 | |
AjK | 0:0a841b89d614 | 82 | /* We use two DMA channels to achieve the required results. |
AjK | 0:0a841b89d614 | 83 | The higher priority channel0 is used to drive the SSP0 |
AjK | 0:0a841b89d614 | 84 | SCLK0 pin with "don't care" bytes. We do this to flush |
AjK | 0:0a841b89d614 | 85 | the bytes out of the flash device. We then use Channel1 |
AjK | 0:0a841b89d614 | 86 | to transfer the incoming bytes to RAM. */ |
AjK | 0:0a841b89d614 | 87 | |
AjK | 0:0a841b89d614 | 88 | while(!DMA_request_channel(0)) WHILE_WAITING_DO_PROCESS_FUNCTIONS; |
AjK | 0:0a841b89d614 | 89 | while(!DMA_request_channel(1)) WHILE_WAITING_DO_PROCESS_FUNCTIONS; |
AjK | 0:0a841b89d614 | 90 | |
AjK | 0:0a841b89d614 | 91 | LPC_GPDMA->DMACIntTCClear = 0x3; |
AjK | 0:0a841b89d614 | 92 | LPC_GPDMA->DMACSoftSReq = 0xC; |
AjK | 0:0a841b89d614 | 93 | |
AjK | 0:0a841b89d614 | 94 | /* Prep Channel1 to receive the incoming byte stream. */ |
AjK | 0:0a841b89d614 | 95 | LPC_GPDMACH1->DMACCSrcAddr = (uint32_t)&LPC_SSP0->DR; |
AjK | 0:0a841b89d614 | 96 | LPC_GPDMACH1->DMACCDestAddr = (uint32_t)buffer; |
AjK | 0:0a841b89d614 | 97 | LPC_GPDMACH1->DMACCLLI = 0; |
AjK | 0:0a841b89d614 | 98 | LPC_GPDMACH1->DMACCControl = DMA_CHANNEL_TCIE | DMA_CHANNEL_DST_INC | (uint32_t)FLASH_PAGE_SIZE; |
AjK | 0:0a841b89d614 | 99 | |
AjK | 0:0a841b89d614 | 100 | /* Prep Channel0 to send "don't care" bytes in order to clock out the data from the flash device. */ |
AjK | 0:0a841b89d614 | 101 | LPC_GPDMACH0->DMACCSrcAddr = (uint32_t)buffer; /* don't care data. */ |
AjK | 0:0a841b89d614 | 102 | LPC_GPDMACH0->DMACCDestAddr = (uint32_t)&LPC_SSP0->DR; |
AjK | 0:0a841b89d614 | 103 | LPC_GPDMACH0->DMACCLLI = 0; |
AjK | 0:0a841b89d614 | 104 | LPC_GPDMACH0->DMACCControl = DMA_CHANNEL_TCIE | (uint32_t)FLASH_PAGE_SIZE; |
AjK | 0:0a841b89d614 | 105 | |
AjK | 0:0a841b89d614 | 106 | /* Enable SSP0 DMA. */ |
AjK | 0:0a841b89d614 | 107 | LPC_SSP0->DMACR = 0x3; |
AjK | 0:0a841b89d614 | 108 | |
AjK | 0:0a841b89d614 | 109 | /* Enable Channel0 */ |
AjK | 0:0a841b89d614 | 110 | LPC_GPDMACH0->DMACCConfig = DMA_CHANNEL_ENABLE | |
AjK | 0:0a841b89d614 | 111 | DMA_CHANNEL_DST_PERIPHERAL_SSP0_TX | |
AjK | 0:0a841b89d614 | 112 | DMA_TRANSFER_TYPE_M2P | |
AjK | 0:0a841b89d614 | 113 | DMA_MASK_IE | |
AjK | 0:0a841b89d614 | 114 | DMA_MASK_ITC; |
AjK | 0:0a841b89d614 | 115 | |
AjK | 0:0a841b89d614 | 116 | /* Wait until at least one byte has arrived into the RX FIFO |
AjK | 0:0a841b89d614 | 117 | and then start-up the Channel1 DMA to begin transferring them. */ |
AjK | 0:0a841b89d614 | 118 | while((LPC_SSP0->SR & (1UL << 2)) == 0); |
AjK | 0:0a841b89d614 | 119 | |
AjK | 0:0a841b89d614 | 120 | /* Enable Channel1 */ |
AjK | 0:0a841b89d614 | 121 | LPC_GPDMACH1->DMACCConfig = DMA_CHANNEL_ENABLE | |
AjK | 0:0a841b89d614 | 122 | DMA_CHANNEL_SRC_PERIPHERAL_SSP0_RX | |
AjK | 0:0a841b89d614 | 123 | DMA_TRANSFER_TYPE_P2M | |
AjK | 0:0a841b89d614 | 124 | DMA_MASK_IE | |
AjK | 0:0a841b89d614 | 125 | DMA_MASK_ITC; |
AjK | 0:0a841b89d614 | 126 | |
AjK | 0:0a841b89d614 | 127 | /* SSP0 CS line and "page_read_in_progress" flag are now |
AjK | 0:0a841b89d614 | 128 | under DMA/SSP0 interrupt control. See the DMA ISR handlers |
AjK | 0:0a841b89d614 | 129 | and SSP0 ISR handlers for more information. */ |
AjK | 0:0a841b89d614 | 130 | |
AjK | 0:0a841b89d614 | 131 | return 1; |
AjK | 0:0a841b89d614 | 132 | } |
AjK | 0:0a841b89d614 | 133 | |
AjK | 0:0a841b89d614 | 134 | /** flash_read_ssp0_irq |
AjK | 0:0a841b89d614 | 135 | * |
AjK | 0:0a841b89d614 | 136 | * Called by the SSP0 ISR handler. |
AjK | 0:0a841b89d614 | 137 | */ |
AjK | 0:0a841b89d614 | 138 | int flash_read_ssp0_irq(void) { |
AjK | 0:0a841b89d614 | 139 | if (page_read_in_progress) { |
AjK | 0:0a841b89d614 | 140 | if (LPC_SSP0->MIS & (1UL << 3)) { |
AjK | 0:0a841b89d614 | 141 | LPC_SSP0->IMSC &= ~(1UL << 3); |
AjK | 0:0a841b89d614 | 142 | while(SSP0_IS_BUSY); |
AjK | 0:0a841b89d614 | 143 | FLASH_CS_DEASSERT; |
AjK | 0:0a841b89d614 | 144 | SSP0_release(); |
AjK | 0:0a841b89d614 | 145 | page_read_in_progress = false; |
AjK | 0:0a841b89d614 | 146 | return 1; |
AjK | 0:0a841b89d614 | 147 | } |
AjK | 0:0a841b89d614 | 148 | } |
AjK | 0:0a841b89d614 | 149 | return 0; |
AjK | 0:0a841b89d614 | 150 | } |
AjK | 0:0a841b89d614 | 151 | |
AjK | 0:0a841b89d614 | 152 | /* The following two functions are the DMA ISR handlers. They are |
AjK | 0:0a841b89d614 | 153 | called from dma.c so see that module for more details. */ |
AjK | 0:0a841b89d614 | 154 | |
AjK | 0:0a841b89d614 | 155 | /** flash_read_dma0_irq |
AjK | 0:0a841b89d614 | 156 | */ |
AjK | 0:0a841b89d614 | 157 | int flash_read_dma0_irq(int channel_number) { |
AjK | 0:0a841b89d614 | 158 | if (page_read_in_progress) { |
AjK | 0:0a841b89d614 | 159 | LPC_GPDMACH0->DMACCConfig = 0; |
AjK | 0:0a841b89d614 | 160 | DMA_release_channel(0); |
AjK | 0:0a841b89d614 | 161 | return 1; |
AjK | 0:0a841b89d614 | 162 | } |
AjK | 0:0a841b89d614 | 163 | return 0; |
AjK | 0:0a841b89d614 | 164 | } |
AjK | 0:0a841b89d614 | 165 | |
AjK | 0:0a841b89d614 | 166 | /** flash_read_dma1_irq |
AjK | 0:0a841b89d614 | 167 | */ |
AjK | 0:0a841b89d614 | 168 | int flash_read_dma1_irq(int channel_number) { |
AjK | 0:0a841b89d614 | 169 | if (page_read_in_progress) { |
AjK | 0:0a841b89d614 | 170 | LPC_GPDMACH1->DMACCConfig = 0; |
AjK | 0:0a841b89d614 | 171 | DMA_release_channel(1); |
AjK | 0:0a841b89d614 | 172 | LPC_SSP0->IMSC = (1UL << 3); |
AjK | 0:0a841b89d614 | 173 | return 1; |
AjK | 0:0a841b89d614 | 174 | } |
AjK | 0:0a841b89d614 | 175 | return 0; |
AjK | 0:0a841b89d614 | 176 | } |
AjK | 0:0a841b89d614 | 177 |