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

Dependencies:   mbed

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?

UserRevisionLine numberNew 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 "ssp0.h"
AjK 0:0a841b89d614 26 #include "dma.h"
AjK 0:0a841b89d614 27 #include "gpio.h"
AjK 0:0a841b89d614 28 #include "rit.h"
AjK 0:0a841b89d614 29 #include "user.h"
AjK 0:0a841b89d614 30 #include "utils.h"
AjK 0:0a841b89d614 31 #include "debug.h"
AjK 0:0a841b89d614 32
AjK 0:0a841b89d614 33 /* Flags to show what state we are in. */
AjK 0:0a841b89d614 34 bool page_write_in_progress = false;
AjK 0:0a841b89d614 35 bool page_write_buffer_in_use = false;
AjK 0:0a841b89d614 36
AjK 0:0a841b89d614 37 /* Flag used by the flash_erase.c file. */
AjK 0:0a841b89d614 38 extern bool sector_erase_in_progress;
AjK 0:0a841b89d614 39
AjK 0:0a841b89d614 40 /* Buffer used to hold a copy of the page to write. Used
AjK 0:0a841b89d614 41 to ensure the DMA has a valid buffer to copy. */
AjK 0:0a841b89d614 42 char flash_page_write_buffer[FLASH_PAGE_SIZE];
AjK 0:0a841b89d614 43
AjK 0:0a841b89d614 44 /** flash_write_in_progress
AjK 0:0a841b89d614 45 */
AjK 0:0a841b89d614 46 bool flash_write_in_progress(void) {
AjK 0:0a841b89d614 47 return page_write_in_progress;
AjK 0:0a841b89d614 48 }
AjK 0:0a841b89d614 49
AjK 0:0a841b89d614 50 /** flash_page_write
AjK 0:0a841b89d614 51 */
AjK 0:0a841b89d614 52 int flash_page_write(int page, char *buffer) {
AjK 0:0a841b89d614 53
AjK 0:0a841b89d614 54 /* Wait for the write page buffer to be released by
AjK 0:0a841b89d614 55 the DMA ISR handler, if in use, then make a copy
AjK 0:0a841b89d614 56 of the source buffer for the DMA. */
AjK 0:0a841b89d614 57 while (page_write_buffer_in_use) WHILE_WAITING_DO_PROCESS_FUNCTIONS;
AjK 0:0a841b89d614 58 memcpy(flash_page_write_buffer, buffer, FLASH_PAGE_SIZE);
AjK 0:0a841b89d614 59 page_write_buffer_in_use = true;
AjK 0:0a841b89d614 60
AjK 0:0a841b89d614 61
AjK 0:0a841b89d614 62 /* Below this we check for conditions that should stall
AjK 0:0a841b89d614 63 us before continuing. However, sector erase is different,
AjK 0:0a841b89d614 64 it can take quite some time to complete. If this is the
AjK 0:0a841b89d614 65 case, rather than block (wait), we'll return zero (not
AjK 0:0a841b89d614 66 done) and allow the caller to schedule a write later. */
AjK 0:0a841b89d614 67 if (sector_erase_in_progress) return 0;
AjK 0:0a841b89d614 68
AjK 0:0a841b89d614 69 /* Do not start a page write while another page write
AjK 0:0a841b89d614 70 is in progress. This flag is released by the RIT
AjK 0:0a841b89d614 71 timer callback when the WIP flag shows a previous
AjK 0:0a841b89d614 72 write has completed. */
AjK 0:0a841b89d614 73 while(page_write_in_progress) WHILE_WAITING_DO_PROCESS_FUNCTIONS;
AjK 0:0a841b89d614 74
AjK 0:0a841b89d614 75 /* Do not start a page write while a page read is in operation. */
AjK 0:0a841b89d614 76 while (flash_read_in_progress()) WHILE_WAITING_DO_PROCESS_FUNCTIONS;
AjK 0:0a841b89d614 77
AjK 0:0a841b89d614 78 /* Request DMA channel0. */
AjK 0:0a841b89d614 79 while(!DMA_request_channel(0)) WHILE_WAITING_DO_PROCESS_FUNCTIONS;
AjK 0:0a841b89d614 80
AjK 0:0a841b89d614 81 /* Request the use of SSP0. */
AjK 0:0a841b89d614 82 while(!SSP0_request()) WHILE_WAITING_DO_PROCESS_FUNCTIONS;
AjK 0:0a841b89d614 83
AjK 0:0a841b89d614 84 /* Flag a write is in progress. */
AjK 0:0a841b89d614 85 page_write_in_progress = true;
AjK 0:0a841b89d614 86
AjK 0:0a841b89d614 87 /* Switch on WIP/WEL. */
AjK 0:0a841b89d614 88 FLASH_CS_ASSERT;
AjK 0:0a841b89d614 89 FLASH_SHORT_COMMAND(FLASH_WREN);
AjK 0:0a841b89d614 90 FLASH_CS_DEASSERT;
AjK 0:0a841b89d614 91
AjK 0:0a841b89d614 92 /* Originally I dropped into a do { ... } while(); here but
AjK 0:0a841b89d614 93 found the time between the CS deassert and reassert inside
AjK 0:0a841b89d614 94 the loop was *very* short and the flash device wasn't to
AjK 0:0a841b89d614 95 keen on this. So, I switched to a "flush rx fifo" and the
AjK 0:0a841b89d614 96 use a while() { ... } loop, just puts some delay between
AjK 0:0a841b89d614 97 the CS manipulation. */
AjK 0:0a841b89d614 98 SSP0_FLUSH_RX_FIFO;
AjK 0:0a841b89d614 99
AjK 0:0a841b89d614 100 /* Wait until the flash device has the WEL bit on. */
AjK 0:0a841b89d614 101 while ((LPC_SSP0->DR & 0x2) == 0) {
AjK 0:0a841b89d614 102 FLASH_CS_ASSERT;
AjK 0:0a841b89d614 103 FLASH_SHORT_COMMAND(FLASH_RDSR);
AjK 0:0a841b89d614 104 SSP0_FLUSH_RX_FIFO;
AjK 0:0a841b89d614 105 SSP0_WRITE_BYTE(0);
AjK 0:0a841b89d614 106 while (SSP0_IS_BUSY);
AjK 0:0a841b89d614 107 FLASH_CS_DEASSERT;
AjK 0:0a841b89d614 108 }
AjK 0:0a841b89d614 109
AjK 0:0a841b89d614 110 FLASH_CS_ASSERT;
AjK 0:0a841b89d614 111 FLASH_LONG_COMMAND(FLASH_PP, page);
AjK 0:0a841b89d614 112
AjK 0:0a841b89d614 113 LPC_GPDMA->DMACIntTCClear = 0x1;
AjK 0:0a841b89d614 114 LPC_GPDMA->DMACSoftSReq = 0xC;
AjK 0:0a841b89d614 115
AjK 0:0a841b89d614 116 /* Prep Channel0 to send the buffer to the flash device. */
AjK 0:0a841b89d614 117 LPC_GPDMACH0->DMACCSrcAddr = (uint32_t)flash_page_write_buffer;
AjK 0:0a841b89d614 118 LPC_GPDMACH0->DMACCDestAddr = (uint32_t)&LPC_SSP0->DR;
AjK 0:0a841b89d614 119 LPC_GPDMACH0->DMACCLLI = 0;
AjK 0:0a841b89d614 120 LPC_GPDMACH0->DMACCControl = DMA_CHANNEL_TCIE | DMA_CHANNEL_SRC_INC | (uint32_t)FLASH_PAGE_SIZE;
AjK 0:0a841b89d614 121
AjK 0:0a841b89d614 122 /* Enable SSP0 DMA. */
AjK 0:0a841b89d614 123 LPC_SSP0->DMACR = 0x2;
AjK 0:0a841b89d614 124
AjK 0:0a841b89d614 125 /* Enable Channel0 */
AjK 0:0a841b89d614 126 LPC_GPDMACH0->DMACCConfig = DMA_CHANNEL_ENABLE |
AjK 0:0a841b89d614 127 DMA_CHANNEL_DST_PERIPHERAL_SSP0_TX |
AjK 0:0a841b89d614 128 DMA_TRANSFER_TYPE_M2P |
AjK 0:0a841b89d614 129 DMA_MASK_IE |
AjK 0:0a841b89d614 130 DMA_MASK_ITC;
AjK 0:0a841b89d614 131
AjK 0:0a841b89d614 132
AjK 0:0a841b89d614 133 /* SSP0 CS line and "page_write_in_progress" flag are now
AjK 0:0a841b89d614 134 under DMA/SSP0 interrupt control. See ISR handlers for
AjK 0:0a841b89d614 135 more information. */
AjK 0:0a841b89d614 136
AjK 0:0a841b89d614 137 return 1;
AjK 0:0a841b89d614 138 }
AjK 0:0a841b89d614 139
AjK 0:0a841b89d614 140 /** _flash_write_timer_callback
AjK 0:0a841b89d614 141 *
AjK 0:0a841b89d614 142 * RIT timer callback.
AjK 0:0a841b89d614 143 *
AjK 0:0a841b89d614 144 * After the write operation is complete this callback
AjK 0:0a841b89d614 145 * is used to examine the WIP flag in the flash status
AjK 0:0a841b89d614 146 * register. If it's still set then we reset the timer
AjK 0:0a841b89d614 147 * and try again in the future. If it's clear then we
AjK 0:0a841b89d614 148 * can mark the process as complete.
AjK 0:0a841b89d614 149 *
AjK 0:0a841b89d614 150 * @param int index The index of the timer the RIT modulr used.
AjK 0:0a841b89d614 151 */
AjK 0:0a841b89d614 152 void _flash_write_timer_callback(int index) {
AjK 0:0a841b89d614 153 uint32_t sr = 1;
AjK 0:0a841b89d614 154
AjK 0:0a841b89d614 155 /* Read the WIP flag from the flash device status
AjK 0:0a841b89d614 156 register and if the write cycle is complete mark
AjK 0:0a841b89d614 157 the operation as complete. Otherwise, reset the
AjK 0:0a841b89d614 158 timer to test again in the future. */
AjK 0:0a841b89d614 159 FLASH_CS_ASSERT;
AjK 0:0a841b89d614 160 FLASH_SHORT_COMMAND(FLASH_RDSR);
AjK 0:0a841b89d614 161 SSP0_WRITE_BYTE(0);
AjK 0:0a841b89d614 162 while (SSP0_IS_BUSY);
AjK 0:0a841b89d614 163 FLASH_CS_DEASSERT;
AjK 0:0a841b89d614 164 while(LPC_SSP0->SR & (1UL << 2)) {
AjK 0:0a841b89d614 165 /* This loop ensures we read the last byte in the
AjK 0:0a841b89d614 166 RX FIFO and test that. */
AjK 0:0a841b89d614 167 sr = LPC_SSP0->DR;
AjK 0:0a841b89d614 168 }
AjK 0:0a841b89d614 169 if (sr & 0x1) {
AjK 0:0a841b89d614 170 if (sector_erase_in_progress) rit_timer_set_counter(index, 100);
AjK 0:0a841b89d614 171 else rit_timer_set_counter(index, FLASH_WIP_TEST_TIME);
AjK 0:0a841b89d614 172 }
AjK 0:0a841b89d614 173 else {
AjK 0:0a841b89d614 174 FLASH_CS_ASSERT;
AjK 0:0a841b89d614 175 FLASH_SHORT_COMMAND(FLASH_WRDI);
AjK 0:0a841b89d614 176 SSP0_FLUSH_RX_FIFO;
AjK 0:0a841b89d614 177 FLASH_CS_DEASSERT;
AjK 0:0a841b89d614 178 if (sector_erase_in_progress) sector_erase_in_progress = false;
AjK 0:0a841b89d614 179 if (page_write_in_progress) page_write_in_progress = false;
AjK 0:0a841b89d614 180 SSP0_release();
AjK 0:0a841b89d614 181 }
AjK 0:0a841b89d614 182 }
AjK 0:0a841b89d614 183
AjK 0:0a841b89d614 184 /** flash_write_dma0_irq
AjK 0:0a841b89d614 185 *
AjK 0:0a841b89d614 186 * DMA transfer irq callback.
AjK 0:0a841b89d614 187 */
AjK 0:0a841b89d614 188 int flash_write_dma0_irq(int channel) {
AjK 0:0a841b89d614 189 int rval = 0;
AjK 0:0a841b89d614 190
AjK 0:0a841b89d614 191 /* If we were using DMA to transfer our buffer to the flash
AjK 0:0a841b89d614 192 device then mark the buffer as "released" and no longer
AjK 0:0a841b89d614 193 in use, release the DMA channel and start the "detect WIP
AjK 0:0a841b89d614 194 indicates complete" timer. */
AjK 0:0a841b89d614 195 if (page_write_buffer_in_use) {
AjK 0:0a841b89d614 196 page_write_buffer_in_use = false;
AjK 0:0a841b89d614 197 LPC_GPDMACH0->DMACCConfig = 0;
AjK 0:0a841b89d614 198 DMA_release_channel(0);
AjK 0:0a841b89d614 199 LPC_SSP0->IMSC = (1UL << 3);
AjK 0:0a841b89d614 200 rit_timer_set_counter(FLASH_WRITE_CB, FLASH_WIP_TEST_TIME);
AjK 0:0a841b89d614 201 rval = 1;
AjK 0:0a841b89d614 202 }
AjK 0:0a841b89d614 203
AjK 0:0a841b89d614 204 return rval;
AjK 0:0a841b89d614 205 }
AjK 0:0a841b89d614 206
AjK 0:0a841b89d614 207 /** flash_read_ssp0_irq
AjK 0:0a841b89d614 208 *
AjK 0:0a841b89d614 209 * Called by the SSP0 ISR handler.
AjK 0:0a841b89d614 210 */
AjK 0:0a841b89d614 211 int flash_write_ssp0_irq(void) {
AjK 0:0a841b89d614 212 if (page_write_in_progress) {
AjK 0:0a841b89d614 213 if (LPC_SSP0->MIS & (1UL << 3)) {
AjK 0:0a841b89d614 214 LPC_SSP0->IMSC &= ~(1UL << 3);
AjK 0:0a841b89d614 215 while(SSP0_IS_BUSY);
AjK 0:0a841b89d614 216 FLASH_CS_DEASSERT;
AjK 0:0a841b89d614 217 SSP0_release();
AjK 0:0a841b89d614 218 return 1;
AjK 0:0a841b89d614 219 }
AjK 0:0a841b89d614 220 }
AjK 0:0a841b89d614 221 return 0;
AjK 0:0a841b89d614 222 }
AjK 0:0a841b89d614 223
AjK 0:0a841b89d614 224