Skip to content

Bootloader LED pulsing and TX/RX blinking #122

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
wants to merge 11 commits into from
11 changes: 9 additions & 2 deletions bootloaders/zero/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -68,14 +68,17 @@ else
CFLAGS+=-Os -DDEBUG=0
endif

ifeq ($(GENUINO),)
# Arduino Zero (PID == 0x004D)
CFLAGS_EXTRA?=-D__SAMD21G18A__ -DUSB_PID_HIGH=0x00 -DUSB_PID_LOW=0x4D -DUSB_VID_LOW=0x41 -DUSB_VID_HIGH=0x23
# Genuino Zero (PID == 0x024D)
# CFLAGS_EXTRA?=-D__SAMD21G18A__ -DUSB_PID_HIGH=0x02 -DUSB_PID_LOW=0x4D -DUSB_VID_LOW=0x41 -DUSB_VID_HIGH=0x23
# Arduino MKR1000 (PID == 0x004E)
# CFLAGS_EXTRA?=-D__SAMD21G18A__ -DUSB_PID_HIGH=0x00 -DUSB_PID_LOW=0x4E -DUSB_VID_LOW=0x41 -DUSB_VID_HIGH=0x23
else
# Genuino Zero (PID == 0x024D)
CFLAGS_EXTRA?=-D__SAMD21G18A__ -DUSB_PID_HIGH=0x02 -DUSB_PID_LOW=0x4D -DUSB_VID_LOW=0x41 -DUSB_VID_HIGH=0x23
# Genuino MKR1000 (PID == 0x024E)
# CFLAGS_EXTRA?=-D__SAMD21G18A__ -DUSB_PID_HIGH=0x02 -DUSB_PID_LOW=0x4E -DUSB_VID_LOW=0x41 -DUSB_VID_HIGH=0x23
endif

INCLUDES=-I"$(MODULE_PATH)/tools/CMSIS/4.0.0-atmel/CMSIS/Include/" -I"$(MODULE_PATH)/tools/CMSIS/4.0.0-atmel/Device/ATMEL/"

Expand All @@ -101,7 +104,11 @@ sam_ba_serial.c
OBJECTS=$(addprefix $(BUILD_PATH)/, $(SOURCES:.c=.o))
DEPS=$(addprefix $(BUILD_PATH)/, $(SOURCES:.c=.d))

ifeq ($(GENUINO),)
NAME=samd21_sam_ba
else
NAME=samd21_sam_ba_genuino
endif
ELF=$(NAME).elf
BIN=$(NAME).bin
HEX=$(NAME).hex
Expand Down
21 changes: 21 additions & 0 deletions bootloaders/zero/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -73,3 +73,24 @@ Bootloader code will be located at 0x0 and executed before any applicative code.
Applications compiled to be executed along with the bootloader will start at 0x2000 (see linker script bootloader_samd21x18.ld).

Before jumping to the application, the bootloader changes the VTOR register to use the interrupt vectors of the application @0x2000.<- not required as application code is taking care of this.

## 5- How to build

**Arduino Zero**

```
make
```

**Genuino Zero**

```
make GENUINO=1
```

**Others (derivatives)**

```
make CFLAGS_EXTRA="-D__SAMD21G18A__ -DUSB_PID_HIGH=<your USB PID> -DUSB_PID_LOW=<your USB PID> -DUSB_VID_LOW=<your USB VID> -DUSB_VID_HIGH=<your USB VID>"
```
You can also check https://github.com/ameltech/sme-arduino-core/blob/master/hardware/AMEL/samd/bootloaders/sme/Makefile for reference.
20 changes: 20 additions & 0 deletions bootloaders/zero/board_driver_led.c
Original file line number Diff line number Diff line change
Expand Up @@ -19,4 +19,24 @@

#include "board_driver_led.h"

volatile uint8_t ledKeepValue = 0;
volatile uint8_t ledTargetValue = 20;
volatile int8_t ledDirection = 1;

inline void LED_pulse()
{
if (ledKeepValue == 0) {
ledTargetValue += ledDirection;
LED_toggle();
}
ledKeepValue ++;

if (ledTargetValue > 240 || ledTargetValue < 10) {
ledDirection = -ledDirection;
ledTargetValue += ledDirection;
}

if (ledKeepValue == ledTargetValue) {
LED_toggle();
}
}
9 changes: 5 additions & 4 deletions bootloaders/zero/board_driver_led.h
Original file line number Diff line number Diff line change
Expand Up @@ -27,15 +27,16 @@ inline void LED_init(void) { PORT->Group[BOARD_LED_PORT].DIRSET.reg = (1<<BOARD_
inline void LED_on(void) { PORT->Group[BOARD_LED_PORT].OUTSET.reg = (1<<BOARD_LED_PIN); }
inline void LED_off(void) { PORT->Group[BOARD_LED_PORT].OUTCLR.reg = (1<<BOARD_LED_PIN); }
inline void LED_toggle(void) { PORT->Group[BOARD_LED_PORT].OUTTGL.reg = (1<<BOARD_LED_PIN); }
void LED_pulse();

inline void LEDRX_init(void) { PORT->Group[BOARD_LEDRX_PORT].DIRSET.reg = (1<<BOARD_LEDRX_PIN); }
inline void LEDRX_on(void) { PORT->Group[BOARD_LEDRX_PORT].OUTSET.reg = (1<<BOARD_LEDRX_PIN); }
inline void LEDRX_off(void) { PORT->Group[BOARD_LEDRX_PORT].OUTCLR.reg = (1<<BOARD_LEDRX_PIN); }
inline void LEDRX_on(void) { PORT->Group[BOARD_LEDRX_PORT].OUTCLR.reg = (1<<BOARD_LEDRX_PIN); }
inline void LEDRX_off(void) { PORT->Group[BOARD_LEDRX_PORT].OUTSET.reg = (1<<BOARD_LEDRX_PIN); }
inline void LEDRX_toggle(void) { PORT->Group[BOARD_LEDRX_PORT].OUTTGL.reg = (1<<BOARD_LEDRX_PIN); }

inline void LEDTX_init(void) { PORT->Group[BOARD_LEDTX_PORT].DIRSET.reg = (1<<BOARD_LEDTX_PIN); }
inline void LEDTX_on(void) { PORT->Group[BOARD_LEDTX_PORT].OUTSET.reg = (1<<BOARD_LEDTX_PIN); }
inline void LEDTX_off(void) { PORT->Group[BOARD_LEDTX_PORT].OUTCLR.reg = (1<<BOARD_LEDTX_PIN); }
inline void LEDTX_on(void) { PORT->Group[BOARD_LEDTX_PORT].OUTCLR.reg = (1<<BOARD_LEDTX_PIN); }
inline void LEDTX_off(void) { PORT->Group[BOARD_LEDTX_PORT].OUTSET.reg = (1<<BOARD_LEDTX_PIN); }
inline void LEDTX_toggle(void) { PORT->Group[BOARD_LEDTX_PORT].OUTTGL.reg = (1<<BOARD_LEDTX_PIN); }

#endif // _BOARD_DRIVER_LED_
6 changes: 0 additions & 6 deletions bootloaders/zero/board_startup.c
Original file line number Diff line number Diff line change
Expand Up @@ -139,9 +139,3 @@ void PendSV_Handler(void)
__BKPT(2);
while (1);
}

void SysTick_Handler(void)
{
__BKPT(1);
while (1);
}
17 changes: 17 additions & 0 deletions bootloaders/zero/main.c
Original file line number Diff line number Diff line change
Expand Up @@ -179,6 +179,16 @@ int main(void)

DEBUG_PIN_LOW;

/* Initialize LEDs */
LED_init();
LEDRX_init();
LEDRX_off();
LEDTX_init();
LEDTX_off();

/* Start the sys tick (1 ms) */
SysTick_Config(1000);

/* Wait for a complete enum on usb or a '#' char on serial line */
while (1)
{
Expand Down Expand Up @@ -214,3 +224,10 @@ int main(void)
#endif
}
}

void SysTick_Handler(void)
{
LED_pulse();

sam_ba_monitor_sys_tick();
}
129 changes: 105 additions & 24 deletions bootloaders/zero/sam_ba_monitor.c
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@
#include "board_driver_usb.h"
#include "sam_ba_usb.h"
#include "sam_ba_cdc.h"
#include "board_driver_led.h"

const char RomBOOT_Version[] = SAM_BA_VERSION;
const char RomBOOT_ExtendedCapabilities[] = "[Arduino:XYZ]";
Expand Down Expand Up @@ -84,6 +85,11 @@ t_monitor_if * ptr_monitor_if;
volatile bool b_terminal_mode = false;
volatile bool b_sam_ba_interface_usart = false;

/* Pulse generation counters to keep track of the time remaining for each pulse type */
#define TX_RX_LED_PULSE_PERIOD 100
volatile uint16_t txLEDPulse = 0; // time remaining for Tx LED pulse
volatile uint16_t rxLEDPulse = 0; // time remaining for Rx LED pulse

void sam_ba_monitor_init(uint8_t com_interface)
{
#if SAM_BA_INTERFACE == SAM_BA_UART_ONLY || SAM_BA_INTERFACE == SAM_BA_BOTH_INTERFACES
Expand All @@ -102,8 +108,74 @@ void sam_ba_monitor_init(uint8_t com_interface)
#endif
}

/*
* Central SAM-BA monitor putdata function using the board LEDs
*/
static uint32_t sam_ba_putdata(t_monitor_if* pInterface, void const* data, uint32_t length)
{
uint32_t result ;

result=pInterface->putdata(data, length);

LEDTX_on();
txLEDPulse = TX_RX_LED_PULSE_PERIOD;

return result;
}

/*
* Central SAM-BA monitor getdata function using the board LEDs
*/
static uint32_t sam_ba_getdata(t_monitor_if* pInterface, void* data, uint32_t length)
{
uint32_t result ;

result=pInterface->getdata(data, length);

if (result)
{
LEDRX_on();
rxLEDPulse = TX_RX_LED_PULSE_PERIOD;
}

return result;
}

/*
* Central SAM-BA monitor putdata function using the board LEDs
*/
static uint32_t sam_ba_putdata_xmd(t_monitor_if* pInterface, void const* data, uint32_t length)
{
uint32_t result ;

result=pInterface->putdata_xmd(data, length);

LEDTX_on();
txLEDPulse = TX_RX_LED_PULSE_PERIOD;

return result;
}

/*
* Central SAM-BA monitor getdata function using the board LEDs
*/
static uint32_t sam_ba_getdata_xmd(t_monitor_if* pInterface, void* data, uint32_t length)
{
uint32_t result ;

result=pInterface->getdata_xmd(data, length);

if (result)
{
LEDRX_on();
rxLEDPulse = TX_RX_LED_PULSE_PERIOD;
}

return result;
}

/**
* \brief This function allows data rx by USART
* \brief This function allows data emission by USART
*
* \param *data Data pointer
* \param length Length of the data
Expand Down Expand Up @@ -141,10 +213,10 @@ void sam_ba_putdata_term(uint8_t* data, uint32_t length)
buf[1] = 'x';
buf[length * 2 + 2] = '\n';
buf[length * 2 + 3] = '\r';
ptr_monitor_if->putdata(buf, length * 2 + 4);
sam_ba_putdata(ptr_monitor_if, buf, length * 2 + 4);
}
else
ptr_monitor_if->putdata(data, length);
sam_ba_putdata(ptr_monitor_if, data, length);
return;
}

Expand Down Expand Up @@ -187,12 +259,12 @@ static void put_uint32(uint32_t n)

buff[7-i] = d > 9 ? 'A' + d - 10 : '0' + d;
}
ptr_monitor_if->putdata(buff, 8);
sam_ba_putdata( ptr_monitor_if, buff, 8);
}

static void sam_ba_monitor_loop(void)
{
length = ptr_monitor_if->getdata(data, SIZEBUFMAX);
length = sam_ba_getdata(ptr_monitor_if, data, SIZEBUFMAX);
ptr = data;

for (i = 0; i < length; i++, ptr++)
Expand All @@ -203,7 +275,7 @@ static void sam_ba_monitor_loop(void)
{
if (b_terminal_mode)
{
ptr_monitor_if->putdata("\n\r", 2);
sam_ba_putdata(ptr_monitor_if, "\n\r", 2);
}
if (command == 'S')
{
Expand Down Expand Up @@ -235,13 +307,13 @@ static void sam_ba_monitor_loop(void)
ptr--;
//Do we expect more data ?
if(j<current_number)
ptr_monitor_if->getdata_xmd(ptr_data, current_number-j);
sam_ba_getdata_xmd(ptr_monitor_if, ptr_data, current_number-j);

__asm("nop");
}
else if (command == 'R')
{
ptr_monitor_if->putdata_xmd(ptr_data, current_number);
sam_ba_putdata_xmd(ptr_monitor_if, ptr_data, current_number);
}
else if (command == 'O')
{
Expand Down Expand Up @@ -282,35 +354,35 @@ static void sam_ba_monitor_loop(void)
else if (command == 'T')
{
b_terminal_mode = 1;
ptr_monitor_if->putdata("\n\r", 2);
sam_ba_putdata(ptr_monitor_if, "\n\r", 2);
}
else if (command == 'N')
{
if (b_terminal_mode == 0)
{
ptr_monitor_if->putdata("\n\r", 2);
sam_ba_putdata( ptr_monitor_if, "\n\r", 2);
}
b_terminal_mode = 0;
}
else if (command == 'V')
{
ptr_monitor_if->putdata("v", 1);
ptr_monitor_if->putdata((uint8_t *) RomBOOT_Version, strlen(RomBOOT_Version));
ptr_monitor_if->putdata(" ", 1);
ptr_monitor_if->putdata((uint8_t *) RomBOOT_ExtendedCapabilities, strlen(RomBOOT_ExtendedCapabilities));
ptr_monitor_if->putdata(" ", 1);
sam_ba_putdata( ptr_monitor_if, "v", 1);
sam_ba_putdata( ptr_monitor_if, (uint8_t *) RomBOOT_Version, strlen(RomBOOT_Version));
sam_ba_putdata( ptr_monitor_if, " ", 1);
sam_ba_putdata( ptr_monitor_if, (uint8_t *) RomBOOT_ExtendedCapabilities, strlen(RomBOOT_ExtendedCapabilities));
sam_ba_putdata( ptr_monitor_if, " ", 1);
ptr = (uint8_t*) &(__DATE__);
i = 0;
while (*ptr++ != '\0')
i++;
ptr_monitor_if->putdata((uint8_t *) &(__DATE__), i);
ptr_monitor_if->putdata(" ", 1);
sam_ba_putdata( ptr_monitor_if, (uint8_t *) &(__DATE__), i);
sam_ba_putdata( ptr_monitor_if, " ", 1);
i = 0;
ptr = (uint8_t*) &(__TIME__);
while (*ptr++ != '\0')
i++;
ptr_monitor_if->putdata((uint8_t *) &(__TIME__), i);
ptr_monitor_if->putdata("\n\r", 2);
sam_ba_putdata( ptr_monitor_if, (uint8_t *) &(__TIME__), i);
sam_ba_putdata( ptr_monitor_if, "\n\r", 2);
}
else if (command == 'X')
{
Expand All @@ -334,7 +406,7 @@ static void sam_ba_monitor_loop(void)
}

// Notify command completed
ptr_monitor_if->putdata("X\n\r", 3);
sam_ba_putdata( ptr_monitor_if, "X\n\r", 3);
}
else if (command == 'Y')
{
Expand Down Expand Up @@ -393,7 +465,7 @@ static void sam_ba_monitor_loop(void)
}

// Notify command completed
ptr_monitor_if->putdata("Y\n\r", 3);
sam_ba_putdata( ptr_monitor_if, "Y\n\r", 3);
}
else if (command == 'Z')
{
Expand All @@ -412,17 +484,17 @@ static void sam_ba_monitor_loop(void)
crc = serial_add_crc(*data++, crc);

// Send response
ptr_monitor_if->putdata("Z", 1);
sam_ba_putdata( ptr_monitor_if, "Z", 1);
put_uint32(crc);
ptr_monitor_if->putdata("#\n\r", 3);
sam_ba_putdata( ptr_monitor_if, "#\n\r", 3);
}

command = 'z';
current_number = 0;

if (b_terminal_mode)
{
ptr_monitor_if->putdata(">", 1);
sam_ba_putdata( ptr_monitor_if, ">", 1);
}
}
else
Expand Down Expand Up @@ -453,6 +525,15 @@ static void sam_ba_monitor_loop(void)
}
}

void sam_ba_monitor_sys_tick(void)
{
/* Check whether the TX or RX LED one-shot period has elapsed. if so, turn off the LED */
if (txLEDPulse && !(--txLEDPulse))
LEDTX_off();
if (rxLEDPulse && !(--rxLEDPulse))
LEDRX_off();
}

/**
* \brief This function starts the SAM-BA monitor.
*/
Expand Down
Loading