/******************************************************************************
|
/******************************************************************************
|
* void - Bootloader Version 0.2.1 *
|
* void - Bootloader Version 0.2.1 *
|
******************************************************************************
|
******************************************************************************
|
* Copyright (C)2011 Mathias Hörtnagl <mathias.hoertnagl@gmail.com> *
|
* Copyright (C)2011 Mathias Hörtnagl <mathias.hoertnagl@gmail.com> *
|
* *
|
* *
|
* This program is free software: you can redistribute it and/or modify *
|
* This program is free software: you can redistribute it and/or modify *
|
* it under the terms of the GNU General Public License as published by *
|
* it under the terms of the GNU General Public License as published by *
|
* the Free Software Foundation, either version 3 of the License, or *
|
* the Free Software Foundation, either version 3 of the License, or *
|
* (at your option) any later version. *
|
* (at your option) any later version. *
|
* *
|
* *
|
* This program is distributed in the hope that it will be useful, *
|
* This program is distributed in the hope that it will be useful, *
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
|
* GNU General Public License for more details. *
|
* GNU General Public License for more details. *
|
* *
|
* *
|
* You should have received a copy of the GNU General Public License *
|
* You should have received a copy of the GNU General Public License *
|
* along with this program. If not, see <http://www.gnu.org/licenses/>. *
|
* along with this program. If not, see <http://www.gnu.org/licenses/>. *
|
******************************************************************************/
|
******************************************************************************/
|
#include "stdio.h"
|
#include "stdio.h"
|
#include "stdlib.h"
|
#include "stdlib.h"
|
#include "flash.h"
|
#include "flash.h"
|
#include "ui.h"
|
#include "ui.h"
|
#include "view.h"
|
#include "view.h"
|
|
|
#define DDR_ADDRESS ((volatile uint *) 0x20000000)
|
#define DDR_ADDRESS ((volatile uint *) 0x20000000)
|
#define NUM_OF_WORDS 77
|
#define NUM_OF_WORDS 77
|
|
|
/******************************************************************************
|
/******************************************************************************
|
* Upload View *
|
* Upload View *
|
******************************************************************************/
|
******************************************************************************/
|
/* NOTE: Automatic deduction of the number of blocks, that need to be erased
|
/* NOTE: Automatic deduction of the number of blocks, that need to be erased
|
has not been tested extensive. */
|
has not been tested extensive. */
|
void upload() {
|
void upload() {
|
|
|
uchar state; // Flash state.
|
uchar state; // Flash state.
|
uint size; // Image size.
|
uint size; // Image size.
|
uint step; // Progress bar step size.
|
uint step; // Progress bar step size.
|
uint cval; //
|
uint cval; // Current progress value.
|
|
|
// Clear screen.
|
// Clear screen.
|
cls();
|
cls();
|
|
|
// User Upload Menu.
|
// User Upload Menu.
|
drawWindow(&wUpload);
|
drawWindow(&wUpload);
|
|
|
// Upload Initialization.
|
// Upload Initialization.
|
drawMessage(&wUpload, &msgUploadWait);
|
drawMessage(&wUpload, &msgUploadWait);
|
pbUpload.val = 0;
|
pbUpload.val = 0;
|
drawProgressBar(&wUpload, &pbUpload);
|
drawProgressBar(&wUpload, &pbUpload);
|
|
|
// Receive 4 bytes of size data.
|
// Receive 4 bytes of size data.
|
for(uchar i=0; i < 4; i++) {
|
for(uchar i=0; i < 4; i++) {
|
size <<= 8;
|
size <<= 8;
|
size += rs232_receive();
|
size += rs232_receive();
|
}
|
}
|
|
|
// Check for image size to fit into flash.
|
// Check for image size to fit into flash.
|
if(size > FLASH_BLOCK_SIZE * FLASH_BLOCKS) {
|
if(size > FLASH_BLOCK_SIZE * FLASH_BLOCKS) {
|
drawErrorWindow(&errErrorFlashSize);
|
drawErrorWindow(&errErrorFlashSize);
|
return 0;
|
return 0;
|
}
|
}
|
|
|
// Flash Clean Up.
|
// Flash Clean Up.
|
drawMessage(&wUpload, &msgUploadErase);
|
drawMessage(&wUpload, &msgUploadErase);
|
pbUpload.val = 0; // Reset progress bar.
|
pbUpload.val = 0; // Reset progress bar.
|
drawProgressBar(&wUpload, &pbUpload);
|
drawProgressBar(&wUpload, &pbUpload);
|
|
|
// Erase affected flash blocks.
|
// Erase affected flash blocks.
|
for(uint i=0; i < (size / FLASH_BLOCK_SIZE) + 1; i++) {
|
for(uint i=0; i < (size / FLASH_BLOCK_SIZE) + 1; i++) {
|
flash_block_erase(i * FLASH_BLOCK_SIZE);
|
flash_block_erase(i * FLASH_BLOCK_SIZE);
|
|
|
// Update the Progress Bar.
|
// Update the Progress Bar.
|
pbUpload.val = (i >> 1);
|
pbUpload.val = (i >> 1);
|
drawProgressBar(&wUpload, &pbUpload);
|
drawProgressBar(&wUpload, &pbUpload);
|
|
|
// Check for errors while erasing.
|
// Check for errors while erasing.
|
if(flash_wait() & FLASH_ERASE_ERROR) {
|
if(flash_wait() & FLASH_ERASE_ERROR) {
|
drawErrorWindow(&errErrorFlashErase);
|
drawErrorWindow(&errErrorFlashErase);
|
return 0;
|
return 0;
|
}
|
}
|
}
|
}
|
|
|
// Echoing received image size.
|
// Echoing received image size.
|
rs232_transmit(size >> 24);
|
rs232_transmit(size >> 24);
|
rs232_transmit(size >> 16);
|
rs232_transmit(size >> 16);
|
rs232_transmit(size >> 8);
|
rs232_transmit(size >> 8);
|
rs232_transmit(size);
|
rs232_transmit(size);
|
|
|
// Upload data.
|
// Upload data.
|
drawMessage(&wUpload, &msgUploadWrite);
|
drawMessage(&wUpload, &msgUploadWrite);
|
pbUpload.val = 0; // Reset progress bar.
|
pbUpload.val = 0; // Reset progress bar.
|
step = size / 64; // Calculate progress step size.
|
step = size / 64; // Calculate progress step size.
|
cval = step;
|
cval = step;
|
|
|
// Write each single byte to Flash.
|
// Write each single byte to Flash.
|
for(uint i=0; i < size; i++) {
|
for(uint i=0; i < size; i++) {
|
flash_write(i, rs232_receive());
|
flash_write(i, rs232_receive());
|
|
|
// Update status bar.
|
// Update status bar.
|
if(i == cval) {
|
if(i == cval) {
|
pbUpload.val++;
|
pbUpload.val++;
|
drawProgressBar(&wUpload, &pbUpload);
|
drawProgressBar(&wUpload, &pbUpload);
|
cval += step;
|
cval += step;
|
}
|
}
|
|
|
// Error checking.
|
// Error checking.
|
state = flash_wait();
|
state = flash_wait();
|
if(state & FLASH_BLOCK_LOCKED) {
|
if(state & FLASH_BLOCK_LOCKED) {
|
drawErrorWindow(&errErrorFlashLocked);
|
drawErrorWindow(&errErrorFlashLocked);
|
return 0;
|
return 0;
|
}
|
}
|
if(state & FLASH_PROGRAM_ERROR) {
|
if(state & FLASH_PROGRAM_ERROR) {
|
drawErrorWindow(&errErrorFlashWrite);
|
drawErrorWindow(&errErrorFlashWrite);
|
return 0;
|
return 0;
|
}
|
}
|
}
|
}
|
|
|
// Copy flash data to DDR2 memory.
|
// Copy flash data to DDR2 memory.
|
// NOTE: Missing bytes, if binary file is not 4 bytes aligned.
|
// NOTE: Missing bytes, if binary file is not 4 bytes aligned.
|
for(uint i=0; i < (size / 4) /* + 1 */; i++) {
|
// for(uint i=0; i < (size / 4) /* + 1 */; i++) {
|
DDR_ADDRESS[i] = flash_read(i);
|
// DDR_ADDRESS[i] = flash_read(i);
|
}
|
// }
|
|
|
// Go back to main menu.
|
// Go back to main menu.
|
boot();
|
boot();
|
}
|
}
|
|
|
|
|
/******************************************************************************
|
/******************************************************************************
|
|
* DDR Load View *
|
|
******************************************************************************/
|
|
/* Load Flash contents into DDR. */
|
|
void load() {
|
|
|
|
uint step; // Progress bar step size.
|
|
uint cval; // Current progress value.
|
|
|
|
cls();
|
|
|
|
// User Upload Menu.
|
|
drawWindow(&wDDRUpload);
|
|
|
|
// Upload Initialization.
|
|
pbUpload.val = 0;
|
|
drawProgressBar(&wDDRUpload, &pbUpload);
|
|
|
|
step = FLASH_BLOCK_SIZE * 2;
|
|
cval = step;
|
|
|
|
// Copy flash data to DDR2 memory.
|
|
for(uint i=0; i < FLASH_BLOCKS * FLASH_BLOCK_SIZE; i++) {
|
|
|
|
DDR_ADDRESS[i] = flash_read(i);
|
|
|
|
// Update status bar.
|
|
if(i == cval) {
|
|
pbUpload.val++;
|
|
drawProgressBar(&wUpload, &pbUpload);
|
|
cval += step;
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
/******************************************************************************
|
* Memory View *
|
* Memory View *
|
******************************************************************************/
|
******************************************************************************/
|
/* TODO: Cleaner generic version.
|
/* TODO: Cleaner generic version.
|
Quick and dirty implementation of an memory matrix view. Shows the next
|
Quick and dirty implementation of an memory matrix view. Shows the next
|
'NUM_OF_WORDS' starting at location 'adr' of the Flash and the DDR memory
|
'NUM_OF_WORDS' starting at location 'adr' of the Flash and the DDR memory
|
device. */
|
device. */
|
void show_memory_contents(uint adr) {
|
void show_memory_contents(uint adr) {
|
|
|
uchar b;
|
uchar b;
|
uchar t;
|
uchar t;
|
|
|
b = 0; t = 0;
|
b = 0; t = 0;
|
for(uint i=adr; i < adr + NUM_OF_WORDS; i++) {
|
for(uint i=adr; i < adr + NUM_OF_WORDS; i++) {
|
|
|
if(b == 0) {
|
if(b == 0) {
|
gotoxy(6, 4 + t++);
|
gotoxy(6, 4 + t++);
|
printf("$y%x:$w ", FLASH_MEMORY + (i << 2));
|
printf("$y%x:$w ", FLASH_MEMORY + (i << 2));
|
}
|
}
|
printf("%x ", flash_read(i));
|
printf("%x ", flash_read(i));
|
if(b++ == 6) b = 0;
|
if(b++ == 6) b = 0;
|
}
|
}
|
|
|
b = 0; t = 0;
|
b = 0; t = 0;
|
for(uint i=adr; i < adr + NUM_OF_WORDS; i++) {
|
for(uint i=adr; i < adr + NUM_OF_WORDS; i++) {
|
|
|
if(b == 0) {
|
if(b == 0) {
|
gotoxy(6, 20 + t++);
|
gotoxy(6, 20 + t++);
|
printf("$y%x:$w ", DDR_ADDRESS + i);
|
printf("$y%x:$w ", DDR_ADDRESS + i);
|
}
|
}
|
printf("%x ", DDR_ADDRESS[i]);
|
printf("%x ", DDR_ADDRESS[i]);
|
if(b++ == 6) b = 0;
|
if(b++ == 6) b = 0;
|
}
|
}
|
}
|
}
|
|
|
/* View the memory contents of the Flash and DDR devices. Navigate through the
|
/* View the memory contents of the Flash and DDR devices. Navigate through the
|
address space with ARROW UP and DOWN keys. Returns to the boot loader on
|
address space with ARROW UP and DOWN keys. Returns to the boot loader on
|
ESC key pressed. */
|
ESC key pressed. */
|
void view_memories() {
|
void view_memories() {
|
|
|
uint adr = 0;
|
uint adr = 0;
|
|
|
cls();
|
cls();
|
|
|
drawWindow(&wFlashMemory);
|
drawWindow(&wFlashMemory);
|
drawWindow(&wDDRMemory);
|
drawWindow(&wDDRMemory);
|
|
|
// Show contetnts starting at address 0 at the beginning.
|
// Show contetnts starting at address 0 at the beginning.
|
show_memory_contents(0);
|
show_memory_contents(0);
|
|
|
while(TRUE) {
|
while(TRUE) {
|
switch(getc()->chr) {
|
switch(getc()->chr) {
|
case KEY_ARROWD:
|
case KEY_ARROWD:
|
adr += NUM_OF_WORDS;
|
adr += NUM_OF_WORDS;
|
show_memory_contents(adr);
|
show_memory_contents(adr);
|
break;
|
break;
|
|
|
case KEY_ARROWU:
|
case KEY_ARROWU:
|
if(adr >= NUM_OF_WORDS) adr -= NUM_OF_WORDS;
|
if(adr >= NUM_OF_WORDS) adr -= NUM_OF_WORDS;
|
show_memory_contents(adr);
|
show_memory_contents(adr);
|
break;
|
break;
|
|
|
case KEY_ESC:
|
case KEY_ESC:
|
boot();
|
boot();
|
break;
|
break;
|
|
|
default:
|
default:
|
break;
|
break;
|
}
|
}
|
}
|
}
|
}
|
}
|
|
|
|
|
/******************************************************************************
|
/******************************************************************************
|
* Boot View *
|
* Boot View *
|
******************************************************************************/
|
******************************************************************************/
|
/* Wait for completed flash initialization. Set up main menu box. */
|
/* Wait for completed flash initialization. Set up main menu box. */
|
int main() {
|
int main() {
|
|
|
// Clear screen.
|
// Clear screen.
|
cls();
|
cls();
|
|
|
// Wait for flash hardware initialization end.
|
// Wait for flash hardware initialization end.
|
uchar s = flash_wait();
|
uchar s = flash_wait();
|
|
|
// Flash not ready.
|
// Flash not ready.
|
if( !(s & FLASH_READY) ) {
|
if( !(s & FLASH_READY) ) {
|
drawErrorWindow(&errFlashNotReady);
|
drawErrorWindow(&errFlashNotReady);
|
return 0;
|
return 0;
|
}
|
}
|
|
|
// Flash command error.
|
// Flash command error.
|
if(s & FLASH_CMD_ERROR) {
|
if(s & FLASH_CMD_ERROR) {
|
drawErrorWindow(&errFlashState);
|
drawErrorWindow(&errFlashState);
|
flash_clear_sr();
|
flash_clear_sr();
|
//boot();
|
//boot();
|
return 0;
|
return 0;
|
}
|
}
|
|
|
// User Main Menu.
|
// User Main Menu.
|
drawWindow(&wBoot);
|
drawWindow(&wBoot);
|
|
|
while(TRUE) {
|
while(TRUE) {
|
switch(getc()->chr) {
|
switch(getc()->chr) {
|
case KEY_ARROWD:
|
case KEY_ARROWD:
|
menuKeyDown(&wBoot, &menu);
|
menuKeyDown(&wBoot, &menu);
|
break;
|
break;
|
|
|
case KEY_ARROWU:
|
case KEY_ARROWU:
|
menuKeyUp(&wBoot, &menu);
|
menuKeyUp(&wBoot, &menu);
|
break;
|
break;
|
|
|
case KEY_ENTER:
|
case KEY_ENTER:
|
switch(menu.index) {
|
switch(menu.index) {
|
case OPTION_UPLOAD:
|
case OPTION_UPLOAD:
|
upload();
|
upload();
|
break;
|
break;
|
|
|
case OPTION_MEMORY:
|
case OPTION_MEMORY:
|
view_memories();
|
view_memories();
|
break;
|
break;
|
|
|
case OPTION_START:
|
case OPTION_START:
|
|
load();
|
start();
|
start();
|
break;
|
break;
|
|
|
default:
|
default:
|
break;
|
break;
|
}
|
}
|
break;
|
break;
|
|
|
default:
|
default:
|
break;
|
break;
|
}
|
}
|
}
|
}
|
}
|
}
|
|
|