Merge pull request #38 from tannewt/autoreset
atmel-samd: Support auto-reset based on USB write activity.
This commit is contained in:
commit
04284a9fe3
@ -101,6 +101,7 @@ CFLAGS_CORTEX_M0 = \
|
||||
-DEXTINT_CALLBACK_MODE=true \
|
||||
-DUDD_ENABLE \
|
||||
-DUSART_CALLBACK_MODE=true \
|
||||
-DTC_ASYNC=true \
|
||||
-DUSB_DEVICE_LPM_SUPPORT
|
||||
CFLAGS = $(INC) -Wall -Werror -ansi -std=gnu99 -nostdlib $(CFLAGS_CORTEX_M0) $(COPT)
|
||||
|
||||
@ -135,6 +136,7 @@ SRC_ASF = $(addprefix asf/sam0/,\
|
||||
drivers/system/interrupt/system_interrupt.c \
|
||||
drivers/system/pinmux/pinmux.c \
|
||||
drivers/system/system.c \
|
||||
drivers/tc/tc_interrupt.c \
|
||||
drivers/tc/tc_sam_d_r/tc.c \
|
||||
drivers/tcc/tcc.c \
|
||||
drivers/usb/stack_interface/usb_device_udd.c \
|
||||
@ -144,6 +146,7 @@ SRC_ASF = $(addprefix asf/sam0/,\
|
||||
|
||||
SRC_C = \
|
||||
access_vfs.c \
|
||||
autoreset.c \
|
||||
builtin_open.c \
|
||||
fatfs_port.c \
|
||||
main.c \
|
||||
|
@ -27,11 +27,13 @@
|
||||
#include <string.h>
|
||||
|
||||
#include "access_vfs.h"
|
||||
#include "autoreset.h"
|
||||
|
||||
#include "asf/common/services/usb/class/msc/device/udi_msc.h"
|
||||
#include "extmod/fsusermount.h"
|
||||
#include "lib/fatfs/diskio.h"
|
||||
#include "py/mpconfig.h"
|
||||
#include "py/mphal.h"
|
||||
#include "py/mpstate.h"
|
||||
#include "py/misc.h"
|
||||
|
||||
@ -140,7 +142,6 @@ Ctrl_status vfs_usb_read_10(uint32_t addr, volatile uint16_t nb_sector)
|
||||
return CTRL_GOOD;
|
||||
}
|
||||
|
||||
|
||||
//! This function transfers the USB MSC data to the memory
|
||||
//!
|
||||
//! @param addr Sector address to start write
|
||||
@ -183,5 +184,6 @@ Ctrl_status vfs_usb_write_10(uint32_t addr, volatile uint16_t nb_sector)
|
||||
}
|
||||
}
|
||||
}
|
||||
autoreset_start();
|
||||
return CTRL_GOOD;
|
||||
}
|
||||
|
87
atmel-samd/autoreset.c
Normal file
87
atmel-samd/autoreset.c
Normal file
@ -0,0 +1,87 @@
|
||||
/*
|
||||
* This file is part of the Micro Python project, http://micropython.org/
|
||||
*
|
||||
* The MIT License (MIT)
|
||||
*
|
||||
* Copyright (c) 2016 Scott Shawcroft for Adafruit Industries
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#include "autoreset.h"
|
||||
|
||||
#include "asf/sam0/drivers/tc/tc_interrupt.h"
|
||||
#include "lib/mp-readline/readline.h"
|
||||
#include "py/mphal.h"
|
||||
|
||||
struct tc_module autoreset_timer;
|
||||
|
||||
static bool autoreset_initialized = false;
|
||||
|
||||
static bool autoreset_enabled = false;
|
||||
|
||||
extern void inject_character(char);
|
||||
void mp_keyboard_interrupt(void);
|
||||
|
||||
void autoreset_callback(struct tc_module *const module_inst) {
|
||||
if (autoreset_enabled) {
|
||||
mp_keyboard_interrupt();
|
||||
inject_character(CHAR_CTRL_D);
|
||||
}
|
||||
|
||||
tc_stop_counter(&autoreset_timer);
|
||||
}
|
||||
|
||||
void autoreset_init() {
|
||||
#ifdef AUTORESET_TIMER
|
||||
struct tc_config config_tc;
|
||||
tc_get_config_defaults(&config_tc);
|
||||
config_tc.counter_size = TC_COUNTER_SIZE_16BIT;
|
||||
config_tc.clock_prescaler = TC_CLOCK_PRESCALER_DIV256;
|
||||
config_tc.counter_16_bit.compare_capture_channel[0] = 0xFFFF;
|
||||
tc_init(&autoreset_timer, AUTORESET_TIMER, &config_tc);
|
||||
tc_enable(&autoreset_timer);
|
||||
tc_register_callback(&autoreset_timer, autoreset_callback, TC_CALLBACK_CC_CHANNEL0);
|
||||
tc_enable_callback(&autoreset_timer, TC_CALLBACK_CC_CHANNEL0);
|
||||
tc_stop_counter(&autoreset_timer);
|
||||
|
||||
autoreset_initialized = true;
|
||||
#endif
|
||||
}
|
||||
|
||||
void autoreset_enable() {
|
||||
autoreset_enabled = true;
|
||||
}
|
||||
|
||||
void autoreset_disable() {
|
||||
autoreset_enabled = false;
|
||||
}
|
||||
|
||||
void autoreset_start() {
|
||||
if (!autoreset_initialized) return;
|
||||
|
||||
tc_stop_counter(&autoreset_timer);
|
||||
tc_start_counter(&autoreset_timer);
|
||||
}
|
||||
|
||||
void autoreset_stop() {
|
||||
if (!autoreset_initialized) return;
|
||||
|
||||
tc_stop_counter(&autoreset_timer);
|
||||
}
|
39
atmel-samd/autoreset.h
Normal file
39
atmel-samd/autoreset.h
Normal file
@ -0,0 +1,39 @@
|
||||
/*
|
||||
* This file is part of the Micro Python project, http://micropython.org/
|
||||
*
|
||||
* The MIT License (MIT)
|
||||
*
|
||||
* Copyright (c) 2016 Scott Shawcroft for Adafruit Industries
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#ifndef __MICROPY_INCLUDED_ATMEL_SAMD_AUTORESET_H__
|
||||
#define __MICROPY_INCLUDED_ATMEL_SAMD_AUTORESET_H__
|
||||
|
||||
#include "asf/sam0/drivers/tc/tc.h"
|
||||
|
||||
void autoreset_callback(struct tc_module *const module_inst);
|
||||
void autoreset_init();
|
||||
void autoreset_start();
|
||||
void autoreset_stop();
|
||||
void autoreset_enable();
|
||||
void autoreset_disable();
|
||||
|
||||
#endif // __MICROPY_INCLUDED_ATMEL_SAMD_AUTORESET_H__
|
@ -8,3 +8,5 @@
|
||||
|
||||
#define MICROPY_HW_LED_TX PIN_PA27
|
||||
#define MICROPY_HW_LED_RX PIN_PB03
|
||||
|
||||
#define AUTORESET_TIMER TC5
|
||||
|
@ -5,3 +5,5 @@
|
||||
|
||||
#define MICROPY_HW_BOARD_NAME "Adafruit Feather M0 Adalogger"
|
||||
#define MICROPY_HW_MCU_NAME "samd21g18"
|
||||
|
||||
#define AUTORESET_TIMER TC5
|
||||
|
@ -5,3 +5,5 @@
|
||||
|
||||
#define MICROPY_HW_BOARD_NAME "Adafruit Feather M0 Basic"
|
||||
#define MICROPY_HW_MCU_NAME "samd21g18"
|
||||
|
||||
#define AUTORESET_TIMER TC5
|
||||
|
@ -29,3 +29,5 @@
|
||||
#define SPI_FLASH_PAD3_PINMUX PINMUX_PB11D_SERCOM4_PAD3 // SCK
|
||||
#define SPI_FLASH_CS PIN_PA13
|
||||
#define SPI_FLASH_SERCOM SERCOM4
|
||||
|
||||
#define AUTORESET_TIMER TC5
|
||||
|
@ -27,6 +27,7 @@
|
||||
#include <stdint.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "py/mphal.h"
|
||||
#include "py/obj.h"
|
||||
#include "py/runtime.h"
|
||||
#include "lib/fatfs/ff.h"
|
||||
@ -40,7 +41,7 @@
|
||||
#define TOTAL_INTERNAL_FLASH_SIZE 0x010000
|
||||
|
||||
#define INTERNAL_FLASH_MEM_SEG1_START_ADDR (0x00040000 - TOTAL_INTERNAL_FLASH_SIZE)
|
||||
#define INTERNAL_FLASH_PART1_START_BLOCK (0x100)
|
||||
#define INTERNAL_FLASH_PART1_START_BLOCK (0x1)
|
||||
#define INTERNAL_FLASH_PART1_NUM_BLOCKS (TOTAL_INTERNAL_FLASH_SIZE / INTERNAL_FLASH_BLOCK_SIZE)
|
||||
|
||||
static bool internal_flash_is_initialised = false;
|
||||
|
@ -22,6 +22,7 @@
|
||||
#include "asf/sam0/drivers/system/system.h"
|
||||
#include <board.h>
|
||||
|
||||
#include "autoreset.h"
|
||||
#include "mpconfigboard.h"
|
||||
#include "modmachine_pin.h"
|
||||
|
||||
@ -172,6 +173,9 @@ static char *stack_top;
|
||||
static char heap[16384];
|
||||
|
||||
void reset_mp() {
|
||||
autoreset_stop();
|
||||
autoreset_enable();
|
||||
|
||||
// Sync the file systems in case any used RAM from the GC to cache. As soon
|
||||
// as we re-init the GC all bets are off on the cache.
|
||||
disk_ioctl(0, CTRL_SYNC, NULL);
|
||||
@ -191,8 +195,18 @@ void reset_mp() {
|
||||
MP_STATE_PORT(mp_kbd_exception) = mp_obj_new_exception(&mp_type_KeyboardInterrupt);
|
||||
|
||||
pin_init0();
|
||||
}
|
||||
|
||||
void start_mp() {
|
||||
#ifdef AUTORESET_TIMER
|
||||
mp_hal_stdout_tx_str("\r\n");
|
||||
mp_hal_stdout_tx_str("Auto-soft reset is on. Simply save files over USB to run them.\r\n");
|
||||
mp_hal_stdout_tx_str("Type anything into the REPL to disable and manually reset (CTRL-D) to re-enable.\r\n");
|
||||
#endif
|
||||
|
||||
mp_hal_stdout_tx_str("boot.py output:\r\n");
|
||||
pyexec_file("boot.py");
|
||||
mp_hal_stdout_tx_str("\r\nmain.py output:\r\n");
|
||||
pyexec_file("main.py");
|
||||
}
|
||||
|
||||
@ -216,11 +230,18 @@ int main(int argc, char **argv) {
|
||||
// as current dir.
|
||||
init_flash_fs();
|
||||
|
||||
// Initialize the autoreset timer. It will automatically reset the repl
|
||||
// after a burst of writes to the FS.
|
||||
autoreset_init();
|
||||
|
||||
// Start USB after getting everything going.
|
||||
#ifdef USB_REPL
|
||||
udc_start();
|
||||
#endif
|
||||
|
||||
// Run boot and main.
|
||||
start_mp();
|
||||
|
||||
// Main script is finished, so now go into REPL mode.
|
||||
// The REPL mode can change, or it can request a soft reset.
|
||||
int exit_code = 0;
|
||||
@ -233,6 +254,7 @@ int main(int argc, char **argv) {
|
||||
if (exit_code == PYEXEC_FORCED_EXIT) {
|
||||
mp_hal_stdout_tx_str("soft reboot\r\n");
|
||||
reset_mp();
|
||||
start_mp();
|
||||
} else if (exit_code != 0) {
|
||||
break;
|
||||
}
|
||||
|
@ -1,5 +1,6 @@
|
||||
#include <string.h>
|
||||
|
||||
#include "autoreset.h"
|
||||
#include "compiler.h"
|
||||
#include "asf/common/services/sleepmgr/sleepmgr.h"
|
||||
#include "asf/common/services/usb/class/cdc/device/udi_cdc.h"
|
||||
@ -67,6 +68,40 @@ void usb_rts_notify(uint8_t port, bool set) {
|
||||
return;
|
||||
}
|
||||
|
||||
void inject_character(char c) {
|
||||
// Introduce a critical section to avoid buffer corruption. We use
|
||||
// cpu_irq_save instead of cpu_irq_disable because we don't know the
|
||||
// current state of IRQs. They may have been turned off already and
|
||||
// we don't want to accidentally turn them back on.
|
||||
irqflags_t flags = cpu_irq_save();
|
||||
// If our buffer is full, then don't get another character otherwise
|
||||
// we'll lose a previous character.
|
||||
if (usb_rx_count >= USB_RX_BUF_SIZE) {
|
||||
cpu_irq_restore(flags);
|
||||
return;
|
||||
}
|
||||
|
||||
uint8_t current_tail = usb_rx_buf_tail;
|
||||
// Pretend we've received a character so that any nested calls to
|
||||
// this function have to consider the spot we've reserved.
|
||||
if ((USB_RX_BUF_SIZE - 1) == usb_rx_buf_tail) {
|
||||
// Reached the end of buffer, revert back to beginning of
|
||||
// buffer.
|
||||
usb_rx_buf_tail = 0x00;
|
||||
} else {
|
||||
usb_rx_buf_tail++;
|
||||
}
|
||||
// The count of characters present in receive buffer is
|
||||
// incremented.
|
||||
usb_rx_count++;
|
||||
|
||||
// We put the next character where we expected regardless of whether
|
||||
// the next character was already loaded in the buffer.
|
||||
usb_rx_buf[current_tail] = c;
|
||||
|
||||
cpu_irq_restore(flags);
|
||||
}
|
||||
|
||||
void usb_rx_notify(void)
|
||||
{
|
||||
irqflags_t flags;
|
||||
@ -129,6 +164,9 @@ int receive_usb() {
|
||||
return 0;
|
||||
}
|
||||
|
||||
// Disable autoreset if someone is using the repl.
|
||||
autoreset_disable();
|
||||
|
||||
// Copy from head.
|
||||
cpu_irq_disable();
|
||||
int data = usb_rx_buf[usb_rx_buf_head];
|
||||
|
@ -24,6 +24,8 @@
|
||||
* THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#include "py/misc.h"
|
||||
|
||||
#define CHAR_CTRL_A (1)
|
||||
#define CHAR_CTRL_B (2)
|
||||
#define CHAR_CTRL_C (3)
|
||||
|
@ -226,6 +226,7 @@ STATIC int pyexec_friendly_repl_process_char(int c) {
|
||||
} else if (ret == CHAR_CTRL_B) {
|
||||
// reset friendly REPL
|
||||
mp_hal_stdout_tx_str("\r\n");
|
||||
mp_hal_stdout_tx_str("\r\n");
|
||||
mp_hal_stdout_tx_str("Adafruit MicroPython " MICROPY_GIT_TAG " on " MICROPY_BUILD_DATE "; " MICROPY_HW_BOARD_NAME " with " MICROPY_HW_MCU_NAME "\r\n");
|
||||
// mp_hal_stdout_tx_str("Type \"help()\" for more information.\r\n");
|
||||
goto input_restart;
|
||||
|
Loading…
x
Reference in New Issue
Block a user