pulse D13 LED during bootloader active
This commit is contained in:
parent
a62ef21615
commit
f8481c1ae9
4 changed files with 348 additions and 186 deletions
|
|
@ -1,105 +1,3 @@
|
|||
<<<<<<< HEAD
|
||||
# Copyright (c) 2015 Atmel Corporation/Thibaut VIARD. All right reserved.
|
||||
# Copyright (c) 2015 Arduino LLC. All right reserved.
|
||||
#
|
||||
# This library is free software; you can redistribute it and/or
|
||||
# modify it under the terms of the GNU Lesser General Public
|
||||
# License as published by the Free Software Foundation; either
|
||||
# version 2.1 of the License, or (at your option) any later version.
|
||||
#
|
||||
# This library is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
||||
# See the GNU Lesser General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU Lesser General Public
|
||||
# License along with this library; if not, write to the Free Software
|
||||
# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
|
||||
# -----------------------------------------------------------------------------
|
||||
# Paths
|
||||
ifeq ($(OS),Windows_NT)
|
||||
# Are we using mingw/msys/msys2/cygwin?
|
||||
ifeq ($(TERM),xterm)
|
||||
T=$(shell cygpath -u $(LOCALAPPDATA))
|
||||
MODULE_PATH?=$(T)/Arduino15/packages/arduino
|
||||
RM=rm
|
||||
SEP=/
|
||||
else
|
||||
MODULE_PATH?=$(LOCALAPPDATA)/Arduino15/packages/arduino
|
||||
RM=rm
|
||||
SEP=\\
|
||||
endif
|
||||
else
|
||||
UNAME_S := $(shell uname -s)
|
||||
|
||||
ifeq ($(UNAME_S),Linux)
|
||||
MODULE_PATH?=$(HOME)/.arduino15/packages/arduino
|
||||
RM=rm
|
||||
SEP=/
|
||||
endif
|
||||
|
||||
ifeq ($(UNAME_S),Darwin)
|
||||
MODULE_PATH?=$(HOME)/Library/Arduino15/packages/arduino/
|
||||
RM=rm
|
||||
SEP=/
|
||||
endif
|
||||
endif
|
||||
|
||||
ARM_GCC_PATH?=$(MODULE_PATH)/tools/arm-none-eabi-gcc/4.8.3-2014q1/bin/arm-none-eabi-
|
||||
BUILD_PATH=build
|
||||
|
||||
# -----------------------------------------------------------------------------
|
||||
# Tools
|
||||
CC=$(ARM_GCC_PATH)gcc
|
||||
OBJCOPY=$(ARM_GCC_PATH)objcopy
|
||||
NM=$(ARM_GCC_PATH)nm
|
||||
SIZE=$(ARM_GCC_PATH)size
|
||||
|
||||
# -----------------------------------------------------------------------------
|
||||
# Boards definitions
|
||||
BOARD_ID?=arduino_zero
|
||||
NAME?=samd21_sam_ba
|
||||
|
||||
# -----------------------------------------------------------------------------
|
||||
# Compiler options
|
||||
CFLAGS_EXTRA=-D__SAMD21G18A__ -DBOARD_ID_$(BOARD_ID)
|
||||
CFLAGS=-mthumb -mcpu=cortex-m0plus -Wall -c -std=gnu99 -ffunction-sections -fdata-sections -nostdlib -nostartfiles --param max-inline-insns-single=500
|
||||
ifdef DEBUG
|
||||
CFLAGS+=-g3 -O1 -DDEBUG=1
|
||||
else
|
||||
CFLAGS+=-Os -DDEBUG=0
|
||||
endif
|
||||
|
||||
ELF=$(NAME).elf
|
||||
BIN=$(NAME).bin
|
||||
HEX=$(NAME).hex
|
||||
|
||||
|
||||
INCLUDES=-I"$(MODULE_PATH)/tools/CMSIS/4.5.0/CMSIS/Include/" -I"$(MODULE_PATH)/tools/CMSIS-Atmel/1.1.0/CMSIS/Device/ATMEL/"
|
||||
|
||||
# -----------------------------------------------------------------------------
|
||||
# Linker options
|
||||
LDFLAGS=-mthumb -mcpu=cortex-m0plus -Wall -Wl,--cref -Wl,--check-sections -Wl,--gc-sections -Wl,--unresolved-symbols=report-all
|
||||
LDFLAGS+=-Wl,--warn-common -Wl,--warn-section-align -Wl,--warn-unresolved-symbols --specs=nano.specs --specs=nosys.specs
|
||||
|
||||
# -----------------------------------------------------------------------------
|
||||
# Source files and objects
|
||||
SOURCES= \
|
||||
board_driver_i2c.c \
|
||||
board_driver_led.c \
|
||||
board_driver_pmic.c \
|
||||
board_driver_serial.c \
|
||||
board_driver_usb.c \
|
||||
board_init.c \
|
||||
board_startup.c \
|
||||
main.c \
|
||||
sam_ba_usb.c \
|
||||
sam_ba_cdc.c \
|
||||
sam_ba_monitor.c \
|
||||
sam_ba_serial.c
|
||||
|
||||
=======
|
||||
IDE_PATH="../../../../.."
|
||||
ARM_GCC_PATH=$(IDE_PATH)/hardware/tools/gcc-arm-none-eabi-4.8.3-2014q1/bin
|
||||
CC=$(ARM_GCC_PATH)/arm-none-eabi-gcc
|
||||
|
|
@ -109,7 +7,6 @@ BLD_EXTA_FLAGS=-D__SAMD21G18A__
|
|||
BUILD_PATH=build
|
||||
INCLUDES=-I$(IDE_PATH)/hardware/tools/CMSIS/CMSIS/Include/ -I$(IDE_PATH)/hardware/tools/CMSIS/Device/ATMEL/ -I./drivers/ -I./utils/ -I./utils/preprocessor/ -I./utils/interrupt
|
||||
SOURCES=main.c sam_ba_monitor.c startup_samd21.c usart_sam_ba.c drivers/cdc_enumerate.c drivers/uart_driver.c utils/interrupt/interrupt_sam_nvic.c
|
||||
>>>>>>> fix makefile for easier programming
|
||||
OBJECTS=$(addprefix $(BUILD_PATH)/, $(SOURCES:.c=.o))
|
||||
DEPS=$(addprefix $(BUILD_PATH)/, $(SOURCES:.c=.d))
|
||||
|
||||
|
|
@ -121,75 +18,11 @@ else
|
|||
AS_CLEAN=
|
||||
endif
|
||||
|
||||
<<<<<<< HEAD
|
||||
LD_SCRIPT=bootloader_samd21x18.ld
|
||||
=======
|
||||
NAME=samd21_sam_ba
|
||||
EXECUTABLE=$(NAME).bin
|
||||
>>>>>>> fix makefile for easier programming
|
||||
|
||||
all: print_info $(SOURCES) $(BIN) $(HEX) $(AS_BUILD)
|
||||
|
||||
<<<<<<< HEAD
|
||||
$(ELF): Makefile $(BUILD_PATH) $(OBJECTS)
|
||||
@echo ----------------------------------------------------------
|
||||
@echo Creating ELF binary
|
||||
"$(CC)" -L. -L$(BUILD_PATH) $(LDFLAGS) -Os -Wl,--gc-sections -save-temps -T$(LD_SCRIPT) -Wl,-Map,"$(BUILD_PATH)/$(NAME).map" -o "$(BUILD_PATH)/$(ELF)" -Wl,--start-group $(OBJECTS) -lm -Wl,--end-group
|
||||
"$(NM)" "$(BUILD_PATH)/$(ELF)" >"$(BUILD_PATH)/$(NAME)_symbols.txt"
|
||||
"$(SIZE)" --format=sysv -t -x $(BUILD_PATH)/$(ELF)
|
||||
|
||||
$(BIN): $(ELF)
|
||||
@echo ----------------------------------------------------------
|
||||
@echo Creating flash binary
|
||||
"$(OBJCOPY)" -O binary $(BUILD_PATH)/$< $@
|
||||
|
||||
$(HEX): $(ELF)
|
||||
@echo ----------------------------------------------------------
|
||||
@echo Creating flash binary
|
||||
"$(OBJCOPY)" -O ihex $(BUILD_PATH)/$< $@
|
||||
|
||||
$(BUILD_PATH)/%.o: %.c
|
||||
@echo ----------------------------------------------------------
|
||||
@echo Compiling $< to $@
|
||||
"$(CC)" $(CFLAGS) $(CFLAGS_EXTRA) $(INCLUDES) $< -o $@
|
||||
@echo ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
|
||||
|
||||
$(BUILD_PATH):
|
||||
@echo ----------------------------------------------------------
|
||||
@echo Creating build folder
|
||||
-mkdir $(BUILD_PATH)
|
||||
|
||||
print_info:
|
||||
@echo ----------------------------------------------------------
|
||||
@echo Compiling bootloader using
|
||||
@echo BASE PATH = $(MODULE_PATH)
|
||||
@echo GCC PATH = $(ARM_GCC_PATH)
|
||||
# @echo OS = $(OS)
|
||||
# @echo SHELL = $(SHELL)
|
||||
# @echo TERM = $(TERM)
|
||||
# "$(CC)" -v
|
||||
# env
|
||||
|
||||
copy_for_atmel_studio: $(BIN) $(HEX)
|
||||
@echo ----------------------------------------------------------
|
||||
@echo Atmel Studio detected, copying ELF to project root for debug
|
||||
cp $(BUILD_PATH)/$(ELF) .
|
||||
|
||||
clean_for_atmel_studio:
|
||||
@echo ----------------------------------------------------------
|
||||
@echo Atmel Studio detected, cleaning ELF from project root
|
||||
-$(RM) ./$(ELF)
|
||||
|
||||
clean: $(AS_CLEAN)
|
||||
@echo ----------------------------------------------------------
|
||||
@echo Cleaning project
|
||||
-$(RM) $(BIN)
|
||||
-$(RM) $(HEX)
|
||||
-$(RM) $(BUILD_PATH)/*.*
|
||||
-rmdir $(BUILD_PATH)
|
||||
|
||||
.phony: print_info $(BUILD_PATH)
|
||||
=======
|
||||
all: $(SOURCES) $(EXECUTABLE)
|
||||
|
||||
$(EXECUTABLE): $(OBJECTS)
|
||||
|
|
@ -202,4 +35,3 @@ $(BUILD_PATH)/%.o: %.c
|
|||
|
||||
clean:
|
||||
del $(EXECUTABLE) $(subst /,\,$(OBJECTS)) $(subst /,\,$(BUILD_PATH)/$(NAME).*)
|
||||
>>>>>>> fix makefile for easier programming
|
||||
|
|
|
|||
|
|
@ -191,22 +191,16 @@ int main(void)
|
|||
#if SAM_BA_INTERFACE == SAM_BA_USBCDC_ONLY || SAM_BA_INTERFACE == SAM_BA_BOTH_INTERFACES
|
||||
pCdc = usb_init();
|
||||
#endif
|
||||
DEBUG_PIN_LOW;
|
||||
|
||||
DEBUG_PIN_LOW;
|
||||
// output on D13 (PA.17)
|
||||
LED_PORT.PINCFG[LED_PIN].reg &= ~ (uint8_t)(PORT_PINCFG_INEN);
|
||||
LED_PORT.DIRSET.reg = (uint32_t)(1 << LED_PIN);
|
||||
|
||||
/* Initialize LEDs */
|
||||
LED_init();
|
||||
LEDRX_init();
|
||||
LEDRX_off();
|
||||
LEDTX_init();
|
||||
LEDTX_off();
|
||||
/* Wait for a complete enum on usb or a '#' char on serial line */
|
||||
while (1) {
|
||||
pulse_led(1); // while we're waiting, blink the D13
|
||||
|
||||
/* Start the sys tick (1 ms) */
|
||||
SysTick_Config(1000);
|
||||
|
||||
/* Wait for a complete enum on usb or a '#' char on serial line */
|
||||
while (1)
|
||||
{
|
||||
#if SAM_BA_INTERFACE == SAM_BA_USBCDC_ONLY || SAM_BA_INTERFACE == SAM_BA_BOTH_INTERFACES
|
||||
if (pCdc->IsConfigured(pCdc) != 0)
|
||||
{
|
||||
|
|
@ -246,3 +240,28 @@ void SysTick_Handler(void)
|
|||
|
||||
sam_ba_monitor_sys_tick();
|
||||
}
|
||||
|
||||
|
||||
// We'll have the D13 LED slowly pulse on and off with bitbang PWM
|
||||
// for a nice 'hey we're in bootload mode' indication! -ada
|
||||
static uint8_t pulse_tick=0;
|
||||
static int8_t pulse_dir=1;
|
||||
static int16_t pulse_pwm;
|
||||
void pulse_led(int8_t speed) {
|
||||
// blink D13
|
||||
pulse_tick++;
|
||||
if (pulse_tick==0) {
|
||||
pulse_pwm += pulse_dir * speed;
|
||||
if (pulse_pwm > 255) {
|
||||
pulse_pwm = 255;
|
||||
pulse_dir = -1;
|
||||
}
|
||||
if (pulse_pwm < 0) {
|
||||
pulse_pwm = 0;
|
||||
pulse_dir = +1;
|
||||
}
|
||||
LED_ON;
|
||||
}
|
||||
if (pulse_tick==pulse_pwm)
|
||||
LED_OFF;
|
||||
}
|
||||
|
|
|
|||
69
bootloaders/zero/main.h
Normal file
69
bootloaders/zero/main.h
Normal file
|
|
@ -0,0 +1,69 @@
|
|||
/* ----------------------------------------------------------------------------
|
||||
* SAM Software Package License
|
||||
* ----------------------------------------------------------------------------
|
||||
* Copyright (c) 2011-2012, Atmel Corporation
|
||||
*
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following condition is met:
|
||||
*
|
||||
* Redistributions of source code must retain the above copyright notice,
|
||||
* this list of conditions and the disclaimer below.
|
||||
*
|
||||
* Atmel's name may not be used to endorse or promote products derived from
|
||||
* this software without specific prior written permission.
|
||||
*
|
||||
* DISCLAIMER: THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR
|
||||
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE
|
||||
* DISCLAIMED. IN NO EVENT SHALL ATMEL BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
|
||||
* OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
||||
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
|
||||
* EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
* ----------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
// Gently pulse the D13 LED
|
||||
#define LED_PIN 17
|
||||
#define PORTA PORT->Group[0]
|
||||
#define LED_PORT PORTA
|
||||
|
||||
#define LED_ON LED_PORT.OUTSET.reg = (uint32_t)(1 << LED_PIN);
|
||||
#define LED_OFF LED_PORT.OUTCLR.reg = (uint32_t)(1 << LED_PIN);
|
||||
/*
|
||||
* If BOOT_DOUBLE_TAP_ADDRESS is defined the bootloader is started by
|
||||
* quickly tapping two times on the reset button.
|
||||
* BOOT_DOUBLE_TAP_ADDRESS must point to a free SRAM cell that must not
|
||||
* be touched from the loaded application.
|
||||
*/
|
||||
#define BOOT_DOUBLE_TAP_ADDRESS 0x20007FFC
|
||||
#define BOOT_DOUBLE_TAP_DATA (*((volatile uint32_t *) BOOT_DOUBLE_TAP_ADDRESS))
|
||||
|
||||
/*
|
||||
* If BOOT_LOAD_PIN is defined the bootloader is started if the selected
|
||||
* pin is tied LOW.
|
||||
*/
|
||||
//#define BOOT_LOAD_PIN PIN_PA21 // Pin 7
|
||||
//#define BOOT_LOAD_PIN PIN_PA15 // Pin 5
|
||||
#define BOOT_PIN_MASK (1U << (BOOT_LOAD_PIN & 0x1f))
|
||||
|
||||
#define CPU_FREQUENCY 8000000
|
||||
#define APP_START_ADDRESS 0x00002000
|
||||
#define FLASH_WAIT_STATES 1
|
||||
|
||||
#define BOOT_USART_MODULE SERCOM0
|
||||
//#define BOOT_USART_MODULE SERCOM5
|
||||
#define BOOT_USART_MUX_SETTINGS UART_RX_PAD3_TX_PAD2
|
||||
//#define BOOT_USART_PAD3 PINMUX_PB23D_SERCOM5_PAD3
|
||||
//#define BOOT_USART_PAD2 PINMUX_PB22D_SERCOM5_PAD2
|
||||
#define BOOT_USART_PAD3 PINMUX_PA11C_SERCOM0_PAD3
|
||||
#define BOOT_USART_PAD2 PINMUX_PA10C_SERCOM0_PAD2
|
||||
#define BOOT_USART_PAD1 PINMUX_UNUSED
|
||||
#define BOOT_USART_PAD0 PINMUX_UNUSED
|
||||
|
||||
|
|
@ -527,11 +527,253 @@ 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();
|
||||
pulse_led(3);
|
||||
length = ptr_monitor_if->getdata(data, SIZEBUFMAX);
|
||||
ptr = data;
|
||||
for (i = 0; i < length; i++, ptr++)
|
||||
{
|
||||
if (*ptr == 0xff) continue;
|
||||
|
||||
if (*ptr == '#')
|
||||
{
|
||||
if (b_terminal_mode)
|
||||
{
|
||||
ptr_monitor_if->putdata("\n\r", 2);
|
||||
}
|
||||
if (command == 'S')
|
||||
{
|
||||
//Check if some data are remaining in the "data" buffer
|
||||
if(length>i)
|
||||
{
|
||||
//Move current indexes to next avail data (currently ptr points to "#")
|
||||
ptr++;
|
||||
i++;
|
||||
//We need to add first the remaining data of the current buffer already read from usb
|
||||
//read a maximum of "current_number" bytes
|
||||
u32tmp=min((length-i),current_number);
|
||||
memcpy(ptr_data, ptr, u32tmp);
|
||||
i += u32tmp;
|
||||
ptr += u32tmp;
|
||||
j = u32tmp;
|
||||
}
|
||||
//update i with the data read from the buffer
|
||||
i--;
|
||||
ptr--;
|
||||
//Do we expect more data ?
|
||||
if(j<current_number)
|
||||
ptr_monitor_if->getdata_xmd(ptr_data, current_number-j);
|
||||
|
||||
__asm("nop");
|
||||
}
|
||||
else if (command == 'R')
|
||||
{
|
||||
ptr_monitor_if->putdata_xmd(ptr_data, current_number);
|
||||
}
|
||||
else if (command == 'O')
|
||||
{
|
||||
*ptr_data = (char) current_number;
|
||||
}
|
||||
else if (command == 'H')
|
||||
{
|
||||
*((uint16_t *) ptr_data) = (uint16_t) current_number;
|
||||
}
|
||||
else if (command == 'W')
|
||||
{
|
||||
*((int *) ptr_data) = current_number;
|
||||
}
|
||||
else if (command == 'o')
|
||||
{
|
||||
sam_ba_putdata_term(ptr_data, 1);
|
||||
}
|
||||
else if (command == 'h')
|
||||
{
|
||||
current_number = *((uint16_t *) ptr_data);
|
||||
sam_ba_putdata_term((uint8_t*) ¤t_number, 2);
|
||||
}
|
||||
else if (command == 'w')
|
||||
{
|
||||
current_number = *((uint32_t *) ptr_data);
|
||||
sam_ba_putdata_term((uint8_t*) ¤t_number, 4);
|
||||
}
|
||||
else if (command == 'G')
|
||||
{
|
||||
call_applet(current_number);
|
||||
/* Rebase the Stack Pointer */
|
||||
__set_MSP(sp);
|
||||
cpu_irq_enable();
|
||||
if (b_sam_ba_interface_usart) {
|
||||
ptr_monitor_if->put_c(0x6);
|
||||
}
|
||||
}
|
||||
else if (command == 'T')
|
||||
{
|
||||
b_terminal_mode = 1;
|
||||
ptr_monitor_if->putdata("\n\r", 2);
|
||||
}
|
||||
else if (command == 'N')
|
||||
{
|
||||
if (b_terminal_mode == 0)
|
||||
{
|
||||
ptr_monitor_if->putdata("\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);
|
||||
ptr = (uint8_t*) &(__DATE__);
|
||||
i = 0;
|
||||
while (*ptr++ != '\0')
|
||||
i++;
|
||||
ptr_monitor_if->putdata((uint8_t *) &(__DATE__), i);
|
||||
ptr_monitor_if->putdata(" ", 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);
|
||||
}
|
||||
else if (command == 'X')
|
||||
{
|
||||
// Syntax: X[ADDR]#
|
||||
// Erase the flash memory starting from ADDR to the end of flash.
|
||||
|
||||
// Note: the flash memory is erased in ROWS, that is in block of 4 pages.
|
||||
// Even if the starting address is the last byte of a ROW the entire
|
||||
// ROW is erased anyway.
|
||||
|
||||
uint32_t dst_addr = current_number; // starting address
|
||||
|
||||
while (dst_addr < MAX_FLASH) {
|
||||
// Execute "ER" Erase Row
|
||||
NVMCTRL->ADDR.reg = dst_addr / 2;
|
||||
NVMCTRL->CTRLA.reg = NVMCTRL_CTRLA_CMDEX_KEY | NVMCTRL_CTRLA_CMD_ER;
|
||||
while (NVMCTRL->INTFLAG.bit.READY == 0)
|
||||
;
|
||||
dst_addr += PAGE_SIZE * 4; // Skip a ROW
|
||||
}
|
||||
|
||||
// Notify command completed
|
||||
ptr_monitor_if->putdata("X\n\r", 3);
|
||||
}
|
||||
else if (command == 'Y')
|
||||
{
|
||||
// This command writes the content of a buffer in SRAM into flash memory.
|
||||
|
||||
// Syntax: Y[ADDR],0#
|
||||
// Set the starting address of the SRAM buffer.
|
||||
|
||||
// Syntax: Y[ROM_ADDR],[SIZE]#
|
||||
// Write the first SIZE bytes from the SRAM buffer (previously set) into
|
||||
// flash memory starting from address ROM_ADDR
|
||||
|
||||
static uint32_t *src_buff_addr = NULL;
|
||||
|
||||
if (current_number == 0) {
|
||||
// Set buffer address
|
||||
src_buff_addr = ptr_data;
|
||||
|
||||
} else {
|
||||
// Write to flash
|
||||
uint32_t size = current_number/4;
|
||||
uint32_t *src_addr = src_buff_addr;
|
||||
uint32_t *dst_addr = ptr_data;
|
||||
|
||||
// Set automatic page write
|
||||
NVMCTRL->CTRLB.bit.MANW = 0;
|
||||
|
||||
// Do writes in pages
|
||||
while (size) {
|
||||
// Execute "PBC" Page Buffer Clear
|
||||
NVMCTRL->CTRLA.reg = NVMCTRL_CTRLA_CMDEX_KEY | NVMCTRL_CTRLA_CMD_PBC;
|
||||
while (NVMCTRL->INTFLAG.bit.READY == 0)
|
||||
;
|
||||
|
||||
// Fill page buffer
|
||||
uint32_t i;
|
||||
for (i=0; i<(PAGE_SIZE/4) && i<size; i++) {
|
||||
dst_addr[i] = src_addr[i];
|
||||
}
|
||||
|
||||
// Execute "WP" Write Page
|
||||
//NVMCTRL->ADDR.reg = ((uint32_t)dst_addr) / 2;
|
||||
NVMCTRL->CTRLA.reg = NVMCTRL_CTRLA_CMDEX_KEY | NVMCTRL_CTRLA_CMD_WP;
|
||||
while (NVMCTRL->INTFLAG.bit.READY == 0)
|
||||
;
|
||||
|
||||
// Advance to next page
|
||||
dst_addr += i;
|
||||
src_addr += i;
|
||||
size -= i;
|
||||
}
|
||||
}
|
||||
|
||||
// Notify command completed
|
||||
ptr_monitor_if->putdata("Y\n\r", 3);
|
||||
}
|
||||
else if (command == 'Z')
|
||||
{
|
||||
// This command calculate CRC for a given area of memory.
|
||||
// It's useful to quickly check if a transfer has been done
|
||||
// successfully.
|
||||
|
||||
// Syntax: Z[START_ADDR],[SIZE]#
|
||||
// Returns: Z[CRC]#
|
||||
|
||||
uint8_t *data = (uint8_t *)ptr_data;
|
||||
uint32_t size = current_number;
|
||||
uint16_t crc = 0;
|
||||
uint32_t i = 0;
|
||||
for (i=0; i<size; i++)
|
||||
crc = add_crc(*data++, crc);
|
||||
|
||||
// Send response
|
||||
ptr_monitor_if->putdata("Z", 1);
|
||||
put_uint32(crc);
|
||||
ptr_monitor_if->putdata("#\n\r", 3);
|
||||
}
|
||||
|
||||
command = 'z';
|
||||
current_number = 0;
|
||||
|
||||
if (b_terminal_mode)
|
||||
{
|
||||
ptr_monitor_if->putdata(">", 1);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (('0' <= *ptr) && (*ptr <= '9'))
|
||||
{
|
||||
current_number = (current_number << 4) | (*ptr - '0');
|
||||
}
|
||||
else if (('A' <= *ptr) && (*ptr <= 'F'))
|
||||
{
|
||||
current_number = (current_number << 4) | (*ptr - 'A' + 0xa);
|
||||
}
|
||||
else if (('a' <= *ptr) && (*ptr <= 'f'))
|
||||
{
|
||||
current_number = (current_number << 4) | (*ptr - 'a' + 0xa);
|
||||
}
|
||||
else if (*ptr == ',')
|
||||
{
|
||||
ptr_data = (uint8_t *) current_number;
|
||||
current_number = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
command = *ptr;
|
||||
current_number = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
|||
Loading…
Reference in a new issue