just280
Joined: 17 Apr 2012 Posts: 4 Location: UK
|
CCS I2C Bootloader |
Posted: Tue Jul 15, 2025 9:20 am |
|
|
Okay I'm reaching out for help as I've run out of idea's. I'm using the CCS ex_i2c_bootloader which seems to run fine and using the debug will state when the bootloader is running or not. I have a simple test application that flashes an LED and outputs periodically on the UART, this works fine as a standalone. If however I add in the i2c_bootloader.h which imports the bootloader hex file the application just freezes. Any Ideas?
Bootloader Code: | #include <16F18044.h>
#fuses RSTOSC_HFINTRC_32MHZ
#fuses NOMCLR
#fuses NOWDT
#pin_select U1TX=pin_c3 // 8583 PCB
//#pin_select U1TX=pin_c5 // 8582 PCB
#pin_select U1RX=pin_c4
#pin_select SDA1IN=pin_B4
#pin_select SCL1IN=pin_B6
#use delay(internal=32000000)
#define defined(__PCM__)
#define INT_I2C_BOOTLOADER INT_SSP
#use i2c(SLAVE, address=0xA0, SDA=PIN_B4, SCL=PIN_B6, STREAM=STREAM_I2C_BOOTLOADER) //SDA=PIN_C4, SCL=PIN_C3
#define BUTTON_PRESSED() (!input(PIN_A2))
#define IS_BOOTLOADER_FORCED() BUTTON_PRESSED()
#define DEBUG_BOOTLOADER
#ifdef DEBUG_BOOTLOADER
// The following selects if the bootloader debug message are sent through the
// ICD or with an RS232 connection. If defined sent through the ICD, if not
// defined sent with the RS232 connection.
#ifdef DEBUG_BOOTLOADER
#use rs232(xmit=PIN_C3, rcv=PIN_C4, ERRORS, BAUD=57600, BITS=8, stream=DEBUG_STREAM) // 8583 PCB
//#use rs232(xmit=PIN_C5, rcv=PIN_C4, ERRORS, BAUD=57600, BITS=8, stream=DEBUG_STREAM) // 8582 PCB
#endif
#define debug_printf printf
void debug_putc(char c)
{
fputc(c, DEBUG_STREAM);
}
#if defined(__PCM__)
#define LOADER_END 0x47F
#elif defined(__PCH__)
#define LOADER_END 0x7FF
#endif
#endif
//////////// end configuration /////////////
#define __bootloader //tell i2c_bootloader.h that this is the bootloader program
#include "i2c_bootloader.h"
#include "rom_write.c"
#ifndef debug_printf
#define debug_printf(a,b,c,d,e,f,g,h,i,j,k,l,m,n,o,p)
#endif
void goto_application(void)
{
enable_interrupts(GLOBAL);
enable_interrupts(INT_I2C_BOOTLOADER);
#asm
GOTO PROGRAM_APP_START
#endasm
}
#ifndef IS_BOOTLOADER_FORCED
#define IS_BOOTLOADER_FORCED() FALSE
#endif
#int_global
void isr(void)
{
jump_to_isr(PROGRAM_ISR_START);
}
int1 g_PointerIsRam;
char *g_RamPointer;
unsigned int32 g_RomPointer;
unsigned int16 g_Magic;
unsigned int8 g_LastCmd;
inline void i2c_slave_interrupt(void)
{
unsigned int8 incoming, state;
static union
{
unsigned int8 b[4];
unsigned int16 w[2];
unsigned int32 dw;
} val;
static struct
{
unsigned int8 b[2]; //max data bytes in hex file is 32
unsigned int8 index;
} data;
state = i2c_isr_state(STREAM_I2C_BOOTLOADER);
if(state <= 0x80) //Master is sending data
{
incoming = i2c_read(STREAM_I2C_BOOTLOADER, 2); //Passing 2 as parameter, causes the function to read the SSPBUF without releasing the clock
if (state == 1)
{
//First received byte is the command
g_LastCmd = incoming;
}
else if
(
(g_LastCmd == I2C_LOADER_COMMAND_GOTO_APPLICATION) &&
((state==2) || (state==3))
)
{
val.b[state-2] = incoming;
if ((state == 3) && (val.w[0] == I2C_LOADER_MAGIC))
{
debug_printf(debug_putc, "W=GOTO_APPLICATION\r\n");
rom_flush();
i2c_write(STREAM_I2C_BOOTLOADER, 0); //dummy write to release the clock lines. this does not actually TX
clear_interrupt(INT_I2C_BOOTLOADER);
goto_application();
}
}
else if
(
(g_LastCmd == I2C_LOADER_COMMAND_ROM_ADDRESS) &&
((state>=2) || (state<=5))
)
{
val.b[state-2] = incoming;
if (state == 5)
{
g_RomPointer = val.dw;
data.index = 0;
debug_printf(debug_putc, "W=ADDRESS %LX\r\n", g_RomPointer);
}
}
else if (g_LastCmd == I2C_LOADER_COMMAND_ROM_ACCESS)
{
data.b[data.index] = incoming;
if(++data.index >= 2)
data.index = 0;
if ((g_RomPointer >= PROGRAM_APP_START) && (g_RomPointer < getenv("PROGRAM_MEMORY")))
{
if(data.index == 0)
rom_modify(g_RomPointer, data.b, 2);
}
if(data.index == 0)
{
#if defined(__PCM__)
g_RomPointer++;
#elif defined(__PCH__)
g_RomPointer += 2;
#endif
}
}
if (state != 0x80)
{
i2c_write(STREAM_I2C_BOOTLOADER, 0); //dummy write to release the clock lines. this does not actually TX
}
}
if(state >= 0x80) //Master is requesting data
{
if (state == 0x80)
{
g_PointerIsRam = TRUE;
if (g_LastCmd == I2C_LOADER_COMMAND_ROM_ADDRESS)
{
debug_printf(debug_putc, "R=ROM_ADDRESS %LX\r\n", g_RomPointer);
g_RamPointer = &g_RomPointer;
}
else if (g_LastCmd == I2C_LOADER_COMMAND_ROM_ACCESS)
{
debug_printf(debug_putc, "R=ROM_ACCESS %LX\r\n", g_RomPointer);
g_PointerIsRam = FALSE;
rom_flush();
}
else if (g_LastCmd == I2C_LOADER_COMMAND_GOTO_BOOTLOADER)
{
debug_printf(debug_putc, "R=GOTO_BOOTLOADER\r\n");
g_RamPointer = &g_Magic;
}
i2c_write(STREAM_I2C_BOOTLOADER, g_LastCmd);
}
else
{
if (g_RamPointer)
{
i2c_write(STREAM_I2C_BOOTLOADER, *g_RamPointer++);
}
else
{
read_program_memory(g_RomPointer, &val.b[0], 1);
g_RomPointer++;
i2c_write(STREAM_I2C_BOOTLOADER, val.b[0]);
}
}
}
clear_interrupt(INT_I2C_BOOTLOADER);
}
void bootloader_loop(void)
{
g_RomPointer = 0;
g_Magic = I2C_LOADER_MAGIC;
g_LastCmd = I2C_LOADER_COMMAND_GOTO_BOOTLOADER;
rom_init();
debug_printf(debug_putc, "BOOTLOADER_STARTED\r\n");
for(;;)
{
if (interrupt_active(INT_I2C_BOOTLOADER))
{
i2c_slave_interrupt();
}
}
}
#org PROGRAM_BOOTLOADER_START, PROGRAM_BOOTLOADER_START+0xf
void proxy_bootloader_start(void)
{
bootloader_loop();
}
void main(void)
{
if (IS_BOOTLOADER_FORCED())
{
debug_printf(debug_putc, "BOOTLOADER_FORCED\r\n");
bootloader_loop();
}
debug_printf(debug_putc, "NO_BOOTLOADER\r\n");
goto_application();
} |
Application Code
Code: |
#include <16F18044.h>
#device ADC=10
#FUSES NOWDT
#FUSES RSTOSC_HFINTRC_32MHZ
#FUSES NOMCLR
#FUSES NOCLKOUT
#use delay(internal=32000000,restart_wdt)
#pin_select U1TX=pin_c3 // 8583 PCB
//#pin_select U1TX=pin_c5 // 8582 PCB
#pin_select U1RX=pin_c4
#use rs232(baud=57600,xmit=PIN_C3,rcv=PIN_C4,bits=8,errors,STREAM=UART) // 8583 PCB
//#use rs232(baud=57600,xmit=PIN_C5,rcv=PIN_C4,bits=8,errors,STREAM=UART) //8582 PCB
#pin_select SDA1IN=pin_B4
#pin_select SCL1IN=pin_B6
#define INT_I2C_BOOTLOADER INT_SSP
//#use i2c(Master,sda=PIN_B4,scl=PIN_B6,FORCE_SW,SLOW,STREAM=STREAM_I2C_BOOTLOADER)
#use i2c(SLAVE, address=0xA0, SDA=PIN_B4, SCL=PIN_B6, STREAM=STREAM_I2C_BOOTLOADER)
//#define UART_DEBUG
#define defined(__PCM__)
#define DEBUG_BOOTLOADER
#define LOADER_END 0x47F
//#include <85800623.h>
//#include <bootloader.h> // UART version
#include <i2c_bootloader.h>
#define clk_test pin_a1
#define encoder_switch pin_a2
#define standby_led_green pin_c2
#define standby_led_red pin_c1
#define RGB_led_red pin_a1 //a1
#define RGB_led_green pin_c5 //c5
#define RGB_led_blue pin_a0 //a0
//#define test_pin2 pin_b7
//#define test_pin1 pin_b6
#define OFF 0
#define ON 1
#define PAUSE 0
#define PLAYING 1
#define STANDBY 0
#define WORKING 1
#define NO_FLASH 0
#define SLOW_FLASH 1
#define FAST_FLASH 2
#define RED 1
#define BLUE 2
#define GREEN 3
#define PURPLE 4
#define WHITE 5
#define ORANGE 6
#define VERSION 2.0
#define debug_printf printf
void debug_putc(char c)
{
fputc(c, UART);
}
int8 led_toggle;
int8 on_off_status;
int8 switch_latch;
int16 read_count;
int16 switch_debounce;
int16 switch_on_delay;
int16 play_status_count;
int16 m_sec_count;
int16 sec_count;
#INT_TIMER2
void TIMER2_isr(void)
{
read_count++;
switch_debounce++;
play_status_count++;
//status_flash_count++;
switch_on_delay++;
if(switch_on_delay>2999) switch_on_delay=3000;
m_sec_count++;
if(m_sec_count>9999)
{
m_sec_count=0;
sec_count++;
}
}
#use timer(tick=10ms, bits=16, ISR)
#INT_SSP
void i2c_slave_interrupt()
{
unsigned int8 state, read;
state = i2c_isr_state(STREAM_I2C_BOOTLOADER);
if(state <= 0x80) //Master is sending data
{
if(state == 0x80)
read = i2c_read(STREAM_I2C_BOOTLOADER, 2); //Passing 2 as parameter, causes the function to read the SSPBUF without releasing the clock
else
read = i2c_read(STREAM_I2C_BOOTLOADER);
if (state < 0x80)
{
i2c_isr_bootload_check(state, read);
}
}
if(state >= 0x80) //Master is requesting data
{
i2c_write(STREAM_I2C_BOOTLOADER, 0); //we don't have any data, write dummy data
}
}
void main()
{
//setup_timer_2(T2_DIV_BY_32 | T2_CLK_INTERNAL,255,1); //1.0 ms overflow, 1.0 ms interrupt
setup_timer_2(T2_DIV_BY_16 | T2_CLK_INTERNAL,49,1); //100 us overflow, 100 us interrupt
//setup_timer_4(T4_DIV_BY_128 | T4_CLK_INTERNAL,255,1); //1.0 ms overflow, 1.0 ms interrupt
enable_interrupts(INT_TIMER2);
enable_interrupts(INT_SSP);
enable_interrupts(GLOBAL);
set_tris_c(0x11);
//port_c_pullups(0x00);
//****** inialise outputs ******
output_high(RGB_led_red);
output_low(RGB_led_green);
output_high(RGB_led_blue);
delay_ms(200);
on_off_status=OFF;
debug_printf(debug_putc, "PROGRAM RUNNING\r\n");
while(TRUE)
{
restart_wdt();
unsigned int16 tick;
tick = get_ticks();
for(;;)
{
if ((get_ticks() - tick) >= TICKS_PER_SECOND/2)
{
tick = get_ticks();
}
}
if((!input(encoder_switch) && switch_debounce>1999) && switch_latch==0)
{
switch_latch=1;
if(on_off_status==OFF)
{
on_off_status=ON;
output_low(RGB_led_red);
output_high(standby_led_red); // off
output_low(standby_led_green); // on
}
else
{
on_off_status=OFF;
output_high(RGB_led_red);
output_low(standby_led_red); // on
output_high(standby_led_green); // off
}
}
if(input(encoder_switch)) { switch_latch=0; switch_debounce=0; }
if(read_count>9999)
{
read_count=0;
if(led_toggle>0) { led_toggle=0; output_low(RGB_led_green); }
else { led_toggle=1; output_high(RGB_led_green); }
debug_printf(debug_putc, "PROGRAM RUNNING\r\n");
}
}
}
|
|
|