• Main Page
  • Modules
  • Index
  • File List
  • Globals

projects/nrfgo_sdk/bootloader_32k/firmware/bootloader.c

Go to the documentation of this file.
00001 /* Copyright (c) 2009 Nordic Semiconductor. All Rights Reserved.
00002  *
00003  * The information contained herein is confidential property of Nordic 
00004  * Semiconductor ASA.Terms and conditions of usage are described in detail 
00005  * in NORDIC SEMICONDUCTOR STANDARD SOFTWARE LICENSE AGREEMENT. 
00006  *
00007  * Licensees are granted free, non-transferable use of the information. NO
00008  * WARRENTY of ANY KIND is provided. This heading must NOT be removed from
00009  * the file.
00010  *              
00011  * $LastChangedRevision: 133 $
00012  */
00013 
00018 #include <Nordic\reg24lu1.h>
00019 #include <intrins.h>
00020 
00021 #include "usb.h"
00022 #include "bootloader.h"
00023 #include "version.h"
00024 #include "usb_cmds.h"
00025 #include "flash.h"
00026 #include "config.h"
00027 
00028 // Place all code and constants in this file in the segment "BOOTLOADER":
00029 #pragma userclass (code = BOOTLOADER)
00030 #pragma userclass (const = BOOTLOADER)
00031 
00032 extern bool packet_received;
00033 
00034 extern xdata volatile uint8_t in1buf[];
00035 extern xdata volatile uint8_t out1buf[];
00036 extern xdata volatile uint8_t in1bc;
00037 
00038 static xdata uint8_t rdismb _at_ 0x0023;                // Readback Disable byte in InfoPage
00039 
00040 static bool page_write;
00041 static uint16_t nblock;                                 // Holds the number of the current USB_EP1_SIZE bytes block
00042 static uint8_t nblocks;                                 // Holds number of the blocks programmed
00043 
00044 static bool idata used_flash_pages[NUM_FLASH_PAGES];    // Holds which flash pages to erase
00045 
00046 
00047 void parse_commands(void)
00048 {
00049     uint8_t count = 0, tmp;
00050 
00051     if(page_write)
00052     {
00053         // Multiply nblock with 64 to get block start address in flash:
00054         flash_bytes_write(nblock << 6, out1buf, USB_EP1_SIZE);
00055         nblock++;
00056         nblocks++;
00057         in1buf[0] = 0;
00058         count = 1;
00059         if (nblocks == (FLASH_PAGE_SIZE/USB_EP1_SIZE))
00060         {
00061             page_write = false;
00062         }
00063     }
00064     else
00065     {
00066         switch(out1buf[0])
00067         {
00068             case CMD_FIRMWARE_VERSION:
00069                 in1buf[0] = FW_VER_MAJOR;
00070                 in1buf[1] = FW_VER_MINOR;
00071                 count = 2;
00072                 break;
00073 
00074             case CMD_FLASH_ERASE_PAGE:
00075                 flash_page_erase(out1buf[1]);
00076                 used_flash_pages[out1buf[1]] = false;
00077                 in1buf[0] = 0;
00078                 count = 1;
00079                 break;
00080 
00081             case CMD_FLASH_WRITE_INIT:                  // Eight 64 bytes bulk packets <- PC follow after this command
00082                 if (used_flash_pages[out1buf[1]])
00083                 {
00084                     flash_page_erase(out1buf[1]);
00085                 }
00086                 used_flash_pages[out1buf[1]] = 1;
00087                 nblock = (uint16_t)out1buf[1] << 3;     // Multiply page number by 8 to get block number
00088                 nblocks = 0;
00089                 page_write = true;
00090                 in1buf[0] = 0;
00091                 count = 1;
00092                 break;
00093 
00094             case CMD_FLASH_READ:
00095                 // Read one USB_EP1_SIZE bytes block from the address given
00096                 // by out1buf[1] << 6 and MS bit set by CMD_FLASH_SELECT_HALF
00097                 // below:
00098                 nblock = (nblock & 0xff00) | (uint16_t)out1buf[1];
00099                 if (RDIS)
00100                 {
00101                     // RDISMB is set. Will return 0x00 for pages that are in use and 0xff
00102                     // for unused pages.
00103                     if (used_flash_pages[nblock >> 3])
00104                         tmp = 0x00;
00105                     else
00106                         tmp = 0xff;
00107                     for(count=0;count<USB_EP1_SIZE;count++)
00108                         in1buf[count] = tmp;
00109                 } 
00110                 else
00111                     flash_bytes_read((uint16_t)nblock<<6, in1buf, USB_EP1_SIZE);
00112                 count = USB_EP1_SIZE;
00113                 break;
00114 
00115             case CMD_FLASH_SET_PROTECTED:
00116                 count = 1;
00117                 INFEN = 1;
00118                 if (rdismb != 0xff)
00119                 {
00120                     in1buf[0] = 1;
00121                 }
00122                 else
00123                 {
00124                     flash_byte_write((uint16_t)&rdismb, 0x00);
00125                     in1buf[0] = 0;
00126                 }
00127                 INFEN = 0;
00128                 break;
00129 
00130             case CMD_FLASH_SELECT_HALF:
00131                 // When outbuf[1] = 0 program the lower half of the 32K bytes flash
00132                 // and when outbuf[1] = 1 program the upper part:
00133                 if (out1buf[1] == 1)
00134                     nblock = (nblock & 0x00ff) | 0x0100;
00135                 else
00136                     nblock &= 0x00ff;
00137                 in1buf[0] = 0;
00138                 count = 1;
00139                 break;
00140 
00141             default:
00142                 break;
00143         }
00144     }
00145     if (count > 0)
00146         in1bc = count;
00147 }
00148 
00149 static void get_used_flash_pages(void)
00150 {    
00151     uint8_t xdata *pb;
00152     uint8_t i;
00153     uint16_t j;
00154     //
00155     // Read through the whole flash to find out which flash
00156     // pages that are in use. Store the result in the NUM_FLASH_PAGES
00157     // sized array used_flash_pages[]:
00158     for(i=0;i<NUM_FLASH_PAGES;i++)
00159     {
00160         used_flash_pages[i] = false;        
00161         for(j=0,pb = (uint8_t xdata *)(FLASH_PAGE_SIZE * (uint16_t)i);j<FLASH_PAGE_SIZE;j++, pb++)
00162         {
00163             if(*pb != 0xff)
00164             {
00165                 used_flash_pages[i] = true;
00166                 break;
00167             }
00168         }
00169     }
00170 }
00171 
00172 void bootloader(void)
00173 {
00174     EA = 0;
00175     get_used_flash_pages();
00176     usb_init();
00177     CKCON = 0x02;       // See nRF24LU1p AX PAN
00178     nblock = 0;
00179     packet_received = page_write = false;
00180     //
00181     // Enter an infinite loop waiting checking the USB interrupt flag and
00182     // call the interrupt handler, usb_irq, when the flag is set. The interrupt
00183     // handler will set the variable packet_received to true when a packet is
00184     // received.     
00185     for(;;)
00186     {
00187         if (USBF)
00188         {
00189             USBF = 0;
00190             usb_irq();
00191             if(packet_received)
00192             {
00193                 parse_commands();
00194                 packet_received = false;
00195             }
00196         }
00197     }
00198 }

Generated on Fri Apr 20 2012 14:11:45 for nRFGo SDK by  doxygen 1.7.2