Skip to content

Commit

Permalink
Added support for bootloader_jump (cdh) plus other small cleanups
Browse files Browse the repository at this point in the history
  • Loading branch information
ChadTaylor17 committed Feb 24, 2023
1 parent 852a728 commit 71684fc
Show file tree
Hide file tree
Showing 8 changed files with 147 additions and 10 deletions.
19 changes: 19 additions & 0 deletions DOCUMENTATION.md
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ If you are interested in using and understanding TAB, refer to this document.
* [Bootlaoder Erase](#bootloader-erase)
* [Bootloader Write Page](#bootloader-write-page)
* [Bootloader Write Page Addr32](#bootloader-write-page-addr32)
* [Bootloader Jump](#bootloader-jump)
* [Protocol](#protocol): TAB protocol
* [License](#license)

Expand Down Expand Up @@ -261,6 +262,24 @@ of the board using the address provided.
* Addr Byte4 is the LSByte
* Page Data has 128 bytes.

### <a name="bootloader-jump"></a> Bootloader Jump

The command instructs the bootloader to jump to a different address in memory
* Name: `bootloader_jump`
* Required parameters: None
* Optional parameters: None
* Reply:
* If the bootloader is active and successfully performs the jump:
`bootloader_ack` with the JUMP payload
* If the bootloader is active and fails to perform the jump:
`bootloader_nack`
* Otherwise: `common_nack`

**Header**

| Start Byte 0 | Start Byte 1 | Remaining Bytes | HW ID LSByte | HW ID MSByte | MSG ID LSByte | MSG ID MSByte | Route Nibbles | Opcode |
| ------------ | ------------ | --------------- | ------------ | ------------ | ------------- | ------------- | ------------- | ------ |
| 0x22 | 0x69 | 0x06 | 0xHH | 0xHH | 0xHH | 0xHH | 0xSD | 0x0b |

## <a name="protocol"></a> Protocol

Expand Down
28 changes: 24 additions & 4 deletions c-examples/cdh-monolithic/cdh_monolithic.c
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
// TAB C Example CDH Monolithic
//
// Written by Bradley Denby
// Other contributors: None
// Other contributors: Chad Taylor
//
// See the top-level LICENSE file for the license.

Expand All @@ -16,6 +16,12 @@
// TAB header
#include <tab.h> // TAB header

//// in_bootloader is an extern variable read by bootloader_running
int in_bootloader;

//// app_jump_pending is an extern variable modified in write_reply
int app_jump_pending;

// Main
int main(void) {
// MCU initialization
Expand All @@ -26,11 +32,25 @@ int main(void) {
clear_rx_cmd_buff(&rx_cmd_buff);
tx_cmd_buff_t tx_cmd_buff = {.size=CMD_MAX_LEN};
clear_tx_cmd_buff(&tx_cmd_buff);
in_bootloader = 1;
app_jump_pending = 0;
// TAB loop
while(1) {
rx_usart1(&rx_cmd_buff); // Collect command bytes
reply(&rx_cmd_buff, &tx_cmd_buff); // Command reply logic
tx_usart1(&tx_cmd_buff); // Send a response if any
if(!app_jump_pending) {
rx_usart1(&rx_cmd_buff); // Collect command bytes
reply(&rx_cmd_buff, &tx_cmd_buff); // Command reply logic
tx_usart1(&tx_cmd_buff); // Send a response if any
} else { // Jump triggered
while(!tx_cmd_buff.empty) { // If jumping to user app,
tx_usart1(&tx_cmd_buff); // finish sending response if any
}
for(size_t i=0; i<4000000; i++) { // Wait for UART TX FIFO to flush
__asm__ volatile("nop");
}
app_jump_pending = 0; // Housekeeping
in_bootloader = 0;
bl_jump_to_app(); // Jump
}
}
// Should never reach this point
return 0;
Expand Down
46 changes: 44 additions & 2 deletions c-examples/cdh-monolithic/support/cdh.c
Original file line number Diff line number Diff line change
Expand Up @@ -14,13 +14,18 @@
#include <libopencm3/stm32/gpio.h> // used in init_gpio
#include <libopencm3/stm32/rcc.h> // used in init_clock, init_rtc
#include <libopencm3/stm32/usart.h> // used in init_uart
#include <libopencm3/cm3/scb.h> // SCB_VTOR

// Board-specific header
#include <cdh.h> // Header file

// TAB header
#include <tab.h> // TAOLST protocol macros, typedefs, fnctns

// Variables
extern int in_bootloader; // Used in bootloader main to indicate MCU state
extern int app_jump_pending; // Used in bootloader main to signal jump to app

// Functions required by TAB

// This example implementation of handle_common_data checks whether the bytes
Expand Down Expand Up @@ -132,9 +137,46 @@ int handle_bootloader_write_page_addr32(rx_cmd_buff_t* rx_cmd_buff){
}
}

// This example implementation of bootloader_active always returns true
// This example implementation of bl_check_app checks whether the jump address
// is valid or not
int bl_check_app(void) {
// Does the first four bytes of the application represent the initialization
// location of a stack pointer within the boundaries of the RAM?
return (((*(uint32_t*)APP_ADDR)-SRAM1_BASE) <= SRAM1_SIZE);
}

// This example implementation of bl_jump_to_app jumps to a hardcoded
// address in memory called APP_ADDR
void bl_jump_to_app(void) {
// The first 4 bytes hold the stack address, so jump address is after that
uint32_t jump_addr =
*(volatile uint32_t*)(APP_ADDR+((uint32_t)0x00000004U));
// Create a jump() function
void (*jump)(void) = (void (*)(void))jump_addr;
// Set the vector table
SCB_VTOR = APP_ADDR;
// Set the master stack pointer
__asm__ volatile("msr msp, %0"::"g" (*(volatile uint32_t*)APP_ADDR));
// Jump to the application
jump();
}

// This example implementation of handle_bootloader_jump sets app_jump_pending
// to 1 to trigger a jump after checking for a valid app address
int handle_bootloader_jump(void){
if (bl_check_app()) {
app_jump_pending = 1;
return 1;
} else { // Something wrong, abort jump
return 0;
}

}

// This example implementation of bootloader_active always returns whether the
// board is in bootloader mode or not
int bootloader_active(void) {
return 1;
return in_bootloader;
}

// Board initialization functions
Expand Down
12 changes: 12 additions & 0 deletions c-examples/cdh-monolithic/support/cdh.h
Original file line number Diff line number Diff line change
Expand Up @@ -19,19 +19,31 @@
//// Application start address
#define APP_ADDR ((uint32_t)0x08008000U)

//// SRAM1 start address
#define SRAM1_BASE ((uint32_t)0x20000000U)

//// SRAM1 size
#define SRAM1_SIZE ((uint32_t)0x00040000U)

// Functions required by TAB

int handle_common_data(common_data_t common_data_buff_i);
int handle_bootloader_erase(void);
int handle_bootloader_write_page(rx_cmd_buff_t* rx_cmd_buff);
int handle_bootloader_write_page_addr32(rx_cmd_buff_t* rx_cmd_buff);
int handle_bootloader_jump(void);
int bootloader_active(void);

// Board initialization functions

void init_clock(void);
void init_uart(void);

// Board jump functions

int bl_check_app(void);
void bl_jump_to_app(void);

// Feature functions

void rx_usart1(rx_cmd_buff_t* rx_cmd_buff_o);
Expand Down
17 changes: 17 additions & 0 deletions c-implementation/tab.c
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ extern int handle_common_data(common_data_t common_data_buff_i);
extern int handle_bootloader_erase(void);
extern int handle_bootloader_write_page(rx_cmd_buff_t* rx_cmd_buff);
extern int handle_bootloader_write_page_addr32(rx_cmd_buff_t* rx_cmd_buff);
extern int handle_bootloader_jump(void);
extern int bootloader_active(void);

// Helper functions
Expand Down Expand Up @@ -248,6 +249,22 @@ void write_reply(rx_cmd_buff_t* rx_cmd_buff_o, tx_cmd_buff_t* tx_cmd_buff_o) {
tx_cmd_buff_o->data[OPCODE_INDEX] = COMMON_NACK_OPCODE;
}
break;
case BOOTLOADER_JUMP_OPCODE:
if(bootloader_active()) {
success = handle_bootloader_jump();
if(success) {
tx_cmd_buff_o->data[MSG_LEN_INDEX] = ((uint8_t)0x07);
tx_cmd_buff_o->data[OPCODE_INDEX] = BOOTLOADER_ACK_OPCODE;
tx_cmd_buff_o->data[PLD_START_INDEX] = BOOTLOADER_ACK_REASON_JUMP;
} else {
tx_cmd_buff_o->data[MSG_LEN_INDEX] = ((uint8_t)0x06);
tx_cmd_buff_o->data[OPCODE_INDEX] = BOOTLOADER_NACK_OPCODE;
}
} else {
tx_cmd_buff_o->data[MSG_LEN_INDEX] = ((uint8_t)0x06);
tx_cmd_buff_o->data[OPCODE_INDEX] = COMMON_NACK_OPCODE;
}
break;
default:
break;
}
Expand Down
1 change: 1 addition & 0 deletions c-implementation/tab.h
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@
#define BOOTLOADER_ERASE_OPCODE ((uint8_t)0x0c)
#define BOOTLOADER_WRITE_PAGE_OPCODE ((uint8_t)0x02)
#define BOOTLOADER_WRITE_PAGE_ADDR32_OPCODE ((uint8_t)0x20)
#define BOOTLOADER_JUMP_OPCODE ((uint8_t)0x0b)

//// BOOTLOADER_ACK reasons
#define BOOTLOADER_ACK_REASON_PONG ((uint8_t)0x00)
Expand Down
26 changes: 22 additions & 4 deletions python-examples/tx/tx_example.py
Original file line number Diff line number Diff line change
Expand Up @@ -215,8 +215,7 @@

#10. Test Bootloader Write Page with expected reply of Bootloader Ack
# with Page Number reason
print("Bootloader Write Page")
cmd = TxCmd(BOOTLOADER_WRITE_PAGE_OPCODE, HWID, msgid, SRC, DST)
cmd = TxCmd(BOOTLOADER_WRITE_PAGE_OPCODE, HWID, msgid, GND, CDH)
dummy_page_num = 1
dummy_page = [0] * 128
cmd.bootloader_write_page(page_number=dummy_page_num, page_data=dummy_page)
Expand All @@ -238,7 +237,7 @@

#11. Test Bootloader Write Page Addr32 with expected reply of
# Bootloader Ack with Address reason
cmd = TxCmd(BOOTLOADER_WRITE_PAGE_ADDR32_OPCODE, HWID, msgid, SRC, DST)
cmd = TxCmd(BOOTLOADER_WRITE_PAGE_ADDR32_OPCODE, HWID, msgid, GND, CDH)
page_num = 0
addr_write = START_ADDR + page_num * BYTES_PER_CMD
dummy_page = [0] * 128
Expand All @@ -256,4 +255,23 @@
print('reply: '+str(rx_cmd_buff)+'\n')
cmd.clear()
rx_cmd_buff.clear()
msgid += 1
msgid += 1

#11. Test Bootloader Jump with expected reply of
# Bootloader Nack
cmd = TxCmd(BOOTLOADER_JUMP_OPCODE, HWID, msgid, GND, CDH)
byte_i = 0
while rx_cmd_buff.state != RxCmdBuffState.COMPLETE:
if byte_i < cmd.get_byte_count():
serial_port.write(cmd.data[byte_i].to_bytes(1, byteorder='big'))
byte_i += 1
if serial_port.in_waiting>0:
bytes = serial_port.read(1)
for b in bytes:
rx_cmd_buff.append_byte(b)
print('txcmd: '+str(cmd))
print('reply: '+str(rx_cmd_buff)+'\n')
cmd.clear()
rx_cmd_buff.clear()
msgid += 1
time.sleep(1.0)
8 changes: 8 additions & 0 deletions python-implementation/tab.py
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@
BOOTLOADER_ERASE_OPCODE = 0x0c
BOOTLOADER_WRITE_PAGE_OPCODE = 0x02
BOOTLOADER_WRITE_PAGE_ADDR32_OPCODE = 0x20
BOOTLOADER_JUMP_OPCODE = 0x0b

## Route Nibble IDs
GND = 0x00
Expand Down Expand Up @@ -229,6 +230,9 @@ def generate_reply(self, rx_cmd_buff):
elif rx_cmd_buff.data[OPCODE_INDEX] == BOOTLOADER_WRITE_PAGE_ADDR32_OPCODE:
self.data[MSG_LEN_INDEX] = 0x06
self.data[OPCODE_INDEX] = COMMON_NACK_OPCODE
elif rx_cmd_buff.data[OPCODE_INDEX] == BOOTLOADER_JUMP_OPCODE:
self.data[MSG_LEN_INDEX] = 0x06
self.data[OPCODE_INDEX] = COMMON_NACK_OPCODE

# Helper functions

Expand Down Expand Up @@ -319,6 +323,8 @@ def cmd_bytes_to_str(data):
pld_str += ' hex_data:'
for i in range(0,data[MSG_LEN_INDEX]-0x07):
pld_str += '{:02x}'.format(data[PLD_START_INDEX+4+i])
elif data[OPCODE_INDEX] == BOOTLOADER_JUMP_OPCODE:
cmd_str += 'bootloader_jump'
# string construction common to all commands
cmd_str += ' hw_id:0x{:04x}'.format(\
(data[HWID_MSB_INDEX]<<8)|(data[HWID_LSB_INDEX]<<0)\
Expand Down Expand Up @@ -371,6 +377,8 @@ def __init__(self, opcode, hw_id, msg_id, src, dst):
elif self.data[OPCODE_INDEX] == BOOTLOADER_WRITE_PAGE_ADDR32_OPCODE:
self.data[MSG_LEN_INDEX] = 0x0a
self.data[PLD_START_INDEX] = 0x00
elif self.data[OPCODE_INDEX] == BOOTLOADER_JUMP_OPCODE:
self.data[MSG_LEN_INDEX] = 0x06
else:
self.data[MSG_LEN_INDEX] = 0x06

Expand Down

0 comments on commit 71684fc

Please sign in to comment.