atmel-samd: Add APA102 support and flash more advanced status.

The new sequence is as follows:
* Solid blue during the boot/settings script.
* Solid green during the main/code script.
* After main while waiting to enter repl or reset:
  * Fading green once main is done successfully.
  * On error produce a series of flashes:
    * Long flash color of script.
    * Long flash color of error:
      * Green = IndentationError
      * Cyan = SyntaxError
      * White = NameError
      * Orange = OSError
      * Yellow = Other error
    * Line number of the exception by digit. Number of flashes represents value.
      * Thousands = White
      * Hundreds = Blue
      * Tens = Yellow
      * Ones = Cyan
    * Off for a period and then repeats.

At any point a write to the flash storage will flicker red.

Fixes #63
This commit is contained in:
Scott Shawcroft 2016-12-09 19:27:41 -08:00
parent 6225b89c76
commit b6f1eebab3
16 changed files with 371 additions and 127 deletions

View File

@ -178,7 +178,7 @@ SRC_C = \
moduos.c \
mphalport.c \
samd21_pins.c \
neopixel_status.c \
rgb_led_status.c \
tick.c \
$(FLASH_IMPL) \
asf/common/services/sleepmgr/samd/sleepmgr.c \

View File

@ -3,7 +3,6 @@
#define MICROPY_HW_BOARD_NAME "Adafruit Gemma M0 (Experimental)"
#define MICROPY_HW_MCU_NAME "samd21e18"
#define MICROPY_HW_APA102_SERCOM SERCOM0
#define MICROPY_HW_APA102_MOSI &pin_PA04
#define MICROPY_HW_APA102_SCK &pin_PA05

View File

@ -3,7 +3,6 @@
#define MICROPY_HW_BOARD_NAME "Adafruit Trinket M0 (Experimental)"
#define MICROPY_HW_MCU_NAME "samd21e18"
#define MICROPY_HW_APA102_SERCOM SERCOM0
#define MICROPY_HW_APA102_MOSI &pin_PA04
#define MICROPY_HW_APA102_SCK &pin_PA05

View File

@ -37,7 +37,7 @@
#include "asf/sam0/drivers/nvm/nvm.h"
#include "asf/sam0/drivers/port/port.h"
#include "neopixel_status.h"
#include "rgb_led_status.h"
#define TOTAL_INTERNAL_FLASH_SIZE 0x010000
@ -174,9 +174,7 @@ bool internal_flash_write_block(const uint8_t *src, uint32_t block) {
#ifdef MICROPY_HW_LED_MSC
port_pin_set_output_level(MICROPY_HW_LED_MSC, true);
#endif
#ifdef MICROPY_HW_NEOPIXEL
temp_status_color(0x8f, 0x00, 0x00);
#endif
temp_status_color(ACTIVE_WRITE);
// non-MBR block, copy to cache
int32_t dest = convert_block_to_flash_addr(block);
if (dest == -1) {
@ -214,9 +212,7 @@ bool internal_flash_write_block(const uint8_t *src, uint32_t block) {
return false;
}
}
#ifdef MICROPY_HW_NEOPIXEL
clear_temp_status();
#endif
clear_temp_status();
#ifdef MICROPY_HW_LED_MSC
port_pin_set_output_level(MICROPY_HW_LED_MSC, false);
#endif

View File

@ -10,6 +10,7 @@
#include "lib/fatfs/ff.h"
#include "lib/fatfs/diskio.h"
#include "lib/mp-readline/readline.h"
#include "lib/utils/pyexec.h"
#include "extmod/fsusermount.h"
@ -23,7 +24,7 @@
#include "autoreset.h"
#include "mpconfigboard.h"
#include "neopixel_status.h"
#include "rgb_led_status.h"
#include "tick.h"
fs_user_mount_t fs_user_mount_flash;
@ -131,7 +132,7 @@ static char *stack_top;
static char heap[16384];
void reset_mp(void) {
new_status_color(0x8f, 0x00, 0x8f);
new_status_color(0x8f008f);
autoreset_stop();
autoreset_enable();
@ -181,7 +182,7 @@ void reset_samd21(void) {
system_pinmux_group_set_config(&(PORT->Group[1]), pin_mask[1] & ~MICROPY_PORT_B, &config);
}
bool maybe_run(const char* filename, int* ret) {
bool maybe_run(const char* filename, pyexec_result_t* exec_result) {
FILINFO fno;
#if _USE_LFN
fno.lfname = NULL;
@ -193,32 +194,171 @@ bool maybe_run(const char* filename, int* ret) {
}
mp_hal_stdout_tx_str(filename);
mp_hal_stdout_tx_str(" output:\r\n");
*ret = pyexec_file(filename);
pyexec_file(filename, exec_result);
return true;
}
void start_mp(void) {
bool start_mp(void) {
bool cdc_enabled_at_start = mp_cdc_enabled;
#ifdef AUTORESET_DELAY_MS
if (cdc_enabled_at_start) {
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
new_status_color(0x00, 0x00, 0x8f);
int ret = 0;
bool found_boot = maybe_run("settings.txt", &ret) ||
maybe_run("settings.py", &ret) ||
maybe_run("boot.py", &ret) ||
maybe_run("boot.txt", &ret);
if (found_boot && ret & PYEXEC_FORCED_EXIT) {
return;
new_status_color(BOOT_RUNNING);
pyexec_result_t result;
bool found_boot = maybe_run("settings.txt", &result) ||
maybe_run("settings.py", &result) ||
maybe_run("boot.py", &result) ||
maybe_run("boot.txt", &result);
bool found_main = false;
if (!found_boot || !(result.return_code & PYEXEC_FORCED_EXIT)) {
new_status_color(MAIN_RUNNING);
found_main = maybe_run("code.txt", &result) ||
maybe_run("code.py", &result) ||
maybe_run("main.py", &result) ||
maybe_run("main.txt", &result);
}
new_status_color(0x00, 0x8f, 0x00);
maybe_run("code.txt", &ret) ||
maybe_run("code.py", &ret) ||
maybe_run("main.py", &ret) ||
maybe_run("main.txt", &ret);
if (result.return_code & PYEXEC_FORCED_EXIT) {
return reset_next_character;
}
// If not is USB mode then do not skip the repl.
#ifndef USB_REPL
return false;
#endif
// Wait for connection or character.
new_status_color(ALL_DONE);
bool cdc_enabled_before = false;
uint32_t pattern_start = ticks_ms;
printf("result code %d %d.\r\n", result.return_code, result.exception_line);
uint32_t total_exception_cycle = 0;
uint8_t ones = result.exception_line % 10;
ones += ones > 0 ? 1 : 0;
uint8_t tens = (result.exception_line / 10) % 10;
tens += tens > 0 ? 1 : 0;
uint8_t hundreds = (result.exception_line / 100) % 10;
hundreds += hundreds > 0 ? 1 : 0;
uint8_t thousands = (result.exception_line / 1000) % 10;
thousands += thousands > 0 ? 1 : 0;
uint8_t digit_sum = ones + tens + hundreds + thousands;
uint8_t num_places = 0;
uint16_t line = result.exception_line;
for (int i = 0; i < 4; i++) {
if ((line % 10) > 0) {
num_places++;
}
line /= 10;
}
if (result.return_code == PYEXEC_EXCEPTION) {
total_exception_cycle = EXCEPTION_TYPE_LENGTH_MS * 3 + LINE_NUMBER_TOGGLE_LENGTH * digit_sum + LINE_NUMBER_TOGGLE_LENGTH * num_places;
}
while (true) {
#ifdef MICROPY_VM_HOOK_LOOP
MICROPY_VM_HOOK_LOOP
#endif
if (reset_next_character) {
return true;
}
if (usb_rx_count > 0) {
// Skip REPL if reset was requested.
return receive_usb() == CHAR_CTRL_D;
}
if (!cdc_enabled_before && mp_cdc_enabled) {
if (cdc_enabled_at_start) {
mp_hal_stdout_tx_str("\r\n\r\n");
} else {
printf("result code %d %d.\r\n", result.return_code, result.exception_line);
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("Press any key to enter the REPL and disable auto-reset. Use CTRL-D to soft reset.\r\n");
}
if (cdc_enabled_before && !mp_cdc_enabled) {
cdc_enabled_at_start = false;
}
cdc_enabled_before = mp_cdc_enabled;
uint32_t tick_diff = ticks_ms - pattern_start;
if (result.return_code != PYEXEC_EXCEPTION) {
// All is good. Ramp ALL_DONE up and down.
if (tick_diff > ALL_GOOD_CYCLE_MS) {
pattern_start = ticks_ms;
tick_diff = 0;
}
uint16_t brightness = tick_diff * 255 / (ALL_GOOD_CYCLE_MS / 2);
if (brightness > 255) {
brightness = 511 - brightness;
}
new_status_color(color_brightness(ALL_DONE, brightness));
} else {
if (tick_diff > total_exception_cycle) {
pattern_start = ticks_ms;
tick_diff = 0;
}
// First flash the file color.
if (tick_diff < EXCEPTION_TYPE_LENGTH_MS) {
if (found_main) {
new_status_color(MAIN_RUNNING);
} else {
new_status_color(BOOT_RUNNING);
}
// Next flash the exception color.
} else if (tick_diff < EXCEPTION_TYPE_LENGTH_MS * 2) {
if (mp_obj_is_subclass_fast(result.exception_type, &mp_type_IndentationError)) {
new_status_color(INDENTATION_ERROR);
} else if (mp_obj_is_subclass_fast(result.exception_type, &mp_type_SyntaxError)) {
new_status_color(SYNTAX_ERROR);
} else if (mp_obj_is_subclass_fast(result.exception_type, &mp_type_NameError)) {
new_status_color(NAME_ERROR);
} else if (mp_obj_is_subclass_fast(result.exception_type, &mp_type_OSError)) {
new_status_color(OS_ERROR);
} else {
new_status_color(OTHER_ERROR);
}
// Finally flash the line number digits from highest to lowest.
// Zeroes will not produce a flash but can be read by the absence of
// a color from the sequence.
} else if (tick_diff < (EXCEPTION_TYPE_LENGTH_MS * 2 + LINE_NUMBER_TOGGLE_LENGTH * digit_sum)) {
uint32_t digit_diff = tick_diff - EXCEPTION_TYPE_LENGTH_MS * 2;
if ((digit_diff % LINE_NUMBER_TOGGLE_LENGTH) < (LINE_NUMBER_TOGGLE_LENGTH / 2)) {
new_status_color(BLACK);
} else if (digit_diff < LINE_NUMBER_TOGGLE_LENGTH * thousands) {
if (digit_diff < LINE_NUMBER_TOGGLE_LENGTH) {
new_status_color(BLACK);
} else {
new_status_color(THOUSANDS);
}
} else if (digit_diff < LINE_NUMBER_TOGGLE_LENGTH * (thousands + hundreds)) {
if (digit_diff < LINE_NUMBER_TOGGLE_LENGTH * (thousands + 1)) {
new_status_color(BLACK);
} else {
new_status_color(HUNDREDS);
}
} else if (digit_diff < LINE_NUMBER_TOGGLE_LENGTH * (thousands + hundreds + tens)) {
if (digit_diff < LINE_NUMBER_TOGGLE_LENGTH * (thousands + hundreds + 1)) {
new_status_color(BLACK);
} else {
new_status_color(TENS);
}
} else {
if (digit_diff < LINE_NUMBER_TOGGLE_LENGTH * (thousands + hundreds + tens + 1)) {
new_status_color(BLACK);
} else {
new_status_color(ONES);
}
}
} else {
new_status_color(BLACK);
}
}
}
}
#ifdef UART_REPL
@ -283,7 +423,7 @@ void samd21_init(void) {
// port_pin_set_config(MICROPY_HW_LED1, &pin_conf);
// port_pin_set_output_level(MICROPY_HW_LED1, false);
neopixel_status_init();
rgb_led_status_init();
}
int main(int argc, char **argv) {
@ -307,24 +447,29 @@ int main(int argc, char **argv) {
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;
int exit_code = PYEXEC_FORCED_EXIT;
bool skip_repl = true;
bool first_run = true;
for (;;) {
new_status_color(0x3f, 0x3f, 0x3f);
if (pyexec_mode_kind == PYEXEC_MODE_RAW_REPL) {
exit_code = pyexec_raw_repl();
} else {
exit_code = pyexec_friendly_repl();
if (!skip_repl) {
autoreset_disable();
new_status_color(REPL_RUNNING);
if (pyexec_mode_kind == PYEXEC_MODE_RAW_REPL) {
exit_code = pyexec_raw_repl();
} else {
exit_code = pyexec_friendly_repl();
}
}
if (exit_code == PYEXEC_FORCED_EXIT) {
mp_hal_stdout_tx_str("soft reboot\r\n");
reset_samd21();
reset_mp();
start_mp();
if (!first_run) {
mp_hal_stdout_tx_str("soft reboot\r\n");
reset_samd21();
reset_mp();
}
first_run = false;
skip_repl = start_mp();
} else if (exit_code != 0) {
break;
}

View File

@ -30,9 +30,9 @@ static volatile uint8_t usb_rx_buf_head;
static volatile uint8_t usb_rx_buf_tail;
// Number of bytes in receive buffer
static volatile uint8_t usb_rx_count;
volatile uint8_t usb_rx_count;
static volatile bool mp_cdc_enabled = false;
volatile bool mp_cdc_enabled = false;
void mp_keyboard_interrupt(void);
int interrupt_char;

View File

@ -37,6 +37,11 @@ extern volatile uint64_t ticks_ms;
static inline mp_uint_t mp_hal_ticks_ms(void) {
return ticks_ms;
}
// Number of bytes in receive buffer
volatile uint8_t usb_rx_count;
volatile bool mp_cdc_enabled;
int receive_usb(void);
void mp_hal_set_interrupt_char(int c);

View File

@ -1,43 +0,0 @@
#include "asf/common2/services/delay/delay.h"
#include "asf/sam0/drivers/port/port.h"
#include "mphalport.h"
#include "shared-bindings/nativeio/DigitalInOut.h"
#include "shared-bindings/neopixel_write/__init__.h"
#include "neopixel_status.h"
#include "samd21_pins.h"
#ifdef MICROPY_HW_NEOPIXEL
static uint8_t status_neopixel_color[3];
static nativeio_digitalinout_obj_t status_neopixel;
#endif
void neopixel_status_init() {
#ifdef MICROPY_HW_NEOPIXEL
common_hal_nativeio_digitalinout_construct(&status_neopixel, MICROPY_HW_NEOPIXEL);
common_hal_nativeio_digitalinout_switch_to_output(&status_neopixel, false, DRIVE_MODE_PUSH_PULL);
#endif
}
void new_status_color(uint8_t r, uint8_t g, uint8_t b) {
#ifdef MICROPY_HW_NEOPIXEL
status_neopixel_color[0] = g;
status_neopixel_color[1] = r;
status_neopixel_color[2] = b;
common_hal_neopixel_write(&status_neopixel, status_neopixel_color, 3, true);
#endif
}
void temp_status_color(uint8_t r, uint8_t g, uint8_t b) {
#ifdef MICROPY_HW_NEOPIXEL
uint8_t colors[3] = {g, r, b};
common_hal_neopixel_write(&status_neopixel, colors, 3, true);
#endif
}
void clear_temp_status() {
#ifdef MICROPY_HW_NEOPIXEL
common_hal_neopixel_write(&status_neopixel, status_neopixel_color, 3, true);
#endif
}

View File

@ -1,12 +0,0 @@
#ifndef __MICROPY_INCLUDED_ATMEL_SAMD_NEOPIXEL_STATUS_H
#define __MICROPY_INCLUDED_ATMEL_SAMD_NEOPIXEL_STATUS_H
#include <stdint.h>
#include <stdbool.h>
extern void neopixel_status_init(void);
extern void new_status_color(uint8_t r, uint8_t g, uint8_t b);
extern void temp_status_color(uint8_t r, uint8_t g, uint8_t b);
extern void clear_temp_status(void);
#endif // __MICROPY_INCLUDED_ATMEL_SAMD_NEOPIXEL_STATUS_H

View File

@ -0,0 +1,32 @@
#define BLACK 0x000000
#define GREEN 0x003f00
#define BLUE 0x00003f
#define CYAN 0x003f3f
#define RED 0x3f0000
#define ORANGE 0x3f1f00
#define YELLOW 0x3f3f00
#define PURPLE 0x3f003f
#define WHITE 0x3f3f3f
#define BOOT_RUNNING BLUE
#define MAIN_RUNNING GREEN
#define ALL_DONE GREEN
#define REPL_RUNNING WHITE
#define ACTIVE_WRITE 0x8f0000
#define ALL_GOOD_CYCLE_MS 2000u
#define LINE_NUMBER_TOGGLE_LENGTH 300u
#define EXCEPTION_TYPE_LENGTH_MS 1000u
#define THOUSANDS WHITE
#define HUNDREDS BLUE
#define TENS YELLOW
#define ONES CYAN
#define INDENTATION_ERROR GREEN
#define SYNTAX_ERROR CYAN
#define NAME_ERROR WHITE
#define OS_ERROR ORANGE
#define OTHER_ERROR YELLOW

View File

@ -0,0 +1,93 @@
#include "asf/common2/services/delay/delay.h"
#include "asf/sam0/drivers/port/port.h"
#include "mphalport.h"
#include "shared-bindings/bitbangio/SPI.h"
#include "shared-bindings/nativeio/DigitalInOut.h"
#include "shared-bindings/neopixel_write/__init__.h"
#include "shared-module/bitbangio/types.h"
#include "rgb_led_status.h"
#include "samd21_pins.h"
#ifdef MICROPY_HW_NEOPIXEL
static uint8_t status_neopixel_color[3];
static nativeio_digitalinout_obj_t status_neopixel;
#endif
#if defined(MICROPY_HW_APA102_MOSI) && defined(MICROPY_HW_APA102_SCK)
static uint8_t status_apa102_color[12] = {0, 0, 0, 0, 0xff, 0, 0, 0};
static bitbangio_spi_obj_t status_apa102;
#endif
#if defined(MICROPY_HW_NEOPIXEL) || (defined(MICROPY_HW_APA102_MOSI) && defined(MICROPY_HW_APA102_SCK))
static uint32_t current_status_color = 0;
#endif
void rgb_led_status_init() {
#ifdef MICROPY_HW_NEOPIXEL
common_hal_nativeio_digitalinout_construct(&status_neopixel, MICROPY_HW_NEOPIXEL);
common_hal_nativeio_digitalinout_switch_to_output(&status_neopixel, false, DRIVE_MODE_PUSH_PULL);
#endif
#if defined(MICROPY_HW_APA102_MOSI) && defined(MICROPY_HW_APA102_SCK)
shared_module_bitbangio_spi_construct(&status_apa102,
MICROPY_HW_APA102_SCK,
MICROPY_HW_APA102_MOSI,
NULL);
shared_module_bitbangio_spi_try_lock(&status_apa102);
shared_module_bitbangio_spi_configure(&status_apa102, 100000, 0, 1, 8);
#endif
}
void new_status_color(uint32_t rgb) {
#if defined(MICROPY_HW_NEOPIXEL) || (defined(MICROPY_HW_APA102_MOSI) && defined(MICROPY_HW_APA102_SCK))
if (current_status_color == rgb) {
return;
}
current_status_color = rgb;
#endif
#ifdef MICROPY_HW_NEOPIXEL
status_neopixel_color[0] = (rgb >> 8) & 0xff;
status_neopixel_color[1] = (rgb >> 16) & 0xff;
status_neopixel_color[2] = rgb & 0xff;
common_hal_neopixel_write(&status_neopixel, status_neopixel_color, 3, true);
#endif
#if defined(MICROPY_HW_APA102_MOSI) && defined(MICROPY_HW_APA102_SCK)
status_apa102_color[5] = rgb & 0xff;
status_apa102_color[6] = (rgb >> 8) & 0xff;
status_apa102_color[7] = (rgb >> 16) & 0xff;
shared_module_bitbangio_spi_write(&status_apa102, status_apa102_color, 8);
#endif
}
void temp_status_color(uint32_t rgb) {
#ifdef MICROPY_HW_NEOPIXEL
uint8_t colors[3] = {(rgb >> 8) & 0xff, (rgb >> 16) & 0xff, rgb & 0xff};
common_hal_neopixel_write(&status_neopixel, colors, 3, true);
#endif
#if defined(MICROPY_HW_APA102_MOSI) && defined(MICROPY_HW_APA102_SCK)
uint8_t colors[12] = {0, 0, 0, 0, 0xff, rgb & 0xff, (rgb >> 8) & 0xff, (rgb >> 16) & 0xff, 0x0, 0x0, 0x0, 0x0};
shared_module_bitbangio_spi_write(&status_apa102, colors, 8);
#endif
}
void clear_temp_status() {
#ifdef MICROPY_HW_NEOPIXEL
common_hal_neopixel_write(&status_neopixel, status_neopixel_color, 3, true);
#endif
#if defined(MICROPY_HW_APA102_MOSI) && defined(MICROPY_HW_APA102_SCK)
shared_module_bitbangio_spi_write(&status_apa102, status_apa102_color, 12);
#endif
}
uint32_t color_brightness(uint32_t color, uint8_t brightness) {
#if defined(MICROPY_HW_NEOPIXEL) || (defined(MICROPY_HW_APA102_MOSI) && defined(MICROPY_HW_APA102_SCK))
uint32_t result = ((color & 0xff0000) * brightness / 255) & 0xff0000;
result += ((color & 0xff00) * brightness / 255) & 0xff00;
result += ((color & 0xff) * brightness / 255) & 0xff;
return result;
#else
return color;
#endif
}

View File

@ -0,0 +1,16 @@
#ifndef __MICROPY_INCLUDED_ATMEL_SAMD_RGB_LED_STATUS_H
#define __MICROPY_INCLUDED_ATMEL_SAMD_RGB_LED_STATUS_H
#include <stdint.h>
#include <stdbool.h>
#include "rgb_led_colors.h"
extern void rgb_led_status_init(void);
extern void new_status_color(uint32_t rgb);
extern void temp_status_color(uint32_t rgb);
extern void clear_temp_status(void);
uint32_t color_brightness(uint32_t color, uint8_t brightness);
#endif // __MICROPY_INCLUDED_ATMEL_SAMD_RGB_LED_STATUS_H

View File

@ -36,7 +36,7 @@
#include "lib/fatfs/ff.h"
#include "extmod/fsusermount.h"
#include "neopixel_status.h"
#include "rgb_led_status.h"
#define SPI_FLASH_PART1_START_BLOCK (0x1)
@ -384,9 +384,7 @@ static void spi_flash_flush_keep_cache(bool keep_cache) {
#ifdef MICROPY_HW_LED_MSC
port_pin_set_output_level(MICROPY_HW_LED_MSC, true);
#endif
#ifdef MICROPY_HW_NEOPIXEL
temp_status_color(0x8f, 0x00, 0x00);
#endif
temp_status_color(ACTIVE_WRITE);
// If we've cached to the flash itself flush from there.
if (MP_STATE_VM(flash_ram_cache) == NULL) {
flush_scratch_flash();
@ -394,9 +392,7 @@ static void spi_flash_flush_keep_cache(bool keep_cache) {
flush_ram_cache(keep_cache);
}
current_sector = NO_SECTOR_LOADED;
#ifdef MICROPY_HW_NEOPIXEL
clear_temp_status();
#endif
clear_temp_status();
#ifdef MICROPY_HW_LED_MSC
port_pin_set_output_level(MICROPY_HW_LED_MSC, false);
#endif

View File

@ -58,7 +58,7 @@ STATIC bool repl_display_debugging_info = 0;
// EXEC_FLAG_PRINT_EOF prints 2 EOF chars: 1 after normal output, 1 after exception output
// EXEC_FLAG_ALLOW_DEBUGGING allows debugging info to be printed after executing the code
// EXEC_FLAG_IS_REPL is used for REPL inputs (flag passed on to mp_compile)
STATIC int parse_compile_execute(void *source, mp_parse_input_kind_t input_kind, int exec_flags) {
STATIC int parse_compile_execute(void *source, mp_parse_input_kind_t input_kind, int exec_flags, pyexec_result_t *result) {
int ret = 0;
uint32_t start = 0;
@ -88,7 +88,7 @@ STATIC int parse_compile_execute(void *source, mp_parse_input_kind_t input_kind,
mp_call_function_0(module_fun);
mp_hal_set_interrupt_char(-1); // disable interrupt
nlr_pop();
ret = 1;
ret = 0;
if (exec_flags & EXEC_FLAG_PRINT_EOF) {
mp_hal_stdout_tx_strn("\x04", 1);
}
@ -108,7 +108,21 @@ STATIC int parse_compile_execute(void *source, mp_parse_input_kind_t input_kind,
ret = PYEXEC_FORCED_EXIT;
} else {
mp_obj_print_exception(&mp_plat_print, (mp_obj_t)nlr.ret_val);
ret = 0;
ret = PYEXEC_EXCEPTION;
}
}
if (result != NULL) {
result->return_code = ret;
if (ret != 0) {
mp_obj_t return_value = (mp_obj_t)nlr.ret_val;
result->exception_type = mp_obj_get_type(return_value);
result->exception_line = -1;
if (mp_obj_is_exception_instance(return_value)) {
size_t n, *values;
mp_obj_exception_get_traceback(return_value, &n, &values);
result->exception_line = values[n - 2];
}
}
}
@ -203,7 +217,7 @@ STATIC int pyexec_raw_repl_process_char(int c) {
if (lex == NULL) {
mp_hal_stdout_tx_str("\x04MemoryError\r\n\x04");
} else {
int ret = parse_compile_execute(lex, MP_PARSE_FILE_INPUT, EXEC_FLAG_PRINT_EOF);
int ret = parse_compile_execute(lex, MP_PARSE_FILE_INPUT, EXEC_FLAG_PRINT_EOF, NULL);
if (ret & PYEXEC_FORCED_EXIT) {
return ret;
}
@ -285,7 +299,7 @@ exec: ;
if (lex == NULL) {
printf("MemoryError\n");
} else {
int ret = parse_compile_execute(lex, MP_PARSE_SINGLE_INPUT, EXEC_FLAG_ALLOW_DEBUGGING | EXEC_FLAG_IS_REPL);
int ret = parse_compile_execute(lex, MP_PARSE_SINGLE_INPUT, EXEC_FLAG_ALLOW_DEBUGGING | EXEC_FLAG_IS_REPL, NULL);
if (ret & PYEXEC_FORCED_EXIT) {
return ret;
}
@ -361,7 +375,7 @@ raw_repl_reset:
if (lex == NULL) {
printf("\x04MemoryError\n\x04");
} else {
int ret = parse_compile_execute(lex, MP_PARSE_FILE_INPUT, EXEC_FLAG_PRINT_EOF);
int ret = parse_compile_execute(lex, MP_PARSE_FILE_INPUT, EXEC_FLAG_PRINT_EOF, NULL);
if (ret & PYEXEC_FORCED_EXIT) {
return ret;
}
@ -380,7 +394,7 @@ int pyexec_friendly_repl(void) {
#endif
friendly_repl_reset:
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("\r\nAdafruit 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");
// to test ctrl-C
@ -487,7 +501,7 @@ friendly_repl_reset:
if (lex == NULL) {
printf("MemoryError\n");
} else {
ret = parse_compile_execute(lex, parse_input_kind, EXEC_FLAG_ALLOW_DEBUGGING | EXEC_FLAG_IS_REPL);
ret = parse_compile_execute(lex, parse_input_kind, EXEC_FLAG_ALLOW_DEBUGGING | EXEC_FLAG_IS_REPL, NULL);
if (ret & PYEXEC_FORCED_EXIT) {
return ret;
}
@ -497,7 +511,7 @@ friendly_repl_reset:
#endif // MICROPY_REPL_EVENT_DRIVEN
int pyexec_file(const char *filename) {
int pyexec_file(const char *filename, pyexec_result_t *exec_result) {
mp_lexer_t *lex = mp_lexer_new_from_file(filename);
if (lex == NULL) {
@ -505,7 +519,7 @@ int pyexec_file(const char *filename) {
return false;
}
return parse_compile_execute(lex, MP_PARSE_FILE_INPUT, 0);
return parse_compile_execute(lex, MP_PARSE_FILE_INPUT, 0, exec_result);
}
#if MICROPY_MODULE_FROZEN
@ -516,12 +530,12 @@ int pyexec_frozen_module(const char *name) {
switch (frozen_type) {
#if MICROPY_MODULE_FROZEN_STR
case MP_FROZEN_STR:
return parse_compile_execute(frozen_data, MP_PARSE_FILE_INPUT, 0);
return parse_compile_execute(frozen_data, MP_PARSE_FILE_INPUT, 0, NULL);
#endif
#if MICROPY_MODULE_FROZEN_MPY
case MP_FROZEN_MPY:
return parse_compile_execute(frozen_data, MP_PARSE_FILE_INPUT, EXEC_FLAG_SOURCE_IS_RAW_CODE);
return parse_compile_execute(frozen_data, MP_PARSE_FILE_INPUT, EXEC_FLAG_SOURCE_IS_RAW_CODE, NULL);
#endif
default:

View File

@ -31,6 +31,12 @@ typedef enum {
PYEXEC_MODE_FRIENDLY_REPL,
} pyexec_mode_kind_t;
typedef struct {
int return_code;
const mp_obj_type_t * exception_type;
int exception_line;
} pyexec_result_t;
extern pyexec_mode_kind_t pyexec_mode_kind;
// Set this to the value (eg PYEXEC_FORCED_EXIT) that will be propagated through
@ -40,10 +46,11 @@ extern int pyexec_system_exit;
#define PYEXEC_FORCED_EXIT (0x100)
#define PYEXEC_SWITCH_MODE (0x200)
#define PYEXEC_EXCEPTION (0x400)
int pyexec_raw_repl(void);
int pyexec_friendly_repl(void);
int pyexec_file(const char *filename);
int pyexec_file(const char *filename, pyexec_result_t *result);
int pyexec_frozen_module(const char *name);
void pyexec_event_repl_init(void);
int pyexec_event_repl_process_char(int c);

View File

@ -38,7 +38,7 @@
void shared_module_bitbangio_spi_construct(bitbangio_spi_obj_t *self,
const mcu_pin_obj_t * clock, const mcu_pin_obj_t * mosi,
const mcu_pin_obj_t * miso, uint32_t baudrate) {
const mcu_pin_obj_t * miso) {
digitalinout_result_t result = common_hal_nativeio_digitalinout_construct(&self->clock, clock);
if (result != DIGITALINOUT_OK) {
nlr_raise(mp_obj_new_exception_msg(&mp_type_ValueError,
@ -81,7 +81,7 @@ void shared_module_bitbangio_spi_deinit(bitbangio_spi_obj_t *self) {
}
void shared_module_bitbangio_spi_configure(bitbangio_spi_obj_t *self,
uint32_t baudrate, uint8_t polarity, uint8_t phase) {
uint32_t baudrate, uint8_t polarity, uint8_t phase, uint8_t bits) {
self->delay_half = 500000 / baudrate;
// round delay_half up so that: actual_baudrate <= requested_baudrate
if (500000 % baudrate != 0) {
@ -148,14 +148,11 @@ bool shared_module_bitbangio_spi_write(bitbangio_spi_obj_t *self, const uint8_t
if (self->phase == 0) {
common_hal_mcu_delay_us(delay_half);
common_hal_nativeio_digitalinout_set_value(&self->clock, 1 - self->polarity);
} else {
common_hal_nativeio_digitalinout_set_value(&self->clock, 1 - self->polarity);
common_hal_mcu_delay_us(delay_half);
}
if (self->phase == 0) {
common_hal_mcu_delay_us(delay_half);
common_hal_nativeio_digitalinout_set_value(&self->clock, self->polarity);
} else {
common_hal_nativeio_digitalinout_set_value(&self->clock, 1 - self->polarity);
common_hal_mcu_delay_us(delay_half);
common_hal_nativeio_digitalinout_set_value(&self->clock, self->polarity);
common_hal_mcu_delay_us(delay_half);
}