Firmware: reduce bootloader size (8k), LED error codes

This commit is contained in:
ikari 2011-02-22 23:47:01 +01:00
parent 74a9ed346d
commit 8ad34f1ab7
16 changed files with 185 additions and 341 deletions

View File

@ -55,7 +55,7 @@ TARGET = $(OBJDIR)/sd2snes_bootldr
# List C source files here. (C dependencies are automatically generated.)
SRC = timer.c main.c ff.c clock.c uart.c power.c led.c printf.c faulthandler.c crc32.c sdnative.c fileops.c iap.c
SRC = timer.c main.c ff.c clock.c uart.c power.c led.c faulthandler.c crc32.c sdnative.c fileops.c iap.c printf.c
# usbcontrol.c usb_hid.c usbhw_lpc.c usbinit.c usbstdreq.c
@ -73,7 +73,6 @@ ASRC = startup.S crc.S
# Optimization level, can be [0, 1, 2, 3, s].
# 0 = turn off optimization. s = optimize for size.
# (Note: 3 is not always the best optimization level. See avr-libc FAQ.)
# Use s -mcall-prologues when you really need size...
#OPT = 2
OPT = s

View File

@ -5,7 +5,15 @@
// #define DEBUG_IRQ
// #define DEBUG_MSU1
#define FW_START (0x00004000L)
//#define DEBUG_BL
#ifdef DEBUG_BL
#define DBG_BL
#else
#define DBG_BL while(0)
#endif
#define FW_START (0x00002000L)
#define FLASH_SECTORS (17)
#define VER "0.0.1(NSFW)"

View File

@ -2,7 +2,7 @@
* \file crc32.c
* Functions and types for CRC checks.
*
* Generated on Sat Sep 25 18:06:34 2010,
* Generated on Mon Feb 21 23:02:07 2011,
* by pycrc v0.7.1, http://www.tty1.net/pycrc/
* using the configuration:
* Width = 32
@ -11,83 +11,35 @@
* ReflectIn = True
* XorOut = 0xffffffff
* ReflectOut = True
* Algorithm = table-driven
* Algorithm = bit-by-bit-fast
* Direct = True
*****************************************************************************/
#include "crc32.h"
#include "config.h"
#include <arm/NXP/LPC17xx/LPC17xx.h>
#include <stdint.h>
#include <stdlib.h>
#include <stdbool.h>
/**
* Static table used for the table_driven implementation.
*****************************************************************************/
static const uint32_t crc32_table[256] = {
0x00000000, 0x77073096, 0xee0e612c, 0x990951ba,
0x076dc419, 0x706af48f, 0xe963a535, 0x9e6495a3,
0x0edb8832, 0x79dcb8a4, 0xe0d5e91e, 0x97d2d988,
0x09b64c2b, 0x7eb17cbd, 0xe7b82d07, 0x90bf1d91,
0x1db71064, 0x6ab020f2, 0xf3b97148, 0x84be41de,
0x1adad47d, 0x6ddde4eb, 0xf4d4b551, 0x83d385c7,
0x136c9856, 0x646ba8c0, 0xfd62f97a, 0x8a65c9ec,
0x14015c4f, 0x63066cd9, 0xfa0f3d63, 0x8d080df5,
0x3b6e20c8, 0x4c69105e, 0xd56041e4, 0xa2677172,
0x3c03e4d1, 0x4b04d447, 0xd20d85fd, 0xa50ab56b,
0x35b5a8fa, 0x42b2986c, 0xdbbbc9d6, 0xacbcf940,
0x32d86ce3, 0x45df5c75, 0xdcd60dcf, 0xabd13d59,
0x26d930ac, 0x51de003a, 0xc8d75180, 0xbfd06116,
0x21b4f4b5, 0x56b3c423, 0xcfba9599, 0xb8bda50f,
0x2802b89e, 0x5f058808, 0xc60cd9b2, 0xb10be924,
0x2f6f7c87, 0x58684c11, 0xc1611dab, 0xb6662d3d,
0x76dc4190, 0x01db7106, 0x98d220bc, 0xefd5102a,
0x71b18589, 0x06b6b51f, 0x9fbfe4a5, 0xe8b8d433,
0x7807c9a2, 0x0f00f934, 0x9609a88e, 0xe10e9818,
0x7f6a0dbb, 0x086d3d2d, 0x91646c97, 0xe6635c01,
0x6b6b51f4, 0x1c6c6162, 0x856530d8, 0xf262004e,
0x6c0695ed, 0x1b01a57b, 0x8208f4c1, 0xf50fc457,
0x65b0d9c6, 0x12b7e950, 0x8bbeb8ea, 0xfcb9887c,
0x62dd1ddf, 0x15da2d49, 0x8cd37cf3, 0xfbd44c65,
0x4db26158, 0x3ab551ce, 0xa3bc0074, 0xd4bb30e2,
0x4adfa541, 0x3dd895d7, 0xa4d1c46d, 0xd3d6f4fb,
0x4369e96a, 0x346ed9fc, 0xad678846, 0xda60b8d0,
0x44042d73, 0x33031de5, 0xaa0a4c5f, 0xdd0d7cc9,
0x5005713c, 0x270241aa, 0xbe0b1010, 0xc90c2086,
0x5768b525, 0x206f85b3, 0xb966d409, 0xce61e49f,
0x5edef90e, 0x29d9c998, 0xb0d09822, 0xc7d7a8b4,
0x59b33d17, 0x2eb40d81, 0xb7bd5c3b, 0xc0ba6cad,
0xedb88320, 0x9abfb3b6, 0x03b6e20c, 0x74b1d29a,
0xead54739, 0x9dd277af, 0x04db2615, 0x73dc1683,
0xe3630b12, 0x94643b84, 0x0d6d6a3e, 0x7a6a5aa8,
0xe40ecf0b, 0x9309ff9d, 0x0a00ae27, 0x7d079eb1,
0xf00f9344, 0x8708a3d2, 0x1e01f268, 0x6906c2fe,
0xf762575d, 0x806567cb, 0x196c3671, 0x6e6b06e7,
0xfed41b76, 0x89d32be0, 0x10da7a5a, 0x67dd4acc,
0xf9b9df6f, 0x8ebeeff9, 0x17b7be43, 0x60b08ed5,
0xd6d6a3e8, 0xa1d1937e, 0x38d8c2c4, 0x4fdff252,
0xd1bb67f1, 0xa6bc5767, 0x3fb506dd, 0x48b2364b,
0xd80d2bda, 0xaf0a1b4c, 0x36034af6, 0x41047a60,
0xdf60efc3, 0xa867df55, 0x316e8eef, 0x4669be79,
0xcb61b38c, 0xbc66831a, 0x256fd2a0, 0x5268e236,
0xcc0c7795, 0xbb0b4703, 0x220216b9, 0x5505262f,
0xc5ba3bbe, 0xb2bd0b28, 0x2bb45a92, 0x5cb36a04,
0xc2d7ffa7, 0xb5d0cf31, 0x2cd99e8b, 0x5bdeae1d,
0x9b64c2b0, 0xec63f226, 0x756aa39c, 0x026d930a,
0x9c0906a9, 0xeb0e363f, 0x72076785, 0x05005713,
0x95bf4a82, 0xe2b87a14, 0x7bb12bae, 0x0cb61b38,
0x92d28e9b, 0xe5d5be0d, 0x7cdcefb7, 0x0bdbdf21,
0x86d3d2d4, 0xf1d4e242, 0x68ddb3f8, 0x1fda836e,
0x81be16cd, 0xf6b9265b, 0x6fb077e1, 0x18b74777,
0x88085ae6, 0xff0f6a70, 0x66063bca, 0x11010b5c,
0x8f659eff, 0xf862ae69, 0x616bffd3, 0x166ccf45,
0xa00ae278, 0xd70dd2ee, 0x4e048354, 0x3903b3c2,
0xa7672661, 0xd06016f7, 0x4969474d, 0x3e6e77db,
0xaed16a4a, 0xd9d65adc, 0x40df0b66, 0x37d83bf0,
0xa9bcae53, 0xdebb9ec5, 0x47b2cf7f, 0x30b5ffe9,
0xbdbdf21c, 0xcabac28a, 0x53b39330, 0x24b4a3a6,
0xbad03605, 0xcdd70693, 0x54de5729, 0x23d967bf,
0xb3667a2e, 0xc4614ab8, 0x5d681b02, 0x2a6f2b94,
0xb40bbe37, 0xc30c8ea1, 0x5a05df1b, 0x2d02ef8d
};
* Reflect all bits of a \a data word of \a data_len bytes.
*
* \param data The data word to be reflected.
* \param data_len The width of \a data expressed in number of bits.
* \return The reflected data.
******************************************************************************/
uint32_t crc_reflect(uint32_t data, size_t data_len)
{
unsigned int i;
uint32_t ret;
ret = data & 0x01;
for (i = 1; i < data_len; i++)
{
data >>= 1;
ret = (ret << 1) | (data & 0x01);
}
return ret;
}
/**
* Update the crc value with new data.
@ -99,12 +51,22 @@ static const uint32_t crc32_table[256] = {
*****************************************************************************/
uint32_t crc32_update(uint32_t crc, const unsigned char data)
{
unsigned int tbl_idx;
unsigned int i;
uint32_t bit;
unsigned char c;
tbl_idx = (crc ^ data) & 0xff;
crc = (crc32_table[tbl_idx] ^ (crc >> 8)) & 0xffffffff;
return crc & 0xffffffff;
c = data;
for (i = 0x01; i & 0xff; i <<= 1) {
bit = crc & 0x80000000;
if (c & i) {
bit = !bit;
}
crc <<= 1;
if (bit) {
crc ^= 0x04c11db7;
}
}
return crc & 0xffffffff;
}

View File

@ -2,7 +2,7 @@
* \file crc32.h
* Functions and types for CRC checks.
*
* Generated on Sat Sep 25 18:06:37 2010,
* Generated on Mon Feb 21 23:03:39 2011,
* by pycrc v0.7.1, http://www.tty1.net/pycrc/
* using the configuration:
* Width = 32
@ -11,13 +11,13 @@
* ReflectIn = True
* XorOut = 0xffffffff
* ReflectOut = True
* Algorithm = table-driven
* Algorithm = bit-by-bit-fast
* Direct = True
*****************************************************************************/
#ifndef __CRC___H__
#define __CRC___H__
#include <arm/NXP/LPC17xx/LPC17xx.h>
#include <stdint.h>
#include <stdlib.h>
#ifdef __cplusplus
@ -27,7 +27,22 @@ extern "C" {
/**
* The definition of the used algorithm.
*****************************************************************************/
#define CRC_ALGO_TABLE_DRIVEN 1
#define CRC_ALGO_BIT_BY_BIT_FAST 1
/**
* The type of the CRC values.
*
* This type must be big enough to contain at least 32 bits.
*****************************************************************************/
/**
* Reflect all bits of a \a data word of \a data_len bytes.
*
* \param data The data word to be reflected.
* \param data_len The width of \a data expressed in number of bits.
* \return The reflected data.
*****************************************************************************/
uint32_t crc_reflect(uint32_t data, size_t data_len);
/**
* Calculate the initial crc value.
@ -36,7 +51,7 @@ extern "C" {
*****************************************************************************/
static inline uint32_t crc_init(void)
{
return 0xffffffff;
return 0xffffffff;
}
/**
@ -55,9 +70,9 @@ uint32_t crc32_update(uint32_t crc, const unsigned char data);
* \param crc The current crc value.
* \return The final crc value.
*****************************************************************************/
static inline uint32_t crc32_finalize(uint32_t crc)
static inline uint32_t crc_finalize(uint32_t crc)
{
return crc ^ 0xffffffff;
return crc_reflect(crc, 32) ^ 0xffffffff;
}

View File

@ -1,20 +1,22 @@
#include <arm/NXP/LPC17xx/LPC17xx.h>
#include "config.h"
#include "uart.h"
void HardFault_Handler(void) {
printf("HFSR: %lx\n", SCB->HFSR);
DBG_BL printf("HFSR: %lx\n", SCB->HFSR);
uart_putc('H');
while (1) ;
}
void MemManage_Handler(void) {
printf("MemManage - CFSR: %lx; MMFAR: %lx\n", SCB->CFSR, SCB->MMFAR);
DBG_BL printf("MemManage - CFSR: %lx; MMFAR: %lx\n", SCB->CFSR, SCB->MMFAR);
}
void BusFault_Handler(void) {
printf("BusFault - CFSR: %lx; BFAR: %lx\n", SCB->CFSR, SCB->BFAR);
DBG_BL printf("BusFault - CFSR: %lx; BFAR: %lx\n", SCB->CFSR, SCB->BFAR);
}
void UsageFault_Handler(void) {
printf("UsageFault - CFSR: %lx; BFAR: %lx\n", SCB->CFSR, SCB->BFAR);
DBG_BL printf("UsageFault - CFSR: %lx; BFAR: %lx\n", SCB->CFSR, SCB->BFAR);
}

View File

@ -2145,7 +2145,6 @@ FRESULT f_read (
UINT rcnt, cc;
BYTE csect, *rbuff = buff;
if(btr>512) printf("WARNING: read >512 bytes!!\n");
*br = 0; /* Initialize byte counter */

View File

@ -20,13 +20,13 @@
/ data transfer. This reduces memory consumption 512 bytes each file object. */
#define _FS_READONLY 0 /* 0:Read/Write or 1:Read only */
#define _FS_READONLY 1 /* 0:Read/Write or 1:Read only */
/* Setting _FS_READONLY to 1 defines read only configuration. This removes
/ writing functions, f_write, f_sync, f_unlink, f_mkdir, f_chmod, f_rename,
/ f_truncate and useless f_getfree. */
#define _FS_MINIMIZE 2 /* 0 to 3 */
#define _FS_MINIMIZE 3 /* 0 to 3 */
/* The _FS_MINIMIZE option defines minimization level to remove some functions.
/
/ 0: Full function.

View File

@ -72,14 +72,14 @@ UINT file_read() {
return bytes_read;
}
UINT file_write() {
/*UINT file_write() {
UINT bytes_written;
file_res = f_write(&file_handle, file_buf, sizeof(file_buf), &bytes_written);
if(bytes_written < sizeof(file_buf)) {
printf("wrote less than expected - card full?\n");
}
return bytes_written;
}
}*/
UINT file_readblock(void* buf, uint32_t addr, uint16_t size) {
UINT bytes_read;
@ -91,13 +91,13 @@ UINT file_readblock(void* buf, uint32_t addr, uint16_t size) {
return bytes_read;
}
UINT file_writeblock(void* buf, uint32_t addr, uint16_t size) {
/*UINT file_writeblock(void* buf, uint32_t addr, uint16_t size) {
UINT bytes_written;
file_res = f_lseek(&file_handle, addr);
if(file_res) return 0;
file_res = f_write(&file_handle, buf, size, &bytes_written);
return bytes_written;
}
}*/
uint8_t file_getc() {
if(file_block_off == file_block_max) {

View File

@ -6,6 +6,7 @@
#include "uart.h"
#include "fileops.h"
#include "crc32.h"
#include "led.h"
uint32_t iap_cmd[5];
uint32_t iap_res[5];
@ -14,7 +15,7 @@ uint32_t flash_sig[4];
IAP iap_entry = (IAP) IAP_LOCATION;
uint32_t calc_flash_crc(uint32_t start, uint32_t len) {
printf("calc_flash_crc(%08lx, %08lx) {\n", start, len);
DBG_BL printf("calc_flash_crc(%08lx, %08lx) {\n", start, len);
uint32_t end = start + len;
if(end > 0x20000) {
len = 0x1ffff - start;
@ -26,20 +27,20 @@ uint32_t calc_flash_crc(uint32_t start, uint32_t len) {
crc = crc32_update(crc, *(const unsigned char*)(s));
s++;
}
crc ^= 0xffffffff;
printf(" crc generated. result=%08lx\n", crc);
printf("} //calc_flash_crc\n");
crc = crc_finalize(crc);
DBG_BL printf(" crc generated. result=%08lx\n", crc);
DBG_BL printf("} //calc_flash_crc\n");
return crc;
}
void test_iap() {
iap_cmd[0]=54;
iap_entry(iap_cmd, iap_res);
printf("Part ID=%08lx\n", iap_res[1]);
DBG_BL printf("Part ID=%08lx\n", iap_res[1]);
}
void print_header(sd2snes_fw_header *header) {
printf(" magic = %08lx\n version = %08lx\n size = %08lx\n crc = %08lx\n ~crc = %08lx\n",
DBG_BL printf(" magic = %08lx\n version = %08lx\n size = %08lx\n crc = %08lx\n ~crc = %08lx\n",
header->magic, header->version, header->size,
header->crc, header->crcc);
}
@ -61,11 +62,11 @@ FLASH_RES check_flash() {
sd2snes_fw_header *fw_header = (sd2snes_fw_header*) FW_START;
uint32_t flash_addr = FW_START;
if(flash_addr != FW_START) {
printf("address sanity check failed. expected 0x%08lx, got 0x%08lx.\nSomething is terribly wrong.\nBailing out to avoid bootldr self-corruption.\n", FW_START, flash_addr);
DBG_BL printf("address sanity check failed. expected 0x%08lx, got 0x%08lx.\nSomething is terribly wrong.\nBailing out to avoid bootldr self-corruption.\n", FW_START, flash_addr);
return ERR_HW;
}
printf("Current flash contents:\n");
print_header(fw_header);
DBG_BL printf("Current flash contents:\n");
DBG_BL print_header(fw_header);
uint32_t crc = calc_flash_crc(flash_addr + 0x100, (fw_header->size & 0x1ffff));
return check_header(fw_header, crc);
}
@ -74,7 +75,6 @@ IAP_RES iap_wrap(uint32_t *iap_cmd, uint32_t *iap_res) {
NVIC_DisableIRQ(RIT_IRQn);
NVIC_DisableIRQ(UART_IRQ);
iap_entry(iap_cmd, iap_res);
NVIC_EnableIRQ(RIT_IRQn);
NVIC_EnableIRQ(UART_IRQ);
return iap_res[0];
}
@ -116,20 +116,21 @@ FLASH_RES flash_file(uint8_t *filename) {
sd2snes_fw_header file_header;
UINT bytes_read;
if(flash_addr != FW_START) {
printf("address sanity check failed. expected 0x%08lx, got 0x%08lx.\nSomething is terribly wrong.\nBailing out to avoid bootldr self-corruption.\n", FW_START, flash_addr);
DBG_BL printf("address sanity check failed. expected 0x%08lx, got 0x%08lx.\nSomething is terribly wrong.\nBailing out to avoid bootldr self-corruption.\n", FW_START, flash_addr);
return ERR_HW;
}
file_open(filename, FA_READ);
if(file_res) {
printf("file_open: error %d\n", file_res);
DBG_BL printf("file_open: error %d\n", file_res);
return ERR_FS;
}
printf("firmware image found. file size: %ld\n", file_handle.fsize);
printf("reading header...\n");
DBG_BL printf("firmware image found. file size: %ld\n", file_handle.fsize);
DBG_BL printf("reading header...\n");
f_read(&file_handle, &file_header, 32, &bytes_read);
print_header(&file_header);
if(check_flash() || file_header.version != fw_header->version || file_header.version == FW_MAGIC || fw_header->version == FW_MAGIC) {
f_lseek(&file_handle, 0x100);
uart_putc('F');
f_read(&file_handle, file_buf, 0xe0, &bytes_read);
for(;;) {
bytes_read = file_read();
if(file_res || !bytes_read) break;
@ -137,48 +138,59 @@ FLASH_RES flash_file(uint8_t *filename) {
file_crc = crc32_update(file_crc, file_buf[count]);
}
}
file_crc ^= 0xffffffff;
printf("file crc=%08lx\n", file_crc);
file_crc = crc_finalize(file_crc);
DBG_BL printf("file crc=%08lx\n", file_crc);
if(check_header(&file_header, file_header.crc) != ERR_OK) {
printf("Invalid firmware file (header corrupted).\n");
DBG_BL printf("Invalid firmware file (header corrupted).\n");
return ERR_FILEHD;
}
if(file_header.crc != file_crc) {
printf("Firmware file checksum error.\n");
DBG_BL printf("Firmware file checksum error.\n");
return ERR_FILECHK;
}
uint32_t res;
printf("erasing flash...\n");
DBG_BL printf("erasing flash...\n");
if((res = iap_prepare_for_write(FW_START / 0x1000, FLASH_SECTORS)) != CMD_SUCCESS) {
printf("error %ld while preparing for erase\n", res);
DBG_BL printf("error %ld while preparing for erase\n", res);
return ERR_FLASHPREP;
};
if((res = iap_erase(FW_START / 0x1000, FLASH_SECTORS)) != CMD_SUCCESS) {
printf("error %ld while erasing\n", res);
DBG_BL printf("error %ld while erasing\n", res);
return ERR_FLASHERASE;
}
printf("writing... @%08lx\n", flash_addr);
f_lseek(&file_handle, 0);
DBG_BL printf("writing... @%08lx\n", flash_addr);
file_close();
file_open(filename, FA_READ);
uint8_t current_sec;
uint32_t total_read = 0;
for(flash_addr = FW_START; flash_addr < 0x00020000; flash_addr += 0x200) {
bytes_read = file_read();
total_read += (bytes_read = file_read());
if(file_res || !bytes_read) break;
current_sec = flash_addr & 0x10000 ? (16 + ((flash_addr >> 15) & 1))
: (flash_addr >> 12);
printf("current_sec=%d flash_addr=%08lx\n", current_sec, flash_addr);
DBG_BL printf("current_sec=%d flash_addr=%08lx\n", current_sec, flash_addr);
uart_putc('.');
toggle_rdy_led();
if(current_sec < (FW_START / 0x1000)) return ERR_FLASH;
if((res = iap_prepare_for_write(current_sec, current_sec)) != CMD_SUCCESS) {
printf("error %ld while preparing sector %d for write\n", res, current_sec);
DBG_BL printf("error %ld while preparing sector %d for write\n", res, current_sec);
return ERR_FLASH;
}
if((res = iap_ram2flash(flash_addr, file_buf, 512)) != CMD_SUCCESS) {
printf("error %ld while writing to address %08lx (sector %d)\n", res, flash_addr, current_sec);
DBG_BL printf("error %ld while writing to address %08lx (sector %d)\n", res, flash_addr, current_sec);
return ERR_FLASH;
}
}
if(total_read != file_header.size) {
DBG_BL printf("wrote less data than expected! (%08lx vs. %08lx)\n", total_read, file_header.size);
uart_putc('X');
return ERR_FILECHK;
}
} else {
printf("flash content is ok, no version mismatch, no forced upgrade. No need to flash\n");
uart_putc('n');
DBG_BL printf("flash content is ok, no version mismatch, no forced upgrade. No need to flash\n");
}
return ERR_OK;
}

View File

@ -5,53 +5,25 @@
#include "timer.h"
#include "led.h"
static uint8_t led_bright[16]={255,253,252,251,249,247,244,239,232,223,210,191,165,127,74,0};
int led_rdyledstate = 0;
int led_readledstate = 0;
int led_writeledstate = 0;
int led_pwmstate = 0;
void rdyled(unsigned int state) {
if(led_pwmstate) {
rdybright(state?15:0);
} else {
BITBAND(LPC_GPIO2->FIODIR, 0) = state;
}
BITBAND(LPC_GPIO2->FIODIR, 0) = state;
led_rdyledstate = state;
}
void readled(unsigned int state) {
if(led_pwmstate) {
readbright(state?15:0);
} else {
BITBAND(LPC_GPIO2->FIODIR, 1) = state;
}
BITBAND(LPC_GPIO2->FIODIR, 1) = state;
led_readledstate = state;
}
void writeled(unsigned int state) {
if(led_pwmstate) {
writebright(state?15:0);
} else {
BITBAND(LPC_GPIO2->FIODIR, 2) = state;
}
BITBAND(LPC_GPIO2->FIODIR, 2) = state;
led_writeledstate = state;
}
void rdybright(uint8_t bright) {
LPC_PWM1->MR1 = led_bright[(bright & 15)];
BITBAND(LPC_PWM1->LER, 1) = 1;
}
void readbright(uint8_t bright) {
LPC_PWM1->MR2 = led_bright[(bright & 15)];
BITBAND(LPC_PWM1->LER, 2) = 1;
}
void writebright(uint8_t bright) {
LPC_PWM1->MR3 = led_bright[(bright & 15)];
BITBAND(LPC_PWM1->LER, 3) = 1;
}
void led_clkout32(uint32_t val) {
while(1) {
rdyled(1);
@ -64,7 +36,7 @@ void led_clkout32(uint32_t val) {
}
void toggle_rdy_led() {
rdyled(~led_rdyledstate);
rdyled(!led_rdyledstate);
}
void toggle_read_led() {
@ -84,24 +56,6 @@ void led_panic() {
}
}
void led_pwm() {
/* connect PWM to P2.0 - P2.2 */
/* XXX Rev.B P2.???? */
BITBAND(LPC_PINCON->PINSEL4, 1) = 0;
BITBAND(LPC_PINCON->PINSEL4, 3) = 0;
BITBAND(LPC_PINCON->PINSEL4, 5) = 0;
BITBAND(LPC_PINCON->PINSEL4, 0) = 1;
BITBAND(LPC_PINCON->PINSEL4, 2) = 1;
BITBAND(LPC_PINCON->PINSEL4, 4) = 1;
BITBAND(LPC_PWM1->PCR, 9) = 1;
BITBAND(LPC_PWM1->PCR, 10) = 1;
BITBAND(LPC_PWM1->PCR, 11) = 1;
led_pwmstate = 1;
}
void led_std() {
BITBAND(LPC_PINCON->PINSEL4, 1) = 0;
BITBAND(LPC_PINCON->PINSEL4, 3) = 0;
@ -110,12 +64,6 @@ void led_std() {
BITBAND(LPC_PINCON->PINSEL4, 0) = 0;
BITBAND(LPC_PINCON->PINSEL4, 2) = 0;
BITBAND(LPC_PINCON->PINSEL4, 4) = 0;
BITBAND(LPC_PWM1->PCR, 9) = 0;
BITBAND(LPC_PWM1->PCR, 10) = 0;
BITBAND(LPC_PWM1->PCR, 11) = 0;
led_pwmstate = 0;
}
void led_init() {
@ -123,9 +71,4 @@ void led_init() {
/* set PCLK divider to 8 */
BITBAND(LPC_SC->PCLKSEL1, 21) = 1;
BITBAND(LPC_SC->PCLKSEL1, 20) = 1;
LPC_PWM1->MR0 = 255;
BITBAND(LPC_PWM1->LER, 0) = 1;
BITBAND(LPC_PWM1->TCR, 0) = 1;
BITBAND(LPC_PWM1->TCR, 3) = 1;
BITBAND(LPC_PWM1->MCR, 1) = 1;
}

View File

@ -3,9 +3,6 @@
#ifndef _LED_H
#define _LED_H
void readbright(uint8_t bright);
void writebright(uint8_t bright);
void rdybright(uint8_t bright);
void readled(unsigned int state);
void writeled(unsigned int state);
void rdyled(unsigned int state);
@ -14,7 +11,6 @@ void toggle_rdy_led(void);
void toggle_read_led(void);
void toggle_write_led(void);
void led_panic(void);
void led_pwm(void);
void led_std(void);
void led_init(void);

View File

@ -10,7 +10,7 @@ ENTRY(_start)
MEMORY
{
flash (rx) : ORIGIN = 0x00000000, LENGTH = 0x05000
flash (rx) : ORIGIN = 0x00000000, LENGTH = 0x03000
ram (rwx) : ORIGIN = 0x10000000, LENGTH = 0x03fe0 /* leave room for IAP */
ahbram (rwx) : ORIGIN = 0x2007C000, LENGTH = 0x04000
}

View File

@ -44,14 +44,16 @@ int main(void) {
timer_init();
uart_init();
led_init();
readled(0);
rdyled(0);
writeled(0);
/* do this last because the peripheral init()s change PCLK dividers */
clock_init();
LPC_PINCON->PINSEL0 |= BV(20) | BV(21); /* MAT3.0 (FPGA clock) */
led_pwm();
sdn_init();
printf("chksum=%08lx\n", *(uint32_t*)28);
printf("\n\nsd2snes mk.2 bootloader\nver.: " VER "\ncpu clock: %ld Hz\n", CONFIG_CPU_FREQUENCY);
printf("PCONP=%lx\n", LPC_SC->PCONP);
DBG_BL printf("chksum=%08lx\n", *(uint32_t*)28);
DBG_BL printf("\n\nsd2snes mk.2 bootloader\nver.: " VER "\ncpu clock: %ld Hz\n", CONFIG_CPU_FREQUENCY);
DBG_BL printf("PCONP=%lx\n", LPC_SC->PCONP);
/* setup timer (fpga clk) */
LPC_TIM3->CTCR=0;
LPC_TIM3->EMR=EMC0TOGGLE;
@ -59,13 +61,21 @@ printf("PCONP=%lx\n", LPC_SC->PCONP);
LPC_TIM3->MR0=1;
LPC_TIM3->TCR=1;
test_iap();
FLASH_RES res = flash_file((uint8_t*)"/sd2snes/firmware.img");
printf("flash result = %d\n", res);
if(res == ERR_FLASHPREP || res == ERR_FLASHERASE || res == ERR_FLASH) {
writeled(1);
}
if(res == ERR_FILEHD || res == ERR_FILECHK) {
readled(1);
}
DBG_BL printf("flash result = %d\n", res);
if(res != ERR_OK) {
if((res = check_flash()) != ERR_OK) {
printf("check_flash() failed with error %d, not booting.\n", res);
while(1);
DBG_BL printf("check_flash() failed with error %d, not booting.\n", res);
while(1) {
toggle_rdy_led();
delay_ms(500);
}
}
}
NVIC_DisableIRQ(RIT_IRQn);

View File

@ -47,6 +47,7 @@
#define FLAG_UNSIGNED 64
#define FLAG_NEGATIVE 128
#ifdef DEBUG_BL
/* Digits used for conversion */
static const char hexdigits[] = "0123456789abcdef";
@ -289,3 +290,11 @@ int putchar(int c) {
uart_putc(c);
return 0;
}
#else
int printf(const char *format, ...) { return 0; }
int snprintf(char *str, size_t size, const char *format, ...) { return 0; }
int puts(const char *str) { return 0; }
#undef putchar
int putchar(int c) { return 0; }
#endif

View File

@ -152,24 +152,6 @@ static uint32_t getbits(void *buffer, uint16_t start, int8_t bits) {
return result;
}
static inline void wiggle_slow_pos(uint16_t times) {
while(times--) {
delay_us(2);
BITBAND(SD_CLKREG->FIOSET, SD_CLKPIN) = 1;
delay_us(2);
BITBAND(SD_CLKREG->FIOCLR, SD_CLKPIN) = 1;
}
}
static inline void wiggle_slow_neg(uint16_t times) {
while(times--) {
delay_us(2);
BITBAND(SD_CLKREG->FIOCLR, SD_CLKPIN) = 1;
delay_us(2);
BITBAND(SD_CLKREG->FIOSET, SD_CLKPIN) = 1;
}
}
static inline void wiggle_fast_pos(uint16_t times) {
while(times--) {
BITBAND(SD_CLKREG->FIOSET, SD_CLKPIN) = 1;
@ -201,77 +183,6 @@ static inline void wait_busy(void) {
wiggle_fast_neg(4);
}
/*
send_command_slow
send SD command and put response in rsp.
returns length of response or 0 if there was no response
*/
int send_command_slow(uint8_t* cmd, uint8_t* rsp){
uint8_t shift, i=6;
int rsplen;
uint8_t cmdno = *cmd & 0x3f;
wiggle_slow_pos(5);
switch(*cmd & 0x3f) {
case 0:
rsplen = 0;
break;
case 2:
case 9:
case 10:
rsplen = 17;
break;
default:
rsplen = 6;
}
/* send command */
BITBAND(SD_CMDREG->FIODIR, SD_CMDPIN) = 1;
while(i--) {
shift = 8;
do {
shift--;
uint8_t data = *cmd;
*cmd<<=1;
if(data&0x80) {
BITBAND(SD_CMDREG->FIOSET, SD_CMDPIN) = 1;
} else {
BITBAND(SD_CMDREG->FIOCLR, SD_CMDPIN) = 1;
}
wiggle_slow_pos(1);
} while (shift);
cmd++;
}
wiggle_slow_pos(1);
BITBAND(SD_CMDREG->FIODIR, SD_CMDPIN) = 0;
if(rsplen) {
uint16_t timeout=1000;
while((BITBAND(SD_CMDREG->FIOPIN, SD_CMDPIN)) && --timeout) {
wiggle_slow_neg(1);
}
if(!timeout) {
printf("CMD%d timed out\n", cmdno);
return 0; /* no response within timeout */
}
i=rsplen;
while(i--) {
shift = 8;
uint8_t data=0;
do {
shift--;
data |= (BITBAND(SD_CMDREG->FIOPIN, SD_CMDPIN)) << shift;
wiggle_slow_neg(1);
} while (shift);
*rsp=data;
rsp++;
}
}
return rsplen;
}
/*
send_command_fast
send SD command and put response in rsp.
@ -305,7 +216,7 @@ int send_command_fast(uint8_t* cmd, uint8_t* rsp, uint8_t* buf){
rsplen = 6;
}
if(dat && (buf==NULL)) {
printf("send_command_fast error: buf is null but data transfer expected.\n");
DBG_SD printf("send_command_fast error: buf is null but data transfer expected.\n");
return 0;
}
/* send command */
@ -337,7 +248,7 @@ int send_command_fast(uint8_t* cmd, uint8_t* rsp, uint8_t* buf){
wiggle_fast_neg1();
}
if(!timeout) {
printf("CMD%d timed out\n", cmdno);
DBG_SD printf("CMD%d timed out\n", cmdno);
return 0; /* no response within timeout */
}
@ -348,7 +259,7 @@ int send_command_fast(uint8_t* cmd, uint8_t* rsp, uint8_t* buf){
do {
if(dat) {
if(!(BITBAND(SD_DAT0REG->FIOPIN, SD_DAT0PIN))) {
printf("data start during response\n");
DBG_SD printf("data start during response\n");
j=datcnt;
state=CMD_RSPDAT;
break;
@ -470,28 +381,6 @@ static inline void make_crc7(uint8_t* cmd) {
cmd[5]=(cmd[5] << 1) | 1;
}
int cmd_slow(uint8_t cmd, uint32_t param, uint8_t crc, uint8_t* dat, uint8_t* rsp) {
uint8_t cmdbuf[6];
cmdbuf[0] = 0x40 | cmd;
cmdbuf[1] = param >> 24;
cmdbuf[2] = param >> 16;
cmdbuf[3] = param >> 8;
cmdbuf[4] = param;
if(!crc) {
make_crc7(cmdbuf);
} else {
cmdbuf[5] = crc;
}
return send_command_slow(cmdbuf, rsp);
}
int acmd_slow(uint8_t cmd, uint32_t param, uint8_t crc, uint8_t* dat, uint8_t* rsp) {
if(!(cmd_slow(APP_CMD, rca, 0, NULL, rsp))) {
return 0;
}
return cmd_slow(cmd, param, crc, dat, rsp);
}
int cmd_fast(uint8_t cmd, uint32_t param, uint8_t crc, uint8_t* dat, uint8_t* rsp) {
uint8_t cmdbuf[6];
cmdbuf[0] = 0x40 | cmd;
@ -652,11 +541,11 @@ void send_datablock(uint8_t *buf) {
} while (datshift);
DBG_SD printf("crc %02x\n", dat0);
if((dat0 & 7) != 2) {
printf("crc error! %02x\n", dat0);
DBG_SD printf("crc error! %02x\n", dat0);
while(1);
}
if(dat0 & 8) {
printf("missing start bit in CRC status response...\n");
DBG_SD printf("missing start bit in CRC status response...\n");
}
wiggle_fast_neg(2);
wait_busy();
@ -743,57 +632,57 @@ DRESULT sdn_initialize(BYTE drv) {
prior to initialization */
for(rsplen=0; rsplen<2042; rsplen++) {
if(!(BITBAND(SD_DAT3REG->FIOPIN, SD_DAT3PIN))) {
printf("card seems to be sending data, attempting deselect\n");
cmd_slow(SELECT_CARD, 0, 0, NULL, rsp);
DBG_SD printf("card seems to be sending data, attempting deselect\n");
cmd_fast(SELECT_CARD, 0, 0, NULL, rsp);
}
wiggle_slow_neg(1);
wiggle_fast_neg(1);
}
printf("sd_init start\n");
cmd_slow(GO_IDLE_STATE, 0, 0x95, NULL, rsp);
DBG_SD printf("sd_init start\n");
cmd_fast(GO_IDLE_STATE, 0, 0x95, NULL, rsp);
if((rsplen=cmd_slow(SEND_IF_COND, 0x000001aa, 0x87, NULL, rsp))) {
if((rsplen=cmd_fast(SEND_IF_COND, 0x000001aa, 0x87, NULL, rsp))) {
DBG_SD printf("CMD8 response:\n");
DBG_SD uart_trace(rsp, 0, rsplen);
hcs=1;
}
while(1) {
if(!(acmd_slow(SD_SEND_OP_COND, (hcs << 30) | 0xfc0000, 0, NULL, rsp))) {
printf("ACMD41 no response!\n");
if(!(acmd_fast(SD_SEND_OP_COND, (hcs << 30) | 0xfc0000, 0, NULL, rsp))) {
DBG_SD printf("ACMD41 no response!\n");
}
if(rsp[1]&0x80) break;
}
ccs = (rsp[1]>>6) & 1; /* SDHC/XC */
cmd_slow(ALL_SEND_CID, 0, 0x4d, NULL, rsp);
if(cmd_slow(SEND_RELATIVE_ADDR, 0, 0x21, NULL, rsp)) {
cmd_fast(ALL_SEND_CID, 0, 0x4d, NULL, rsp);
if(cmd_fast(SEND_RELATIVE_ADDR, 0, 0x21, NULL, rsp)) {
rca=(rsp[1]<<24) | (rsp[2]<<16);
printf("RCA: %04lx\n", rca>>16);
DBG_SD printf("RCA: %04lx\n", rca>>16);
} else {
printf("CMD3 no response!\n");
DBG_SD printf("CMD3 no response!\n");
rca=0;
}
/* record CSD for getinfo */
cmd_slow(SEND_CSD, rca, 0, NULL, rsp);
cmd_fast(SEND_CSD, rca, 0, NULL, rsp);
/* select the card */
if(cmd_slow(SELECT_CARD, rca, 0, NULL, rsp)) {
printf("card selected!\n");
if(cmd_fast(SELECT_CARD, rca, 0, NULL, rsp)) {
DBG_SD printf("card selected!\n");
} else {
printf("CMD7 no response!\n");
DBG_SD printf("CMD7 no response!\n");
}
/* get card status */
cmd_slow(SEND_STATUS, rca, 0, NULL, rsp);
cmd_fast(SEND_STATUS, rca, 0, NULL, rsp);
/* set bus width */
acmd_slow(SD_SET_BUS_WIDTH, 0x2, 0, NULL, rsp);
acmd_fast(SD_SET_BUS_WIDTH, 0x2, 0, NULL, rsp);
/* set block length */
cmd_slow(SET_BLOCKLEN, 0x200, 0, NULL, rsp);
cmd_fast(SET_BLOCKLEN, 0x200, 0, NULL, rsp);
printf("SD init complete. SDHC/XC=%d\n", ccs);
DBG_SD printf("SD init complete. SDHC/XC=%d\n", ccs);
disk_state = DISK_OK;
during_blocktrans = TRANS_NONE;
return sdn_status(drv);
@ -861,7 +750,7 @@ DRESULT sdn_getinfo(BYTE drv, BYTE page, void *buffer) {
di->sectorsize = 2;
di->sectorcount = capacity;
printf("card capacity: %lu sectors\n", capacity);
DBG_SD printf("card capacity: %lu sectors\n", capacity);
return RES_OK;
}
DRESULT disk_getinfo(BYTE drv, BYTE page, void *buffer) __attribute__ ((weak, alias("sdn_getinfo")));
@ -889,7 +778,7 @@ DRESULT disk_write(BYTE drv, const BYTE *buffer, DWORD sector, BYTE count) __att
/* Detect changes of SD card 0 */
void sdn_changed() {
if (sd_changed) {
printf("ch ");
DBG_SD printf("ch ");
if(SDCARD_DETECT) {
disk_state = DISK_CHANGED;
} else {

View File

@ -7,8 +7,8 @@
#ifndef UART_H
#define UART_H
#include <stdio.h>
#include <stdint.h>
#include <stdio.h>
#include "config.h"
//#ifdef CONFIG_UART_DEBUG