Add Initial Support for MicroPython

* Add pre-compiled MicroPython library and headers.
* Change Makefile to link libmp.a remove libusbgeneric
* Change linker script to support MicroPython memory layout.
* Change OTG handle name in stm32f4xx_it.c
* Change main to init libmp and export Python functions.
* Add MicroPython bindings to src
This commit is contained in:
iabdalkader 2014-02-01 21:39:55 +02:00
parent 659ffc73cc
commit a44540f793
27 changed files with 1824 additions and 364 deletions

View File

@ -0,0 +1 @@
mp_obj_t mp_compile(mp_parse_node_t pn, qstr source_file, bool is_repl);

20
include/MicroPython/gc.h Normal file
View File

@ -0,0 +1,20 @@
void gc_init(void *start, void *end);
void gc_collect_start(void);
void gc_collect_root(void **ptrs, machine_uint_t len);
void gc_collect_end(void);
void gc_collect(void);
void *gc_alloc(machine_uint_t n_bytes);
void gc_free(void *ptr);
machine_uint_t gc_nbytes(void *ptr);
void *gc_realloc(void *ptr, machine_uint_t n_bytes);
typedef struct _gc_info_t {
machine_uint_t total;
machine_uint_t used;
machine_uint_t free;
machine_uint_t num_1block;
machine_uint_t num_2block;
machine_uint_t max_block;
} gc_info_t;
void gc_info(gc_info_t *info);

View File

@ -0,0 +1,8 @@
extern uint32_t _ram_start;
extern uint32_t _heap_start;
extern uint32_t _ram_end;
extern uint32_t _heap_end;
void gc_collect(void);
MP_DECLARE_CONST_FUN_OBJ(pyb_gc_obj);

140
include/MicroPython/lexer.h Normal file
View File

@ -0,0 +1,140 @@
/* lexer.h -- simple tokeniser for Micro Python
*
* Uses (byte) length instead of null termination.
* Tokens are the same - UTF-8 with (byte) length.
*/
typedef enum _mp_token_kind_t {
MP_TOKEN_END, // 0
MP_TOKEN_INVALID,
MP_TOKEN_DEDENT_MISMATCH,
MP_TOKEN_LONELY_STRING_OPEN,
MP_TOKEN_BAD_LINE_CONTINUATION,
MP_TOKEN_NEWLINE, // 5
MP_TOKEN_INDENT, // 6
MP_TOKEN_DEDENT, // 7
MP_TOKEN_NAME, // 8
MP_TOKEN_NUMBER,
MP_TOKEN_STRING,
MP_TOKEN_BYTES,
MP_TOKEN_ELLIPSIS,
MP_TOKEN_KW_FALSE, // 13
MP_TOKEN_KW_NONE,
MP_TOKEN_KW_TRUE,
MP_TOKEN_KW_AND,
MP_TOKEN_KW_AS,
MP_TOKEN_KW_ASSERT,
MP_TOKEN_KW_BREAK,
MP_TOKEN_KW_CLASS,
MP_TOKEN_KW_CONTINUE,
MP_TOKEN_KW_DEF, // 22
MP_TOKEN_KW_DEL,
MP_TOKEN_KW_ELIF,
MP_TOKEN_KW_ELSE,
MP_TOKEN_KW_EXCEPT,
MP_TOKEN_KW_FINALLY,
MP_TOKEN_KW_FOR,
MP_TOKEN_KW_FROM,
MP_TOKEN_KW_GLOBAL,
MP_TOKEN_KW_IF,
MP_TOKEN_KW_IMPORT, // 32
MP_TOKEN_KW_IN,
MP_TOKEN_KW_IS,
MP_TOKEN_KW_LAMBDA,
MP_TOKEN_KW_NONLOCAL,
MP_TOKEN_KW_NOT,
MP_TOKEN_KW_OR,
MP_TOKEN_KW_PASS,
MP_TOKEN_KW_RAISE,
MP_TOKEN_KW_RETURN,
MP_TOKEN_KW_TRY, // 42
MP_TOKEN_KW_WHILE,
MP_TOKEN_KW_WITH,
MP_TOKEN_KW_YIELD,
MP_TOKEN_OP_PLUS, // 46
MP_TOKEN_OP_MINUS,
MP_TOKEN_OP_STAR,
MP_TOKEN_OP_DBL_STAR,
MP_TOKEN_OP_SLASH,
MP_TOKEN_OP_DBL_SLASH,
MP_TOKEN_OP_PERCENT,
MP_TOKEN_OP_LESS,
MP_TOKEN_OP_DBL_LESS,
MP_TOKEN_OP_MORE,
MP_TOKEN_OP_DBL_MORE, // 56
MP_TOKEN_OP_AMPERSAND,
MP_TOKEN_OP_PIPE,
MP_TOKEN_OP_CARET,
MP_TOKEN_OP_TILDE,
MP_TOKEN_OP_LESS_EQUAL,
MP_TOKEN_OP_MORE_EQUAL,
MP_TOKEN_OP_DBL_EQUAL,
MP_TOKEN_OP_NOT_EQUAL,
MP_TOKEN_DEL_PAREN_OPEN, // 65
MP_TOKEN_DEL_PAREN_CLOSE,
MP_TOKEN_DEL_BRACKET_OPEN,
MP_TOKEN_DEL_BRACKET_CLOSE,
MP_TOKEN_DEL_BRACE_OPEN,
MP_TOKEN_DEL_BRACE_CLOSE,
MP_TOKEN_DEL_COMMA,
MP_TOKEN_DEL_COLON,
MP_TOKEN_DEL_PERIOD,
MP_TOKEN_DEL_SEMICOLON,
MP_TOKEN_DEL_AT, // 75
MP_TOKEN_DEL_EQUAL,
MP_TOKEN_DEL_PLUS_EQUAL,
MP_TOKEN_DEL_MINUS_EQUAL,
MP_TOKEN_DEL_STAR_EQUAL,
MP_TOKEN_DEL_SLASH_EQUAL,
MP_TOKEN_DEL_DBL_SLASH_EQUAL,
MP_TOKEN_DEL_PERCENT_EQUAL,
MP_TOKEN_DEL_AMPERSAND_EQUAL,
MP_TOKEN_DEL_PIPE_EQUAL,
MP_TOKEN_DEL_CARET_EQUAL, // 85
MP_TOKEN_DEL_DBL_MORE_EQUAL,
MP_TOKEN_DEL_DBL_LESS_EQUAL,
MP_TOKEN_DEL_DBL_STAR_EQUAL,
MP_TOKEN_DEL_MINUS_MORE,
} mp_token_kind_t;
typedef struct _mp_token_t {
uint src_line; // source line
uint src_column; // source column
mp_token_kind_t kind; // kind of token
const char *str; // string of token (valid only while this token is current token)
uint len; // (byte) length of string of token
} mp_token_t;
// the next-char function must return the next character in the stream
// it must return MP_LEXER_CHAR_EOF if end of stream
// it can be called again after returning MP_LEXER_CHAR_EOF, and in that case must return MP_LEXER_CHAR_EOF
#define MP_LEXER_CHAR_EOF (-1)
typedef unichar (*mp_lexer_stream_next_char_t)(void*);
typedef void (*mp_lexer_stream_close_t)(void*);
typedef struct _mp_lexer_t mp_lexer_t;
void mp_token_show(const mp_token_t *tok);
mp_lexer_t *mp_lexer_new(qstr src_name, void *stream_data, mp_lexer_stream_next_char_t stream_next_char, mp_lexer_stream_close_t stream_close);
mp_lexer_t *mp_lexer_new_from_str_len(qstr src_name, const char *str, uint len, uint free_len);
void mp_lexer_free(mp_lexer_t *lex);
qstr mp_lexer_source_name(mp_lexer_t *lex);
void mp_lexer_to_next(mp_lexer_t *lex);
const mp_token_t *mp_lexer_cur(const mp_lexer_t *lex);
bool mp_lexer_is_kind(mp_lexer_t *lex, mp_token_kind_t kind);
bool mp_lexer_show_error_pythonic_prefix(mp_lexer_t *lex);
bool mp_lexer_show_error_pythonic(mp_lexer_t *lex, const char *msg);
// used to import a module; must be implemented for a specific port
mp_lexer_t *mp_import_open_file(qstr mod_name);

View File

@ -0,0 +1 @@
mp_lexer_t *mp_lexer_new_from_file(const char *filename);

View File

@ -0,0 +1,29 @@
#ifndef __LIBMP_H__
#define __LIBMP_H__
#include <stdio.h>
#include <string.h>
#include "std.h"
#include "misc.h"
#include "ff.h"
#include "mpconfig.h"
#include "qstr.h"
#include "nlr.h"
#include "misc.h"
#include "lexer.h"
#include "lexerfatfs.h"
#include "parse.h"
#include "obj.h"
#include "compile.h"
#include "runtime0.h"
#include "runtime.h"
#include "repl.h"
#include "gc.h"
#include "gccollect.h"
#include "storage.h"
#include "usb.h"
#include "systick.h"
int libmp_init();
void libmp_do_repl(void);
bool libmp_do_file(const char *filename);
#endif /* __LIBMP_H__ */

View File

@ -0,0 +1,92 @@
// a mini library of useful types and functions
#ifndef _INCLUDED_MINILIB_H
#define _INCLUDED_MINILIB_H
/** types *******************************************************/
#include <stdbool.h>
typedef unsigned char byte;
typedef unsigned int uint;
/** memomry allocation ******************************************/
// TODO make a lazy m_renew that can increase by a smaller amount than requested (but by at least 1 more element)
#define m_new(type, num) ((type*)(m_malloc(sizeof(type) * (num))))
#define m_new0(type, num) ((type*)(m_malloc0(sizeof(type) * (num))))
#define m_new_obj(type) (m_new(type, 1))
#define m_new_obj_var(obj_type, var_type, var_num) ((obj_type*)m_malloc(sizeof(obj_type) + sizeof(var_type) * (var_num)))
#define m_renew(type, ptr, old_num, new_num) ((type*)(m_realloc((ptr), sizeof(type) * (old_num), sizeof(type) * (new_num))))
#define m_del(type, ptr, num) m_free(ptr, sizeof(type) * (num))
#define m_del_obj(type, ptr) (m_del(type, ptr, 1))
#define m_del_var(obj_type, var_type, var_num, ptr) (m_free(ptr, sizeof(obj_type) + sizeof(var_type) * (var_num)))
void *m_malloc(int num_bytes);
void *m_malloc0(int num_bytes);
void *m_realloc(void *ptr, int old_num_bytes, int new_num_bytes);
void m_free(void *ptr, int num_bytes);
int m_get_total_bytes_allocated(void);
int m_get_current_bytes_allocated(void);
int m_get_peak_bytes_allocated(void);
/** unichar / UTF-8 *********************************************/
typedef int unichar; // TODO
unichar utf8_get_char(const char *s);
char *utf8_next_char(const char *s);
bool unichar_isspace(unichar c);
bool unichar_isalpha(unichar c);
bool unichar_isprint(unichar c);
bool unichar_isdigit(unichar c);
bool unichar_isxdigit(unichar c);
/** string ******************************************************/
/*
#define streq(s1, s2) (strcmp((s1), (s2)) == 0)
*/
long strtonum(const char *restrict s, int base);
/** variable string *********************************************/
typedef struct _vstr_t {
int alloc;
int len;
char *buf;
bool had_error;
} vstr_t;
void vstr_init(vstr_t *vstr, int alloc);
void vstr_clear(vstr_t *vstr);
vstr_t *vstr_new(void);
vstr_t *vstr_new_size(int alloc);
void vstr_free(vstr_t *vstr);
void vstr_reset(vstr_t *vstr);
bool vstr_had_error(vstr_t *vstr);
char *vstr_str(vstr_t *vstr);
int vstr_len(vstr_t *vstr);
void vstr_hint_size(vstr_t *vstr, int size);
char *vstr_extend(vstr_t *vstr, int size);
bool vstr_set_size(vstr_t *vstr, int size);
bool vstr_shrink(vstr_t *vstr);
char *vstr_add_len(vstr_t *vstr, int len);
void vstr_add_byte(vstr_t *vstr, byte v);
void vstr_add_char(vstr_t *vstr, unichar chr);
void vstr_add_str(vstr_t *vstr, const char *str);
void vstr_add_strn(vstr_t *vstr, const char *str, int len);
//void vstr_add_le16(vstr_t *vstr, unsigned short v);
//void vstr_add_le32(vstr_t *vstr, unsigned int v);
void vstr_cut_tail(vstr_t *vstr, int len);
void vstr_printf(vstr_t *vstr, const char *fmt, ...);
#ifdef va_start
void vstr_vprintf(vstr_t *vstr, const char *fmt, va_list ap);
#endif
#endif // _INCLUDED_MINILIB_H

View File

@ -0,0 +1,123 @@
// This file contains default configuration settings for MicroPython.
// You can override any of these options using mpconfigport.h file located
// in a directory of your port.
#include <mpconfigport.h>
// Any options not explicitly set in mpconfigport.h will get default
// values below.
/*****************************************************************************/
/* Micro Python emitters */
// Whether to emit CPython byte codes (for debugging/testing)
// Enabling this overrides all other emitters
#ifndef MICROPY_EMIT_CPYTHON
#define MICROPY_EMIT_CPYTHON (0)
#endif
// Whether to emit x64 native code
#ifndef MICROPY_EMIT_X64
#define MICROPY_EMIT_X64 (0)
#endif
// Whether to emit thumb native code
#ifndef MICROPY_EMIT_THUMB
#define MICROPY_EMIT_THUMB (0)
#endif
// Whether to enable the thumb inline assembler
#ifndef MICROPY_EMIT_INLINE_THUMB
#define MICROPY_EMIT_INLINE_THUMB (0)
#endif
/*****************************************************************************/
/* Internal debugging stuff */
// Whether to collect memory allocation stats
#ifndef MICROPY_MEM_STATS
#define MICROPY_MEM_STATS (0)
#endif
// Whether to build functions that print debugging info:
// mp_byte_code_print
// mp_parse_node_print
#ifndef MICROPY_DEBUG_PRINTERS
#define MICROPY_DEBUG_PRINTERS (0)
#endif
/*****************************************************************************/
/* Fine control over Python features */
// Whether to include the garbage collector
#ifndef MICROPY_ENABLE_GC
#define MICROPY_ENABLE_GC (0)
#endif
// Whether to include REPL helper function
#ifndef MICROPY_ENABLE_REPL_HELPERS
#define MICROPY_ENABLE_REPL_HELPERS (0)
#endif
// Whether to include lexer helper function for unix
#ifndef MICROPY_ENABLE_LEXER_UNIX
#define MICROPY_ENABLE_LEXER_UNIX (0)
#endif
// Long int implementation
#define MICROPY_LONGINT_IMPL_NONE (0)
#define MICROPY_LONGINT_IMPL_LONGLONG (1)
#ifndef MICROPY_LONGINT_IMPL
#define MICROPY_LONGINT_IMPL (MICROPY_LONGINT_IMPL_NONE)
#endif
#if MICROPY_LONGINT_IMPL == MICROPY_LONGINT_IMPL_LONGLONG
typedef long long mp_longint_impl_t;
#endif
// Whether to include information in the byte code to determine source
// line number (increases RAM usage, but doesn't slow byte code execution)
#ifndef MICROPY_ENABLE_SOURCE_LINE
#define MICROPY_ENABLE_SOURCE_LINE (0)
#endif
// Whether to support float and complex types
#ifndef MICROPY_ENABLE_FLOAT
#define MICROPY_ENABLE_FLOAT (0)
#endif
// Whether to support slice object and correspondingly
// slice subscript operators
#ifndef MICROPY_ENABLE_SLICE
#define MICROPY_ENABLE_SLICE (1)
#endif
// Enable features which improve CPython compatibility
// but may lead to more code size/memory usage.
// TODO: Originally intended as generic category to not
// add bunch of once-off options. May need refactoring later
#ifndef MICROPY_CPYTHON_COMPAT
#define MICROPY_CPYTHON_COMPAT (1)
#endif
/*****************************************************************************/
/* Miscellaneous settings */
#define BITS_PER_BYTE (8)
#define BITS_PER_WORD (BITS_PER_BYTE * BYTES_PER_WORD)
// machine_int_t value with most significant bit set
#define WORD_MSBIT_HIGH (((machine_uint_t)1) << (BYTES_PER_WORD * 8 - 1))
// printf format spec to use for machine_int_t and friends
#ifndef INT_FMT
#ifdef __LP64__
// Archs where machine_int_t == long, long != int
#define UINT_FMT "%lu"
#define INT_FMT "%ld"
#else
// Archs where machine_int_t == int
#define UINT_FMT "%u"
#define INT_FMT "%d"
#endif
#endif //INT_FMT

View File

@ -0,0 +1,165 @@
#include <stdint.h>
// options to control how Micro Python is built
#define MICROPY_EMIT_THUMB (1)
#define MICROPY_EMIT_INLINE_THUMB (1)
#define MICROPY_ENABLE_GC (1)
#define MICROPY_ENABLE_REPL_HELPERS (1)
#define MICROPY_ENABLE_FLOAT (1)
// type definitions for the specific machine
#define BYTES_PER_WORD (4)
typedef int32_t machine_int_t; // must be pointer size
typedef uint32_t machine_uint_t; // must be pointer size
typedef void *machine_ptr_t; // must be of pointer size
typedef const void *machine_const_ptr_t; // must be of pointer size
typedef float machine_float_t;
machine_float_t machine_sqrt(machine_float_t x);
// board specific definitions
// choose 1 of these boards
//#define PYBOARD3
//#define PYBOARD4
#define STM32F4DISC
#if defined (PYBOARD3)
#define MICROPY_HW_BOARD_NAME "PYBv3"
#define MICROPY_HW_HAS_SWITCH (1)
#define MICROPY_HW_HAS_SDCARD (1)
#define MICROPY_HW_HAS_MMA7660 (1)
#define MICROPY_HW_HAS_LIS3DSH (0)
#define MICROPY_HW_HAS_LCD (0)
#define MICROPY_HW_HAS_WLAN (0)
#define MICROPY_HW_ENABLE_RNG (1)
#define MICROPY_HW_ENABLE_RTC (1)
#define MICROPY_HW_ENABLE_TIMER (1)
#define MICROPY_HW_ENABLE_SERVO (1)
#define MICROPY_HW_ENABLE_AUDIO (0)
#define USRSW_PORT (GPIOA)
#define USRSW_PIN (GPIO_Pin_13)
#define USRSW_PUPD (GPIO_PuPd_UP)
#define USRSW_EXTI_PIN (EXTI_PinSource13)
#define USRSW_EXTI_PORT (EXTI_PortSourceGPIOA)
#define USRSW_EXTI_LINE (EXTI_Line13)
#define USRSW_EXTI_IRQN (EXTI15_10_IRQn)
#define USRSW_EXTI_EDGE (EXTI_Trigger_Rising)
/* LED */
#define PYB_LED1_PORT (GPIOA)
#define PYB_LED1_PIN (GPIO_Pin_8)
#define PYB_LED2_PORT (GPIOA)
#define PYB_LED2_PIN (GPIO_Pin_10)
#define PYB_LED3_PORT (GPIOC)
#define PYB_LED3_PIN (GPIO_Pin_4)
#define PYB_LED4_PORT (GPIOC)
#define PYB_LED4_PIN (GPIO_Pin_5)
#define PYB_OTYPE (GPIO_OType_OD)
#define PYB_LED_ON(port, pin) (port->BSRRH = pin)
#define PYB_LED_OFF(port, pin) (port->BSRRL = pin)
#elif defined (PYBOARD4)
#define MICROPY_HW_BOARD_NAME "PYBv4"
#define MICROPY_HW_HAS_SWITCH (1)
#define MICROPY_HW_HAS_SDCARD (1)
#define MICROPY_HW_HAS_MMA7660 (1)
#define MICROPY_HW_HAS_LIS3DSH (0)
#define MICROPY_HW_HAS_LCD (1)
#define MICROPY_HW_HAS_WLAN (0)
#define MICROPY_HW_ENABLE_RNG (1)
#define MICROPY_HW_ENABLE_RTC (1)
#define MICROPY_HW_ENABLE_TIMER (1)
#define MICROPY_HW_ENABLE_SERVO (1)
#define MICROPY_HW_ENABLE_AUDIO (0)
#define USRSW_PORT (GPIOB)
#define USRSW_PIN (GPIO_Pin_3)
#define USRSW_PUPD (GPIO_PuPd_UP)
#define USRSW_EXTI_PIN (EXTI_PinSource3)
#define USRSW_EXTI_PORT (EXTI_PortSourceGPIOB)
#define USRSW_EXTI_LINE (EXTI_Line3)
#define USRSW_EXTI_IRQN (EXTI15_10_IRQn)
#define USRSW_EXTI_EDGE (EXTI_Trigger_Rising)
/* LED */
#define PYB_LED1_PORT (GPIOA)
#define PYB_LED1_PIN (GPIO_Pin_13)
#define PYB_LED2_PORT (GPIOA)
#define PYB_LED2_PIN (GPIO_Pin_14)
#define PYB_LED3_PORT (GPIOA)
#define PYB_LED3_PIN (GPIO_Pin_15)
#define PYB_LED4_PORT (GPIOB)
#define PYB_LED4_PIN (GPIO_Pin_4)
#define PYB_OTYPE (GPIO_OType_PP)
#define PYB_LED_ON(port, pin) (port->BSRRL = pin)
#define PYB_LED_OFF(port, pin) (port->BSRRH = pin)
#elif defined (STM32F4DISC)
#define MICROPY_HW_BOARD_NAME "F4DISC"
#define MICROPY_HW_HAS_SWITCH (0)
#define MICROPY_HW_HAS_SDCARD (0)
#define MICROPY_HW_HAS_MMA7660 (0)
#define MICROPY_HW_HAS_LIS3DSH (0)
#define MICROPY_HW_HAS_LCD (0)
#define MICROPY_HW_HAS_WLAN (0)
#define MICROPY_HW_ENABLE_RNG (0)
#define MICROPY_HW_ENABLE_RTC (0)
#define MICROPY_HW_ENABLE_TIMER (0)
#define MICROPY_HW_ENABLE_SERVO (0)
#define MICROPY_HW_ENABLE_AUDIO (0)
#define USRSW_PORT (GPIOA)
#define USRSW_PIN (GPIO_Pin_0)
#define USRSW_PUPD (GPIO_PuPd_NOPULL)
#define USRSW_EXTI_PIN (EXTI_PinSource0)
#define USRSW_EXTI_PORT (EXTI_PortSourceGPIOA)
#define USRSW_EXTI_LINE (EXTI_Line0)
#define USRSW_EXTI_IRQN (EXTI0_IRQn)
#define USRSW_EXTI_EDGE (EXTI_Trigger_Falling)
/* LED */
#define PYB_LED1_PORT (GPIOD)
#define PYB_LED1_PIN (GPIO_Pin_14)
#define PYB_LED2_PORT (GPIOD)
#define PYB_LED2_PIN (GPIO_Pin_12)
#define PYB_LED3_PORT (GPIOD)
#define PYB_LED3_PIN (GPIO_Pin_15)
#define PYB_LED4_PORT (GPIOD)
#define PYB_LED4_PIN (GPIO_Pin_13)
#define PYB_OTYPE (GPIO_OType_PP)
#define PYB_LED_ON(port, pin) (port->BSRRL = pin)
#define PYB_LED_OFF(port, pin) (port->BSRRH = pin)
#endif
//#define STM32F40_41xxx
//#define USE_STDPERIPH_DRIVER
//#define HSE_VALUE (8000000)
#define USE_DEVICE_MODE
//#define USE_HOST_MODE
#define sys_tick_counter systick_current_millis()
#define sys_tick_has_passed systick_has_passed

28
include/MicroPython/nlr.h Normal file
View File

@ -0,0 +1,28 @@
// non-local return
// exception handling, basically a stack of setjmp/longjmp buffers
#include <limits.h>
//#ifndef __WORDSIZE
//#error __WORDSIZE needs to be defined
//#endif
typedef struct _nlr_buf_t nlr_buf_t;
struct _nlr_buf_t {
// the entries here must all be machine word size
nlr_buf_t *prev;
void *ret_val;
#if __WORDSIZE == 32
void *regs[6];
#elif __WORDSIZE == 64
void *regs[8];
#else
// hack for thumb
void *regs[10];
//#error Unsupported __WORDSIZE
#endif
};
unsigned int nlr_push(nlr_buf_t *);
void nlr_pop(void);
void nlr_jump(void *val) __attribute__((noreturn));

397
include/MicroPython/obj.h Normal file
View File

@ -0,0 +1,397 @@
// All Micro Python objects are at least this type
// It must be of pointer size
typedef machine_ptr_t mp_obj_t;
typedef machine_const_ptr_t mp_const_obj_t;
// Integers that fit in a pointer have this type
// (do we need to expose this in the public API?)
typedef machine_int_t mp_small_int_t;
// The machine floating-point type used for float and complex numbers
#if MICROPY_ENABLE_FLOAT
typedef machine_float_t mp_float_t;
#endif
// Anything that wants to be a Micro Python object must have
// mp_obj_base_t as its first member (except NULL and small ints)
struct _mp_obj_type_t;
struct _mp_obj_base_t {
const struct _mp_obj_type_t *type;
};
typedef struct _mp_obj_base_t mp_obj_base_t;
// The NULL object is used to indicate the absence of an object
// It *cannot* be used when an mp_obj_t is expected, except where explicitly allowed
#define MP_OBJ_NULL ((mp_obj_t)NULL)
// These macros check for small int, qstr or object, and access small int and qstr values
// - xxxx...xxx1: a small int, bits 1 and above are the value
// - xxxx...xx10: a qstr, bits 2 and above are the value
// - xxxx...xx00: a pointer to an mp_obj_base_t
// In SMALL_INT, next-to-highest bits is used as sign, so both must match for value in range
#define MP_OBJ_FITS_SMALL_INT(n) ((((n) ^ ((n) << 1)) & WORD_MSBIT_HIGH) == 0)
#define MP_OBJ_IS_SMALL_INT(o) ((((mp_small_int_t)(o)) & 1) != 0)
#define MP_OBJ_IS_QSTR(o) ((((mp_small_int_t)(o)) & 3) == 2)
#define MP_OBJ_IS_OBJ(o) ((((mp_small_int_t)(o)) & 3) == 0)
#define MP_OBJ_IS_TYPE(o, t) (MP_OBJ_IS_OBJ(o) && (((mp_obj_base_t*)(o))->type == (t))) // this does not work for checking a string, use below macro for that
#define MP_OBJ_IS_INT(o) (MP_OBJ_IS_SMALL_INT(o) || MP_OBJ_IS_TYPE(o, &int_type))
#define MP_OBJ_IS_STR(o) (MP_OBJ_IS_QSTR(o) || MP_OBJ_IS_TYPE(o, &str_type))
#define MP_OBJ_SMALL_INT_VALUE(o) (((mp_small_int_t)(o)) >> 1)
#define MP_OBJ_NEW_SMALL_INT(small_int) ((mp_obj_t)(((small_int) << 1) | 1))
#define MP_OBJ_QSTR_VALUE(o) (((mp_small_int_t)(o)) >> 2)
#define MP_OBJ_NEW_QSTR(qstr) ((mp_obj_t)((((machine_uint_t)qstr) << 2) | 2))
// These macros are used to declare and define constant function objects
// You can put "static" in front of the definitions to make them local
#define MP_DECLARE_CONST_FUN_OBJ(obj_name) extern const mp_obj_fun_native_t obj_name
#define MP_DEFINE_CONST_FUN_OBJ_VOID_PTR(obj_name, is_kw, n_args_min, n_args_max, fun_name) const mp_obj_fun_native_t obj_name = {{&fun_native_type}, is_kw, n_args_min, n_args_max, (void *)fun_name}
#define MP_DEFINE_CONST_FUN_OBJ_0(obj_name, fun_name) MP_DEFINE_CONST_FUN_OBJ_VOID_PTR(obj_name, false, 0, 0, (mp_fun_0_t)fun_name)
#define MP_DEFINE_CONST_FUN_OBJ_1(obj_name, fun_name) MP_DEFINE_CONST_FUN_OBJ_VOID_PTR(obj_name, false, 1, 1, (mp_fun_1_t)fun_name)
#define MP_DEFINE_CONST_FUN_OBJ_2(obj_name, fun_name) MP_DEFINE_CONST_FUN_OBJ_VOID_PTR(obj_name, false, 2, 2, (mp_fun_2_t)fun_name)
#define MP_DEFINE_CONST_FUN_OBJ_3(obj_name, fun_name) MP_DEFINE_CONST_FUN_OBJ_VOID_PTR(obj_name, false, 3, 3, (mp_fun_3_t)fun_name)
#define MP_DEFINE_CONST_FUN_OBJ_VAR(obj_name, n_args_min, fun_name) MP_DEFINE_CONST_FUN_OBJ_VOID_PTR(obj_name, false, n_args_min, (~((machine_uint_t)0)), (mp_fun_var_t)fun_name)
#define MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(obj_name, n_args_min, n_args_max, fun_name) MP_DEFINE_CONST_FUN_OBJ_VOID_PTR(obj_name, false, n_args_min, n_args_max, (mp_fun_var_t)fun_name)
#define MP_DEFINE_CONST_FUN_OBJ_KW(obj_name, n_args_min, fun_name) MP_DEFINE_CONST_FUN_OBJ_VOID_PTR(obj_name, true, n_args_min, (~((machine_uint_t)0)), (mp_fun_kw_t)fun_name)
// These macros are used to declare and define constant staticmethond and classmethod objects
// You can put "static" in front of the definitions to make them local
#define MP_DECLARE_CONST_STATICMETHOD_OBJ(obj_name) extern const mp_obj_staticmethod_t obj_name
#define MP_DECLARE_CONST_CLASSMETHOD_OBJ(obj_name) extern const mp_obj_classmethod_t obj_name
#define MP_DEFINE_CONST_STATICMETHOD_OBJ(obj_name, fun_name) const mp_obj_staticmethod_t obj_name = {{&mp_type_staticmethod}, fun_name}
#define MP_DEFINE_CONST_CLASSMETHOD_OBJ(obj_name, fun_name) const mp_obj_classmethod_t obj_name = {{&mp_type_classmethod}, fun_name}
// Need to declare this here so we are not dependent on map.h
struct _mp_map_t;
struct _mp_map_elem_t;
enum _mp_map_lookup_kind_t;
// Type definitions for methods
typedef mp_obj_t (*mp_fun_0_t)(void);
typedef mp_obj_t (*mp_fun_1_t)(mp_obj_t);
typedef mp_obj_t (*mp_fun_2_t)(mp_obj_t, mp_obj_t);
typedef mp_obj_t (*mp_fun_3_t)(mp_obj_t, mp_obj_t, mp_obj_t);
typedef mp_obj_t (*mp_fun_t)(void);
typedef mp_obj_t (*mp_fun_var_t)(uint n, const mp_obj_t *);
typedef mp_obj_t (*mp_fun_kw_t)(uint n, const mp_obj_t *, struct _mp_map_t *);
typedef enum {
PRINT_STR, PRINT_REPR
} mp_print_kind_t;
typedef void (*mp_print_fun_t)(void (*print)(void *env, const char *fmt, ...), void *env, mp_obj_t o, mp_print_kind_t kind);
typedef mp_obj_t (*mp_make_new_fun_t)(mp_obj_t type_in, uint n_args, uint n_kw, const mp_obj_t *args);
typedef mp_obj_t (*mp_call_fun_t)(mp_obj_t fun, uint n_args, uint n_kw, const mp_obj_t *args);
typedef mp_obj_t (*mp_unary_op_fun_t)(int op, mp_obj_t);
typedef mp_obj_t (*mp_binary_op_fun_t)(int op, mp_obj_t, mp_obj_t);
typedef void (*mp_load_attr_fun_t)(mp_obj_t self_in, qstr attr, mp_obj_t *dest); // for fail, do nothing; for attr, dest[0] = value; for method, dest[0] = method, dest[1] = self
typedef bool (*mp_store_attr_fun_t)(mp_obj_t self_in, qstr attr, mp_obj_t value); // return true if store succeeded
typedef bool (*mp_store_item_fun_t)(mp_obj_t self_in, mp_obj_t index, mp_obj_t value); // return true if store succeeded
typedef struct _mp_method_t {
const char *name;
mp_const_obj_t fun;
} mp_method_t;
// Buffer protocol
typedef struct _buffer_info_t {
// if we'd bother to support various versions of structure
// (with different number of fields), we can distinguish
// them with ver = sizeof(struct). Cons: overkill for *micro*?
//int ver; // ?
void *buf;
machine_int_t len;
// Rationale: have array.array and have SIMD operations on them
// Cons: users can pass item size to processing functions themselves,
// though that's not "plug&play"
// int itemsize;
// Rationale: to load arbitrary-sized sprites directly to LCD
// Cons: a bit adhoc usecase
// int stride;
} buffer_info_t;
#define BUFFER_READ (1)
#define BUFFER_WRITE (2)
#define BUFFER_RW (BUFFER_READ | BUFFER_WRITE)
typedef struct _mp_buffer_p_t {
machine_int_t (*get_buffer)(mp_obj_t obj, buffer_info_t *bufinfo, int flags);
} mp_buffer_p_t;
// Stream protocol
typedef struct _mp_stream_p_t {
// On error, functions should return -1 and fill in *errcode (values are
// implementation-dependent, but will be exposed to user, e.g. via exception).
machine_int_t (*read)(mp_obj_t obj, void *buf, machine_uint_t size, int *errcode);
machine_int_t (*write)(mp_obj_t obj, const void *buf, machine_uint_t size, int *errcode);
// add seek() ?
} mp_stream_p_t;
struct _mp_obj_type_t {
mp_obj_base_t base;
const char *name;
mp_print_fun_t print;
mp_make_new_fun_t make_new; // to make an instance of the type
mp_call_fun_t call;
mp_unary_op_fun_t unary_op; // can return NULL if op not supported
mp_binary_op_fun_t binary_op; // can return NULL if op not supported
mp_fun_1_t getiter;
mp_fun_1_t iternext;
// Alternatively, pointer(s) to interfaces to save space
// in mp_obj_type_t at the expense of extra pointer and extra dereference
// when actually used.
mp_buffer_p_t buffer_p;
mp_stream_p_t stream_p;
const mp_method_t *methods;
mp_load_attr_fun_t load_attr;
mp_store_attr_fun_t store_attr;
// Implements container[index] = val; note that load_item is implemented
// by binary_op(RT_BINARY_OP_SUBSCR)
mp_store_item_fun_t store_item;
// these are for dynamically created types (classes)
mp_obj_t bases_tuple;
mp_obj_t locals_dict;
/*
What we might need to add here:
store_subscr list dict
len str tuple list map
abs float complex
hash bool int none str
equal int str
less int
get_array_n tuple list
unpack seq list tuple
*/
};
typedef struct _mp_obj_type_t mp_obj_type_t;
// Constant objects, globally accessible
extern const mp_obj_type_t mp_const_type;
extern const mp_obj_t mp_const_none;
extern const mp_obj_t mp_const_false;
extern const mp_obj_t mp_const_true;
extern const mp_obj_t mp_const_empty_tuple;
extern const mp_obj_t mp_const_ellipsis;
extern const mp_obj_t mp_const_stop_iteration; // special object indicating end of iteration (not StopIteration exception!)
// General API for objects
mp_obj_t mp_obj_new_type(const char *name, mp_obj_t bases_tuple, mp_obj_t locals_dict);
mp_obj_t mp_obj_new_none(void);
mp_obj_t mp_obj_new_bool(bool value);
mp_obj_t mp_obj_new_cell(mp_obj_t obj);
mp_obj_t mp_obj_new_int(machine_int_t value);
mp_obj_t mp_obj_new_int_from_uint(machine_uint_t value);
mp_obj_t mp_obj_new_int_from_long_str(const char *s);
mp_obj_t mp_obj_new_str(const byte* data, uint len, bool make_qstr_if_not_already);
mp_obj_t mp_obj_new_bytes(const byte* data, uint len);
#if MICROPY_ENABLE_FLOAT
mp_obj_t mp_obj_new_float(mp_float_t val);
mp_obj_t mp_obj_new_complex(mp_float_t real, mp_float_t imag);
#endif
mp_obj_t mp_obj_new_exception(qstr id);
mp_obj_t mp_obj_new_exception_msg(qstr id, const char *msg);
mp_obj_t mp_obj_new_exception_msg_1_arg(qstr id, const char *fmt, const char *a1);
mp_obj_t mp_obj_new_exception_msg_2_args(qstr id, const char *fmt, const char *a1, const char *a2);
mp_obj_t mp_obj_new_exception_msg_varg(qstr id, const char *fmt, ...); // counts args by number of % symbols in fmt, excluding %%; can only handle void* sizes (ie no float/double!)
mp_obj_t mp_obj_new_range(int start, int stop, int step);
mp_obj_t mp_obj_new_range_iterator(int cur, int stop, int step);
mp_obj_t mp_obj_new_fun_bc(int n_args, uint n_state, const byte *code);
mp_obj_t mp_obj_new_fun_asm(uint n_args, void *fun);
mp_obj_t mp_obj_new_gen_wrap(mp_obj_t fun);
mp_obj_t mp_obj_new_gen_instance(const byte *bytecode, uint n_state, int n_args, const mp_obj_t *args);
mp_obj_t mp_obj_new_closure(mp_obj_t fun, mp_obj_t closure_tuple);
mp_obj_t mp_obj_new_tuple(uint n, const mp_obj_t *items);
mp_obj_t mp_obj_new_list(uint n, mp_obj_t *items);
mp_obj_t mp_obj_new_dict(int n_args);
mp_obj_t mp_obj_new_set(int n_args, mp_obj_t *items);
mp_obj_t mp_obj_new_slice(mp_obj_t start, mp_obj_t stop, mp_obj_t step);
mp_obj_t mp_obj_new_bound_meth(mp_obj_t meth, mp_obj_t self);
mp_obj_t mp_obj_new_getitem_iter(mp_obj_t *args);
mp_obj_t mp_obj_new_module(qstr module_name);
mp_obj_type_t *mp_obj_get_type(mp_obj_t o_in);
const char *mp_obj_get_type_str(mp_obj_t o_in);
void mp_obj_print_helper(void (*print)(void *env, const char *fmt, ...), void *env, mp_obj_t o_in, mp_print_kind_t kind);
void mp_obj_print(mp_obj_t o, mp_print_kind_t kind);
void mp_obj_print_exception(mp_obj_t exc);
bool mp_obj_is_callable(mp_obj_t o_in);
machine_int_t mp_obj_hash(mp_obj_t o_in);
bool mp_obj_equal(mp_obj_t o1, mp_obj_t o2);
bool mp_obj_less(mp_obj_t o1, mp_obj_t o2);
machine_int_t mp_obj_get_int(mp_obj_t arg);
#if MICROPY_ENABLE_FLOAT
mp_float_t mp_obj_get_float(mp_obj_t self_in);
void mp_obj_get_complex(mp_obj_t self_in, mp_float_t *real, mp_float_t *imag);
#endif
//qstr mp_obj_get_qstr(mp_obj_t arg);
mp_obj_t *mp_obj_get_array_fixed_n(mp_obj_t o, machine_int_t n);
uint mp_get_index(const mp_obj_type_t *type, machine_uint_t len, mp_obj_t index);
mp_obj_t mp_obj_len_maybe(mp_obj_t o_in); /* may return NULL */
// none
extern const mp_obj_type_t none_type;
// bool
extern const mp_obj_type_t bool_type;
#define MP_BOOL(x) (x ? mp_const_true : mp_const_false)
// cell
mp_obj_t mp_obj_cell_get(mp_obj_t self_in);
void mp_obj_cell_set(mp_obj_t self_in, mp_obj_t obj);
// int
extern const mp_obj_type_t int_type;
// For long int, returns value truncated to machine_int_t
machine_int_t mp_obj_int_get(mp_obj_t self_in);
// Will rains exception if value doesn't fit into machine_int_t
machine_int_t mp_obj_int_get_checked(mp_obj_t self_in);
// exception
extern const mp_obj_type_t exception_type;
qstr mp_obj_exception_get_type(mp_obj_t self_in);
void mp_obj_exception_add_traceback(mp_obj_t self_in, qstr file, machine_uint_t line, qstr block);
void mp_obj_exception_get_traceback(mp_obj_t self_in, machine_uint_t *n, machine_uint_t **values);
// str
extern const mp_obj_type_t str_type;
mp_obj_t mp_obj_str_builder_start(const mp_obj_type_t *type, uint len, byte **data);
mp_obj_t mp_obj_str_builder_end(mp_obj_t o_in);
bool mp_obj_str_equal(mp_obj_t s1, mp_obj_t s2);
uint mp_obj_str_get_hash(mp_obj_t self_in);
uint mp_obj_str_get_len(mp_obj_t self_in);
qstr mp_obj_str_get_qstr(mp_obj_t self_in); // use this if you will anyway convert the string to a qstr
const char *mp_obj_str_get_str(mp_obj_t self_in); // use this only if you need the string to be null terminated
const byte *mp_obj_str_get_data(mp_obj_t self_in, uint *len);
void mp_str_print_quoted(void (*print)(void *env, const char *fmt, ...), void *env, const byte *str_data, uint str_len);
// bytes
extern const mp_obj_type_t bytes_type;
#if MICROPY_ENABLE_FLOAT
// float
extern const mp_obj_type_t float_type;
mp_float_t mp_obj_float_get(mp_obj_t self_in);
mp_obj_t mp_obj_float_binary_op(int op, mp_float_t lhs_val, mp_obj_t rhs);
// complex
extern const mp_obj_type_t complex_type;
void mp_obj_complex_get(mp_obj_t self_in, mp_float_t *real, mp_float_t *imag);
mp_obj_t mp_obj_complex_binary_op(int op, mp_float_t lhs_real, mp_float_t lhs_imag, mp_obj_t rhs_in);
#endif
// tuple
extern const mp_obj_type_t tuple_type;
void mp_obj_tuple_get(mp_obj_t self_in, uint *len, mp_obj_t **items);
void mp_obj_tuple_del(mp_obj_t self_in);
// list
extern const mp_obj_type_t list_type;
mp_obj_t mp_obj_list_append(mp_obj_t self_in, mp_obj_t arg);
void mp_obj_list_get(mp_obj_t self_in, uint *len, mp_obj_t **items);
void mp_obj_list_store(mp_obj_t self_in, mp_obj_t index, mp_obj_t value);
mp_obj_t mp_obj_list_sort(uint n_args, const mp_obj_t *args, struct _mp_map_t *kwargs);
// map (the python builtin, not the dict implementation detail)
extern const mp_obj_type_t map_type;
// enumerate
extern const mp_obj_type_t enumerate_type;
// filter
extern const mp_obj_type_t filter_type;
// dict
extern const mp_obj_type_t dict_type;
uint mp_obj_dict_len(mp_obj_t self_in);
mp_obj_t mp_obj_dict_store(mp_obj_t self_in, mp_obj_t key, mp_obj_t value);
struct _mp_map_t *mp_obj_dict_get_map(mp_obj_t self_in);
// set
extern const mp_obj_type_t set_type;
void mp_obj_set_store(mp_obj_t self_in, mp_obj_t item);
// slice
extern const mp_obj_type_t slice_type;
void mp_obj_slice_get(mp_obj_t self_in, machine_int_t *start, machine_int_t *stop, machine_int_t *step);
// zip
extern const mp_obj_type_t zip_type;
// array
extern const mp_obj_type_t array_type;
uint mp_obj_array_len(mp_obj_t self_in);
mp_obj_t mp_obj_new_bytearray_by_ref(uint n, void *items);
// functions
typedef struct _mp_obj_fun_native_t { // need this so we can define const objects (to go in ROM)
mp_obj_base_t base;
bool is_kw : 1;
machine_uint_t n_args_min : (sizeof(machine_uint_t) - 1); // inclusive
machine_uint_t n_args_max; // inclusive
void *fun;
// TODO add mp_map_t *globals
// for const function objects, make an empty, const map
// such functions won't be able to access the global scope, but that's probably okay
} mp_obj_fun_native_t;
extern const mp_obj_type_t fun_native_type;
extern const mp_obj_type_t fun_bc_type;
void mp_obj_fun_bc_get(mp_obj_t self_in, int *n_args, uint *n_state, const byte **code);
mp_obj_t mp_identity(mp_obj_t self);
// generator
extern const mp_obj_type_t gen_instance_type;
// module
extern const mp_obj_type_t module_type;
mp_obj_t mp_obj_new_module(qstr module_name);
mp_obj_t mp_obj_module_get(qstr module_name);
struct _mp_map_t *mp_obj_module_get_globals(mp_obj_t self_in);
// staticmethod and classmethod types; defined here so we can make const versions
extern const mp_obj_type_t mp_type_staticmethod;
extern const mp_obj_type_t mp_type_classmethod;
typedef struct _mp_obj_staticmethod_t {
mp_obj_base_t base;
mp_obj_t fun;
} mp_obj_staticmethod_t;
typedef struct _mp_obj_classmethod_t {
mp_obj_base_t base;
mp_obj_t fun;
} mp_obj_classmethod_t;
// sequence helpers
void mp_seq_multiply(const void *items, uint item_sz, uint len, uint times, void *dest);

View File

@ -0,0 +1,67 @@
struct _mp_lexer_t;
// a mp_parse_node_t is:
// - 0000...0000: no node
// - xxxx...0001: an identifier; bits 4 and above are the qstr
// - xxxx...0011: a small integer; bits 4 and above are the signed value, 2's complement
// - xxxx...0101: an integer; bits 4 and above are the qstr holding the value
// - xxxx...0111: a decimal; bits 4 and above are the qstr holding the value
// - xxxx...1001: a string; bits 4 and above are the qstr holding the value
// - xxxx...1011: a string with triple quotes; bits 4 and above are the qstr holding the value
// - xxxx...1101: a token; bits 4 and above are mp_token_kind_t
// - xxxx...xxx0: pointer to mp_parse_node_struct_t
// makes sure the top 5 bits of x are all cleared (positive number) or all set (negavite number)
// these macros can probably go somewhere else because they are used more than just in the parser
#define MP_UINT_HIGH_5_BITS (~((~((machine_uint_t)0)) >> 5))
#define MP_FIT_SMALL_INT(x) (((((machine_uint_t)(x)) & MP_UINT_HIGH_5_BITS) == 0) || ((((machine_uint_t)(x)) & MP_UINT_HIGH_5_BITS) == MP_UINT_HIGH_5_BITS))
#define MP_PARSE_NODE_NULL (0)
#define MP_PARSE_NODE_ID (0x1)
#define MP_PARSE_NODE_SMALL_INT (0x3)
#define MP_PARSE_NODE_INTEGER (0x5)
#define MP_PARSE_NODE_DECIMAL (0x7)
#define MP_PARSE_NODE_STRING (0x9)
#define MP_PARSE_NODE_BYTES (0xb)
#define MP_PARSE_NODE_TOKEN (0xd)
typedef machine_uint_t mp_parse_node_t; // must be pointer size
typedef struct _mp_parse_node_struct_t {
uint32_t source_line; // line number in source file
uint32_t kind_num_nodes; // parse node kind, and number of nodes
mp_parse_node_t nodes[]; // nodes
} mp_parse_node_struct_t;
// macros for mp_parse_node_t usage
// some of these evaluate their argument more than once
#define MP_PARSE_NODE_IS_NULL(pn) ((pn) == MP_PARSE_NODE_NULL)
#define MP_PARSE_NODE_IS_LEAF(pn) ((pn) & 1)
#define MP_PARSE_NODE_IS_STRUCT(pn) ((pn) != MP_PARSE_NODE_NULL && ((pn) & 1) == 0)
#define MP_PARSE_NODE_IS_STRUCT_KIND(pn, k) ((pn) != MP_PARSE_NODE_NULL && ((pn) & 1) == 0 && MP_PARSE_NODE_STRUCT_KIND((mp_parse_node_struct_t*)(pn)) == (k))
#define MP_PARSE_NODE_IS_ID(pn) (((pn) & 0xf) == MP_PARSE_NODE_ID)
#define MP_PARSE_NODE_IS_SMALL_INT(pn) (((pn) & 0xf) == MP_PARSE_NODE_SMALL_INT)
#define MP_PARSE_NODE_IS_TOKEN(pn) (((pn) & 0xf) == MP_PARSE_NODE_TOKEN)
#define MP_PARSE_NODE_IS_TOKEN_KIND(pn, k) ((pn) == (MP_PARSE_NODE_TOKEN | (k << 4)))
#define MP_PARSE_NODE_LEAF_KIND(pn) ((pn) & 0xf)
// TODO should probably have int and uint versions of this macro
#define MP_PARSE_NODE_LEAF_ARG(pn) (((machine_int_t)(pn)) >> 4)
#define MP_PARSE_NODE_STRUCT_KIND(pns) ((pns)->kind_num_nodes & 0xff)
#define MP_PARSE_NODE_STRUCT_NUM_NODES(pns) ((pns)->kind_num_nodes >> 8)
mp_parse_node_t mp_parse_node_new_leaf(machine_int_t kind, machine_int_t arg);
uint mp_parse_node_free(mp_parse_node_t pn);
void mp_parse_node_print(mp_parse_node_t pn, int indent);
typedef enum {
MP_PARSE_SINGLE_INPUT,
MP_PARSE_FILE_INPUT,
MP_PARSE_EVAL_INPUT,
} mp_parse_input_kind_t;
// returns MP_PARSE_NODE_NULL on error, and then exc_id_out and exc_msg_out are valid
mp_parse_node_t mp_parse(struct _mp_lexer_t *lex, mp_parse_input_kind_t input_kind, qstr *exc_id_out, const char **exc_msg_out);

View File

@ -0,0 +1,40 @@
// See qstrraw.h for a list of qstr's that are available as constants.
// Reference them as MP_QSTR_xxxx.
//
// Note: it would be possible to define MP_QSTR_xxx as qstr_from_str_static("xxx")
// for qstrs that are referenced this way, but you don't want to have them in ROM.
enum {
MP_QSTR_NULL = 0, // indicates invalid/no qstr
MP_QSTR_ = 1, // the empty qstr
#define Q(id, str) MP_QSTR_##id,
// TODO having 'build/py.' here is a bit of a hack, should take config variable from Makefile
#include "qstrdefs.generated.h"
#undef Q
MP_QSTR_number_of,
} category_t;
typedef machine_uint_t qstr;
#define QSTR_FROM_STR_STATIC(s) (qstr_from_strn((s), strlen(s)))
void qstr_init(void);
machine_uint_t qstr_compute_hash(const byte *data, uint len);
qstr qstr_find_strn(const byte *str, uint str_len); // returns MP_QSTR_NULL if not found
qstr qstr_from_str(const char *str);
qstr qstr_from_strn(const char *str, uint len);
//qstr qstr_from_str_static(const char *str);
qstr qstr_from_strn_take(char *str, uint alloc_len, uint len);
//qstr qstr_from_strn_copy(const char *str, int len);
byte* qstr_build_start(uint len, byte **q_ptr);
qstr qstr_build_end(byte *q_ptr);
machine_uint_t qstr_hash(qstr q);
const char* qstr_str(qstr q);
uint qstr_len(qstr q);
const byte* qstr_data(qstr q, uint *len);
void qstr_pool_info(uint *n_pool, uint *n_qstr, uint *n_str_data_bytes, uint *n_total_bytes);

View File

@ -0,0 +1,108 @@
// This file was automatically generated by makeqstrdata.py
Q(__build_class__, (const byte*)"\x01\x06\x0f\x00" "__build_class__")
Q(__class__, (const byte*)"\x92\x03\x09\x00" "__class__")
Q(__doc__, (const byte*)"\xb2\x02\x07\x00" "__doc__")
Q(__init__, (const byte*)"\x30\x03\x08\x00" "__init__")
Q(__locals__, (const byte*)"\xfa\x03\x0a\x00" "__locals__")
Q(__main__, (const byte*)"\x21\x03\x08\x00" "__main__")
Q(__module__, (const byte*)"\x02\x04\x0a\x00" "__module__")
Q(__name__, (const byte*)"\x1d\x03\x08\x00" "__name__")
Q(__next__, (const byte*)"\x3b\x03\x08\x00" "__next__")
Q(__qualname__, (const byte*)"\xd0\x04\x0c\x00" "__qualname__")
Q(__repl_print__, (const byte*)"\xbb\x05\x0e\x00" "__repl_print__")
Q(__bool__, (const byte*)"\x28\x03\x08\x00" "__bool__")
Q(__len__, (const byte*)"\xbb\x02\x07\x00" "__len__")
Q(__getitem__, (const byte*)"\x6b\x04\x0b\x00" "__getitem__")
Q(__add__, (const byte*)"\xa5\x02\x07\x00" "__add__")
Q(__sub__, (const byte*)"\xc6\x02\x07\x00" "__sub__")
Q(micropython, (const byte*)"\xbc\x04\x0b\x00" "micropython")
Q(byte_code, (const byte*)"\xae\x03\x09\x00" "byte_code")
Q(native, (const byte*)"\x87\x02\x06\x00" "native")
Q(viper, (const byte*)"\x26\x02\x05\x00" "viper")
Q(asm_thumb, (const byte*)"\xc0\x03\x09\x00" "asm_thumb")
Q(Ellipsis, (const byte*)"\x45\x03\x08\x00" "Ellipsis")
Q(StopIteration, (const byte*)"\x55\x05\x0d\x00" "StopIteration")
Q(AssertionError, (const byte*)"\xc2\x05\x0e\x00" "AssertionError")
Q(AttributeError, (const byte*)"\xbe\x05\x0e\x00" "AttributeError")
Q(IndentationError, (const byte*)"\x87\x06\x10\x00" "IndentationError")
Q(IndexError, (const byte*)"\x02\x04\x0a\x00" "IndexError")
Q(KeyError, (const byte*)"\x33\x03\x08\x00" "KeyError")
Q(NameError, (const byte*)"\x8b\x03\x09\x00" "NameError")
Q(OSError, (const byte*)"\xac\x02\x07\x00" "OSError")
Q(SyntaxError, (const byte*)"\x91\x04\x0b\x00" "SyntaxError")
Q(TypeError, (const byte*)"\xac\x03\x09\x00" "TypeError")
Q(ValueError, (const byte*)"\x07\x04\x0a\x00" "ValueError")
Q(OverflowError, (const byte*)"\x5e\x05\x0d\x00" "OverflowError")
Q(abs, (const byte*)"\x36\x01\x03\x00" "abs")
Q(all, (const byte*)"\x39\x01\x03\x00" "all")
Q(any, (const byte*)"\x48\x01\x03\x00" "any")
Q(array, (const byte*)"\x1f\x02\x05\x00" "array")
Q(bool, (const byte*)"\xac\x01\x04\x00" "bool")
Q(bytearray, (const byte*)"\xd3\x03\x09\x00" "bytearray")
Q(bytes, (const byte*)"\x27\x02\x05\x00" "bytes")
Q(callable, (const byte*)"\x30\x03\x08\x00" "callable")
Q(chr, (const byte*)"\x3d\x01\x03\x00" "chr")
Q(complex, (const byte*)"\xf8\x02\x07\x00" "complex")
Q(dict, (const byte*)"\xa4\x01\x04\x00" "dict")
Q(divmod, (const byte*)"\x83\x02\x06\x00" "divmod")
Q(enumerate, (const byte*)"\xc6\x03\x09\x00" "enumerate")
Q(eval, (const byte*)"\xa8\x01\x04\x00" "eval")
Q(filter, (const byte*)"\x86\x02\x06\x00" "filter")
Q(float, (const byte*)"\x16\x02\x05\x00" "float")
Q(hash, (const byte*)"\xa4\x01\x04\x00" "hash")
Q(int, (const byte*)"\x4b\x01\x03\x00" "int")
Q(isinstance, (const byte*)"\x31\x04\x0a\x00" "isinstance")
Q(issubclass, (const byte*)"\x3c\x04\x0a\x00" "issubclass")
Q(iter, (const byte*)"\xb4\x01\x04\x00" "iter")
Q(len, (const byte*)"\x3f\x01\x03\x00" "len")
Q(list, (const byte*)"\xbc\x01\x04\x00" "list")
Q(map, (const byte*)"\x3e\x01\x03\x00" "map")
Q(max, (const byte*)"\x46\x01\x03\x00" "max")
Q(min, (const byte*)"\x44\x01\x03\x00" "min")
Q(next, (const byte*)"\xbf\x01\x04\x00" "next")
Q(ord, (const byte*)"\x45\x01\x03\x00" "ord")
Q(pow, (const byte*)"\x56\x01\x03\x00" "pow")
Q(print, (const byte*)"\x2d\x02\x05\x00" "print")
Q(range, (const byte*)"\x0d\x02\x05\x00" "range")
Q(repr, (const byte*)"\xb9\x01\x04\x00" "repr")
Q(set, (const byte*)"\x4c\x01\x03\x00" "set")
Q(sorted, (const byte*)"\x91\x02\x06\x00" "sorted")
Q(sum, (const byte*)"\x55\x01\x03\x00" "sum")
Q(str, (const byte*)"\x59\x01\x03\x00" "str")
Q(tuple, (const byte*)"\x2a\x02\x05\x00" "tuple")
Q(type, (const byte*)"\xc2\x01\x04\x00" "type")
Q(zip, (const byte*)"\x53\x01\x03\x00" "zip")
Q(append, (const byte*)"\x78\x02\x06\x00" "append")
Q(pop, (const byte*)"\x4f\x01\x03\x00" "pop")
Q(sort, (const byte*)"\xc8\x01\x04\x00" "sort")
Q(join, (const byte*)"\xb0\x01\x04\x00" "join")
Q(strip, (const byte*)"\x32\x02\x05\x00" "strip")
Q(format, (const byte*)"\x89\x02\x06\x00" "format")
Q(_lt_module_gt_, (const byte*)"\x00\x03\x08\x00" "<module>")
Q(_lt_lambda_gt_, (const byte*)"\xdb\x02\x08\x00" "<lambda>")
Q(_lt_listcomp_gt_, (const byte*)"\xe5\x03\x0a\x00" "<listcomp>")
Q(_lt_dictcomp_gt_, (const byte*)"\xcd\x03\x0a\x00" "<dictcomp>")
Q(_lt_setcomp_gt_, (const byte*)"\x75\x03\x09\x00" "<setcomp>")
Q(_lt_genexpr_gt_, (const byte*)"\x73\x03\x09\x00" "<genexpr>")
Q(_lt_string_gt_, (const byte*)"\x11\x03\x08\x00" "<string>")
Q(_lt_stdin_gt_, (const byte*)"\x9c\x02\x07\x00" "<stdin>")
Q(help, (const byte*)"\xa9\x01\x04\x00" "help")
Q(pyb, (const byte*)"\x4b\x01\x03\x00" "pyb")
Q(info, (const byte*)"\xac\x01\x04\x00" "info")
Q(stop, (const byte*)"\xc6\x01\x04\x00" "stop")
Q(standby, (const byte*)"\xf5\x02\x07\x00" "standby")
Q(source_dir, (const byte*)"\x2f\x04\x0a\x00" "source_dir")
Q(main, (const byte*)"\xa5\x01\x04\x00" "main")
Q(sync, (const byte*)"\xbd\x01\x04\x00" "sync")
Q(gc, (const byte*)"\xca\x00\x02\x00" "gc")
Q(delay, (const byte*)"\x0f\x02\x05\x00" "delay")
Q(switch, (const byte*)"\x92\x02\x06\x00" "switch")
Q(pwm, (const byte*)"\x54\x01\x03\x00" "pwm")
Q(time, (const byte*)"\xaf\x01\x04\x00" "time")
Q(rand, (const byte*)"\xa5\x01\x04\x00" "rand")
Q(Led, (const byte*)"\x15\x01\x03\x00" "Led")
Q(vcp_connected, (const byte*)"\x5b\x05\x0d\x00" "vcp_connected")
Q(Usart, (const byte*)"\x0f\x02\x05\x00" "Usart")
Q(ADC, (const byte*)"\xc8\x00\x03\x00" "ADC")
Q(open, (const byte*)"\xb2\x01\x04\x00" "open")

View File

@ -0,0 +1,3 @@
#if MICROPY_ENABLE_REPL_HELPERS
bool mp_repl_is_compound_stmt(const char *line);
#endif

View File

@ -0,0 +1,47 @@
int rt_is_true(mp_obj_t arg);
mp_obj_t rt_load_const_dec(qstr qstr);
mp_obj_t rt_load_const_str(qstr qstr);
mp_obj_t rt_load_const_bytes(qstr qstr);
mp_obj_t rt_load_name(qstr qstr);
mp_obj_t rt_load_global(qstr qstr);
mp_obj_t rt_load_build_class(void);
mp_obj_t rt_get_cell(mp_obj_t cell);
void rt_set_cell(mp_obj_t cell, mp_obj_t val);
void rt_store_name(qstr qstr, mp_obj_t obj);
void rt_store_global(qstr qstr, mp_obj_t obj);
mp_obj_t rt_unary_op(int op, mp_obj_t arg);
mp_obj_t rt_binary_op(int op, mp_obj_t lhs, mp_obj_t rhs);
mp_obj_t rt_make_function_from_id(int unique_code_id);
mp_obj_t rt_make_function_n(int n_args, void *fun); // fun must have the correct signature for n_args fixed arguments
mp_obj_t rt_make_function_var(int n_args_min, mp_fun_var_t fun);
mp_obj_t rt_make_function_var_between(int n_args_min, int n_args_max, mp_fun_var_t fun); // min and max are inclusive
mp_obj_t rt_make_closure_from_id(int unique_code_id, mp_obj_t closure_tuple);
mp_obj_t rt_call_function_0(mp_obj_t fun);
mp_obj_t rt_call_function_1(mp_obj_t fun, mp_obj_t arg);
mp_obj_t rt_call_function_2(mp_obj_t fun, mp_obj_t arg1, mp_obj_t arg2);
mp_obj_t rt_call_function_n_kw(mp_obj_t fun, uint n_args, uint n_kw, const mp_obj_t *args);
mp_obj_t rt_call_method_n_kw(uint n_args, uint n_kw, const mp_obj_t *args);
mp_obj_t rt_build_tuple(int n_args, mp_obj_t *items);
mp_obj_t rt_build_list(int n_args, mp_obj_t *items);
mp_obj_t rt_list_append(mp_obj_t list, mp_obj_t arg);
mp_obj_t rt_build_set(int n_args, mp_obj_t *items);
mp_obj_t rt_store_set(mp_obj_t set, mp_obj_t item);
void rt_unpack_sequence(mp_obj_t seq, uint num, mp_obj_t *items);
mp_obj_t rt_build_map(int n_args);
mp_obj_t rt_store_map(mp_obj_t map, mp_obj_t key, mp_obj_t value);
mp_obj_t rt_load_attr(mp_obj_t base, qstr attr);
void rt_load_method(mp_obj_t base, qstr attr, mp_obj_t *dest);
void rt_store_attr(mp_obj_t base, qstr attr, mp_obj_t val);
void rt_store_subscr(mp_obj_t base, mp_obj_t index, mp_obj_t val);
mp_obj_t rt_getiter(mp_obj_t o);
mp_obj_t rt_iternext(mp_obj_t o);
mp_obj_t rt_import_name(qstr name, mp_obj_t fromlist, mp_obj_t level);
mp_obj_t rt_import_from(mp_obj_t module, qstr name);
struct _mp_map_t;
struct _mp_map_t *rt_locals_get(void);
void rt_locals_set(struct _mp_map_t *m);
struct _mp_map_t *rt_globals_get(void);
void rt_globals_set(struct _mp_map_t *m);
struct _mp_map_t *rt_loaded_modules_get(void);

View File

@ -0,0 +1,87 @@
typedef enum {
RT_UNARY_OP_BOOL, // __bool__
RT_UNARY_OP_LEN, // __len__
RT_UNARY_OP_POSITIVE,
RT_UNARY_OP_NEGATIVE,
RT_UNARY_OP_INVERT,
// Used only for CPython-compatible codegeneration
RT_UNARY_OP_NOT,
} rt_unary_op_t;
typedef enum {
RT_BINARY_OP_SUBSCR,
RT_BINARY_OP_OR,
RT_BINARY_OP_XOR,
RT_BINARY_OP_AND,
RT_BINARY_OP_LSHIFT,
RT_BINARY_OP_RSHIFT,
RT_BINARY_OP_ADD,
RT_BINARY_OP_SUBTRACT,
RT_BINARY_OP_MULTIPLY,
RT_BINARY_OP_FLOOR_DIVIDE,
RT_BINARY_OP_TRUE_DIVIDE,
RT_BINARY_OP_MODULO,
RT_BINARY_OP_POWER,
RT_BINARY_OP_INPLACE_OR,
RT_BINARY_OP_INPLACE_XOR,
RT_BINARY_OP_INPLACE_AND,
RT_BINARY_OP_INPLACE_LSHIFT,
RT_BINARY_OP_INPLACE_RSHIFT,
RT_BINARY_OP_INPLACE_ADD,
RT_BINARY_OP_INPLACE_SUBTRACT,
RT_BINARY_OP_INPLACE_MULTIPLY,
RT_BINARY_OP_INPLACE_FLOOR_DIVIDE,
RT_BINARY_OP_INPLACE_TRUE_DIVIDE,
RT_BINARY_OP_INPLACE_MODULO,
RT_BINARY_OP_INPLACE_POWER,
// TODO probably should rename these COMPARE->BINARY
RT_COMPARE_OP_LESS,
RT_COMPARE_OP_MORE,
RT_COMPARE_OP_EQUAL,
RT_COMPARE_OP_LESS_EQUAL,
RT_COMPARE_OP_MORE_EQUAL,
RT_COMPARE_OP_NOT_EQUAL,
RT_COMPARE_OP_IN,
RT_COMPARE_OP_NOT_IN,
RT_COMPARE_OP_IS,
RT_COMPARE_OP_IS_NOT,
RT_COMPARE_OP_EXCEPTION_MATCH,
} rt_binary_op_t;
typedef enum {
RT_F_LOAD_CONST_DEC = 0,
RT_F_LOAD_CONST_STR,
RT_F_LOAD_NAME,
RT_F_LOAD_GLOBAL,
RT_F_LOAD_BUILD_CLASS,
RT_F_LOAD_ATTR,
RT_F_LOAD_METHOD,
RT_F_STORE_NAME,
RT_F_STORE_ATTR,
RT_F_STORE_SUBSCR,
RT_F_IS_TRUE,
RT_F_UNARY_OP,
RT_F_BUILD_TUPLE,
RT_F_BUILD_LIST,
RT_F_LIST_APPEND,
RT_F_BUILD_MAP,
RT_F_STORE_MAP,
RT_F_BUILD_SET,
RT_F_STORE_SET,
RT_F_MAKE_FUNCTION_FROM_ID,
RT_F_CALL_FUNCTION_N,
RT_F_CALL_METHOD_N,
RT_F_BINARY_OP,
RT_F_GETITER,
RT_F_ITERNEXT,
RT_F_NUMBER_OF,
} rt_fun_kind_t;
extern void *const rt_fun_table[RT_F_NUMBER_OF];
void rt_init(void);
void rt_deinit(void);
uint rt_get_unique_code_id(void);
void rt_assign_byte_code(uint unique_code_id, byte *code, uint len, int n_args, int n_locals, int n_stack, bool is_generator);
void rt_assign_native_code(uint unique_code_id, void *f, uint len, int n_args);
void rt_assign_inline_asm_code(uint unique_code_id, void *f, uint len, int n_args);

24
include/MicroPython/std.h Normal file
View File

@ -0,0 +1,24 @@
typedef unsigned int size_t;
void __assert_func(void);
void *malloc(size_t n);
void free(void *ptr);
void *calloc(size_t sz, size_t n);
void *realloc(void *ptr, size_t n);
void *memcpy(void *dest, const void *src, size_t n);
void *memmove(void *dest, const void *src, size_t n);
void *memset(void *s, int c, size_t n);
size_t strlen(const char *str);
int strcmp(const char *s1, const char *s2);
int strncmp(const char *s1, const char *s2, size_t n);
char *strndup(const char *s, size_t n);
char *strcpy(char *dest, const char *src);
char *strcat(char *dest, const char *src);
char *strchr(const char *s, int c);
char *strstr(const char *haystack, const char *needle);
int printf(const char *fmt, ...);
int snprintf(char *str, size_t size, const char *fmt, ...);

View File

@ -0,0 +1,7 @@
void storage_init(void);
uint32_t storage_get_block_size(void);
uint32_t storage_get_block_count(void);
bool storage_needs_flush(void);
void storage_flush(void);
bool storage_read_block(uint8_t *dest, uint32_t block);
bool storage_write_block(const uint8_t *src, uint32_t block);

18
include/MicroPython/usb.h Normal file
View File

@ -0,0 +1,18 @@
#define VCP_CHAR_NONE (0)
#define VCP_CHAR_CTRL_C (3)
#define VCP_CHAR_CTRL_D (4)
void pyb_usb_dev_init(void);
bool usb_vcp_is_enabled(void);
bool usb_vcp_is_connected(void);
void usb_vcp_set_interrupt_char(int c);
int usb_vcp_rx_any(void);
char usb_vcp_rx_get(void);
void usb_vcp_send_str(const char* str);
void usb_vcp_send_strn(const char* str, int len);
void usb_vcp_send_strn_cooked(const char *str, int len);
void usb_hid_send_report(uint8_t *buf); // 4 bytes for mouse: ?, x, y, ?
void pyb_usb_host_init(void);
void pyb_usb_host_process(void);
uint pyb_usb_host_get_keyboard(void);

BIN
lib/libmp.a Normal file

Binary file not shown.

View File

@ -2,54 +2,63 @@ CC = arm-none-eabi-gcc
AS = arm-none-eabi-as
LD = arm-none-eabi-ld
AR = arm-none-eabi-ar
RM = rm -f
RM = rm
SIZE = arm-none-eabi-size
STRIP = arm-none-eabi-strip -s
OBJCOPY = arm-none-eabi-objcopy
OBJDUMP = arm-none-eabi-objdump
#Debugging/Optimization
# General
BIN=openmv
BUILD_DIR=build
# Debugging/Optimization
ifeq ($(DEBUG), 1)
CFLAGS = -O0 -ggdb
else
CFLAGS = -O2 -ggdb
endif
#Compiler Flags
# Compiler Flags
CFLAGS += -Wall -mlittle-endian -mthumb -mthumb-interwork -nostartfiles -mcpu=cortex-m4
CFLAGS += -fsingle-precision-constant -Wdouble-promotion -mfpu=fpv4-sp-d16 -mfloat-abi=hard
CFLAGS += -I. -I../include/CMSIS -I../include/StdPeriph -I../include/USB_OTG -I../include/FatFS -DSTM32F40_41xxx -DUSE_USB_OTG_FS -DARM_MATH_CM4 -D__FPU_PRESENT
CFLAGS += -I. -I../include/CMSIS -I../include/StdPeriph -I../include/USB_OTG -I../include/FatFS -I../include/MicroPython\
-I../include/MicroPython/py -I./py -DSTM32F40_41xxx -DUSE_USB_OTG_FS -DARM_MATH_CM4 -D__FPU_PRESENT -std=gnu99
#Linker Flags
# Linker Flags
LDFLAGS = -mcpu=cortex-m4 -mthumb -mcpu=cortex-m4 -mthumb -mthumb-interwork -mlittle-endian -mfloat-abi=hard -mfpu=fpv4-sp-d16
LDFLAGS += -Wl,-Map=$(BIN).map -Tstm32f4xx.ld -L. -L../lib
LDFLAGS += -Wl,-Map=$(BUILD_DIR)/$(BIN).map -Tstm32f4xx.ld -L. -L../lib
# Sources
BIN = "openmv"
SRCS = $(wildcard *.c)
OBJS = $(SRCS:.c=.o)
#Libraries
LIB = -lc -lm -ldsp -lusbgeneric -lusbdevcore -lusbcore -lfatfs -lstdperiph
SRCS = $(wildcard *.c) $(wildcard py/*.c)
OBJS = $(addprefix $(BUILD_DIR)/, $(SRCS:.c=.o))
all:: $(BIN)
# Libraries
LIB = -lmp -lc -lm -ldsp -lstdperiph -lusbcore -lusbdevcore
$(BIN): $(OBJS)
$(CC) $(LDFLAGS) $(OBJS) $(LIB) -o $(BIN).elf
$(OBJCOPY) -Oihex -j .text -j .data $(BIN).elf $(BIN).hex
$(OBJCOPY) -Obinary $(BIN).elf $(BIN).bin
$(OBJDUMP) -d $(BIN).elf > $(BIN).dis
all:: $(BUILD_DIR) $(BUILD_DIR) $(BUILD_DIR)/$(BIN).bin
$(BUILD_DIR):
mkdir $@
mkdir $@/py
$(BUILD_DIR)/$(BIN).bin: $(BUILD_DIR)/$(BIN).elf
$(OBJCOPY) -Obinary $^ $@
$(BUILD_DIR)/$(BIN).elf: $(OBJS)
$(CC) $(LDFLAGS) $(OBJS) $(LIB) -o $@
stats: $(BIN).elf
$(SIZE) $(BIN).elf
clean:
$(RM) *.o *.elf *.bin *.map *.hex *.dis
$(RM) -fr $(BUILD_DIR)
.c.o :
$(CC) $(CFLAGS) -c $<
$(BUILD_DIR)/%.o : %.c
$(CC) $(CFLAGS) -c -o $@ $<
.s.o :
$(BUILD_DIR)/%.o : %.s
$(AS) $(AFLAGS) $< -o $@
flash::
dfu-util -d 0483:df11 -c 1 -i 0 -a 0 -s 0x08000000 -D $(BIN).bin
dfu-util -d 0483:df11 -c 1 -i 0 -a 0 -s 0x08000000 -D $(BUILD_DIR)/$(BIN).bin

View File

@ -1,324 +1,290 @@
#include <stdlib.h>
#include <string.h>
#include <stm32f4xx_rcc.h>
#include <stm32f4xx_gpio.h>
#include <stm32f4xx_syscfg.h>
#include <stm32f4xx_misc.h>
#include "sensor.h"
#include "rgb_led.h"
#include "usart.h"
#include "imlib.h"
#include "array.h"
#include "systick.h"
#include "usb_generic.h"
#include "ff.h"
#include "rcc_ctrl.h"
#define BREAK() __asm__ volatile ("BKPT");
enum sensor_result run_command(struct sensor_dev *sensor, uint8_t *args)
{
switch (args[0]) {
case CMD_RESET_SENSOR:
sensor_reset(sensor);
break;
case CMD_READ_REGISTER:
//sensor_read_reg(sensor, args[1]);
break;
case CMD_WRITE_REGISTER:
sensor_write_reg(sensor, args[1], args[2]);
break;
case CMD_SET_BRIGHTNESS:
sensor_set_brightness(sensor, args[1]);
break;
case CMD_SET_PIXFORMAT:
/* Configure image size and format and FPS */
if (sensor_set_pixformat(sensor, args[1]) != 0) {
goto error;
}
break;
case CMD_SET_FRAMESIZE:
/* Configure image size and format and FPS */
if (sensor_set_framesize(sensor, args[1]) != 0) {
goto error;
}
break;
case CMD_SET_FRAMERATE:
/* Configure framerate */
if (sensor_set_framerate(sensor, args[1]) != 0) {
goto error;
}
break;
case CMD_SET_GAINCEILING:
/* Configure framerate */
if (sensor_set_gainceiling(sensor, args[1]) != 0) {
goto error;
}
break;
case CMD_SNAPSHOT: {
if (sensor_snapshot(sensor) != 0) {
goto error;
}
break;
}
case CMD_COLOR_TRACK: {
struct point point= {0};
struct frame_buffer *fb = &sensor->frame_buffer;
#if 0
struct color hsv;
hsv.h = usart_recv();
hsv.s = usart_recv();
hsv.v = usart_recv();
#else
/* red */
struct color hsv= {.h = 340, .s = 50, .v = 50};
#endif
if (sensor_snapshot(sensor) != 0) {
goto error;
}
imlib_color_track(fb, &hsv, &point, 10);
if (point.x && point.y) {
struct rectangle r = {.x=point.x-5, .y=point.y-5, .w=10, .h=10};
imlib_draw_rectangle(fb, &r);
/* Send point coords from 0%..100% */
usart_send(point.x*100/fb->width);
usart_send(point.y*100/fb->height);
}
break;
}
case CMD_MOTION_DETECTION: {
int i;
int pixels;
struct frame_buffer *fb = &sensor->frame_buffer;
uint8_t *background = malloc(fb->width * fb->height * 1);//grayscale
if (background == NULL) {
goto error;
}
if (sensor->pixformat != PIXFORMAT_YUV422) {
/* Switch sensor to YUV422 to get
a grayscale image from the Y channel */
// if (sensor_config(&sensor, sensor_QQVGA_YUV422, sensor_30FPS) != 0) {
// goto error;
// }
}
if (sensor_snapshot(sensor) != 0) {
goto error;
}
/* Save this frame as background */
for (i=0; i<(fb->width*fb->height); i++) {
background[i] = fb->pixels[i*2];
}
while (1) {
systick_sleep(1000);
if (sensor_snapshot(sensor) != 0) {
goto error;
}
for (i=0, pixels=0; i<(fb->width*fb->height); i++) {
uint8_t y = fb->pixels[i*2];
int diff = (y-background[i]) * (y-background[i]);
/* consider pixel changed if change more than 25% */
if ((diff*100)/(255*255) > 25) {
pixels++;
/* reuse the frame buffer */
fb->pixels[i] = 0xff;
} else {
fb->pixels[i] = 0x00;
}
}
/* send if more than 10% of the image changed */
if ((pixels*100)/(fb->width*fb->height)>5) {
uint8_t kernel[] = {1,1,1,
1,1,1,
1,1,1};
/* free background frame */
free(background);
/* perform image erosion */
imlib_erosion_filter(fb, kernel, 3);
for (i=0; i<(fb->width*fb->height); i++) {
/* send twice because lcd expects RGB565 */
usart_send(fb->pixels[i]);
usart_send(fb->pixels[i]);
}
break;
}
}
break;
}
case CMD_FACE_DETECTION: {
/* detection objects array */
struct array *objects;
/* detection parameters */
struct cascade cascade = {
.step = 2,
.n_stages = 12,
.window = {24, 24},
.scale_factor = 1.25f,
};
if (sensor->framesize > FRAMESIZE_QQVGA) {
goto error;
}
if (sensor_snapshot(sensor) != 0) {
goto error;
}
objects = imlib_detect_objects(&cascade, &sensor->frame_buffer);
int x_pos=0,y_pos=0;
int objs = array_length(objects);
if (objs) {
int i;
for (i=0; i<objs; i++) {
imlib_draw_rectangle(&sensor->frame_buffer, array_at(objects, i));
}
struct rectangle *r = array_at(objects, 0);
x_pos = r->x+r->w/2;
y_pos = r->y+r->h/2;
/* Send point coords from 0%..100% */
usart_send(x_pos*100/sensor->frame_buffer.width);
usart_send(y_pos*100/sensor->frame_buffer.height);
}
array_free(objects);
break;
}
}
return CMD_ACK;
error:
return CMD_NACK;
}
static int frame_tx_bytes;
void usb_data_in(void *buffer, int *length, void *user_data)
{
int usb_tx_length=64;
struct sensor_dev *sensor = user_data;
struct frame_buffer *fb = &sensor->frame_buffer;
int size = (fb->width*fb->height*fb->bpp);
if (frame_tx_bytes < size) {
memcpy(buffer, fb->pixels+frame_tx_bytes, *length);
*length = usb_tx_length;
frame_tx_bytes += usb_tx_length;
} else {
*length = 0;
}
}
void usb_data_out(void *buffer, int *length, void *user_data)
{
int usb_tx_length=64;
struct sensor_dev *sensor = user_data;
struct frame_buffer *fb = &sensor->frame_buffer;
enum sensor_result ret;
uint8_t *cmd_buf = ((uint8_t*)buffer);
ret = run_command(sensor, cmd_buf);
switch (cmd_buf[0]) {
case CMD_SNAPSHOT:
case CMD_COLOR_TRACK:
case CMD_MOTION_DETECTION:
case CMD_FACE_DETECTION:
/* send back frame */
memcpy(buffer, fb->pixels, usb_tx_length);
*length = usb_tx_length;
/* reset bytes counter */
frame_tx_bytes = usb_tx_length;
break;
default:
/* send back ACK/NACK */
//*length = 1;
*length =0; //ignore it for now
cmd_buf[0] = ret;
}
}
int main(void)
{
/* sensor handle */
struct sensor_dev sensor;
/* USB callback */
struct usb_user_cb usb_cb = {
&sensor,
usb_data_in,
usb_data_out,
};
rcc_ctrl_set_frequency(SYSCLK_168_MHZ);
/* Init SysTick timer */
systick_init();
/* init USART */
usart_init(9600);
/* init RGB LED module */
rgb_led_init(LED_BLUE);
/* init sensor module */
if (sensor_init(&sensor) != 0) {
goto error;
}
/* init usb device */
usb_dev_init(&usb_cb);
// systick_sleep(3000);
rgb_led_set_color(LED_GREEN);
#if 0
/* FPS test */
while (1) {
volatile int fps = 0;
uint8_t args[]= {CMD_FACE_DETECTION};
uint32_t ticks = systick_current_millis();
while ((systick_current_millis()-ticks)<1000) {
run_command(&sensor, args);
fps++;
}
BREAK();
}
#endif
while (1) {
}
error:
rgb_led_set_color(LED_RED);
while (1) {
/* Do nothing */
}
}
#include <stdio.h>
#include <string.h>
#include <stm32f4xx.h>
#include <stm32f4xx_rcc.h>
#include <stm32f4xx_syscfg.h>
#include <stm32f4xx_gpio.h>
#include <stm32f4xx_exti.h>
#include <stm32f4xx_tim.h>
#include <stm32f4xx_pwr.h>
#include <stm32f4xx_rtc.h>
#include <stm32f4xx_usart.h>
#include <stm32f4xx_rng.h>
#include <stm32f4xx_misc.h>
#include "libmp.h"
#include "systick.h"
#include "rcc_ctrl.h"
#include "led_py.h"
int errno;
static FATFS fatfs0;
void __fatal_error(const char *msg) {
printf("%s\n", msg);
while (1) {
led_state(LED_RED, 1);
systick_sleep(250);
led_state(LED_RED, 0);
systick_sleep(250);
}
}
// sync all file systems
mp_obj_t pyb_sync(void) {
storage_flush();
return mp_const_none;
}
mp_obj_t pyb_delay(mp_obj_t count) {
systick_sleep(mp_obj_get_int(count));
return mp_const_none;
}
mp_obj_t pyb_vcp_connected() {
bool connected = usb_vcp_is_connected();
return mp_obj_new_int(connected);
}
void fatality(void) {
led_state(LED_RED, 1);
led_state(LED_GREEN, 1);
led_state(LED_BLUE, 1);
while (1);
}
static const char fresh_boot_py[] =
"# boot.py -- run on boot-up\n"
"# can run arbitrary Python, but best to keep it minimal\n"
"\n"
"pyb.source_dir('/src')\n"
"pyb.main('main.py')\n"
"#pyb.usb_usr('VCP')\n"
"#pyb.usb_msd(True, 'dual partition')\n"
"#pyb.flush_cache(False)\n"
"#pyb.error_log('error.txt')\n"
;
static const char fresh_main_py[] =
"# main.py -- put your code here!\n"
"led = pyb.Led(32)\n"
"while(pyb.vcp_connected()==0):\n"
" led.on()\n"
" pyb.delay(500)\n"
" led.off()\n"
" pyb.delay(500)\n"
;
static const char *help_text =
"Welcome to Micro Python!\n\n"
"This is a *very* early version of Micro Python and has minimal functionality.\n\n"
"Specific commands for the board:\n"
" pyb.info() -- print some general information\n"
" pyb.gc() -- run the garbage collector\n"
" pyb.repl_info(<val>) -- enable/disable printing of info after each command\n"
" pyb.delay(<n>) -- wait for n milliseconds\n"
" pyb.Led(<n>) -- create Led object for LED n (n=1,2)\n"
" Led methods: on(), off()\n"
" pyb.Servo(<n>) -- create Servo object for servo n (n=1,2,3,4)\n"
" Servo methods: angle(<x>)\n"
" pyb.switch() -- return True/False if switch pressed or not\n"
" pyb.accel() -- get accelerometer values\n"
" pyb.rand() -- get a 16-bit random number\n"
" pyb.gpio(<port>) -- get port value (port='A4' for example)\n"
" pyb.gpio(<port>, <val>) -- set port value, True or False, 1 or 0\n"
" pyb.ADC(<port>) -- make an analog port object (port='C0' for example)\n"
" ADC methods: read()\n"
;
// get some help about available functions
static mp_obj_t pyb_help(void) {
printf("%s", help_text);
return mp_const_none;
}
// get lots of info about the board
static mp_obj_t pyb_info(void) {
// get and print unique id; 96 bits
{
byte *id = (byte*)0x1fff7a10;
printf("ID=%02x%02x%02x%02x:%02x%02x%02x%02x:%02x%02x%02x%02x\n", id[0], id[1], id[2], id[3], id[4], id[5], id[6], id[7], id[8], id[9], id[10], id[11]);
}
// get and print clock speeds
// SYSCLK=168MHz, HCLK=168MHz, PCLK1=42MHz, PCLK2=84MHz
{
RCC_ClocksTypeDef rcc_clocks;
RCC_GetClocksFreq(&rcc_clocks);
printf("S=%lu\nH=%lu\nP1=%lu\nP2=%lu\n", rcc_clocks.SYSCLK_Frequency, rcc_clocks.HCLK_Frequency, rcc_clocks.PCLK1_Frequency, rcc_clocks.PCLK2_Frequency);
}
// to print info about memory
{
extern void *_sidata;
extern void *_sdata;
extern void *_edata;
extern void *_sbss;
extern void *_ebss;
extern void *_estack;
extern void *_etext;
printf("_etext=%p\n", &_etext);
printf("_sidata=%p\n", &_sidata);
printf("_sdata=%p\n", &_sdata);
printf("_edata=%p\n", &_edata);
printf("_sbss=%p\n", &_sbss);
printf("_ebss=%p\n", &_ebss);
printf("_estack=%p\n", &_estack);
printf("_ram_start=%p\n", &_ram_start);
printf("_heap_start=%p\n", &_heap_start);
printf("_heap_end=%p\n", &_heap_end);
printf("_ram_end=%p\n", &_ram_end);
}
// qstr info
{
uint n_pool, n_qstr, n_str_data_bytes, n_total_bytes;
qstr_pool_info(&n_pool, &n_qstr, &n_str_data_bytes, &n_total_bytes);
printf("qstr:\n n_pool=%u\n n_qstr=%u\n n_str_data_bytes=%u\n n_total_bytes=%u\n", n_pool, n_qstr, n_str_data_bytes, n_total_bytes);
}
// GC info
{
gc_info_t info;
gc_info(&info);
printf("GC:\n");
printf(" %lu total\n", info.total);
printf(" %lu : %lu\n", info.used, info.free);
printf(" 1=%lu 2=%lu m=%lu\n", info.num_1block, info.num_2block, info.max_block);
}
// free space on flash
{
DWORD nclst;
FATFS *fatfs;
f_getfree("0:", &nclst, &fatfs);
printf("LFS free: %u bytes\n", (uint)(nclst * fatfs->csize * 512));
}
return mp_const_none;
}
static void SYSCLKConfig_STOP(void) {
/* After wake-up from STOP reconfigure the system clock */
/* Enable HSE */
RCC_HSEConfig(RCC_HSE_ON);
/* Wait till HSE is ready */
while (RCC_GetFlagStatus(RCC_FLAG_HSERDY) == RESET) {
}
/* Enable PLL */
RCC_PLLCmd(ENABLE);
/* Wait till PLL is ready */
while (RCC_GetFlagStatus(RCC_FLAG_PLLRDY) == RESET) {
}
/* Select PLL as system clock source */
RCC_SYSCLKConfig(RCC_SYSCLKSource_PLLCLK);
/* Wait till PLL is used as system clock source */
while (RCC_GetSYSCLKSource() != 0x08) {
}
}
static mp_obj_t pyb_stop(void) {
PWR_EnterSTANDBYMode();
//PWR_FlashPowerDownCmd(ENABLE); don't know what the logic is with this
/* Enter Stop Mode */
PWR_EnterSTOPMode(PWR_Regulator_LowPower, PWR_STOPEntry_WFI);
/* Configures system clock after wake-up from STOP: enable HSE, PLL and select
* PLL as system clock source (HSE and PLL are disabled in STOP mode) */
SYSCLKConfig_STOP();
//PWR_FlashPowerDownCmd(DISABLE);
return mp_const_none;
}
static mp_obj_t pyb_standby(void) {
PWR_EnterSTANDBYMode();
return mp_const_none;
}
mp_obj_t pyb_rng_get(void) {
return mp_obj_new_int(RNG_GetRandomNumber() >> 16);
}
int main(void)
{
rcc_ctrl_set_frequency(SYSCLK_168_MHZ);
/* Init MicroPython */
libmp_init();
/* Init SysTick timer */
systick_init();
/* init RGB LED module */
led_init(LED_BLUE);
// add some functions to the python namespace
rt_store_name(MP_QSTR_help, rt_make_function_n(0, pyb_help));
mp_obj_t m = mp_obj_new_module(MP_QSTR_pyb);
rt_store_attr(m, MP_QSTR_vcp_connected, rt_make_function_n(0, pyb_vcp_connected));
rt_store_attr(m, MP_QSTR_info, rt_make_function_n(0, pyb_info));
rt_store_attr(m, MP_QSTR_gc, (mp_obj_t)&pyb_gc_obj);
rt_store_attr(m, MP_QSTR_Led, (mp_obj_t)&pyb_Led_obj);
rt_store_attr(m, MP_QSTR_stop, rt_make_function_n(0, pyb_stop));
rt_store_attr(m, MP_QSTR_standby, rt_make_function_n(0, pyb_standby));
rt_store_attr(m, MP_QSTR_sync, rt_make_function_n(0, pyb_sync));
rt_store_attr(m, MP_QSTR_delay, rt_make_function_n(1, pyb_delay));
rt_store_name(MP_QSTR_pyb, m);
/* Try to mount the flash fs */
bool reset_filesystem = true;
FRESULT res = f_mount(&fatfs0, "0:", 1);
if (!reset_filesystem && res == FR_OK) {
/* Mount sucessful */
} else if (reset_filesystem || res == FR_NO_FILESYSTEM) {
/* No filesystem, so create a fresh one */
res = f_mkfs("0:", 0, 0);
if (res != FR_OK) {
__fatal_error("could not create LFS");
}
/* Create main.py */
FIL fp;
f_open(&fp, "0:/main.py", FA_WRITE | FA_CREATE_ALWAYS);
UINT n;
f_write(&fp, fresh_main_py, sizeof(fresh_main_py) - 1 /* don't count null terminator */, &n);
// TODO check we could write n bytes
f_close(&fp);
} else {
__fatal_error("could not access LFS");
}
/* Init USB device */
pyb_usb_dev_init();
/* Try to run user script first */
if (!libmp_do_file("0:/user.py")) {
/* no user script */
}
/* Fall back to main script */
if (!libmp_do_file("0:/main.py")) {
__fatal_error("failed to run main script");
}
libmp_do_repl();
printf("PYB: sync filesystems\n");
pyb_sync();
printf("PYB: soft reboot\n");
while(1);
}

60
src/py/led_py.c Normal file
View File

@ -0,0 +1,60 @@
#include <stdlib.h>
#include "misc.h"
#include "mpconfig.h"
#include "qstr.h"
#include "obj.h"
#include "led.h"
#include "led_py.h"
typedef struct _pyb_led_obj_t {
mp_obj_base_t base;
uint led_id;
} pyb_led_obj_t;
void led_obj_print(void (*print)(void *env, const char *fmt, ...), void *env, mp_obj_t self_in, mp_print_kind_t kind) {
pyb_led_obj_t *self = self_in;
print(env, "<LED %lu>", self->led_id);
}
mp_obj_t led_obj_on(mp_obj_t self_in) {
pyb_led_obj_t *self = self_in;
led_state(self->led_id, 1);
return mp_const_none;
}
mp_obj_t led_obj_off(mp_obj_t self_in) {
pyb_led_obj_t *self = self_in;
led_state(self->led_id, 0);
return mp_const_none;
}
mp_obj_t led_obj_toggle(mp_obj_t self_in) {
pyb_led_obj_t *self = self_in;
// led_toggle(self->led_id);
return mp_const_none;
}
static MP_DEFINE_CONST_FUN_OBJ_1(led_obj_on_obj, led_obj_on);
static MP_DEFINE_CONST_FUN_OBJ_1(led_obj_off_obj, led_obj_off);
static const mp_method_t led_methods[] = {
{ "on", &led_obj_on_obj },
{ "off", &led_obj_off_obj },
{ NULL, NULL },
};
static const mp_obj_type_t led_obj_type = {
{ &mp_const_type },
"Led",
.print = led_obj_print,
.methods = led_methods,
};
static mp_obj_t pyb_Led(mp_obj_t led_id) {
pyb_led_obj_t *o = m_new_obj(pyb_led_obj_t);
o->base.type = &led_obj_type;
o->led_id = mp_obj_get_int(led_id);
return o;
}
MP_DEFINE_CONST_FUN_OBJ_1(pyb_Led_obj, pyb_Led);

3
src/py/led_py.h Normal file
View File

@ -0,0 +1,3 @@
#include "led.h"
MP_DECLARE_CONST_FUN_OBJ(pyb_Led_obj);

View File

@ -5,21 +5,24 @@
/* Entry Point */
ENTRY(Reset_Handler)
/* Generate a link error if heap and stack don't fit into RAM */
_Min_Stack_Size = 0x1000; /* required amount of stack */
/* Specify the memory areas */
MEMORY
{
FLASH (rx) : ORIGIN = 0x08000000, LENGTH = 512K
FLASH_ISR (rx) : ORIGIN = 0x08000000, LENGTH = 16K
FLASH_TEXT (rx) : ORIGIN = 0x08020000, LENGTH = 512K
RAM (xrw) : ORIGIN = 0x20000000, LENGTH = 128K
CCM (w!rx) : ORIGIN = 0x10000000, LENGTH = 64K
}
/* Highest address of the user mode stack */
_estack = 0x10010000; /* Stack is allocated on CCM block */
_heap_start = 0x20000000; /* Heap starts at the main RAM block */
_heap_end = 0x20020000; /* Heap is given the whole RAM block */
_ram_start = 0x10000000;
_ram_end = 0x10010000; /* 64KB CCM */
/* Generate a link error if heap and stack don't fit into RAM */
_stack_size = 0x1000; /* required amount of stack */
_heap_size = 0x4000; /* required amount of heap */
/* Define output sections */
SECTIONS
@ -30,7 +33,7 @@ SECTIONS
. = ALIGN(4);
KEEP(*(.isr_vector)) /* Startup code */
. = ALIGN(4);
} >FLASH
} >FLASH_ISR
/* The program code and other data goes into FLASH */
.text :
@ -50,21 +53,24 @@ SECTIONS
. = ALIGN(4);
_etext = .; /* define a global symbols at end of code */
_exit = .;
} >FLASH
} >FLASH_TEXT
.ARM.extab : {
*(.ARM.extab* .gnu.linkonce.armextab.*)
} >FLASH_TEXT
.ARM.extab : { *(.ARM.extab* .gnu.linkonce.armextab.*) } >FLASH
.ARM : {
__exidx_start = .;
*(.ARM.exidx*)
__exidx_end = .;
} >FLASH
} >FLASH_TEXT
.preinit_array :
{
PROVIDE_HIDDEN (__preinit_array_start = .);
KEEP (*(.preinit_array*))
PROVIDE_HIDDEN (__preinit_array_end = .);
} >FLASH
} >FLASH_TEXT
.init_array :
{
@ -72,7 +78,7 @@ SECTIONS
KEEP (*(SORT(.init_array.*)))
KEEP (*(.init_array*))
PROVIDE_HIDDEN (__init_array_end = .);
} >FLASH
} >FLASH_TEXT
.fini_array :
{
@ -80,7 +86,7 @@ SECTIONS
KEEP (*(.fini_array*))
KEEP (*(SORT(.fini_array.*)))
PROVIDE_HIDDEN (__fini_array_end = .);
} >FLASH
} >FLASH_TEXT
/* used by the startup to initialize data */
_sidata = .;
@ -114,21 +120,32 @@ SECTIONS
__bss_end__ = _ebss;
} >CCM
._heap :
{
. = ALIGN(4);
_heap_start = .;
. = . + _heap_size;
. = ALIGN(4);
_heap_end = .;
} >CCM
/* Make sure there is enough RAM left for the stack */
._user_heap_stack :
{
. = ALIGN(4);
. = . + _Min_Stack_Size;
. = . + _stack_size;
. = ALIGN(4);
} >CCM
/* Remove information from the standard libraries */
/*
/DISCARD/ :
{
libc.a ( * )
libm.a ( * )
libgcc.a ( * )
}
*/
.ARM.attributes 0 : { *(.ARM.attributes) }
}

View File

@ -2,7 +2,7 @@
#include <stm32f4xx_exti.h>
#define BREAK() __asm__ volatile ("BKPT");
extern USB_OTG_CORE_HANDLE USB_OTG_dev;
extern USB_OTG_CORE_HANDLE USB_OTG_Core;
extern uint32_t USBD_OTG_ISR_Handler (USB_OTG_CORE_HANDLE *pdev);
/**
@ -87,17 +87,17 @@ void PendSV_Handler(void)
void OTG_FS_WKUP_IRQHandler(void)
{
BREAK();
if(USB_OTG_dev.cfg.low_power)
if(USB_OTG_Core.cfg.low_power)
{
*(uint32_t *)(0xE000ED10) &= 0xFFFFFFF9 ;
SystemInit();
USB_OTG_UngateClock(&USB_OTG_dev);
USB_OTG_UngateClock(&USB_OTG_Core);
}
EXTI_ClearITPendingBit(EXTI_Line18);
}
void OTG_FS_IRQHandler(void)
{
USBD_OTG_ISR_Handler (&USB_OTG_dev);
USBD_OTG_ISR_Handler (&USB_OTG_Core);
}