Add forgotten crtstart.asm

This commit is contained in:
logicog
2025-09-26 06:51:29 +02:00
parent c636ef3b8f
commit 8aaca9ae10
4 changed files with 365 additions and 28 deletions
+10 -9
View File
@@ -1,4 +1,5 @@
INSTALLER_ADDRESS=0x1016 CODE_LOCATION=0x1000
INSTALLER_ADDRESS=0x1100
CC = sdcc CC = sdcc
CC_FLAGS = -mmcs51 CC_FLAGS = -mmcs51
@@ -8,13 +9,13 @@ AFLAGS= -plosgff
SRCS = installer.c SRCS = installer.c
OBJS = ${SRCS:.c=.rel} OBJS = ${SRCS:.c=.rel}
all: updatebuilder rtlinstall.bin all: updatebuilder rtlplayground.bin
updatebuilder: updatebuilder.c updatebuilder: updatebuilder.c
gcc $^ -o $@ gcc $^ -o $@
%.rel: %.c installer.rel: installer.c
$(CC) $(CC_FLAGS) -code-loc 0x1000 -c $< $(CC) $(CC_FLAGS) --code-loc ${CODE_LOCATION} -c $<
%.rel: %.asm %.rel: %.asm
${ASM} ${AFLAGS} $^ ${ASM} ${AFLAGS} $^
@@ -22,12 +23,12 @@ updatebuilder: updatebuilder.c
%.rel: %.c %.rel: %.c
$(CC) $(CC_FLAGS) -c $< $(CC) $(CC_FLAGS) -c $<
rtlinstall.ihx: crtstart.rel $(OBJS) rtlinstaller.ihx: crtstart.rel $(OBJS)
$(CC) $(CC_FLAGS) -Wl-bHOME=${INSTALLER_ADDRESS} -Wl-r -o $@ $^ $(CC) $(CC_FLAGS) -Wl-bHOME=${INSTALLER_ADDRESS} -Wl-r -o $@ $^
%.bin: %.ihx rtlplayground.bin: rtlinstaller.ihx ../rtlplayground.bin
objcopy --input-target=ihex -O binary $< $@ cp ../rtlplayground.bin .
./updatebuilder -i $< rtlplayground.bin
clean: clean:
rm *.lst *.rel *.rst *.sym *.lst *.map *.mem *.lk $(OBJS) rm *.ihx *.lst *.rel *.rst *.sym *.lst *.map *.mem *.lk $(OBJS) installer.asm
+26
View File
@@ -0,0 +1,26 @@
.globl __start__stack
;--------------------------------------------------------
; Stack segment in internal ram
;--------------------------------------------------------
.area SSEG (DATA)
__start__stack:
.ds 1
.area VECTOR (CODE)
.globl __interrupt_vect
__interrupt_vect:
ljmp __sdcc_gsinit_startup + 0x1000
ljmp _isr_ext0 ; 0x03
.ds 5
ljmp _isr_timer0 ; 0x0b
.ds 5
ljmp _isr_ext1 ; 0x13
.globl __start__stack
.area GSINIT0 (CODE)
__sdcc_gsinit_startup:
mov sp,#__start__stack - 1
.area GSFINAL (CODE)
ljmp _installer
+256 -2
View File
@@ -4,7 +4,12 @@
// #define REGDBG 1 // #define REGDBG 1
// #define RXTXDBG 1 // #define RXTXDBG 1
#define UPDATE_LOC 0x0001D000
#define HEADER_LENGTH 0x14
#define UPDATE_CODE_LOC (UPDATE_LOC + HEADER_LENGTH)
#include "../rtl837x_sfr.h" #include "../rtl837x_sfr.h"
#include "../rtl837x_regs.h"
#define SYS_TICK_HZ 100 #define SYS_TICK_HZ 100
#define SERIAL_BAUD_RATE 57600 #define SERIAL_BAUD_RATE 57600
@@ -25,6 +30,12 @@ volatile __xdata uint32_t ticks;
volatile __xdata uint8_t sec_counter; volatile __xdata uint8_t sec_counter;
volatile __xdata uint16_t sleep_ticks; volatile __xdata uint16_t sleep_ticks;
// We buffer 1 sector as this is also the erase size
__xdata uint8_t buffer[0x1000];
__xdata uint8_t dio_enabled;
__code uint8_t * __code hex = "0123456789abcdef";
void isr_timer0(void) __interrupt(1) void isr_timer0(void) __interrupt(1)
{ {
TR0 = 0; // Stop timer 0 TR0 = 0; // Stop timer 0
@@ -77,6 +88,20 @@ void print_string(__code char *p)
} }
void print_byte(uint8_t a)
{
write_char(hex[(a >> 4) & 0xf]);
write_char(hex[a & 0xf]);
}
void print_short(uint16_t a)
{
print_string("0x");
for (signed char i = 12; i >= 0; i -= 4) {
write_char(hex[(a >> i) & 0xf]);
}
}
void setup_serial(void) void setup_serial(void)
{ {
IE = 0; IE = 0;
@@ -98,6 +123,214 @@ void setup_serial(void)
ES = 1; // Enable serial IRQ ES = 1; // Enable serial IRQ
} }
/*
* Configure Memory Managed IO
*/
void flash_configure_mmio(void)
{
// Set configuration for MMIO access by controller
if (dio_enabled) {
SFR_FLASH_MODEB = 0x18;
SFR_FLASH_CMD_R = 0xbb; // By default we read with Dual speed
SFR_FLASH_DUMMYCYCLES = 4;
return;
}
SFR_FLASH_MODEB = 0x0;
SFR_FLASH_CMD_R = 0xb; // By default we read with single speed
SFR_FLASH_DUMMYCYCLES = 8;
}
/*
* Initializes the flash controller for programmed control
* The configuration options are not really understood, the SPI speed
* seems to be directly linked to the CPU frequency
* This configures fast single IO at 20.8 MHz when the CPU clock is at 20.8MHz
* and 62.5MHz when the CPU clock is configured at 125MHz
*/
void flash_init(uint8_t enable_dio)
{
if (enable_dio) {
// Configure fast DIO via divider/DIO/SIOconfig = 4 and read-cmd being 0xbb (for mmio)
SFR_FLASH_CONFIG = 9; // There may be a chip-select in here
SFR_FLASH_CONF_RCMD = 0xbb;
SFR_FLASH_CONF_DIV = 4;
} else {
// Configure fast read via divider = 8 and read-cmd being 0xb (for mmio)
SFR_FLASH_CONFIG = 9;
SFR_FLASH_CONF_RCMD = 0xb;
SFR_FLASH_CONF_DIV = 8;
}
// Test Controller Busy
while(SFR_FLASH_EXEC_BUSY);
// Write 0 to status register
SFR_FLASH_DUMMYCYCLES = 8;
SFR_FLASH_MODEB = 0;
SFR_FLASH_TCONF = 0x19;
SFR_FLASH_CMD = 1;
SFR_FLASH_DATA0 = 0;
SFR_FLASH_EXEC_GO = 1;
while(SFR_FLASH_EXEC_BUSY);
dio_enabled = enable_dio;
flash_configure_mmio();
}
uint8_t flash_read_status(void)
{
// Test Controller Busy (we might call this directly after executing a command)
while(SFR_FLASH_EXEC_BUSY);
// setup status read command
SFR_FLASH_TCONF = 0x11;
SFR_FLASH_CMD_R = 5;
// execute and wait for controller done
SFR_FLASH_EXEC_GO = 1;
while(SFR_FLASH_EXEC_BUSY);
return SFR_FLASH_DATA0;
}
/*
* Reads bulk data of length len from the flash memory starging at address src
* and writes the data into a buffer pointed to by dst in XMEM
*/
void flash_read_bulk(register __xdata uint8_t *dst, __xdata uint32_t src, register uint16_t len)
{
short status;
do {
status = flash_read_status();
} while (status & 0x1);
// Set fast read mode
if (dio_enabled) {
SFR_FLASH_MODEB = 0x18;
SFR_FLASH_CMD_R = 0xbb;
SFR_FLASH_DUMMYCYCLES = 4;
} else {
SFR_FLASH_MODEB = 0x0;
SFR_FLASH_CMD_R = 0xb; // Fast read
SFR_FLASH_DUMMYCYCLES = 8; // Add 8 dummy clocks after read?
}
// Read 4 bytes
SFR_FLASH_TCONF = 4;
while (len) {
SFR_FLASH_ADDR16 = src >> 16;
SFR_FLASH_ADDR8 = src >> 8;
SFR_FLASH_ADDR0 = src;
src += 4;
SFR_FLASH_EXEC_GO = 1;
while(SFR_FLASH_EXEC_BUSY);
*dst++ = SFR_FLASH_DATA0;
if (len == 1)
return;
*dst++ = SFR_FLASH_DATA8;
if (len == 2)
return;
*dst++ = SFR_FLASH_DATA16;
if (len == 3)
return;
*dst++ = SFR_FLASH_DATA24;
len -= 4;
}
}
void flash_write_enable(void)
{
short status;
// Wait until busy bit clear
do {
status = flash_read_status();
} while (status & 0x1);
// while (flash_read_status() & 0x1);
SFR_FLASH_TCONF = 0x18;
SFR_FLASH_CMD = 6;
// The following is explicitly set for SIO, is this necessary?:
SFR_FLASH_DUMMYCYCLES = 0;
SFR_FLASH_MODEB = 0;
SFR_FLASH_EXEC_GO = 1;
// Wait for write status enabled
do {
status = flash_read_status();
} while (!(status & 0x2));
}
// Erases the 4k sector in which the address lies
void flash_sector_erase(uint32_t addr)
{
flash_write_enable();
SFR_FLASH_TCONF = 8;
SFR_FLASH_CMD = 0x20;
SFR_FLASH_ADDR16 = addr >> 16;
SFR_FLASH_ADDR8 = addr >> 8;
SFR_FLASH_ADDR0 = addr;
SFR_FLASH_EXEC_GO = 1;
while (flash_read_status() & 0x1);
flash_configure_mmio();
}
void flash_write_bytes(__xdata uint32_t addr, __xdata uint8_t *ptr, uint16_t len)
{
uint8_t exit_loop = 0;
while(1) {
flash_write_enable();
SFR_FLASH_CMD = 2;
SFR_FLASH_TCONF = 0x40 | 8 | 4; // Bytes written is 4, 8 enables write, 0x40 is unknown
// Last transfer?
if (len < 5) {
SFR_FLASH_TCONF = 8 | len;
exit_loop = 1;
}
SFR_FLASH_ADDR16 = addr >> 16;
SFR_FLASH_ADDR8 = addr >> 8;
SFR_FLASH_ADDR0 = addr;
SFR_FLASH_DATA0 = *ptr++;
SFR_FLASH_DATA8 = *ptr++;
SFR_FLASH_DATA16 = *ptr++;
SFR_FLASH_DATA24 = *ptr++;
// Execute transfer, we wait for completion at top of loop
SFR_FLASH_EXEC_GO = 1;
if (exit_loop)
break;
len -= 4;
addr += 4;
}
while (flash_read_status() & 0x1);
flash_configure_mmio();
}
void reg_write(uint16_t reg_addr)
{
/* Data to write must be in SFR A4, A5, A6, A7 */
SFR_REG_ADDR_U16 = reg_addr;
SFR_EXEC_GO = SFR_EXEC_WRITE_REG;
do {
} while (SFR_EXEC_STATUS != 0);
}
void installer(void) void installer(void)
{ {
@@ -117,6 +350,27 @@ void installer(void)
EA = 0; // SFR A8.7 / IE.7 EA = 0; // SFR A8.7 / IE.7
setup_serial(); setup_serial();
while (1) print_string("\nRTLPlayground installer starting...\n");
print_string("Image installer running\n");
// Initialize flash functions with disable DIO because writing does not work otherwise
flash_init(0);
__xdata uint32_t dest = 0x0;
__xdata uint32_t source = UPDATE_CODE_LOC;
// A 512kByte = 4MBit Flash has 128 sectors, we copy only 120
for (uint8_t i=0; i < 120; i++) {
print_string("Moving block\n");
flash_read_bulk(buffer, source, 0x1000);
for (uint8_t j = 0; j < 32; j++) {
write_char(' '); print_byte(buffer[j]);
}
write_char('\n');
flash_sector_erase(dest);
flash_write_bytes(dest, buffer, 0x1000);
dest += 0x1000;
source += 0x1000;
}
print_string("Done.\n");
print_string("Reseting now\n");
REG_SET(RTL837X_REG_RESET, 1);
} }
+71 -15
View File
@@ -27,6 +27,7 @@
uint8_t buffer[BUFFER_SIZE]; uint8_t buffer[BUFFER_SIZE];
FILE *inptr; FILE *inptr;
int outptr; int outptr;
char line[256];
const char *argp_program_version = "updatebuilder 0.1"; const char *argp_program_version = "updatebuilder 0.1";
const char *argp_program_bug_address = "<git@logicog.de>"; const char *argp_program_bug_address = "<git@logicog.de>";
@@ -49,6 +50,32 @@ struct arguments {
}; };
int get_byte(int pos)
{
int c1 = line[pos];
if (c1 >= '0' && c1 <= '9')
c1 -= '0';
else if (c1 >= 'a' && c1 <= 'f')
c1 = c1 - 'a' + 10;
else if (c1 >= 'A' && c1 <= 'F')
c1 = c1 - 'A' + 10;
else
return -1;
int c2 = line[pos + 1];
if (c2 >= '0' && c2 <= '9')
c2 -= '0';
else if (c2 >= 'a' && c2 <= 'f')
c2 = c2 - 'a' + 10;
else if (c2 >= 'A' && c2 <= 'F')
c2 = c2 - 'A' + 10;
else
return -1;
return c1 << 4 | c2;
}
static error_t parse_opt(int key, char *arg, struct argp_state *state) static error_t parse_opt(int key, char *arg, struct argp_state *state)
{ {
struct arguments *arguments = state->input; struct arguments *arguments = state->input;
@@ -110,7 +137,7 @@ int main(int argc, char **argv)
printf("File too large.\n"); printf("File too large.\n");
return 5; return 5;
} }
size_t bytes_read = fread(buffer + SEG_1d000_OFFSET + HEADER_LENGTH, 1, sizeof(buffer), inptr); size_t bytes_read = fread(buffer + SEG_1d000_OFFSET + 2 * HEADER_LENGTH, 1, sizeof(buffer), inptr);
printf("Bytes read: %ld\n", bytes_read); printf("Bytes read: %ld\n", bytes_read);
@@ -119,31 +146,60 @@ int main(int argc, char **argv)
return 5; return 5;
} }
fclose(inptr); fclose(inptr);
filesize += SEG_1d000_OFFSET + HEADER_LENGTH; filesize += SEG_1d000_OFFSET + 2 * HEADER_LENGTH;
// Read the installer file, which is in Intel Hex format
if (arguments.installer_file) { if (arguments.installer_file) {
inptr = fopen(arguments.installer_file, "rb"); inptr = fopen(arguments.installer_file, "rb");
if (inptr == NULL) { if (inptr == NULL) {
printf("Cannot open installer file %s\n", arguments.installer_file); printf("Cannot open installer file %s\n", arguments.installer_file);
return 5; return 5;
} }
int line_num = 1;
fseek(inptr, 0L, SEEK_END); int address_high = 0;
size_t isize = ftell(inptr); bool eof = false;
rewind(inptr); while(fgets(line, 255, inptr)) {
printf("Installer file size: %ld\n", isize); if (line[0] != ':') {
if (isize > SEG_01002_LENGTH) { printf("Unknwon installer file format for %s\n", arguments.installer_file);
printf("File too large.\n");
return 5; return 5;
} }
size_t bytes_read = fread(buffer + HEADER_LENGTH, 1, sizeof(buffer), inptr); int bytes = get_byte(1);
if (bytes < 0 || bytes > 200) {
printf("Bytes read: %ld\n", bytes_read); printf("Error in %s, line %d, incorrect byte number\n", arguments.installer_file, line_num);
if (bytes_read != isize) {
printf("Error reading input file.\n");
return 5; return 5;
} }
int address = (get_byte(3) *256) + get_byte(5);
if (address < 0) {
printf("Error in %s, line %d, not an address\n", arguments.installer_file, line_num);
return 5;
}
int type = get_byte(7);
if (type < 0 || type > 5) {
printf("Error in %s, line %d incorrect type\n", arguments.installer_file, line_num);
return 5;
}
if (type == 0) {
for (int i = 0; i < bytes; i++) {
int data = get_byte(9 + 2 * i);
if (data < 0) {
printf("Error in %s, line %d, illegal data byte\n", arguments.installer_file, line_num);
return 5;
} else {
address = address > 0x1000 ? address - 0x1000 : address;
buffer[address + HEADER_LENGTH + i] = data;
}
}
} else if (type == 1) {
eof = true;
printf("EOF\n");
} else {
printf("UNKNOWN type, line %d\n", line_num);
}
line_num++;
}
if (!eof)
printf("Something was wrong: EOF not found\n");
fclose(inptr); fclose(inptr);
} }