예제 #1
0
 public virtual Tuple <FlashBuilderConsts.flash_page, UInt32> _next_nonsame_page(UInt32 i)
 {
     if (i >= this.page_list.Count)
     {
         return(new Tuple <FlashBuilderConsts.flash_page, UInt32>(null, i));
     }
     FlashBuilderConsts.flash_page page = this.page_list[(int)i];
     while ((bool)page.same)
     {
         i += 1;
         if (i >= this.page_list.Count)
         {
             return(new Tuple <FlashBuilderConsts.flash_page, UInt32>(null, i));
         }
         page = this.page_list[(int)i];
     }
     return(Tuple.Create(page, i + 1));
 }
예제 #2
0
        //
        //         Determine fastest method of flashing and then run flash programming.
        //
        //         Data must have already been added with addData
        //
        public virtual FlashBuilderConsts.ProgrammingInfo program(bool?chip_erase = null, Action <double> progress_cb = null, bool smart_flash = true, bool fast_verify = false)
        {
            // Assumptions
            // 1. Page erases must be on page boundaries ( page_erase_addr % page_size == 0 )
            // 2. Page erase can have a different size depending on location
            // 3. It is safe to program a page with less than a page of data
            // Examples
            // - lpc4330     -Non 0 base address
            // - nRF51       -UICR location far from flash (address 0x10001000)
            // - LPC1768     -Different sized pages
            DateTime program_start = DateTime.Now;

            progress_cb = progress_cb ?? FlashBuilderConsts._stub_progress;
            // There must be at least 1 flash operation
            if (this.flash_operation_list.Count == 0)
            {
                Trace.TraceWarning("No pages were programmed");
                return(null);
            }
            // Convert the list of flash operations into flash pages
            UInt32 program_byte_count = 0;
            UInt32 flash_addr         = this.flash_operation_list[0].addr;

            FlashConsts.PageInfo info = this.flash.getPageInfo(flash_addr);
            UInt32 page_addr          = flash_addr - flash_addr % (UInt32)info.size;
            var    current_page       = new FlashBuilderConsts.flash_page(page_addr, (UInt32)info.size, new List <byte>(), (double)info.erase_weight, (double)info.program_weight);

            this.page_list.Add(current_page);
            foreach (FlashBuilderConsts.flash_operation flash_op in this.flash_operation_list)
            {
                UInt32 pos = 0;
                while (pos < flash_op.data.Count)
                {
                    // Check if operation is in next page
                    flash_addr = flash_op.addr + pos;
                    if (flash_addr >= current_page.addr + current_page.size)
                    {
                        info         = this.flash.getPageInfo(flash_addr);
                        page_addr    = flash_addr - flash_addr % (UInt32)info.size;
                        current_page = new FlashBuilderConsts.flash_page(page_addr, (UInt32)info.size, new List <byte>(), (double)info.erase_weight, (double)info.program_weight);
                        this.page_list.Add(current_page);
                    }
                    // Fill the page gap if there is one
                    UInt32 page_data_end = current_page.addr + (UInt32)current_page.data.Count;
                    if (flash_addr != page_data_end)
                    {
                        List <byte> old_data = this.flash.target.readBlockMemoryUnaligned8(page_data_end, flash_addr - page_data_end);
                        current_page.data.AddRange(old_data);
                    }
                    // Copy data to page and increment pos
                    UInt32 space_left_in_page = (UInt32)(info.size - current_page.data.Count);
                    UInt32 space_left_in_data = (UInt32)flash_op.data.Count - pos;
                    UInt32 amount             = Math.Min(space_left_in_page, space_left_in_data);
                    current_page.data.AddRange(flash_op.data.GetRange((int)pos, (int)amount));
                    program_byte_count += amount;
                    //increment position
                    pos += amount;
                }
            }
            // If smart flash was set to false then mark all pages
            // as requiring programming
            if (!smart_flash)
            {
                this._mark_all_pages_for_programming();
            }
            // If the first page being programmed is not the first page
            // in ROM then don't use a chip erase
            if (this.page_list[0].addr > this.flash_start)
            {
                if (chip_erase == null)
                {
                    chip_erase = false;
                }
                else if (chip_erase == true)
                {
                    Trace.TraceWarning("Chip erase used when flash address 0x{0:X} is not the same as flash start 0x{1:X}", this.page_list[0].addr, this.flash_start);
                }
            }
            this.flash.init();
            var      _tup_1                      = this._compute_chip_erase_pages_and_weight();
            var      chip_erase_count            = _tup_1.Item1;
            TimeSpan chip_erase_program_time     = TimeSpan.FromSeconds(_tup_1.Item2);
            TimeSpan page_erase_min_program_time = TimeSpan.FromSeconds(this._compute_page_erase_pages_weight_min());

            // If chip_erase hasn't been specified determine if chip erase is faster
            // than page erase regardless of contents
            if (chip_erase == null && chip_erase_program_time < page_erase_min_program_time)
            {
                chip_erase = true;
            }

            TimeSpan page_program_time  = TimeSpan.Zero;
            UInt32   sector_erase_count = 0;

            // If chip erase isn't True then analyze the flash
            if (!(bool)chip_erase)
            {
                DateTime analyze_start = DateTime.Now;
                if ((bool)this.flash.getFlashInfo().crc_supported)
                {
                    var _tup_2 = this._compute_page_erase_pages_and_weight_crc32(fast_verify);
                    sector_erase_count     = _tup_2.Item1;
                    page_program_time      = TimeSpan.FromSeconds(_tup_2.Item2);
                    this.perf.analyze_type = FlashBuilder.FLASH_ANALYSIS_CRC32;
                }
                else
                {
                    var _tup_3 = this._compute_page_erase_pages_and_weight_sector_read();
                    sector_erase_count     = _tup_3.Item1;
                    page_program_time      = TimeSpan.FromSeconds(_tup_3.Item2);
                    this.perf.analyze_type = FlashBuilder.FLASH_ANALYSIS_PARTIAL_PAGE_READ;
                }
                DateTime analyze_finish = DateTime.Now;
                this.perf.analyze_time = analyze_finish - analyze_start;
                Trace.TraceInformation(String.Format("Analyze time: {0}", analyze_finish - analyze_start));
            }
            // If chip erase hasn't been set then determine fastest method to program
            if (chip_erase == null)
            {
                Trace.TraceInformation(String.Format("Chip erase count {0}, Page erase est count {1}", chip_erase_count, sector_erase_count));
                //Trace.TraceInformation(String.Format("Chip erase weight {0}, Page erase weight {2}", chip_erase_program_time, page_program_time));
                chip_erase = chip_erase_program_time < page_program_time;
            }

            byte?flash_operation = null;

            if ((bool)chip_erase)
            {
                if (this.flash.isDoubleBufferingSupported() && this.enable_double_buffering)
                {
                    Trace.TraceInformation("Using double buffer chip erase program");
                    flash_operation = this._chip_erase_program_double_buffer(progress_cb);
                }
                else
                {
                    flash_operation = this._chip_erase_program(progress_cb);
                }
            }
            else if (this.flash.isDoubleBufferingSupported() && this.enable_double_buffering)
            {
                Trace.TraceInformation("Using double buffer page erase program");
                flash_operation = this._page_erase_program_double_buffer(progress_cb);
            }
            else
            {
                flash_operation = this._page_erase_program(progress_cb);
            }
            this.flash.target.resetStopOnReset();
            DateTime program_finish = DateTime.Now;

            this.perf.program_time = program_finish - program_start;
            this.perf.program_type = flash_operation.ToString();
            Trace.TraceInformation("Programmed {0} bytes ({1} pages) at {2:0.00} kB/s", program_byte_count, this.page_list.Count, program_byte_count / 1024 / ((TimeSpan)this.perf.program_time).TotalSeconds);
            return(this.perf);
        }