Skip to content
GitLab
Projects
Groups
Snippets
/
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
Menu
Open sidebar
fleur
firmware
Commits
b457c4b6
Commit
b457c4b6
authored
Jul 18, 2019
by
schneider
Browse files
feat(interrupt): API for Python interrupts
parent
00750677
Changes
14
Hide whitespace changes
Inline
Side-by-side
epicardium/api/common.h
View file @
b457c4b6
#pragma once
#include
"epicardium.h"
#include
<stdint.h>
#include
<stdbool.h>
...
...
@@ -26,6 +29,9 @@ struct api_call_mem {
/* ID if the ongoing API call */
api_id_t
id
;
/* ID of the current interrupt */
api_int_id_t
int_id
;
/*
* Buffer for arguments/return value. This buffer will be
* *overflown*, because there is guaranteed space behind it.
...
...
epicardium/api/interrupt-receiver.c
0 → 100644
View file @
b457c4b6
#include
"max32665.h"
#include
"tmr.h"
#include
"api/common.h"
#include
"epicardium.h"
void
api_interrupt_handler_ctrl_c
(
api_int_id_t
id
)
__attribute__
((
weak
,
alias
(
"api_interrupt_handler_default"
)));
void
api_interrupt_handler_bhi160
(
api_int_id_t
id
)
__attribute__
((
weak
,
alias
(
"api_interrupt_handler_default"
)));
/* Timer Interrupt used for control char notification */
void
TMR5_IRQHandler
(
void
)
{
TMR_IntClear
(
MXC_TMR5
);
switch
(
API_CALL_MEM
->
int_id
)
{
case
API_INT_CTRL_C
:
api_interrupt_handler_ctrl_c
(
API_CALL_MEM
->
int_id
);
break
;
case
API_INT_BHI160
:
api_interrupt_handler_bhi160
(
API_CALL_MEM
->
int_id
);
break
;
}
API_CALL_MEM
->
int_id
=
0
;
}
__attribute__
((
weak
))
void
api_interrupt_handler_catch_all
(
api_int_id_t
id
)
{
}
void
api_interrupt_handler_default
(
api_int_id_t
id
)
{
api_interrupt_handler_catch_all
(
id
);
}
epicardium/api/interrupt-sender.c
0 → 100644
View file @
b457c4b6
#include
"api/interrupt-sender.h"
#include
"api/common.h"
#include
"tmr_utils.h"
static
bool
enabled
[
API_INT_MAX
+
1
];
void
api_interrupt_trigger
(
api_int_id_t
id
)
{
if
(
id
<=
API_INT_MAX
)
{
if
(
enabled
[
id
])
{
while
(
API_CALL_MEM
->
int_id
)
;
API_CALL_MEM
->
int_id
=
id
;
TMR_TO_Start
(
MXC_TMR5
,
1
,
0
);
}
}
}
void
api_interrupt_init
(
void
)
{
int
i
;
API_CALL_MEM
->
int_id
=
0
;
for
(
i
=
0
;
i
<=
API_INT_MAX
;
i
++
)
{
enabled
[
i
]
=
false
;
}
}
void
epic_interrupt_enable
(
api_int_id_t
int_id
)
{
if
(
int_id
<=
API_INT_MAX
)
{
enabled
[
int_id
]
=
true
;
}
}
void
epic_interrupt_disable
(
api_int_id_t
int_id
)
{
if
(
int_id
<=
API_INT_MAX
)
{
enabled
[
int_id
]
=
false
;
}
}
epicardium/api/interrupt-sender.h
0 → 100644
View file @
b457c4b6
#pragma once
#include
"api/common.h"
void
api_interrupt_init
(
void
);
void
api_interrupt_trigger
(
api_int_id_t
id
);
epicardium/epicardium.h
View file @
b457c4b6
...
...
@@ -4,17 +4,24 @@
#include
<stddef.h>
#include
<errno.h>
/* clang-format off */
#define API_INT_CTRL_C 1
#define API_INT_BHI160 2
#define API_INT_MAX API_INT_BHI160
#ifndef API
#define API(id, def) def
#endif
/* clang-format off */
#define API_UART_WRITE 0x1
#define API_UART_READ 0x2
#define API_LEDS_SET 0x3
#define API_VIBRA_SET 0x4
#define API_VIBRA_VIBRATE 0x5
#define API_STREAM_READ 0x6
#define API_INTERRUPT_ENABLE 0x7
#define API_INTERRUPT_DISABLE 0x8
/* clang-format on */
/**
...
...
@@ -139,4 +146,23 @@ API(API_VIBRA_SET, void epic_vibra_set(int status));
*/
API
(
API_VIBRA_VIBRATE
,
void
epic_vibra_vibrate
(
int
millis
));
/**
* API interrupt type
*/
typedef
uint32_t
api_int_id_t
;
/**
* Enable/unmask an API interrupt
*
* :param int_id: The interrupt to be enabled
*/
API
(
API_INTERRUPT_ENABLE
,
void
epic_interrupt_enable
(
api_int_id_t
int_id
));
/**
* Disable/mask an API interrupt
*
* :param int_id: The interrupt to be disabled
*/
API
(
API_INTERRUPT_DISABLE
,
void
epic_interrupt_disable
(
api_int_id_t
int_id
));
#endif
/* _EPICARDIUM_H */
epicardium/main.c
View file @
b457c4b6
...
...
@@ -12,6 +12,7 @@
#include
"modules/modules.h"
#include
"modules/log.h"
#include
"modules/stream.h"
#include
"api/interrupt-sender.h"
#include
<Heart.h>
#include
"GUI_Paint.h"
...
...
@@ -54,6 +55,7 @@ int main(void)
}
fatfs_init
();
api_interrupt_init
();
stream_init
();
LOG_INFO
(
"startup"
,
"Initializing tasks ..."
);
...
...
epicardium/meson.build
View file @
b457c4b6
...
...
@@ -22,6 +22,7 @@ api = custom_target(
api_caller_lib
=
static_library
(
'api-caller'
,
'api/caller.c'
,
'api/interrupt-receiver.c'
,
api
[
0
],
# Caller
dependencies
:
periphdriver
,
)
...
...
@@ -35,6 +36,7 @@ api_caller = declare_dependency(
api_dispatcher_lib
=
static_library
(
'api-dispatcher'
,
'api/dispatcher.c'
,
'api/interrupt-sender.c'
,
api
[
1
],
# Dispatcher
dependencies
:
periphdriver
,
)
...
...
epicardium/modules/serial.c
View file @
b457c4b6
...
...
@@ -4,7 +4,6 @@
#include
"max32665.h"
#include
"cdcacm.h"
#include
"uart.h"
#include
"tmr_utils.h"
#include
"FreeRTOS.h"
#include
"task.h"
...
...
@@ -12,6 +11,7 @@
#include
"modules.h"
#include
"modules/log.h"
#include
"api/interrupt-sender.h"
/* Task ID for the serial handler */
TaskHandle_t
serial_task_id
=
NULL
;
...
...
@@ -24,7 +24,7 @@ static QueueHandle_t read_queue;
/*
* API-call to write a string. Output goes to both CDCACM and UART
*/
void
epic_uart_write_str
(
char
*
str
,
intptr_t
length
)
void
epic_uart_write_str
(
const
char
*
str
,
intptr_t
length
)
{
UART_Write
(
ConsoleUart
,
(
uint8_t
*
)
str
,
length
);
cdcacm_write
((
uint8_t
*
)
str
,
length
);
...
...
@@ -57,7 +57,12 @@ static void enqueue_char(char chr)
{
if
(
chr
==
0x3
)
{
/* Control-C */
TMR_TO_Start
(
MXC_TMR5
,
1
,
0
);
api_interrupt_trigger
(
API_INT_CTRL_C
);
}
if
(
chr
==
0x0e
)
{
/* Control-N */
api_interrupt_trigger
(
API_INT_BHI160
);
}
if
(
xQueueSend
(
read_queue
,
&
chr
,
100
)
==
errQUEUE_FULL
)
{
...
...
pycardium/main.c
View file @
b457c4b6
...
...
@@ -19,7 +19,7 @@ int main(void)
NVIC_EnableIRQ
(
TMR5_IRQn
);
while
(
1
)
{
gc_init
(
&
__HeapBase
,
&
__HeapLimit
);
gc_init
(
&
__HeapBase
+
1024
*
10
,
&
__HeapLimit
);
mp_init
();
pyexec_friendly_repl
();
...
...
pycardium/meson.build
View file @
b457c4b6
...
...
@@ -4,6 +4,7 @@ modsrc = files(
'modules/utime.c'
,
'modules/leds.c'
,
'modules/vibra.c'
,
'modules/interrupt.c'
,
)
#################################
...
...
@@ -75,7 +76,7 @@ elf = executable(
include_directories
:
micropython_includes
,
dependencies
:
[
max32665_startup_core1
,
periphdriver
,
api_caller
],
link_with
:
upy
,
link_whole
:
[
max32665_startup_core1_lib
],
link_whole
:
[
max32665_startup_core1_lib
,
api_caller_lib
],
link_args
:
[
'-Wl,-Map='
+
meson
.
current_build_dir
()
+
'/'
+
name
+
'.map'
,
],
...
...
pycardium/modules/interrupt.c
0 → 100644
View file @
b457c4b6
#include
"py/obj.h"
#include
"py/runtime.h"
#include
"py/builtin.h"
#include
"epicardium.h"
#include
"api/common.h"
#include
"mphalport.h"
// TODO: these should be intialized as mp_const_none
mp_obj_t
callbacks
[
API_INT_MAX
+
1
]
=
{
0
,
};
void
api_interrupt_handler_catch_all
(
api_int_id_t
id
)
{
// TODO: check if id is out of rante
// TOOD: check against mp_const_none
if
(
id
<=
API_INT_MAX
)
{
if
(
callbacks
[
id
])
{
mp_sched_schedule
(
callbacks
[
id
],
MP_OBJ_NEW_SMALL_INT
(
id
)
);
}
}
}
STATIC
mp_obj_t
mp_interrupt_set_callback
(
mp_obj_t
id_in
,
mp_obj_t
callback_obj
)
{
api_int_id_t
id
=
mp_obj_get_int
(
id_in
);
if
(
callback_obj
!=
mp_const_none
&&
!
mp_obj_is_callable
(
callback_obj
))
{
mp_raise_ValueError
(
"handler must be None or callable"
);
}
// TODO: throw error if id is out of range
if
(
id
<=
API_INT_MAX
)
{
callbacks
[
id
]
=
callback_obj
;
}
return
mp_const_none
;
}
STATIC
mp_obj_t
mp_interrupt_enable_callback
(
mp_obj_t
id_in
)
{
api_int_id_t
id
=
mp_obj_get_int
(
id_in
);
// TODO: throw error if id is out of range or epic_interrupt_enable failed
epic_interrupt_enable
(
id
);
return
mp_const_none
;
}
STATIC
MP_DEFINE_CONST_FUN_OBJ_2
(
interrupt_set_callback_obj
,
mp_interrupt_set_callback
);
STATIC
MP_DEFINE_CONST_FUN_OBJ_1
(
interrupt_enable_callback_obj
,
mp_interrupt_enable_callback
);
STATIC
const
mp_rom_map_elem_t
interrupt_module_globals_table
[]
=
{
{
MP_ROM_QSTR
(
MP_QSTR___name__
),
MP_ROM_QSTR
(
MP_QSTR_interrupt
)
},
{
MP_ROM_QSTR
(
MP_QSTR_set_callback
),
MP_ROM_PTR
(
&
interrupt_set_callback_obj
)
},
{
MP_ROM_QSTR
(
MP_QSTR_enable_callback
),
MP_ROM_PTR
(
&
interrupt_enable_callback_obj
)
},
{
MP_ROM_QSTR
(
MP_QSTR_BHI160
),
MP_OBJ_NEW_SMALL_INT
(
2
)
},
};
STATIC
MP_DEFINE_CONST_DICT
(
interrupt_module_globals
,
interrupt_module_globals_table
);
// Define module object.
const
mp_obj_module_t
interrupt_module
=
{
.
base
=
{
&
mp_type_module
},
.
globals
=
(
mp_obj_dict_t
*
)
&
interrupt_module_globals
,
};
/* clang-format off */
// Register the module to make it available in Python
MP_REGISTER_MODULE
(
MP_QSTR_interrupt
,
interrupt_module
,
MODULE_INTERRUPT_ENABLED
);
pycardium/modules/qstrdefs.h
View file @
b457c4b6
...
...
@@ -25,3 +25,7 @@ Q(ticks_diff)
/* vibra */
Q
(
vibra
)
Q
(
vibrate
)
Q
(
set_callback
)
Q
(
enable_callback
)
Q
(
BHI160
)
pycardium/mpconfigport.h
View file @
b457c4b6
...
...
@@ -19,6 +19,8 @@
#define MICROPY_HELPER_REPL (1)
#define MICROPY_LONGINT_IMPL (MICROPY_LONGINT_IMPL_LONGLONG)
#define MICROPY_ENABLE_SCHEDULER (1)
/* Builtin function and modules */
#define MICROPY_PY_ALL_SPECIAL_METHODS (1)
#define MICROPY_PY_BUILTINS_HELP (1)
...
...
@@ -38,6 +40,7 @@
#define MODULE_UTIME_ENABLED (1)
#define MODULE_LEDS_ENABLED (1)
#define MODULE_VIBRA_ENABLED (1)
#define MODULE_INTERRUPT_ENABLED (1)
/*
* This port is intended to be 32-bit, but unfortunately, int32_t for
...
...
pycardium/mphalport.c
View file @
b457c4b6
...
...
@@ -14,7 +14,7 @@
#include
"tmr.h"
#include
"epicardium.h"
#include
"api/common.h"
/******************************************************************************
* Serial Communication
*/
...
...
@@ -62,23 +62,16 @@ long _write(int fd, const char *buf, size_t cnt)
return
cnt
;
}
bool
do_interrupt
=
false
;
/* Timer Interrupt used for control char notification */
void
TMR5_IRQHandler
(
void
)
void
api_interrupt_handler_ctrl_c
(
void
)
{
TMR_IntClear
(
MXC_TMR5
);
if
(
do_interrupt
)
{
/* Taken from lib/micropython/micropython/lib/utils/interrupt_char.c */
MP_STATE_VM
(
mp_pending_exception
)
=
MP_OBJ_FROM_PTR
(
&
MP_STATE_VM
(
mp_kbd_exception
));
/* Taken from lib/micropython/micropython/lib/utils/interrupt_char.c */
MP_STATE_VM
(
mp_pending_exception
)
=
MP_OBJ_FROM_PTR
(
&
MP_STATE_VM
(
mp_kbd_exception
));
#if MICROPY_ENABLE_SCHEDULER
if
(
MP_STATE_VM
(
sched_state
)
==
MP_SCHED_IDLE
)
{
MP_STATE_VM
(
sched_state
)
=
MP_SCHED_PENDING
;
}
#endif
if
(
MP_STATE_VM
(
sched_state
)
==
MP_SCHED_IDLE
)
{
MP_STATE_VM
(
sched_state
)
=
MP_SCHED_PENDING
;
}
#endif
}
void
mp_hal_set_interrupt_char
(
char
c
)
...
...
@@ -88,7 +81,12 @@ void mp_hal_set_interrupt_char(char c)
MP_OBJ_FROM_PTR
(
&
MP_STATE_VM
(
mp_kbd_exception
))
);
}
do_interrupt
=
(
c
==
0x03
);
if
(
c
==
0x03
)
{
epic_interrupt_enable
(
API_INT_CTRL_C
);
}
else
{
epic_interrupt_disable
(
API_INT_CTRL_C
);
}
}
/******************************************************************************
...
...
@@ -137,7 +135,7 @@ mp_import_stat_t mp_import_stat(const char *path)
mp_obj_t
mp_builtin_open
(
size_t
n_args
,
const
mp_obj_t
*
args
,
mp_map_t
*
kwargs
)
{
/* TODO: Once fs is implemented, get this working as well */
mp_raise_NotImplementedError
(
"FS is not yet implemented"
);
mp_raise_NotImplementedError
(
"FS is not yet implemented"
);
return
mp_const_none
;
}
MP_DEFINE_CONST_FUN_OBJ_KW
(
mp_builtin_open_obj
,
1
,
mp_builtin_open
);
Write
Preview
Supports
Markdown
0%
Try again
or
attach a new file
.
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment