From e00cc6594166e24181dd3da02cdd078d439c5c07 Mon Sep 17 00:00:00 2001 From: "Federico Pasqua (eisterman)" Date: Wed, 12 Jun 2024 23:21:05 +0200 Subject: [PATCH] Initial Commit --- .gdbinit | 2382 +++++++++++++++++++++++++++++++++++++++++ .gitignore | 4 + README.md | 84 ++ extra_script.py | 61 ++ include/README | 39 + lib/README | 46 + oldblink/main.c | 123 +++ oldblink/stm8s_conf.h | 118 ++ oldblink/stm8s_it.c | 482 +++++++++ oldblink/stm8s_it.h | 201 ++++ oldtest/main.c | 129 +++ oldtest/main.h | 50 + oldtest/stm8s_conf.h | 118 ++ oldtest/stm8s_it.c | 488 +++++++++ oldtest/stm8s_it.h | 201 ++++ platformio.ini | 24 + src/main.c | 284 +++++ src/main.h | 67 ++ src/stm8s_conf.h | 118 ++ src/stm8s_it.c | 541 ++++++++++ src/stm8s_it.h | 201 ++++ test/README | 11 + 22 files changed, 5772 insertions(+) create mode 100644 .gdbinit create mode 100644 .gitignore create mode 100644 README.md create mode 100644 extra_script.py create mode 100644 include/README create mode 100644 lib/README create mode 100644 oldblink/main.c create mode 100644 oldblink/stm8s_conf.h create mode 100644 oldblink/stm8s_it.c create mode 100644 oldblink/stm8s_it.h create mode 100644 oldtest/main.c create mode 100644 oldtest/main.h create mode 100644 oldtest/stm8s_conf.h create mode 100644 oldtest/stm8s_it.c create mode 100644 oldtest/stm8s_it.h create mode 100644 platformio.ini create mode 100644 src/main.c create mode 100644 src/main.h create mode 100644 src/stm8s_conf.h create mode 100644 src/stm8s_it.c create mode 100644 src/stm8s_it.h create mode 100644 test/README diff --git a/.gdbinit b/.gdbinit new file mode 100644 index 0000000..5e6c6cb --- /dev/null +++ b/.gdbinit @@ -0,0 +1,2382 @@ +python + +# GDB dashboard - Modular visual interface for GDB in Python. +# +# https://github.com/cyrus-and/gdb-dashboard + +# License ---------------------------------------------------------------------- + +# Copyright (c) 2015-2024 Andrea Cardaci +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in all +# copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +# SOFTWARE. + +# Imports ---------------------------------------------------------------------- + +import ast +import io +import itertools +import math +import os +import re +import struct +import traceback + +# Common attributes ------------------------------------------------------------ + +class R(): + + @staticmethod + def attributes(): + return { + # miscellaneous + 'ansi': { + 'doc': 'Control the ANSI output of the dashboard.', + 'default': True, + 'type': bool + }, + 'syntax_highlighting': { + 'doc': '''Pygments style to use for syntax highlighting. + +Using an empty string (or a name not in the list) disables this feature. The +list of all the available styles can be obtained with (from GDB itself): + + python from pygments.styles import * + python for style in get_all_styles(): print(style)''', + 'default': 'monokai' + }, + 'discard_scrollback': { + 'doc': '''Discard the scrollback buffer at each redraw. + +This makes scrolling less confusing by discarding the previously printed +dashboards but only works with certain terminals.''', + 'default': True, + 'type': bool + }, + # values formatting + 'compact_values': { + 'doc': 'Display complex objects in a single line.', + 'default': True, + 'type': bool + }, + 'max_value_length': { + 'doc': 'Maximum length of displayed values before truncation.', + 'default': 100, + 'type': int + }, + 'value_truncation_string': { + 'doc': 'String to use to mark value truncation.', + 'default': '…', + }, + 'dereference': { + 'doc': 'Annotate pointers with the pointed value.', + 'default': True, + 'type': bool + }, + # prompt + 'prompt': { + 'doc': '''GDB prompt. + +This value is used as a Python format string where `{status}` is expanded with +the substitution of either `prompt_running` or `prompt_not_running` attributes, +according to the target program status. The resulting string must be a valid GDB +prompt, see the command `python print(gdb.prompt.prompt_help())`''', + 'default': '{status}' + }, + 'prompt_running': { + 'doc': '''Define the value of `{status}` when the target program is running. + +See the `prompt` attribute. This value is used as a Python format string where +`{pid}` is expanded with the process identifier of the target program.''', + 'default': r'\[\e[1;35m\]>>>\[\e[0m\]' + }, + 'prompt_not_running': { + 'doc': '''Define the value of `{status}` when the target program is running. + +See the `prompt` attribute. This value is used as a Python format string.''', + 'default': r'\[\e[90m\]>>>\[\e[0m\]' + }, + # divider + 'omit_divider': { + 'doc': 'Omit the divider in external outputs when only one module is displayed.', + 'default': False, + 'type': bool + }, + 'divider_fill_char_primary': { + 'doc': 'Filler around the label for primary dividers', + 'default': '─' + }, + 'divider_fill_char_secondary': { + 'doc': 'Filler around the label for secondary dividers', + 'default': '─' + }, + 'divider_fill_style_primary': { + 'doc': 'Style for `divider_fill_char_primary`', + 'default': '36' + }, + 'divider_fill_style_secondary': { + 'doc': 'Style for `divider_fill_char_secondary`', + 'default': '90' + }, + 'divider_label_style_on_primary': { + 'doc': 'Label style for non-empty primary dividers', + 'default': '1;33' + }, + 'divider_label_style_on_secondary': { + 'doc': 'Label style for non-empty secondary dividers', + 'default': '1;37' + }, + 'divider_label_style_off_primary': { + 'doc': 'Label style for empty primary dividers', + 'default': '33' + }, + 'divider_label_style_off_secondary': { + 'doc': 'Label style for empty secondary dividers', + 'default': '90' + }, + 'divider_label_skip': { + 'doc': 'Gap between the aligning border and the label.', + 'default': 3, + 'type': int, + 'check': check_ge_zero + }, + 'divider_label_margin': { + 'doc': 'Number of spaces around the label.', + 'default': 1, + 'type': int, + 'check': check_ge_zero + }, + 'divider_label_align_right': { + 'doc': 'Label alignment flag.', + 'default': False, + 'type': bool + }, + # common styles + 'style_selected_1': { + 'default': '1;32' + }, + 'style_selected_2': { + 'default': '32' + }, + 'style_low': { + 'default': '90' + }, + 'style_high': { + 'default': '1;37' + }, + 'style_error': { + 'default': '31' + }, + 'style_critical': { + 'default': '0;41' + } + } + +# Common ----------------------------------------------------------------------- + +class Beautifier(): + + def __init__(self, hint, tab_size=4): + self.tab_spaces = ' ' * tab_size if tab_size else None + self.active = False + if not R.ansi or not R.syntax_highlighting: + return + # attempt to set up Pygments + try: + import pygments + from pygments.lexers import GasLexer, NasmLexer + from pygments.formatters import Terminal256Formatter + if hint == 'att': + self.lexer = GasLexer() + elif hint == 'intel': + self.lexer = NasmLexer() + else: + from pygments.lexers import get_lexer_for_filename + self.lexer = get_lexer_for_filename(hint, stripnl=False) + self.formatter = Terminal256Formatter(style=R.syntax_highlighting) + self.active = True + except ImportError: + # Pygments not available + pass + except pygments.util.ClassNotFound: + # no lexer for this file or invalid style + pass + + def process(self, source): + # convert tabs if requested + if self.tab_spaces: + source = source.replace('\t', self.tab_spaces) + if self.active: + import pygments + source = pygments.highlight(source, self.lexer, self.formatter) + return source.rstrip('\n') + +def run(command): + return gdb.execute(command, to_string=True) + +def ansi(string, style): + if R.ansi: + return '\x1b[{}m{}\x1b[0m'.format(style, string) + else: + return string + +def divider(width, label='', primary=False, active=True): + if primary: + divider_fill_style = R.divider_fill_style_primary + divider_fill_char = R.divider_fill_char_primary + divider_label_style_on = R.divider_label_style_on_primary + divider_label_style_off = R.divider_label_style_off_primary + else: + divider_fill_style = R.divider_fill_style_secondary + divider_fill_char = R.divider_fill_char_secondary + divider_label_style_on = R.divider_label_style_on_secondary + divider_label_style_off = R.divider_label_style_off_secondary + if label: + if active: + divider_label_style = divider_label_style_on + else: + divider_label_style = divider_label_style_off + skip = R.divider_label_skip + margin = R.divider_label_margin + before = ansi(divider_fill_char * skip, divider_fill_style) + middle = ansi(label, divider_label_style) + after_length = width - len(label) - skip - 2 * margin + after = ansi(divider_fill_char * after_length, divider_fill_style) + if R.divider_label_align_right: + before, after = after, before + return ''.join([before, ' ' * margin, middle, ' ' * margin, after]) + else: + return ansi(divider_fill_char * width, divider_fill_style) + +def check_gt_zero(x): + return x > 0 + +def check_ge_zero(x): + return x >= 0 + +def to_unsigned(value, size=8): + # values from GDB can be used transparently but are not suitable for + # being printed as unsigned integers, so a conversion is needed + mask = (2 ** (size * 8)) - 1 + return int(value.cast(gdb.Value(mask).type)) & mask + +def to_string(value): + # attempt to convert an inferior value to string; OK when (Python 3 || + # simple ASCII); otherwise (Python 2.7 && not ASCII) encode the string as + # utf8 + try: + value_string = str(value) + except UnicodeEncodeError: + value_string = unicode(value).encode('utf8') + except gdb.error as e: + value_string = ansi(e, R.style_error) + return value_string + +def format_address(address): + pointer_size = gdb.parse_and_eval('$pc').type.sizeof + return ('0x{{:0{}x}}').format(pointer_size * 2).format(address) + +def format_value(value, compact=None): + # format references as referenced values + # (TYPE_CODE_RVALUE_REF is not supported by old GDB) + if value.type.code in (getattr(gdb, 'TYPE_CODE_REF', None), + getattr(gdb, 'TYPE_CODE_RVALUE_REF', None)): + try: + value = value.referenced_value() + except gdb.error as e: + return ansi(e, R.style_error) + # format the value + out = to_string(value) + # dereference up to the actual value if requested + if R.dereference and value.type.code == gdb.TYPE_CODE_PTR: + while value.type.code == gdb.TYPE_CODE_PTR: + try: + value = value.dereference() + except gdb.error as e: + break + else: + formatted = to_string(value) + out += '{} {}'.format(ansi(':', R.style_low), formatted) + # compact the value + if compact is not None and compact or R.compact_values: + out = re.sub(r'$\s*', '', out, flags=re.MULTILINE) + # truncate the value + if R.max_value_length > 0 and len(out) > R.max_value_length: + out = out[0:R.max_value_length] + ansi(R.value_truncation_string, R.style_critical) + return out + +# XXX parsing the output of `info breakpoints` is apparently the best option +# right now, see: https://sourceware.org/bugzilla/show_bug.cgi?id=18385 +# XXX GDB version 7.11 (quire recent) does not have the pending field, so +# fall back to the parsed information +def fetch_breakpoints(watchpoints=False, pending=False): + # fetch breakpoints addresses + parsed_breakpoints = dict() + catch_what_regex = re.compile(r'([^,]+".*")?[^,]*') + for line in run('info breakpoints').split('\n'): + # just keep numbered lines + if not line or not line[0].isdigit(): + continue + # extract breakpoint number, address and pending status + fields = line.split() + number = int(fields[0].split('.')[0]) + try: + if len(fields) >= 5 and fields[1] == 'breakpoint': + # multiple breakpoints have no address yet + is_pending = fields[4] == '' + is_multiple = fields[4] == '' + address = None if is_multiple or is_pending else int(fields[4], 16) + is_enabled = fields[3] == 'y' + address_info = address, is_enabled + parsed_breakpoints[number] = [address_info], is_pending, '' + elif len(fields) >= 5 and fields[1] == 'catchpoint': + # only take before comma, but ignore commas in quotes + what = catch_what_regex.search(' '.join(fields[4:]))[0].strip() + parsed_breakpoints[number] = [], False, what + elif len(fields) >= 3 and number in parsed_breakpoints: + # add this address to the list of multiple locations + address = int(fields[2], 16) + is_enabled = fields[1] == 'y' + address_info = address, is_enabled + parsed_breakpoints[number][0].append(address_info) + else: + # watchpoints + parsed_breakpoints[number] = [], False, '' + except ValueError: + pass + # fetch breakpoints from the API and complement with address and source + # information + breakpoints = [] + # XXX in older versions gdb.breakpoints() returns None + for gdb_breakpoint in gdb.breakpoints() or []: + # skip internal breakpoints + if gdb_breakpoint.number < 0: + continue + addresses, is_pending, what = parsed_breakpoints[gdb_breakpoint.number] + is_pending = getattr(gdb_breakpoint, 'pending', is_pending) + if not pending and is_pending: + continue + if not watchpoints and gdb_breakpoint.type != gdb.BP_BREAKPOINT: + continue + # add useful fields to the object + breakpoint = dict() + breakpoint['number'] = gdb_breakpoint.number + breakpoint['type'] = gdb_breakpoint.type + breakpoint['enabled'] = gdb_breakpoint.enabled + breakpoint['location'] = gdb_breakpoint.location + breakpoint['expression'] = gdb_breakpoint.expression + breakpoint['condition'] = gdb_breakpoint.condition + breakpoint['temporary'] = gdb_breakpoint.temporary + breakpoint['hit_count'] = gdb_breakpoint.hit_count + breakpoint['pending'] = is_pending + breakpoint['what'] = what + # add addresses and source information + breakpoint['addresses'] = [] + for address, is_enabled in addresses: + if address: + sal = gdb.find_pc_line(address) + breakpoint['addresses'].append({ + 'address': address, + 'enabled': is_enabled, + 'file_name': sal.symtab.filename if address and sal.symtab else None, + 'file_line': sal.line if address else None + }) + breakpoints.append(breakpoint) + return breakpoints + +# Dashboard -------------------------------------------------------------------- + +class Dashboard(gdb.Command): + '''Redisplay the dashboard.''' + + def __init__(self): + gdb.Command.__init__(self, 'dashboard', gdb.COMMAND_USER, gdb.COMPLETE_NONE, True) + # setup subcommands + Dashboard.ConfigurationCommand(self) + Dashboard.OutputCommand(self) + Dashboard.EnabledCommand(self) + Dashboard.LayoutCommand(self) + # setup style commands + Dashboard.StyleCommand(self, 'dashboard', R, R.attributes()) + # main terminal + self.output = None + # used to inhibit redisplays during init parsing + self.inhibited = None + # enabled by default + self.enabled = None + self.enable() + + def on_continue(self, _): + # try to contain the GDB messages in a specified area unless the + # dashboard is printed to a separate file (dashboard -output ...) + # or there are no modules to display in the main terminal + enabled_modules = list(filter(lambda m: not m.output and m.enabled, self.modules)) + if self.is_running() and not self.output and len(enabled_modules) > 0: + width, _ = Dashboard.get_term_size() + gdb.write(Dashboard.clear_screen()) + gdb.write(divider(width, 'Output/messages', True)) + gdb.write('\n') + gdb.flush() + + def on_stop(self, _): + if self.is_running(): + self.render(clear_screen=False) + + def on_exit(self, _): + if not self.is_running(): + return + # collect all the outputs + outputs = set() + outputs.add(self.output) + outputs.update(module.output for module in self.modules) + outputs.remove(None) + # reset the terminal status + for output in outputs: + try: + with open(output, 'w') as fs: + fs.write(Dashboard.reset_terminal()) + except: + # skip cleanup for invalid outputs + pass + + def enable(self): + if self.enabled: + return + self.enabled = True + # setup events + gdb.events.cont.connect(self.on_continue) + gdb.events.stop.connect(self.on_stop) + gdb.events.exited.connect(self.on_exit) + + def disable(self): + if not self.enabled: + return + self.enabled = False + # setup events + gdb.events.cont.disconnect(self.on_continue) + gdb.events.stop.disconnect(self.on_stop) + gdb.events.exited.disconnect(self.on_exit) + + def load_modules(self, modules): + self.modules = [] + for module in modules: + info = Dashboard.ModuleInfo(self, module) + self.modules.append(info) + + def redisplay(self, style_changed=False): + # manually redisplay the dashboard + if self.is_running() and not self.inhibited: + self.render(True, style_changed) + + def inferior_pid(self): + return gdb.selected_inferior().pid + + def is_running(self): + return self.inferior_pid() != 0 + + def render(self, clear_screen, style_changed=False): + # fetch module content and info + all_disabled = True + display_map = dict() + for module in self.modules: + # fall back to the global value + output = module.output or self.output + # add the instance or None if disabled + if module.enabled: + all_disabled = False + instance = module.instance + else: + instance = None + display_map.setdefault(output, []).append(instance) + # process each display info + for output, instances in display_map.items(): + try: + buf = '' + # use GDB stream by default + fs = None + if output: + fs = open(output, 'w') + fd = fs.fileno() + fs.write(Dashboard.setup_terminal()) + else: + fs = gdb + fd = 1 # stdout + # get the terminal size (default main terminal if either the + # output is not a file) + try: + width, height = Dashboard.get_term_size(fd) + except: + width, height = Dashboard.get_term_size() + # clear the "screen" if requested for the main terminal, + # auxiliary terminals are always cleared + if fs is not gdb or clear_screen: + buf += Dashboard.clear_screen() + # show message if all the modules in this output are disabled + if not any(instances): + # skip the main terminal + if fs is gdb: + continue + # write the error message + buf += divider(width, 'Warning', True) + buf += '\n' + if self.modules: + buf += 'No module to display (see `dashboard -layout`)' + else: + buf += 'No module loaded' + buf += '\n' + fs.write(buf) + continue + # process all the modules for that output + for n, instance in enumerate(instances, 1): + # skip disabled modules + if not instance: + continue + try: + # ask the module to generate the content + lines = instance.lines(width, height, style_changed) + except Exception as e: + # allow to continue on exceptions in modules + stacktrace = traceback.format_exc().strip() + lines = [ansi(stacktrace, R.style_error)] + # create the divider if needed + div = [] + if not R.omit_divider or len(instances) > 1 or fs is gdb: + div = [divider(width, instance.label(), True, lines)] + # write the data + buf += '\n'.join(div + lines) + # write the newline for all but last unless main terminal + if n != len(instances) or fs is gdb: + buf += '\n' + # write the final newline and the terminator only if it is the + # main terminal to allow the prompt to display correctly (unless + # there are no modules to display) + if fs is gdb and not all_disabled: + buf += divider(width, primary=True) + buf += '\n' + fs.write(buf) + except Exception as e: + cause = traceback.format_exc().strip() + Dashboard.err('Cannot write the dashboard\n{}'.format(cause)) + finally: + # don't close gdb stream + if fs and fs is not gdb: + fs.close() + +# Utility methods -------------------------------------------------------------- + + @staticmethod + def start(): + # save the instance for customization convenience + global dashboard + # initialize the dashboard + dashboard = Dashboard() + Dashboard.set_custom_prompt(dashboard) + # parse Python inits, load modules then parse GDB inits + dashboard.inhibited = True + Dashboard.parse_inits(True) + modules = Dashboard.get_modules() + dashboard.load_modules(modules) + Dashboard.parse_inits(False) + dashboard.inhibited = False + # GDB overrides + run('set pagination off') + # display if possible (program running and not explicitly disabled by + # some configuration file) + if dashboard.enabled: + dashboard.redisplay() + + @staticmethod + def get_term_size(fd=1): # defaults to the main terminal + try: + if sys.platform == 'win32': + import curses + # XXX always neglects the fd parameter + height, width = curses.initscr().getmaxyx() + curses.endwin() + return int(width), int(height) + else: + import termios + import fcntl + # first 2 shorts (4 byte) of struct winsize + raw = fcntl.ioctl(fd, termios.TIOCGWINSZ, ' ' * 4) + height, width = struct.unpack('hh', raw) + return int(width), int(height) + except (ImportError, OSError): + # this happens when no curses library is found on windows or when + # the terminal is not properly configured + return 80, 24 # hardcoded fallback value + + @staticmethod + def set_custom_prompt(dashboard): + def custom_prompt(_): + # render thread status indicator + if dashboard.is_running(): + pid = dashboard.inferior_pid() + status = R.prompt_running.format(pid=pid) + else: + status = R.prompt_not_running + # build prompt + prompt = R.prompt.format(status=status) + prompt = gdb.prompt.substitute_prompt(prompt) + return prompt + ' ' # force trailing space + gdb.prompt_hook = custom_prompt + + @staticmethod + def parse_inits(python): + # paths where the .gdbinit.d directory might be + search_paths = [ + '/etc/gdb-dashboard', + '{}/gdb-dashboard'.format(os.getenv('XDG_CONFIG_HOME', '~/.config')), + '~/Library/Preferences/gdb-dashboard', + '~/.gdbinit.d' + ] + # expand the tilde and walk the paths + inits_dirs = (os.walk(os.path.expanduser(path)) for path in search_paths) + # process all the init files in order + for root, dirs, files in itertools.chain.from_iterable(inits_dirs): + dirs.sort() + # skipping dotfiles + for init in sorted(file for file in files if not file.startswith('.')): + path = os.path.join(root, init) + _, ext = os.path.splitext(path) + # either load Python files or GDB + if python == (ext == '.py'): + gdb.execute('source ' + path) + + @staticmethod + def get_modules(): + # scan the scope for modules + modules = [] + for name in globals(): + obj = globals()[name] + try: + if issubclass(obj, Dashboard.Module): + modules.append(obj) + except TypeError: + continue + # sort modules alphabetically + modules.sort(key=lambda x: x.__name__) + return modules + + @staticmethod + def create_command(name, invoke, doc, is_prefix, complete=None): + if callable(complete): + Class = type('', (gdb.Command,), { + '__doc__': doc, + 'invoke': invoke, + 'complete': complete + }) + Class(name, gdb.COMMAND_USER, prefix=is_prefix) + else: + Class = type('', (gdb.Command,), { + '__doc__': doc, + 'invoke': invoke + }) + Class(name, gdb.COMMAND_USER, complete or gdb.COMPLETE_NONE, is_prefix) + + @staticmethod + def err(string): + print(ansi(string, R.style_error)) + + @staticmethod + def complete(word, candidates): + return filter(lambda candidate: candidate.startswith(word), candidates) + + @staticmethod + def parse_arg(arg): + # encode unicode GDB command arguments as utf8 in Python 2.7 + if type(arg) is not str: + arg = arg.encode('utf8') + return arg + + @staticmethod + def clear_screen(): + # ANSI: move the cursor to top-left corner and clear the screen + # (optionally also clear the scrollback buffer if supported by the + # terminal) + return '\x1b[H\x1b[2J' + ('\x1b[3J' if R.discard_scrollback else '') + + @staticmethod + def setup_terminal(): + # ANSI: enable alternative screen buffer and hide cursor + return '\x1b[?1049h\x1b[?25l' + + @staticmethod + def reset_terminal(): + # ANSI: disable alternative screen buffer and show cursor + return '\x1b[?1049l\x1b[?25h' + +# Module descriptor ------------------------------------------------------------ + + class ModuleInfo: + + def __init__(self, dashboard, module): + self.name = module.__name__.lower() # from class to module name + self.enabled = True + self.output = None # value from the dashboard by default + self.instance = module() + self.doc = self.instance.__doc__ or '(no documentation)' + self.prefix = 'dashboard {}'.format(self.name) + # add GDB commands + self.add_main_command(dashboard) + self.add_output_command(dashboard) + self.add_style_command(dashboard) + self.add_subcommands(dashboard) + + def add_main_command(self, dashboard): + module = self + def invoke(self, arg, from_tty, info=self): + arg = Dashboard.parse_arg(arg) + if arg == '': + info.enabled ^= True + if dashboard.is_running(): + dashboard.redisplay() + else: + status = 'enabled' if info.enabled else 'disabled' + print('{} module {}'.format(module.name, status)) + else: + Dashboard.err('Wrong argument "{}"'.format(arg)) + doc_brief = 'Configure the {} module, with no arguments toggles its visibility.'.format(self.name) + doc = '{}\n\n{}'.format(doc_brief, self.doc) + Dashboard.create_command(self.prefix, invoke, doc, True) + + def add_output_command(self, dashboard): + Dashboard.OutputCommand(dashboard, self.prefix, self) + + def add_style_command(self, dashboard): + Dashboard.StyleCommand(dashboard, self.prefix, self.instance, self.instance.attributes()) + + def add_subcommands(self, dashboard): + for name, command in self.instance.commands().items(): + self.add_subcommand(dashboard, name, command) + + def add_subcommand(self, dashboard, name, command): + action = command['action'] + doc = command['doc'] + complete = command.get('complete') + def invoke(self, arg, from_tty, info=self): + arg = Dashboard.parse_arg(arg) + if info.enabled: + try: + action(arg) + except Exception as e: + Dashboard.err(e) + return + # don't catch redisplay errors + dashboard.redisplay() + else: + Dashboard.err('Module disabled') + prefix = '{} {}'.format(self.prefix, name) + Dashboard.create_command(prefix, invoke, doc, False, complete) + +# GDB commands ----------------------------------------------------------------- + + # handler for the `dashboard` command itself + def invoke(self, arg, from_tty): + arg = Dashboard.parse_arg(arg) + # show messages for checks in redisplay + if arg != '': + Dashboard.err('Wrong argument "{}"'.format(arg)) + elif not self.is_running(): + Dashboard.err('Is the target program running?') + else: + self.redisplay() + + class ConfigurationCommand(gdb.Command): + '''Dump or save the dashboard configuration. + +With an optional argument the configuration will be written to the specified +file. + +This command allows to configure the dashboard live then make the changes +permanent, for example: + + dashboard -configuration ~/.gdbinit.d/init + +At startup the `~/.gdbinit.d/` directory tree is walked and files are evaluated +in alphabetical order but giving priority to Python files. This is where user +configuration files must be placed.''' + + def __init__(self, dashboard): + gdb.Command.__init__(self, 'dashboard -configuration', + gdb.COMMAND_USER, gdb.COMPLETE_FILENAME) + self.dashboard = dashboard + + def invoke(self, arg, from_tty): + arg = Dashboard.parse_arg(arg) + if arg: + with open(os.path.expanduser(arg), 'w') as fs: + fs.write('# auto generated by GDB dashboard\n\n') + self.dump(fs) + self.dump(gdb) + + def dump(self, fs): + # dump layout + self.dump_layout(fs) + # dump styles + self.dump_style(fs, R) + for module in self.dashboard.modules: + self.dump_style(fs, module.instance, module.prefix) + # dump outputs + self.dump_output(fs, self.dashboard) + for module in self.dashboard.modules: + self.dump_output(fs, module, module.prefix) + + def dump_layout(self, fs): + layout = ['dashboard -layout'] + for module in self.dashboard.modules: + mark = '' if module.enabled else '!' + layout.append('{}{}'.format(mark, module.name)) + fs.write(' '.join(layout)) + fs.write('\n') + + def dump_style(self, fs, obj, prefix='dashboard'): + attributes = getattr(obj, 'attributes', lambda: dict())() + for name, attribute in attributes.items(): + real_name = attribute.get('name', name) + default = attribute.get('default') + value = getattr(obj, real_name) + if value != default: + fs.write('{} -style {} {!r}\n'.format(prefix, name, value)) + + def dump_output(self, fs, obj, prefix='dashboard'): + output = getattr(obj, 'output') + if output: + fs.write('{} -output {}\n'.format(prefix, output)) + + class OutputCommand(gdb.Command): + '''Set the output file/TTY for the whole dashboard or single modules. + +The dashboard/module will be written to the specified file, which will be +created if it does not exist. If the specified file identifies a terminal then +its geometry will be used, otherwise it falls back to the geometry of the main +GDB terminal. + +When invoked without argument on the dashboard, the output/messages and modules +which do not specify an output themselves will be printed on standard output +(default). + +When invoked without argument on a module, it will be printed where the +dashboard will be printed. + +An overview of all the outputs can be obtained with the `dashboard -layout` +command.''' + + def __init__(self, dashboard, prefix=None, obj=None): + if not prefix: + prefix = 'dashboard' + if not obj: + obj = dashboard + prefix = prefix + ' -output' + gdb.Command.__init__(self, prefix, gdb.COMMAND_USER, gdb.COMPLETE_FILENAME) + self.dashboard = dashboard + self.obj = obj # None means the dashboard itself + + def invoke(self, arg, from_tty): + arg = Dashboard.parse_arg(arg) + # reset the terminal status + if self.obj.output: + try: + with open(self.obj.output, 'w') as fs: + fs.write(Dashboard.reset_terminal()) + except: + # just do nothing if the file is not writable + pass + # set or open the output file + if arg == '': + self.obj.output = None + else: + self.obj.output = arg + # redisplay the dashboard in the new output + self.dashboard.redisplay() + + class EnabledCommand(gdb.Command): + '''Enable or disable the dashboard. + +The current status is printed if no argument is present.''' + + def __init__(self, dashboard): + gdb.Command.__init__(self, 'dashboard -enabled', gdb.COMMAND_USER) + self.dashboard = dashboard + + def invoke(self, arg, from_tty): + arg = Dashboard.parse_arg(arg) + if arg == '': + status = 'enabled' if self.dashboard.enabled else 'disabled' + print('The dashboard is {}'.format(status)) + elif arg == 'on': + self.dashboard.enable() + self.dashboard.redisplay() + elif arg == 'off': + self.dashboard.disable() + else: + msg = 'Wrong argument "{}"; expecting "on" or "off"' + Dashboard.err(msg.format(arg)) + + def complete(self, text, word): + return Dashboard.complete(word, ['on', 'off']) + + class LayoutCommand(gdb.Command): + '''Set or show the dashboard layout. + +Accepts a space-separated list of directive. Each directive is in the form +"[!]". Modules in the list are placed in the dashboard in the same order +as they appear and those prefixed by "!" are disabled by default. Omitted +modules are hidden and placed at the bottom in alphabetical order. + +Without arguments the current layout is shown where the first line uses the same +form expected by the input while the remaining depict the current status of +output files. + +Passing `!` as a single argument resets the dashboard original layout.''' + + def __init__(self, dashboard): + gdb.Command.__init__(self, 'dashboard -layout', gdb.COMMAND_USER) + self.dashboard = dashboard + + def invoke(self, arg, from_tty): + arg = Dashboard.parse_arg(arg) + directives = str(arg).split() + if directives: + # apply the layout + if directives == ['!']: + self.reset() + else: + if not self.layout(directives): + return # in case of errors + # redisplay or otherwise notify + if from_tty: + if self.dashboard.is_running(): + self.dashboard.redisplay() + else: + self.show() + else: + self.show() + + def reset(self): + modules = self.dashboard.modules + modules.sort(key=lambda module: module.name) + for module in modules: + module.enabled = True + + def show(self): + global_str = 'Dashboard' + default = '(default TTY)' + max_name_len = max(len(module.name) for module in self.dashboard.modules) + max_name_len = max(max_name_len, len(global_str)) + fmt = '{{}}{{:{}s}}{{}}'.format(max_name_len + 2) + print((fmt + '\n').format(' ', global_str, self.dashboard.output or default)) + for module in self.dashboard.modules: + mark = ' ' if module.enabled else '!' + style = R.style_high if module.enabled else R.style_low + line = fmt.format(mark, module.name, module.output or default) + print(ansi(line, style)) + + def layout(self, directives): + modules = self.dashboard.modules + # parse and check directives + parsed_directives = [] + selected_modules = set() + for directive in directives: + enabled = (directive[0] != '!') + name = directive[not enabled:] + if name in selected_modules: + Dashboard.err('Module "{}" already set'.format(name)) + return False + if next((False for module in modules if module.name == name), True): + Dashboard.err('Cannot find module "{}"'.format(name)) + return False + parsed_directives.append((name, enabled)) + selected_modules.add(name) + # reset visibility + for module in modules: + module.enabled = False + # move and enable the selected modules on top + last = 0 + for name, enabled in parsed_directives: + todo = enumerate(modules[last:], start=last) + index = next(index for index, module in todo if name == module.name) + modules[index].enabled = enabled + modules.insert(last, modules.pop(index)) + last += 1 + return True + + def complete(self, text, word): + all_modules = (m.name for m in self.dashboard.modules) + return Dashboard.complete(word, all_modules) + + class StyleCommand(gdb.Command): + '''Access the stylable attributes. + +Without arguments print all the stylable attributes. + +When only the name is specified show the current value. + +With name and value set the stylable attribute. Values are parsed as Python +literals and converted to the proper type. ''' + + def __init__(self, dashboard, prefix, obj, attributes): + self.prefix = prefix + ' -style' + gdb.Command.__init__(self, self.prefix, gdb.COMMAND_USER, gdb.COMPLETE_NONE, True) + self.dashboard = dashboard + self.obj = obj + self.attributes = attributes + self.add_styles() + + def add_styles(self): + this = self + for name, attribute in self.attributes.items(): + # fetch fields + attr_name = attribute.get('name', name) + attr_type = attribute.get('type', str) + attr_check = attribute.get('check', lambda _: True) + attr_default = attribute['default'] + # set the default value (coerced to the type) + value = attr_type(attr_default) + setattr(self.obj, attr_name, value) + # create the command + def invoke(self, arg, from_tty, + name=name, + attr_name=attr_name, + attr_type=attr_type, + attr_check=attr_check): + new_value = Dashboard.parse_arg(arg) + if new_value == '': + # print the current value + value = getattr(this.obj, attr_name) + print('{} = {!r}'.format(name, value)) + else: + try: + # convert and check the new value + parsed = ast.literal_eval(new_value) + value = attr_type(parsed) + if not attr_check(value): + msg = 'Invalid value "{}" for "{}"' + raise Exception(msg.format(new_value, name)) + except Exception as e: + Dashboard.err(e) + else: + # set and redisplay + setattr(this.obj, attr_name, value) + this.dashboard.redisplay(True) + prefix = self.prefix + ' ' + name + doc = attribute.get('doc', 'This style is self-documenting') + Dashboard.create_command(prefix, invoke, doc, False) + + def invoke(self, arg, from_tty): + # an argument here means that the provided attribute is invalid + if arg: + Dashboard.err('Invalid argument "{}"'.format(arg)) + return + # print all the pairs + for name, attribute in self.attributes.items(): + attr_name = attribute.get('name', name) + value = getattr(self.obj, attr_name) + print('{} = {!r}'.format(name, value)) + +# Base module ------------------------------------------------------------------ + + # just a tag + class Module(): + '''Base class for GDB dashboard modules. + + Modules are instantiated once at initialization time and kept during the + whole the GDB session. + + The name of a module is automatically obtained by the class name. + + Optionally, a module may include a description which will appear in the + GDB help system by specifying a Python docstring for the class. By + convention the first line should contain a brief description.''' + + def label(self): + '''Return the module label which will appear in the divider.''' + pass + + def lines(self, term_width, term_height, style_changed): + '''Return a list of strings which will form the module content. + + When a module is temporarily unable to produce its content, it + should return an empty list; its divider will then use the styles + with the "off" qualifier. + + term_width and term_height are the dimension of the terminal where + this module will be displayed. If `style_changed` is `True` then + some attributes have changed since the last time so the + implementation may want to update its status.''' + pass + + def attributes(self): + '''Return the dictionary of available attributes. + + The key is the attribute name and the value is another dictionary + with items: + + - `default` is the initial value for this attribute; + + - `doc` is the optional documentation of this attribute which will + appear in the GDB help system; + + - `name` is the name of the attribute of the Python object (defaults + to the key value); + + - `type` is the Python type of this attribute defaulting to the + `str` type, it is used to coerce the value passed as an argument + to the proper type, or raise an exception; + + - `check` is an optional control callback which accept the coerced + value and returns `True` if the value satisfies the constraint and + `False` otherwise. + + Those attributes can be accessed from the implementation using + instance variables named `name`.''' + return {} + + def commands(self): + '''Return the dictionary of available commands. + + The key is the attribute name and the value is another dictionary + with items: + + - `action` is the callback to be executed which accepts the raw + input string from the GDB prompt, exceptions in these functions + will be shown automatically to the user; + + - `doc` is the documentation of this command which will appear in + the GDB help system; + + - `completion` is the optional completion policy, one of the + `gdb.COMPLETE_*` constants defined in the GDB reference manual + (https://sourceware.org/gdb/onlinedocs/gdb/Commands-In-Python.html).''' + return {} + +# Default modules -------------------------------------------------------------- + +class Source(Dashboard.Module): + '''Show the program source code, if available.''' + + def __init__(self): + self.file_name = None + self.source_lines = [] + self.ts = None + self.highlighted = False + self.offset = 0 + + def label(self): + label = 'Source' + if self.show_path and self.file_name: + label += ': {}'.format(self.file_name) + return label + + def lines(self, term_width, term_height, style_changed): + # skip if the current thread is not stopped + if not gdb.selected_thread().is_stopped(): + return [] + # try to fetch the current line (skip if no line information) + sal = gdb.selected_frame().find_sal() + current_line = sal.line + if current_line == 0: + self.file_name = None + return [] + # try to lookup the source file + candidates = [ + sal.symtab.fullname(), + sal.symtab.filename, + # XXX GDB also uses absolute filename but it is harder to implement + # properly and IMHO useless + os.path.basename(sal.symtab.filename)] + for candidate in candidates: + file_name = candidate + ts = None + try: + ts = os.path.getmtime(file_name) + break + except: + # try another or delay error check to open() + continue + # style changed, different file name or file modified in the meanwhile + if style_changed or file_name != self.file_name or ts and ts > self.ts: + try: + # reload the source file if changed + with io.open(file_name, errors='replace') as source_file: + highlighter = Beautifier(file_name, self.tab_size) + self.highlighted = highlighter.active + source = highlighter.process(source_file.read()) + self.source_lines = source.split('\n') + # store file name and timestamp only if success to have + # persistent errors + self.file_name = file_name + self.ts = ts + except IOError as e: + msg = 'Cannot display "{}"'.format(file_name) + return [ansi(msg, R.style_error)] + # compute the line range + height = self.height or (term_height - 1) + start = current_line - 1 - int(height / 2) + self.offset + end = start + height + # extra at start + extra_start = 0 + if start < 0: + extra_start = min(-start, height) + start = 0 + # extra at end + extra_end = 0 + if end > len(self.source_lines): + extra_end = min(end - len(self.source_lines), height) + end = len(self.source_lines) + else: + end = max(end, 0) + # return the source code listing + breakpoints = fetch_breakpoints() + out = [] + number_format = '{{:>{}}}'.format(len(str(end))) + for number, line in enumerate(self.source_lines[start:end], start + 1): + # properly handle UTF-8 source files + line = to_string(line) + if int(number) == current_line: + # the current line has a different style without ANSI + if R.ansi: + if self.highlighted and not self.highlight_line: + line_format = '{}' + ansi(number_format, R.style_selected_1) + ' {}' + else: + line_format = '{}' + ansi(number_format + ' {}', R.style_selected_1) + else: + # just show a plain text indicator + line_format = '{}' + number_format + '> {}' + else: + line_format = '{}' + ansi(number_format, R.style_low) + ' {}' + # check for breakpoint presence + enabled = None + for breakpoint in breakpoints: + addresses = breakpoint['addresses'] + is_root_enabled = addresses[0]['enabled'] + for address in addresses: + # note, despite the lookup path always use the relative + # (sal.symtab.filename) file name to match source files with + # breakpoints + if address['file_line'] == number and address['file_name'] == sal.symtab.filename: + enabled = enabled or (address['enabled'] and is_root_enabled) + if enabled is None: + breakpoint = ' ' + else: + breakpoint = ansi('!', R.style_critical) if enabled else ansi('-', R.style_low) + out.append(line_format.format(breakpoint, number, line.rstrip('\n'))) + # return the output along with scroll indicators + if len(out) <= height: + extra = [ansi('~', R.style_low)] + return extra_start * extra + out + extra_end * extra + else: + return out + + def commands(self): + return { + 'scroll': { + 'action': self.scroll, + 'doc': 'Scroll by relative steps or reset if invoked without argument.' + } + } + + def attributes(self): + return { + 'height': { + 'doc': '''Height of the module. + +A value of 0 uses the whole height.''', + 'default': 10, + 'type': int, + 'check': check_ge_zero + }, + 'tab-size': { + 'doc': 'Number of spaces used to display the tab character.', + 'default': 4, + 'name': 'tab_size', + 'type': int, + 'check': check_gt_zero + }, + 'path': { + 'doc': 'Path visibility flag in the module label.', + 'default': False, + 'name': 'show_path', + 'type': bool + }, + 'highlight-line': { + 'doc': 'Decide whether the whole current line should be highlighted.', + 'default': False, + 'name': 'highlight_line', + 'type': bool + } + } + + def scroll(self, arg): + if arg: + self.offset += int(arg) + else: + self.offset = 0 + +class Assembly(Dashboard.Module): + '''Show the disassembled code surrounding the program counter. + +The instructions constituting the current statement are marked, if available.''' + + def __init__(self): + self.offset = 0 + self.cache_key = None + self.cache_asm = None + + def label(self): + return 'Assembly' + + def lines(self, term_width, term_height, style_changed): + # skip if the current thread is not stopped + if not gdb.selected_thread().is_stopped(): + return [] + # flush the cache if the style is changed + if style_changed: + self.cache_key = None + # prepare the highlighter + try: + flavor = gdb.parameter('disassembly-flavor') + except: + flavor = 'att' # not always defined (see #36) + highlighter = Beautifier(flavor, tab_size=None) + # fetch the assembly code + line_info = None + frame = gdb.selected_frame() # PC is here + height = self.height or (term_height - 1) + try: + # disassemble the current block + asm_start, asm_end = self.fetch_function_boundaries() + asm = self.fetch_asm(asm_start, asm_end, False, highlighter) + # find the location of the PC + pc_index = next(index for index, instr in enumerate(asm) + if instr['addr'] == frame.pc()) + # compute the instruction range + start = pc_index - int(height / 2) + self.offset + end = start + height + # extra at start + extra_start = 0 + if start < 0: + extra_start = min(-start, height) + start = 0 + # extra at end + extra_end = 0 + if end > len(asm): + extra_end = min(end - len(asm), height) + end = len(asm) + else: + end = max(end, 0) + # fetch actual interval + asm = asm[start:end] + # if there are line information then use it, it may be that + # line_info is not None but line_info.last is None + line_info = gdb.find_pc_line(frame.pc()) + line_info = line_info if line_info.last else None + except (gdb.error, RuntimeError, StopIteration): + # if it is not possible (stripped binary or the PC is not present in + # the output of `disassemble` as per issue #31) start from PC + try: + extra_start = 0 + extra_end = 0 + # allow to scroll down nevertheless + clamped_offset = min(self.offset, 0) + asm = self.fetch_asm(frame.pc(), height - clamped_offset, True, highlighter) + asm = asm[-clamped_offset:] + except gdb.error as e: + msg = '{}'.format(e) + return [ansi(msg, R.style_error)] + # fetch function start if available (e.g., not with @plt) + func_start = None + if self.show_function and frame.function(): + func_start = to_unsigned(frame.function().value()) + # compute the maximum offset size + if asm and func_start: + max_offset = max(len(str(abs(asm[0]['addr'] - func_start))), + len(str(abs(asm[-1]['addr'] - func_start)))) + # return the machine code + breakpoints = fetch_breakpoints() + max_length = max(instr['length'] for instr in asm) if asm else 0 + inferior = gdb.selected_inferior() + out = [] + for index, instr in enumerate(asm): + addr = instr['addr'] + length = instr['length'] + text = instr['asm'] + addr_str = format_address(addr) + if self.show_opcodes: + # fetch and format opcode + region = inferior.read_memory(addr, length) + opcodes = (' '.join('{:02x}'.format(ord(byte)) for byte in region)) + opcodes += (max_length - len(region)) * 3 * ' ' + ' ' + else: + opcodes = '' + # compute the offset if available + if self.show_function: + if func_start: + offset = '{:+d}'.format(addr - func_start) + offset = offset.ljust(max_offset + 1) # sign + func_info = '{}{}'.format(frame.function(), offset) + else: + func_info = '?' + else: + func_info = '' + format_string = '{}{}{}{}{}{}' + indicator = ' ' + text = ' ' + text + if addr == frame.pc(): + if not R.ansi: + indicator = '> ' + addr_str = ansi(addr_str, R.style_selected_1) + indicator = ansi(indicator, R.style_selected_1) + opcodes = ansi(opcodes, R.style_selected_1) + func_info = ansi(func_info, R.style_selected_1) + if not highlighter.active or self.highlight_line: + text = ansi(text, R.style_selected_1) + elif line_info and line_info.pc <= addr < line_info.last: + if not R.ansi: + indicator = ': ' + addr_str = ansi(addr_str, R.style_selected_2) + indicator = ansi(indicator, R.style_selected_2) + opcodes = ansi(opcodes, R.style_selected_2) + func_info = ansi(func_info, R.style_selected_2) + if not highlighter.active or self.highlight_line: + text = ansi(text, R.style_selected_2) + else: + addr_str = ansi(addr_str, R.style_low) + func_info = ansi(func_info, R.style_low) + # check for breakpoint presence + enabled = None + for breakpoint in breakpoints: + addresses = breakpoint['addresses'] + is_root_enabled = addresses[0]['enabled'] + for address in addresses: + if address['address'] == addr: + enabled = enabled or (address['enabled'] and is_root_enabled) + if enabled is None: + breakpoint = ' ' + else: + breakpoint = ansi('!', R.style_critical) if enabled else ansi('-', R.style_low) + out.append(format_string.format(breakpoint, addr_str, indicator, opcodes, func_info, text)) + # return the output along with scroll indicators + if len(out) <= height: + extra = [ansi('~', R.style_low)] + return extra_start * extra + out + extra_end * extra + else: + return out + + def commands(self): + return { + 'scroll': { + 'action': self.scroll, + 'doc': 'Scroll by relative steps or reset if invoked without argument.' + } + } + + def attributes(self): + return { + 'height': { + 'doc': '''Height of the module. + +A value of 0 uses the whole height.''', + 'default': 10, + 'type': int, + 'check': check_ge_zero + }, + 'opcodes': { + 'doc': 'Opcodes visibility flag.', + 'default': False, + 'name': 'show_opcodes', + 'type': bool + }, + 'function': { + 'doc': 'Function information visibility flag.', + 'default': True, + 'name': 'show_function', + 'type': bool + }, + 'highlight-line': { + 'doc': 'Decide whether the whole current line should be highlighted.', + 'default': False, + 'name': 'highlight_line', + 'type': bool + } + } + + def scroll(self, arg): + if arg: + self.offset += int(arg) + else: + self.offset = 0 + + def fetch_function_boundaries(self): + frame = gdb.selected_frame() + # parse the output of the disassemble GDB command to find the function + # boundaries, this should handle cases in which a function spans + # multiple discontinuous blocks + disassemble = run('disassemble') + for block_start, block_end in re.findall(r'Address range 0x([0-9a-f]+) to 0x([0-9a-f]+):', disassemble): + block_start = int(block_start, 16) + block_end = int(block_end, 16) + if block_start <= frame.pc() < block_end: + return block_start, block_end - 1 # need to be inclusive + # if function information is available then try to obtain the + # boundaries by looking at the superblocks + block = frame.block() + if frame.function(): + while block and (not block.function or block.function.name != frame.function().name): + block = block.superblock + block = block or frame.block() + return block.start, block.end - 1 + + def fetch_asm(self, start, end_or_count, relative, highlighter): + # fetch asm from cache or disassemble + if self.cache_key == (start, end_or_count): + asm = self.cache_asm + else: + kwargs = { + 'start_pc': start, + 'count' if relative else 'end_pc': end_or_count + } + asm = gdb.selected_frame().architecture().disassemble(**kwargs) + self.cache_key = (start, end_or_count) + self.cache_asm = asm + # syntax highlight the cached entry + for instr in asm: + instr['asm'] = highlighter.process(instr['asm']) + return asm + +class Variables(Dashboard.Module): + '''Show arguments and locals of the selected frame.''' + + def label(self): + return 'Variables' + + def lines(self, term_width, term_height, style_changed): + return Variables.format_frame( + gdb.selected_frame(), self.show_arguments, self.show_locals, self.compact, self.align, self.sort) + + def attributes(self): + return { + 'arguments': { + 'doc': 'Frame arguments visibility flag.', + 'default': True, + 'name': 'show_arguments', + 'type': bool + }, + 'locals': { + 'doc': 'Frame locals visibility flag.', + 'default': True, + 'name': 'show_locals', + 'type': bool + }, + 'compact': { + 'doc': 'Single-line display flag.', + 'default': True, + 'type': bool + }, + 'align': { + 'doc': 'Align variables in column flag (only if not compact).', + 'default': False, + 'type': bool + }, + 'sort': { + 'doc': 'Sort variables by name.', + 'default': False, + 'type': bool + } + } + + @staticmethod + def format_frame(frame, show_arguments, show_locals, compact, align, sort): + out = [] + # fetch frame arguments and locals + decorator = gdb.FrameDecorator.FrameDecorator(frame) + separator = ansi(', ', R.style_low) + if show_arguments: + def prefix(line): + return Stack.format_line('arg', line) + frame_args = decorator.frame_args() + args_lines = Variables.fetch(frame, frame_args, compact, align, sort) + if args_lines: + if compact: + args_line = separator.join(args_lines) + single_line = prefix(args_line) + out.append(single_line) + else: + out.extend(map(prefix, args_lines)) + if show_locals: + def prefix(line): + return Stack.format_line('loc', line) + frame_locals = decorator.frame_locals() + locals_lines = Variables.fetch(frame, frame_locals, compact, align, sort) + if locals_lines: + if compact: + locals_line = separator.join(locals_lines) + single_line = prefix(locals_line) + out.append(single_line) + else: + out.extend(map(prefix, locals_lines)) + return out + + @staticmethod + def fetch(frame, data, compact, align, sort): + lines = [] + name_width = 0 + if align and not compact: + name_width = max(len(str(elem.sym)) for elem in data) if data else 0 + for elem in data or []: + name = ansi(elem.sym, R.style_high) + ' ' * (name_width - len(str(elem.sym))) + equal = ansi('=', R.style_low) + value = format_value(elem.sym.value(frame), compact) + lines.append('{} {} {}'.format(name, equal, value)) + if sort: + lines.sort() + return lines + +class Stack(Dashboard.Module): + '''Show the current stack trace including the function name and the file location, if available. + +Optionally list the frame arguments and locals too.''' + + def label(self): + return 'Stack' + + def lines(self, term_width, term_height, style_changed): + # skip if the current thread is not stopped + if not gdb.selected_thread().is_stopped(): + return [] + # find the selected frame level (XXX Frame.level() is a recent addition) + start_level = 0 + frame = gdb.newest_frame() + while frame: + if frame == gdb.selected_frame(): + break + frame = frame.older() + start_level += 1 + # gather the frames + more = False + frames = [gdb.selected_frame()] + going_down = True + while True: + # stack frames limit reached + if len(frames) == self.limit: + more = True + break + # zigzag the frames starting from the selected one + if going_down: + frame = frames[-1].older() + if frame: + frames.append(frame) + else: + frame = frames[0].newer() + if frame: + frames.insert(0, frame) + start_level -= 1 + else: + break + else: + frame = frames[0].newer() + if frame: + frames.insert(0, frame) + start_level -= 1 + else: + frame = frames[-1].older() + if frame: + frames.append(frame) + else: + break + # switch direction + going_down = not going_down + # format the output + lines = [] + for number, frame in enumerate(frames, start=start_level): + selected = frame == gdb.selected_frame() + lines.extend(self.get_frame_lines(number, frame, selected)) + # add the placeholder + if more: + lines.append('[{}]'.format(ansi('+', R.style_selected_2))) + return lines + + def attributes(self): + return { + 'limit': { + 'doc': 'Maximum number of displayed frames (0 means no limit).', + 'default': 10, + 'type': int, + 'check': check_ge_zero + }, + 'arguments': { + 'doc': 'Frame arguments visibility flag.', + 'default': False, + 'name': 'show_arguments', + 'type': bool + }, + 'locals': { + 'doc': 'Frame locals visibility flag.', + 'default': False, + 'name': 'show_locals', + 'type': bool + }, + 'compact': { + 'doc': 'Single-line display flag.', + 'default': False, + 'type': bool + }, + 'align': { + 'doc': 'Align variables in column flag (only if not compact).', + 'default': False, + 'type': bool + }, + 'sort': { + 'doc': 'Sort variables by name.', + 'default': False, + 'type': bool + } + } + + def get_frame_lines(self, number, frame, selected=False): + # fetch frame info + style = R.style_selected_1 if selected else R.style_selected_2 + frame_id = ansi(str(number), style) + info = Stack.get_pc_line(frame, style) + frame_lines = [] + frame_lines.append('[{}] {}'.format(frame_id, info)) + # add frame arguments and locals + variables = Variables.format_frame( + frame, self.show_arguments, self.show_locals, self.compact, self.align, self.sort) + frame_lines.extend(variables) + return frame_lines + + @staticmethod + def format_line(prefix, line): + prefix = ansi(prefix, R.style_low) + return '{} {}'.format(prefix, line) + + @staticmethod + def get_pc_line(frame, style): + frame_pc = ansi(format_address(frame.pc()), style) + info = 'from {}'.format(frame_pc) + # if a frame function symbol is available then use it to fetch the + # current function name and address, otherwise fall back relying on the + # frame name + if frame.function(): + name = ansi(frame.function(), style) + func_start = to_unsigned(frame.function().value()) + offset = ansi(str(frame.pc() - func_start), style) + info += ' in {}+{}'.format(name, offset) + elif frame.name(): + name = ansi(frame.name(), style) + info += ' in {}'.format(name) + sal = frame.find_sal() + if sal and sal.symtab: + file_name = ansi(sal.symtab.filename, style) + file_line = ansi(str(sal.line), style) + info += ' at {}:{}'.format(file_name, file_line) + return info + +class History(Dashboard.Module): + '''List the last entries of the value history.''' + + def label(self): + return 'History' + + def lines(self, term_width, term_height, style_changed): + out = [] + # fetch last entries + for i in range(-self.limit + 1, 1): + try: + value = format_value(gdb.history(i)) + value_id = ansi('$${}', R.style_high).format(abs(i)) + equal = ansi('=', R.style_low) + line = '{} {} {}'.format(value_id, equal, value) + out.append(line) + except gdb.error: + continue + return out + + def attributes(self): + return { + 'limit': { + 'doc': 'Maximum number of values to show.', + 'default': 3, + 'type': int, + 'check': check_gt_zero + } + } + +class Memory(Dashboard.Module): + '''Allow to inspect memory regions.''' + + DEFAULT_LENGTH = 16 + + class Region(): + def __init__(self, expression, length, module): + self.expression = expression + self.length = length + self.module = module + self.original = None + self.latest = None + + def reset(self): + self.original = None + self.latest = None + + def format(self, per_line): + # fetch the memory content + try: + address = Memory.parse_as_address(self.expression) + inferior = gdb.selected_inferior() + memory = inferior.read_memory(address, self.length) + # set the original memory snapshot if needed + if not self.original: + self.original = memory + except gdb.error as e: + msg = 'Cannot access {} bytes starting at {}: {}' + msg = msg.format(self.length, self.expression, e) + return [ansi(msg, R.style_error)] + # format the memory content + out = [] + for i in range(0, len(memory), per_line): + region = memory[i:i + per_line] + pad = per_line - len(region) + address_str = format_address(address + i) + # compute changes + hexa = [] + text = [] + for j in range(len(region)): + rel = i + j + byte = memory[rel] + hexa_byte = '{:02x}'.format(ord(byte)) + text_byte = self.module.format_byte(byte) + # differences against the latest have the highest priority + if self.latest and memory[rel] != self.latest[rel]: + hexa_byte = ansi(hexa_byte, R.style_selected_1) + text_byte = ansi(text_byte, R.style_selected_1) + # cumulative changes if enabled + elif self.module.cumulative and memory[rel] != self.original[rel]: + hexa_byte = ansi(hexa_byte, R.style_selected_2) + text_byte = ansi(text_byte, R.style_selected_2) + # format the text differently for clarity + else: + text_byte = ansi(text_byte, R.style_high) + hexa.append(hexa_byte) + text.append(text_byte) + # output the formatted line + hexa_placeholder = ' {}'.format(self.module.placeholder[0] * 2) + text_placeholder = self.module.placeholder[0] + out.append('{} {}{} {}{}'.format( + ansi(address_str, R.style_low), + ' '.join(hexa), ansi(pad * hexa_placeholder, R.style_low), + ''.join(text), ansi(pad * text_placeholder, R.style_low))) + # update the latest memory snapshot + self.latest = memory + return out + + def __init__(self): + self.table = {} + + def label(self): + return 'Memory' + + def lines(self, term_width, term_height, style_changed): + out = [] + for expression, region in self.table.items(): + out.append(divider(term_width, expression)) + out.extend(region.format(self.get_per_line(term_width))) + return out + + def commands(self): + return { + 'watch': { + 'action': self.watch, + 'doc': '''Watch a memory region by expression and length. + +The length defaults to 16 bytes.''', + 'complete': gdb.COMPLETE_EXPRESSION + }, + 'unwatch': { + 'action': self.unwatch, + 'doc': 'Stop watching a memory region by expression.', + 'complete': gdb.COMPLETE_EXPRESSION + }, + 'clear': { + 'action': self.clear, + 'doc': 'Clear all the watched regions.' + } + } + + def attributes(self): + return { + 'cumulative': { + 'doc': 'Highlight changes cumulatively, watch again to reset.', + 'default': False, + 'type': bool + }, + 'full': { + 'doc': 'Take the whole horizontal space.', + 'default': False, + 'type': bool + }, + 'placeholder': { + 'doc': 'Placeholder used for missing items and unprintable characters.', + 'default': '·' + } + } + + def watch(self, arg): + if arg: + expression, _, length_str = arg.partition(' ') + length = Memory.parse_as_address(length_str) if length_str else Memory.DEFAULT_LENGTH + # keep the length when the memory is watched to reset the changes + region = self.table.get(expression) + if region and not length_str: + region.reset() + else: + self.table[expression] = Memory.Region(expression, length, self) + else: + raise Exception('Specify a memory location') + + def unwatch(self, arg): + if arg: + try: + del self.table[arg] + except KeyError: + raise Exception('Memory expression not watched') + else: + raise Exception('Specify a matched memory expression') + + def clear(self, arg): + self.table.clear() + + def format_byte(self, byte): + # `type(byte) is bytes` in Python 3 + if 0x20 < ord(byte) < 0x7f: + return chr(ord(byte)) + else: + return self.placeholder[0] + + def get_per_line(self, term_width): + if self.full: + padding = 3 # two double spaces separator (one is part of below) + elem_size = 4 # HH + 1 space + T + address_length = gdb.parse_and_eval('$pc').type.sizeof * 2 + 2 # 0x + return max(int((term_width - address_length - padding) / elem_size), 1) + else: + return Memory.DEFAULT_LENGTH + + @staticmethod + def parse_as_address(expression): + value = gdb.parse_and_eval(expression) + return to_unsigned(value) + +class Registers(Dashboard.Module): + '''Show the CPU registers and their values.''' + + def __init__(self): + self.table = {} + + def label(self): + return 'Registers' + + def lines(self, term_width, term_height, style_changed): + # skip if the current thread is not stopped + if not gdb.selected_thread().is_stopped(): + return [] + # obtain the registers to display + if style_changed: + self.table = {} + if self.register_list: + register_list = self.register_list.split() + else: + register_list = Registers.fetch_register_list() + # fetch registers status + registers = [] + for name in register_list: + # exclude registers with a dot '.' or parse_and_eval() will fail + if '.' in name: + continue + value = gdb.parse_and_eval('${}'.format(name)) + string_value = Registers.format_value(value) + # exclude unavailable registers (see #255) + if string_value == '': + continue + changed = self.table and (self.table.get(name, '') != string_value) + self.table[name] = string_value + registers.append((name, string_value, changed)) + # handle the empty register list + if not registers: + msg = 'No registers to show (check the "dashboard registers -style list" attribute)' + return [ansi(msg, R.style_error)] + # compute lengths considering an extra space between and around the + # entries (hence the +2 and term_width - 1) + max_name = max(len(name) for name, _, _ in registers) + max_value = max(len(value) for _, value, _ in registers) + max_width = max_name + max_value + 2 + columns = min(int((term_width - 1) / max_width) or 1, len(registers)) + rows = int(math.ceil(float(len(registers)) / columns)) + # build the registers matrix + if self.column_major: + matrix = list(registers[i:i + rows] for i in range(0, len(registers), rows)) + else: + matrix = list(registers[i::columns] for i in range(columns)) + # compute the lengths column wise + max_names_column = list(max(len(name) for name, _, _ in column) for column in matrix) + max_values_column = list(max(len(value) for _, value, _ in column) for column in matrix) + line_length = sum(max_names_column) + columns + sum(max_values_column) + extra = term_width - line_length + # compute padding as if there were one more column + base_padding = int(extra / (columns + 1)) + padding_column = [base_padding] * columns + # distribute the remainder among columns giving the precedence to + # internal padding + rest = extra % (columns + 1) + while rest: + padding_column[rest % columns] += 1 + rest -= 1 + # format the registers + out = [''] * rows + for i, column in enumerate(matrix): + max_name = max_names_column[i] + max_value = max_values_column[i] + for j, (name, value, changed) in enumerate(column): + name = ' ' * (max_name - len(name)) + ansi(name, R.style_low) + style = R.style_selected_1 if changed else '' + value = ansi(value, style) + ' ' * (max_value - len(value)) + padding = ' ' * padding_column[i] + item = '{}{} {}'.format(padding, name, value) + out[j] += item + return out + + def attributes(self): + return { + 'column-major': { + 'doc': 'Show registers in columns instead of rows.', + 'default': False, + 'name': 'column_major', + 'type': bool + }, + 'list': { + 'doc': '''String of space-separated register names to display. + +The empty list (default) causes to show all the available registers. For +architectures different from x86 setting this attribute might be mandatory.''', + 'default': '', + 'name': 'register_list', + } + } + + @staticmethod + def format_value(value): + try: + if value.type.code in [gdb.TYPE_CODE_INT, gdb.TYPE_CODE_PTR]: + int_value = to_unsigned(value, value.type.sizeof) + value_format = '0x{{:0{}x}}'.format(2 * value.type.sizeof) + return value_format.format(int_value) + except (gdb.error, ValueError): + # convert to unsigned but preserve code and flags information + pass + return str(value) + + @staticmethod + def fetch_register_list(*match_groups): + names = [] + for line in run('maintenance print register-groups').split('\n'): + fields = line.split() + if len(fields) != 7: + continue + name, _, _, _, _, _, groups = fields + if not re.match(r'\w', name): + continue + for group in groups.split(','): + if group in (match_groups or ('general',)): + names.append(name) + break + return names + +class Threads(Dashboard.Module): + '''List the currently available threads.''' + + def label(self): + return 'Threads' + + def lines(self, term_width, term_height, style_changed): + out = [] + selected_thread = gdb.selected_thread() + # do not restore the selected frame if the thread is not stopped + restore_frame = gdb.selected_thread().is_stopped() + if restore_frame: + selected_frame = gdb.selected_frame() + # fetch the thread list + threads = [] + for inferior in gdb.inferiors(): + if self.all_inferiors or inferior == gdb.selected_inferior(): + threads += gdb.Inferior.threads(inferior) + for thread in threads: + # skip running threads if requested + if self.skip_running and thread.is_running(): + continue + is_selected = (thread.ptid == selected_thread.ptid) + style = R.style_selected_1 if is_selected else R.style_selected_2 + if self.all_inferiors: + number = '{}.{}'.format(thread.inferior.num, thread.num) + else: + number = str(thread.num) + number = ansi(number, style) + tid = ansi(str(thread.ptid[1] or thread.ptid[2]), style) + info = '[{}] id {}'.format(number, tid) + if thread.name: + info += ' name {}'.format(ansi(thread.name, style)) + # switch thread to fetch info (unless is running in non-stop mode) + try: + thread.switch() + frame = gdb.newest_frame() + info += ' ' + Stack.get_pc_line(frame, style) + except gdb.error: + info += ' (running)' + out.append(info) + # restore thread and frame + selected_thread.switch() + if restore_frame: + selected_frame.select() + return out + + def attributes(self): + return { + 'skip-running': { + 'doc': 'Skip running threads.', + 'default': False, + 'name': 'skip_running', + 'type': bool + }, + 'all-inferiors': { + 'doc': 'Show threads from all inferiors.', + 'default': False, + 'name': 'all_inferiors', + 'type': bool + }, + } + +class Expressions(Dashboard.Module): + '''Watch user expressions.''' + + def __init__(self): + self.table = [] + + def label(self): + return 'Expressions' + + def lines(self, term_width, term_height, style_changed): + out = [] + label_width = 0 + if self.align: + label_width = max(len(expression) for expression in self.table) if self.table else 0 + default_radix = Expressions.get_default_radix() + for number, expression in enumerate(self.table, start=1): + label = expression + match = re.match(r'^/(\d+) +(.+)$', expression) + try: + if match: + radix, expression = match.groups() + run('set output-radix {}'.format(radix)) + value = format_value(gdb.parse_and_eval(expression)) + except gdb.error as e: + value = ansi(e, R.style_error) + finally: + if match: + run('set output-radix {}'.format(default_radix)) + number = ansi(str(number), R.style_selected_2) + label = ansi(expression, R.style_high) + ' ' * (label_width - len(expression)) + equal = ansi('=', R.style_low) + out.append('[{}] {} {} {}'.format(number, label, equal, value)) + return out + + def commands(self): + return { + 'watch': { + 'action': self.watch, + 'doc': 'Watch an expression using the format `[/] `.', + 'complete': gdb.COMPLETE_EXPRESSION + }, + 'unwatch': { + 'action': self.unwatch, + 'doc': 'Stop watching an expression by index.' + }, + 'clear': { + 'action': self.clear, + 'doc': 'Clear all the watched expressions.' + } + } + + def attributes(self): + return { + 'align': { + 'doc': 'Align variables in column flag.', + 'default': False, + 'type': bool + } + } + + def watch(self, arg): + if arg: + if arg not in self.table: + self.table.append(arg) + else: + raise Exception('Expression already watched') + else: + raise Exception('Specify an expression') + + def unwatch(self, arg): + if arg: + try: + number = int(arg) - 1 + except: + number = -1 + if 0 <= number < len(self.table): + self.table.pop(number) + else: + raise Exception('Expression not watched') + else: + raise Exception('Specify an expression') + + def clear(self, arg): + self.table.clear() + + @staticmethod + def get_default_radix(): + try: + return gdb.parameter('output-radix') + except RuntimeError: + # XXX this is a fix for GDB <8.1.x see #161 + message = run('show output-radix') + match = re.match(r'^Default output radix for printing of values is (\d+)\.$', message) + return match.groups()[0] if match else 10 # fallback + +# XXX workaround to support BP_BREAKPOINT in older GDB versions +setattr(gdb, 'BP_CATCHPOINT', getattr(gdb, 'BP_CATCHPOINT', 26)) + +class Breakpoints(Dashboard.Module): + '''Display the breakpoints list.''' + + NAMES = { + gdb.BP_BREAKPOINT: 'break', + gdb.BP_WATCHPOINT: 'watch', + gdb.BP_HARDWARE_WATCHPOINT: 'write watch', + gdb.BP_READ_WATCHPOINT: 'read watch', + gdb.BP_ACCESS_WATCHPOINT: 'access watch', + gdb.BP_CATCHPOINT: 'catch' + } + + def label(self): + return 'Breakpoints' + + def lines(self, term_width, term_height, style_changed): + out = [] + breakpoints = fetch_breakpoints(watchpoints=True, pending=self.show_pending) + for breakpoint in breakpoints: + sub_lines = [] + # format common information + style = R.style_selected_1 if breakpoint['enabled'] else R.style_selected_2 + number = ansi(breakpoint['number'], style) + bp_type = ansi(Breakpoints.NAMES[breakpoint['type']], style) + if breakpoint['temporary']: + bp_type = bp_type + ' {}'.format(ansi('once', style)) + if not R.ansi and breakpoint['enabled']: + bp_type = 'disabled ' + bp_type + line = '[{}] {}'.format(number, bp_type) + if breakpoint['type'] == gdb.BP_BREAKPOINT: + for i, address in enumerate(breakpoint['addresses']): + addr = address['address'] + if i == 0 and addr: + # this is a regular breakpoint + line += ' at {}'.format(ansi(format_address(addr), style)) + # format source information + file_name = address.get('file_name') + file_line = address.get('file_line') + if file_name and file_line: + file_name = ansi(file_name, style) + file_line = ansi(file_line, style) + line += ' in {}:{}'.format(file_name, file_line) + elif i > 0: + # this is a sub breakpoint + sub_style = R.style_selected_1 if address['enabled'] else R.style_selected_2 + sub_number = ansi('{}.{}'.format(breakpoint['number'], i), sub_style) + sub_line = '[{}]'.format(sub_number) + sub_line += ' at {}'.format(ansi(format_address(addr), sub_style)) + # format source information + file_name = address.get('file_name') + file_line = address.get('file_line') + if file_name and file_line: + file_name = ansi(file_name, sub_style) + file_line = ansi(file_line, sub_style) + sub_line += ' in {}:{}'.format(file_name, file_line) + sub_lines += [sub_line] + # format user location + location = breakpoint['location'] + line += ' for {}'.format(ansi(location, style)) + elif breakpoint['type'] == gdb.BP_CATCHPOINT: + what = breakpoint['what'] + line += ' {}'.format(ansi(what, style)) + else: + # format user expression + expression = breakpoint['expression'] + line += ' for {}'.format(ansi(expression, style)) + # format condition + condition = breakpoint['condition'] + if condition: + line += ' if {}'.format(ansi(condition, style)) + # format hit count + hit_count = breakpoint['hit_count'] + if hit_count: + word = 'time{}'.format('s' if hit_count > 1 else '') + line += ' hit {} {}'.format(ansi(breakpoint['hit_count'], style), word) + # append the main line and possibly sub breakpoints + out.append(line) + out.extend(sub_lines) + return out + + def attributes(self): + return { + 'pending': { + 'doc': 'Also show pending breakpoints.', + 'default': True, + 'name': 'show_pending', + 'type': bool + } + } + +# XXX traceback line numbers in this Python block must be increased by 1 +end + +# Better GDB defaults ---------------------------------------------------------- + +set history save +set verbose off +set print pretty on +set print array off +set print array-indexes on +set python print-stack full + +# Start ------------------------------------------------------------------------ + +python Dashboard.start() + +# File variables --------------------------------------------------------------- + +# vim: filetype=python +# Local Variables: +# mode: python +# End: diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..fbb5bce --- /dev/null +++ b/.gitignore @@ -0,0 +1,4 @@ +.cache/ +.clangd +.pio/ +compile_commands.json diff --git a/README.md b/README.md new file mode 100644 index 0000000..70a1869 --- /dev/null +++ b/README.md @@ -0,0 +1,84 @@ +Commands to initialize: + +To run every time you create a new file to update the compile\_commands.json: +pio run -t compiledb + +Command to generate/override a .clangd and write the symlink in the toolchain folder +pio run -t clangd + +Command to build the firmware without uploading +pio run -t buildprog + +Command to build the firmware and upload it +pio run -t upload + +If in the buildprog/upload you use the verbose like: +pio run -t upload -v +The system will tell you the exact size of the ELF sections. + +Commadn to open the serial monitor +pio device monitor + +Command extremely powerful to obtain the size of every symbol inside a firmware.elf: +```bash +objdump -t .pio/build/stm8sblue/firmware.elf | sort | uniq | awk ' +/^[0-9a-f]+ / { + if (prev_addr != "") { + sizes[prev_symbol] = strtonum("0x"$1) - prev_addr; + } + prev_addr = strtonum("0x"$1); + prev_symbol = $NF; + addresses[NR] = prev_addr; + symbols[NR] = prev_symbol; + count++; +} +END { + for (i = 1; i <= count; i++) { + if (i == count) { + sizes[symbols[i]] = 0; # Size of the last symbol is unknown, set to 0 + } + printf "Address: 0x%08x Symbol: %s Size: %d\n", addresses[i], symbols[i], sizes[symbols[i]]; + } +}' +``` + +Acconsenti al caricamento del .gdbinit in GDB mettendo nel tuo ~/.gdbinit: +``` +add-auto-load-safe-path /PROJECT_DIR_ABSOLUTE_PATH/.gdbinit +``` + +Librerie richieste da stm8-gdb +paru -S python2-bin +sudo ln -s /usr/lib/libmpfr.so /usr/lib/libmpfr.so.4 + +Per lanciare il debugger: +Assicurati di avere un firmware compilato con i debug symbols. Per crearlo fai: +pio debug +Apri poi un terminale e fai +pio pkg exec openocd -- -f interface/stlink-dap.cfg -f target/stm8s103.cfg -c "init" -c "reset halt" +Poi in un altro +pio pkg exec stm8-gdb -- .pio/build/stm8sblue/firmware.elf + + +Note: +Nel caso serva flashare a mano: +~/git/stm8flash/stm8flash -c stlinkv3 -p stm8s103f3 -s flash -w .pio/build/stm8sblue/firmware.hex + +Risulta che nonostante la parte di sviluppo sia compensabile easy con Platformio, esistono dei problemi che sono difficili da sistemare. +I problemi sono: +- Su Windows stm8flash e' troppo vecchio e non funziona correttamente +- Durante il Debug, OpenOCD non si apre propriamente in background, non ho idea di come deubggare la cosa... +- L'OpenOCD shippato potrebbe essere troppo vecchio per STLink-V3 +- stm8gdb shippato e' buildato senza il supporto alla TUI rendendo il debugging estremamente macchinoso senza VSCode +- VSCode e' impossibile da configurare propriamente per ignorare le peculiarita di SDCC toolchain, dato che non ho trovato modo di aggiungere build flag al solo c/cpp json config senza che esse venissero usate effettivamente per il build. L'approccio su VSCode richiede env separati per sviluppo e compilazione nel platformio.ini, cosa estremamente scomoda e prona a errori + +Attualmente l'assetto con Clangd e vim sembra ottimo, quindi VSCode non e' un opzione. +L'unica alternativa che ho in mente e' utilizzare una versione aggiornata di: +- stm8flash (su Windows) +- openocd (per STLink-V3) +- stm8binutils (per avere TUI GDB!) +Gli altri possiamo lasciarli cosi come sono... per ora. +Qual e' il modo migliore? Generalmente openocd (e sdcc) sono comuni sulle repo dei sistemi operativi, gli unici magagni sono stm8flash e stm8binutils che van sicuramente compilati. +Su Linux per un environment base l'unica necessita e' avere stm8binutils compilato con le flag giuste. + +stm8binutils sembra INCOMPILABILE... diff --git a/extra_script.py b/extra_script.py new file mode 100644 index 0000000..45b8376 --- /dev/null +++ b/extra_script.py @@ -0,0 +1,61 @@ +Import("env") + +def gen_clangd(target, source, env): + _ = target + _ = source + from subprocess import run + import shlex + from pathlib import Path + + SDCC = run(shlex.split("which sdcc"), capture_output=True).stdout.decode().strip() + # SDCC = '/home/fpasqua/.platformio/packages/toolchain-sdcc/bin/sdcc' + p = Path(SDCC).parent.parent # toolchain root + SDCC_INCLUDE = p / 'share' / 'sdcc' / 'include' + # SDCC_INCLUDE = '/home/fpasqua/.platformio/packages/toolchain-sdcc/share/sdcc/include/' + GETDEFINEFLAGS = '-E -dM -mstm8 -x c /dev/null' + res = run([SDCC] + shlex.split(GETDEFINEFLAGS), capture_output=True) + res.check_returncode() + defines_raw = res.stdout.decode().strip().split('\n') + defines = [d.replace('#define ', '-D').replace(' ', '=') for d in defines_raw] + sdcc_defines = ", ".join(defines) + + sdccext_defines = ", ".join(['-D__trap=', '-D__interrupt(x)=']) + + SUPPRESSED = [ + "clang-diagnostic-main-return-type", + "clang-diagnostic-empty-body", + "pp_including_mainfile_in_preamble", + ] + + with open('.clangd', 'w') as f: + f.writelines([ + 'CompileFlags:\n', + f' Add: [-I{SDCC_INCLUDE}, {sdcc_defines}, {sdccext_defines}]\n' + ' Remove: [--opt-code-size, -mstm8]\n', + 'Index:\n', + ' StandardLibrary: No\n', + 'Diagnostics:\n', + ' Suppress:\n', + *[f' - "{s}"\n' for s in SUPPRESSED], + ' UnusedIncludes: None\n', + ]) + print("Project .clangd created") + + o = run(shlex.split(f'ln -s -f {env["PROJECT_DIR"]}/.clangd .clangd'), cwd=p) + o.check_returncode() + print(f"Symlink to toolchain {p / '.clangd'} done.") + +# include toolchain paths +env.Replace(COMPILATIONDB_INCLUDE_TOOLCHAIN=True) + +# custom .clangd initialization +env.AddCustomTarget( + name='clangd', + dependencies=None, + actions=gen_clangd, + title='Gen .clangd', + description='Generate required files for clangd to work properly.', + always_build=True, +) + +# TODO: add target to load the .clangd in the sdcc toolchain too diff --git a/include/README b/include/README new file mode 100644 index 0000000..194dcd4 --- /dev/null +++ b/include/README @@ -0,0 +1,39 @@ + +This directory is intended for project header files. + +A header file is a file containing C declarations and macro definitions +to be shared between several project source files. You request the use of a +header file in your project source file (C, C++, etc) located in `src` folder +by including it, with the C preprocessing directive `#include'. + +```src/main.c + +#include "header.h" + +int main (void) +{ + ... +} +``` + +Including a header file produces the same results as copying the header file +into each source file that needs it. Such copying would be time-consuming +and error-prone. With a header file, the related declarations appear +in only one place. If they need to be changed, they can be changed in one +place, and programs that include the header file will automatically use the +new version when next recompiled. The header file eliminates the labor of +finding and changing all the copies as well as the risk that a failure to +find one copy will result in inconsistencies within a program. + +In C, the usual convention is to give header files names that end with `.h'. +It is most portable to use only letters, digits, dashes, and underscores in +header file names, and at most one dot. + +Read more about using header files in official GCC documentation: + +* Include Syntax +* Include Operation +* Once-Only Headers +* Computed Includes + +https://gcc.gnu.org/onlinedocs/cpp/Header-Files.html diff --git a/lib/README b/lib/README new file mode 100644 index 0000000..2593a33 --- /dev/null +++ b/lib/README @@ -0,0 +1,46 @@ + +This directory is intended for project specific (private) libraries. +PlatformIO will compile them to static libraries and link into executable file. + +The source code of each library should be placed in an own separate directory +("lib/your_library_name/[here are source files]"). + +For example, see a structure of the following two libraries `Foo` and `Bar`: + +|--lib +| | +| |--Bar +| | |--docs +| | |--examples +| | |--src +| | |- Bar.c +| | |- Bar.h +| | |- library.json (optional, custom build options, etc) https://docs.platformio.org/page/librarymanager/config.html +| | +| |--Foo +| | |- Foo.c +| | |- Foo.h +| | +| |- README --> THIS FILE +| +|- platformio.ini +|--src + |- main.c + +and a contents of `src/main.c`: +``` +#include +#include + +int main (void) +{ + ... +} + +``` + +PlatformIO Library Dependency Finder will find automatically dependent +libraries scanning project source files. + +More information about PlatformIO Library Dependency Finder +- https://docs.platformio.org/page/librarymanager/ldf.html diff --git a/oldblink/main.c b/oldblink/main.c new file mode 100644 index 0000000..833b898 --- /dev/null +++ b/oldblink/main.c @@ -0,0 +1,123 @@ +/** + ****************************************************************************** + * @file GPIO_Toggle\main.c + * @author MCD Application Team + * @version V2.0.4 + * @date 26-April-2018 + * @brief This file contains the main function for GPIO Toggle example. + ****************************************************************************** + * @attention + * + *

© COPYRIGHT 2014 STMicroelectronics

+ * + * Licensed under MCD-ST Liberty SW License Agreement V2, (the "License"); + * You may not use this file except in compliance with the License. + * You may obtain a copy of the License at: + * + * http://www.st.com/software_license_agreement_liberty_v2 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + ****************************************************************************** + */ + +/* Includes ------------------------------------------------------------------*/ +#include "stm8s.h" +#include "stm8s_it.h" /* SDCC patch: required by SDCC for interrupts */ + +/** + * @addtogroup GPIO_Toggle + * @{ + */ + +/* Private typedef -----------------------------------------------------------*/ +/* Private define ------------------------------------------------------------*/ +/* Evalboard I/Os configuration */ + +/* automatically use built-in LED for known nucleo boards */ +#if defined(STM8S_NUCLEO_208RB) || defined(STM8S_NUCLEO_207K8) +#define LED_GPIO_PORT (GPIOC) +#define LED_GPIO_PINS (GPIO_PIN_5) +#elif defined(STM8S103) +/* for STM8S103F3 breakout board. building with GPIOG would result in failure (chip + * does not have that GPIO peripheral) */ +#define LED_GPIO_PORT (GPIOB) +#define LED_GPIO_PINS (GPIO_PIN_5) +#else +#define LED_GPIO_PORT (GPIOG) +#define LED_GPIO_PINS (GPIO_PIN_3 | GPIO_PIN_2 | GPIO_PIN_1 | GPIO_PIN_0) +#endif + +/* Private macro -------------------------------------------------------------*/ +/* Private variables ---------------------------------------------------------*/ +/* Private function prototypes -----------------------------------------------*/ +void Delay (uint16_t nCount); + +/* Private functions ---------------------------------------------------------*/ +/* Public functions ----------------------------------------------------------*/ + +/** + * @brief Main program. + * @param None + * @retval None + */ +void main(void) +{ + + /* Initialize I/Os in Output Mode */ + GPIO_Init(LED_GPIO_PORT, (GPIO_Pin_TypeDef)LED_GPIO_PINS, GPIO_MODE_OUT_PP_LOW_FAST); + + while (1) + { + /* Toggles LEDs */ + GPIO_WriteReverse(LED_GPIO_PORT, (GPIO_Pin_TypeDef)LED_GPIO_PINS); + Delay(0xFFFF); + } + +} + +/** + * @brief Delay + * @param nCount + * @retval None + */ +void Delay(uint16_t nCount) +{ + /* Decrement nCount value */ + while (nCount != 0) + { + nCount--; + } +} + +#ifdef USE_FULL_ASSERT + +/** + * @brief Reports the name of the source file and the source line number + * where the assert_param error has occurred. + * @param file: pointer to the source file name + * @param line: assert_param error line source number + * @retval None + */ +void assert_failed(uint8_t* file, uint32_t line) +{ + /* User can add his own implementation to report the file name and line number, + ex: printf("Wrong parameters value: file %s on line %d\r\n", file, line) */ + + /* Infinite loop */ + while (1) + { + } +} +#endif + +/** + * @} + */ + + +/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/ diff --git a/oldblink/stm8s_conf.h b/oldblink/stm8s_conf.h new file mode 100644 index 0000000..a9ff7c4 --- /dev/null +++ b/oldblink/stm8s_conf.h @@ -0,0 +1,118 @@ +/** + ****************************************************************************** + * @file stm8s_conf.h + * @author MCD Application Team + * @version V2.0.4 + * @date 26-April-2018 + * @brief This file is used to configure the Library. + ****************************************************************************** + * @attention + * + *

© COPYRIGHT 2014 STMicroelectronics

+ * + * Licensed under MCD-ST Liberty SW License Agreement V2, (the "License"); + * You may not use this file except in compliance with the License. + * You may obtain a copy of the License at: + * + * http://www.st.com/software_license_agreement_liberty_v2 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + ****************************************************************************** + */ + +/* SDCC patch: include "STM8AF622x" defined in "STM8S_StdPeriph_Tempate" */ + +/* Define to prevent recursive inclusion -------------------------------------*/ +#ifndef __STM8S_CONF_H +#define __STM8S_CONF_H + +/* Includes ------------------------------------------------------------------*/ +#include "stm8s.h" + +/* Uncomment the line below to enable peripheral header file inclusion */ +#if defined(STM8S105) || defined(STM8S005) || defined(STM8S103) || defined(STM8S003) ||\ + defined(STM8S001) || defined(STM8S903) || defined (STM8AF626x) || defined (STM8AF622x) +//#include "stm8s_adc1.h" +#endif /* (STM8S105) ||(STM8S103) || (STM8S001) || (STM8S903) || (STM8AF626x) */ +#if defined(STM8S208) || defined(STM8S207) || defined(STM8S007) || defined (STM8AF52Ax) ||\ + defined (STM8AF62Ax) +// #include "stm8s_adc2.h" +#endif /* (STM8S208) || (STM8S207) || (STM8AF62Ax) || (STM8AF52Ax) */ +//#include "stm8s_awu.h" +//#include "stm8s_beep.h" +#if defined (STM8S208) || defined (STM8AF52Ax) +// #include "stm8s_can.h" +#endif /* (STM8S208) || (STM8AF52Ax) */ +//#include "stm8s_clk.h" +//#include "stm8s_exti.h" +//#include "stm8s_flash.h" +#include "stm8s_gpio.h" +//#include "stm8s_i2c.h" +//#include "stm8s_itc.h" +//#include "stm8s_iwdg.h" +//#include "stm8s_rst.h" +//#include "stm8s_spi.h" +//#include "stm8s_tim1.h" +#if !defined(STM8S903) && !defined(STM8AF622x) /* SDCC patch: see https://github.com/tenbaht/sduino/tree/master/STM8S_StdPeriph_Driver */ +// #include "stm8s_tim2.h" +#endif /* (STM8S903) || (STM8AF622x) */ +#if defined(STM8S208) || defined(STM8S207) || defined(STM8S007) ||defined(STM8S105) ||\ + defined(STM8S005) || defined (STM8AF52Ax) || defined (STM8AF62Ax) || defined (STM8AF626x) +// #include "stm8s_tim3.h" +#endif /* (STM8S208) || (STM8S207) || (STM8S007) || (STM8S105) */ +#if !defined(STM8S903) && !defined(STM8AF622x) /* SDCC patch: see https://github.com/tenbaht/sduino/tree/master/STM8S_StdPeriph_Driver */ +// #include "stm8s_tim4.h" +#endif /* (STM8S903) || (STM8AF622x) */ +#if defined(STM8S903) || defined(STM8AF622x) /* SDCC patch: see https://github.com/tenbaht/sduino/tree/master/STM8S_StdPeriph_Driver */ +// #include "stm8s_tim5.h" +// #include "stm8s_tim6.h" +#endif /* (STM8S903) || (STM8AF622x) */ +#if defined(STM8S208) || defined(STM8S207) || defined(STM8S007) || defined(STM8S103) ||\ + defined(STM8S003) || defined(STM8S001) || defined(STM8S903) || defined (STM8AF52Ax) || defined (STM8AF62Ax) +// #include "stm8s_uart1.h" +#endif /* (STM8S208) || (STM8S207) || (STM8S103) || (STM8S001) || (STM8S903) || (STM8AF52Ax) || (STM8AF62Ax) */ +#if defined(STM8S105) || defined(STM8S005) || defined (STM8AF626x) +// #include "stm8s_uart2.h" +#endif /* (STM8S105) || (STM8AF626x) */ +#if defined(STM8S208) ||defined(STM8S207) || defined(STM8S007) || defined (STM8AF52Ax) ||\ + defined (STM8AF62Ax) +// #include "stm8s_uart3.h" +#endif /* (STM8S208) || (STM8S207) || (STM8AF52Ax) || (STM8AF62Ax) */ +#if defined(STM8AF622x) /* SDCC patch: see https://github.com/tenbaht/sduino/tree/master/STM8S_StdPeriph_Driver */ +// #include "stm8s_uart4.h" +#endif /* (STM8AF622x) */ +//#include "stm8s_wwdg.h" + +/* Exported types ------------------------------------------------------------*/ +/* Exported constants --------------------------------------------------------*/ +/* Uncomment the line below to expanse the "assert_param" macro in the + Standard Peripheral Library drivers code */ +#define USE_FULL_ASSERT (1) + +/* Exported macro ------------------------------------------------------------*/ +#ifdef USE_FULL_ASSERT + +/** + * @brief The assert_param macro is used for function's parameters check. + * @param expr: If expr is false, it calls assert_failed function + * which reports the name of the source file and the source + * line number of the call that failed. + * If expr is true, it returns no value. + * @retval : None + */ +#define assert_param(expr) ((expr) ? (void)0 : assert_failed((uint8_t *)__FILE__, __LINE__)) +/* Exported functions ------------------------------------------------------- */ +void assert_failed(uint8_t* file, uint32_t line); +#else +#define assert_param(expr) ((void)0) +#endif /* USE_FULL_ASSERT */ + +#endif /* __STM8S_CONF_H */ + + +/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/ diff --git a/oldblink/stm8s_it.c b/oldblink/stm8s_it.c new file mode 100644 index 0000000..6362de5 --- /dev/null +++ b/oldblink/stm8s_it.c @@ -0,0 +1,482 @@ +/** + ****************************************************************************** + * @file stm8s_it.c + * @author MCD Application Team + * @version V2.0.4 + * @date 26-April-2018 + * @brief Main Interrupt Service Routines. + ****************************************************************************** + * @attention + * + *

© COPYRIGHT 2014 STMicroelectronics

+ * + * Licensed under MCD-ST Liberty SW License Agreement V2, (the "License"); + * You may not use this file except in compliance with the License. + * You may obtain a copy of the License at: + * + * http://www.st.com/software_license_agreement_liberty_v2 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + ****************************************************************************** + */ + +/* Includes ------------------------------------------------------------------*/ +#include "stm8s_it.h" + +/* Private typedef -----------------------------------------------------------*/ +/* Private define ------------------------------------------------------------*/ +/* Private macro -------------------------------------------------------------*/ +/* Private variables ---------------------------------------------------------*/ +/* Private function prototypes -----------------------------------------------*/ +/* Private functions ---------------------------------------------------------*/ + +/* Public functions ----------------------------------------------------------*/ + +/** @addtogroup GPIO_Toggle + * @{ + */ +#ifdef _COSMIC_ +/** + * @brief Dummy interrupt routine + * @param None + * @retval None + */ +INTERRUPT_HANDLER(NonHandledInterrupt, 25) +{ + /* In order to detect unexpected events during development, + it is recommended to set a breakpoint on the following instruction. + */ +} +#endif /*_COSMIC_*/ + +/** + * @brief TRAP interrupt routine + * @param None + * @retval None + */ +INTERRUPT_HANDLER_TRAP(TRAP_IRQHandler) +{ + /* In order to detect unexpected events during development, + it is recommended to set a breakpoint on the following instruction. + */ +} +/** + * @brief Top Level Interrupt routine + * @param None + * @retval None + */ +INTERRUPT_HANDLER(TLI_IRQHandler, 0) +{ + /* In order to detect unexpected events during development, + it is recommended to set a breakpoint on the following instruction. + */ +} + +/** + * @brief Auto Wake Up Interrupt routine + * @param None + * @retval None + */ +INTERRUPT_HANDLER(AWU_IRQHandler, 1) +{ + /* In order to detect unexpected events during development, + it is recommended to set a breakpoint on the following instruction. + */ +} + +/** + * @brief Clock Controller Interrupt routine + * @param None + * @retval None + */ +INTERRUPT_HANDLER(CLK_IRQHandler, 2) +{ + /* In order to detect unexpected events during development, + it is recommended to set a breakpoint on the following instruction. + */ +} + +/** + * @brief External Interrupt PORTA Interrupt routine + * @param None + * @retval None + */ +INTERRUPT_HANDLER(EXTI_PORTA_IRQHandler, 3) +{ + /* In order to detect unexpected events during development, + it is recommended to set a breakpoint on the following instruction. + */ +} + +/** + * @brief External Interrupt PORTB Interrupt routine + * @param None + * @retval None + */ +INTERRUPT_HANDLER(EXTI_PORTB_IRQHandler, 4) +{ + /* In order to detect unexpected events during development, + it is recommended to set a breakpoint on the following instruction. + */ +} + +/** + * @brief External Interrupt PORTC Interrupt routine + * @param None + * @retval None + */ +INTERRUPT_HANDLER(EXTI_PORTC_IRQHandler, 5) +{ + /* In order to detect unexpected events during development, + it is recommended to set a breakpoint on the following instruction. + */ +} + +/** + * @brief External Interrupt PORTD Interrupt routine + * @param None + * @retval None + */ +INTERRUPT_HANDLER(EXTI_PORTD_IRQHandler, 6) +{ + /* In order to detect unexpected events during development, + it is recommended to set a breakpoint on the following instruction. + */ +} + +/** + * @brief External Interrupt PORTE Interrupt routine + * @param None + * @retval None + */ +INTERRUPT_HANDLER(EXTI_PORTE_IRQHandler, 7) +{ + /* In order to detect unexpected events during development, + it is recommended to set a breakpoint on the following instruction. + */ +} +#ifdef STM8S903 +/** + * @brief External Interrupt PORTF Interrupt routine + * @param None + * @retval None + */ + INTERRUPT_HANDLER(EXTI_PORTF_IRQHandler, 8) +{ + /* In order to detect unexpected events during development, + it is recommended to set a breakpoint on the following instruction. + */ +} +#endif /*STM8S903*/ + +#if defined (STM8S208) || defined (STM8AF52Ax) +/** + * @brief CAN RX Interrupt routine. + * @param None + * @retval None + */ + INTERRUPT_HANDLER(CAN_RX_IRQHandler, 8) +{ + /* In order to detect unexpected events during development, + it is recommended to set a breakpoint on the following instruction. + */ +} + +/** + * @brief CAN TX Interrupt routine + * @param None + * @retval None + */ + INTERRUPT_HANDLER(CAN_TX_IRQHandler, 9) +{ + /* In order to detect unexpected events during development, + it is recommended to set a breakpoint on the following instruction. + */ +} +#endif /*STM8S208 || STM8AF52Ax */ + +/** + * @brief SPI Interrupt routine + * @param None + * @retval None + */ +INTERRUPT_HANDLER(SPI_IRQHandler, 10) +{ + /* In order to detect unexpected events during development, + it is recommended to set a breakpoint on the following instruction. + */ +} + +/** + * @brief Timer1 Update/Overflow/Trigger/Break Interrupt routine + * @param None + * @retval None + */ +INTERRUPT_HANDLER(TIM1_UPD_OVF_TRG_BRK_IRQHandler, 11) +{ + /* In order to detect unexpected events during development, + it is recommended to set a breakpoint on the following instruction. + */ +} + +/** + * @brief Timer1 Capture/Compare Interrupt routine + * @param None + * @retval None + */ +INTERRUPT_HANDLER(TIM1_CAP_COM_IRQHandler, 12) +{ + /* In order to detect unexpected events during development, + it is recommended to set a breakpoint on the following instruction. + */ +} + +#ifdef STM8S903 +/** + * @brief Timer5 Update/Overflow/Break/Trigger Interrupt routine + * @param None + * @retval None + */ + INTERRUPT_HANDLER(TIM5_UPD_OVF_BRK_TRG_IRQHandler, 13) +{ + /* In order to detect unexpected events during development, + it is recommended to set a breakpoint on the following instruction. + */ +} +/** + * @brief Timer5 Capture/Compare Interrupt routine + * @param None + * @retval None + */ + INTERRUPT_HANDLER(TIM5_CAP_COM_IRQHandler, 14) +{ + /* In order to detect unexpected events during development, + it is recommended to set a breakpoint on the following instruction. + */ +} + +#else /*STM8S208, STM8S207, STM8S105 or STM8S103 or STM8S001 or STM8AF62Ax or STM8AF52Ax or STM8AF626x */ +/** + * @brief Timer2 Update/Overflow/Break Interrupt routine + * @param None + * @retval None + */ + INTERRUPT_HANDLER(TIM2_UPD_OVF_BRK_IRQHandler, 13) +{ + /* In order to detect unexpected events during development, + it is recommended to set a breakpoint on the following instruction. + */ +} + +/** + * @brief Timer2 Capture/Compare Interrupt routine + * @param None + * @retval None + */ + INTERRUPT_HANDLER(TIM2_CAP_COM_IRQHandler, 14) +{ + /* In order to detect unexpected events during development, + it is recommended to set a breakpoint on the following instruction. + */ +} +#endif /*STM8S903*/ + +#if defined(STM8S208) || defined(STM8S207) || defined(STM8S007) || defined(STM8S105) || \ + defined(STM8S005) || defined(STM8AF62Ax) || defined(STM8AF52Ax) || defined(STM8AF626x) +/** + * @brief Timer3 Update/Overflow/Break Interrupt routine. + * @param None + * @retval None + */ + INTERRUPT_HANDLER(TIM3_UPD_OVF_BRK_IRQHandler, 15) +{ + /* In order to detect unexpected events during development, + it is recommended to set a breakpoint on the following instruction. + */ +} + +/** + * @brief Timer3 Capture/Compare Interrupt routine + * @param None + * @retval None + */ + INTERRUPT_HANDLER(TIM3_CAP_COM_IRQHandler, 16) +{ + /* In order to detect unexpected events during development, + it is recommended to set a breakpoint on the following instruction. + */ +} +#endif /*STM8S208, STM8S207 or STM8S105 or STM8AF62Ax or STM8AF52Ax or STM8AF626x */ + +#if defined(STM8S208) || defined(STM8S207) || defined(STM8S007) || defined(STM8S103) || \ + defined(STM8S003) || defined(STM8S001) || defined(STM8AF62Ax) || defined(STM8AF52Ax) || defined(STM8S903) +/** + * @brief UART1 TX Interrupt routine + * @param None + * @retval None + */ + INTERRUPT_HANDLER(UART1_TX_IRQHandler, 17) +{ + /* In order to detect unexpected events during development, + it is recommended to set a breakpoint on the following instruction. + */ +} + +/** + * @brief UART1 RX Interrupt routine + * @param None + * @retval None + */ + INTERRUPT_HANDLER(UART1_RX_IRQHandler, 18) +{ + /* In order to detect unexpected events during development, + it is recommended to set a breakpoint on the following instruction. + */ +} +#endif /*STM8S105 || STM8S001 */ + +/** + * @brief I2C Interrupt routine + * @param None + * @retval None + */ +INTERRUPT_HANDLER(I2C_IRQHandler, 19) +{ + /* In order to detect unexpected events during development, + it is recommended to set a breakpoint on the following instruction. + */ +} + +#if defined(STM8S105) || defined(STM8S005) || defined (STM8AF626x) +/** + * @brief UART2 TX interrupt routine. + * @param None + * @retval None + */ + INTERRUPT_HANDLER(UART2_TX_IRQHandler, 20) +{ + /* In order to detect unexpected events during development, + it is recommended to set a breakpoint on the following instruction. + */ + } + +/** + * @brief UART2 RX interrupt routine. + * @param None + * @retval None + */ + INTERRUPT_HANDLER(UART2_RX_IRQHandler, 21) +{ + /* In order to detect unexpected events during development, + it is recommended to set a breakpoint on the following instruction. + */ + } +#endif /* STM8S105*/ + +#if defined(STM8S207) || defined(STM8S007) || defined(STM8S208) || defined (STM8AF52Ax) || defined (STM8AF62Ax) +/** + * @brief UART3 TX interrupt routine. + * @param None + * @retval None + */ + INTERRUPT_HANDLER(UART3_TX_IRQHandler, 20) +{ + /* In order to detect unexpected events during development, + it is recommended to set a breakpoint on the following instruction. + */ + } + +/** + * @brief UART3 RX interrupt routine. + * @param None + * @retval None + */ + INTERRUPT_HANDLER(UART3_RX_IRQHandler, 21) +{ + /* In order to detect unexpected events during development, + it is recommended to set a breakpoint on the following instruction. + */ + } +#endif /*STM8S208 or STM8S207 or STM8AF52Ax or STM8AF62Ax */ + +#if defined(STM8S207) || defined(STM8S007) || defined(STM8S208) || defined (STM8AF52Ax) || defined (STM8AF62Ax) +/** + * @brief ADC2 interrupt routine. + * @param None + * @retval None + */ + INTERRUPT_HANDLER(ADC2_IRQHandler, 22) +{ + + /* In order to detect unexpected events during development, + it is recommended to set a breakpoint on the following instruction. + */ + return; + +} +#else /*STM8S105, STM8S103 or STM8S903 or STM8AF626x */ +/** + * @brief ADC1 interrupt routine. + * @param None + * @retval None + */ + INTERRUPT_HANDLER(ADC1_IRQHandler, 22) +{ + + /* In order to detect unexpected events during development, + it is recommended to set a breakpoint on the following instruction. + */ + return; + +} +#endif /*STM8S208 or STM8S207 or STM8AF52Ax or STM8AF62Ax */ + +#ifdef STM8S903 +/** + * @brief Timer6 Update/Overflow/Trigger Interrupt routine + * @param None + * @retval None + */ +INTERRUPT_HANDLER(TIM6_UPD_OVF_TRG_IRQHandler, 23) +{ + /* In order to detect unexpected events during development, + it is recommended to set a breakpoint on the following instruction. + */ +} +#else /*STM8S208, STM8S207, STM8S105 or STM8S103 or STM8S001 or STM8AF62Ax or STM8AF52Ax or STM8AF626x */ +/** + * @brief Timer4 Update/Overflow Interrupt routine + * @param None + * @retval None + */ + INTERRUPT_HANDLER(TIM4_UPD_OVF_IRQHandler, 23) +{ + /* In order to detect unexpected events during development, + it is recommended to set a breakpoint on the following instruction. + */ +} +#endif /*STM8S903*/ + +/** + * @brief Eeprom EEC Interrupt routine + * @param None + * @retval None + */ +INTERRUPT_HANDLER(EEPROM_EEC_IRQHandler, 24) +{ + /* In order to detect unexpected events during development, + it is recommended to set a breakpoint on the following instruction. + */ +} + +/** + * @} + */ + + +/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/ diff --git a/oldblink/stm8s_it.h b/oldblink/stm8s_it.h new file mode 100644 index 0000000..d0995d6 --- /dev/null +++ b/oldblink/stm8s_it.h @@ -0,0 +1,201 @@ +/** + ****************************************************************************** + * @file stm8s_it.h + * @author MCD Application Team + * @version V2.0.4 + * @date 26-April-2018 + * @brief This file contains the headers of the interrupt handlers + ****************************************************************************** + * @attention + * + *

© COPYRIGHT 2014 STMicroelectronics

+ * + * Licensed under MCD-ST Liberty SW License Agreement V2, (the "License"); + * You may not use this file except in compliance with the License. + * You may obtain a copy of the License at: + * + * http://www.st.com/software_license_agreement_liberty_v2 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + ****************************************************************************** + */ + +/* Define to prevent recursive inclusion -------------------------------------*/ +#ifndef __STM8S_IT_H +#define __STM8S_IT_H + +/* Includes ------------------------------------------------------------------*/ +#include "stm8s.h" + +/* Exported types ------------------------------------------------------------*/ +/* Exported constants --------------------------------------------------------*/ +/* Exported macro ------------------------------------------------------------*/ +/* Exported functions ------------------------------------------------------- */ +#ifdef _COSMIC_ + void _stext(void); /* RESET startup routine */ + INTERRUPT void NonHandledInterrupt(void); +#endif /* _COSMIC_ */ + +// SDCC patch: requires separate handling for SDCC (see below) +#if !defined(_RAISONANCE_) && !defined(_SDCC_) + INTERRUPT void TRAP_IRQHandler(void); /* TRAP */ + INTERRUPT void TLI_IRQHandler(void); /* TLI */ + INTERRUPT void AWU_IRQHandler(void); /* AWU */ + INTERRUPT void CLK_IRQHandler(void); /* CLOCK */ + INTERRUPT void EXTI_PORTA_IRQHandler(void); /* EXTI PORTA */ + INTERRUPT void EXTI_PORTB_IRQHandler(void); /* EXTI PORTB */ + INTERRUPT void EXTI_PORTC_IRQHandler(void); /* EXTI PORTC */ + INTERRUPT void EXTI_PORTD_IRQHandler(void); /* EXTI PORTD */ + INTERRUPT void EXTI_PORTE_IRQHandler(void); /* EXTI PORTE */ + +#if defined(STM8S903) || defined(STM8AF622x) // SDCC patch: add STM8AF622x + INTERRUPT void EXTI_PORTF_IRQHandler(void); /* EXTI PORTF */ +#endif /* (STM8S903) || (STM8AF622x) */ + +#if defined (STM8S208) || defined (STM8AF52Ax) + INTERRUPT void CAN_RX_IRQHandler(void); /* CAN RX */ + INTERRUPT void CAN_TX_IRQHandler(void); /* CAN TX/ER/SC */ +#endif /* (STM8S208) || (STM8AF52Ax) */ + + INTERRUPT void SPI_IRQHandler(void); /* SPI */ + INTERRUPT void TIM1_CAP_COM_IRQHandler(void); /* TIM1 CAP/COM */ + INTERRUPT void TIM1_UPD_OVF_TRG_BRK_IRQHandler(void); /* TIM1 UPD/OVF/TRG/BRK */ + +#if defined(STM8S903) || defined(STM8AF622x) // SDCC patch: add STM8AF622x + INTERRUPT void TIM5_UPD_OVF_BRK_TRG_IRQHandler(void); /* TIM5 UPD/OVF/BRK/TRG */ + INTERRUPT void TIM5_CAP_COM_IRQHandler(void); /* TIM5 CAP/COM */ +#else /* (STM8S208) || (STM8S207) || (STM8S105) || (STM8S103) || (STM8S001) || (STM8AF52Ax) || (STM8AF62Ax) || (STM8A626x) */ + INTERRUPT void TIM2_UPD_OVF_BRK_IRQHandler(void); /* TIM2 UPD/OVF/BRK */ + INTERRUPT void TIM2_CAP_COM_IRQHandler(void); /* TIM2 CAP/COM */ +#endif /* (STM8S903) || (STM8AF622x) */ + +#if defined (STM8S208) || defined(STM8S207) || defined(STM8S007) || defined(STM8S105) || \ + defined(STM8S005) || defined (STM8AF52Ax) || defined (STM8AF62Ax) || defined (STM8AF626x) + INTERRUPT void TIM3_UPD_OVF_BRK_IRQHandler(void); /* TIM3 UPD/OVF/BRK */ + INTERRUPT void TIM3_CAP_COM_IRQHandler(void); /* TIM3 CAP/COM */ +#endif /* (STM8S208) || (STM8S207) || (STM8S105) || (STM8AF52Ax) || (STM8AF62Ax) || (STM8A626x) */ + +#if defined(STM8S208) || defined(STM8S207) || defined(STM8S007) || defined(STM8S103) || \ + defined(STM8S003) || defined(STM8S001) || defined(STM8AF52Ax) || defined(STM8AF62Ax) || defined(STM8S903) + INTERRUPT void UART1_TX_IRQHandler(void); /* UART1 TX */ + INTERRUPT void UART1_RX_IRQHandler(void); /* UART1 RX */ +#endif /* (STM8S208) || (STM8S207) || (STM8S007) || (STM8S103) || (STM8S003) || (STM8S001) || (STM8AF52Ax) || (STM8AF62Ax) || (STM8S903) */ + +#if defined (STM8AF622x) // SDCC patch: add STM8AF622x + INTERRUPT void UART4_TX_IRQHandler(void); /* UART4 TX */ + INTERRUPT void UART4_RX_IRQHandler(void); /* UART4 RX */ +#endif /* (STM8AF622x) */ + + INTERRUPT void I2C_IRQHandler(void); /* I2C */ + +#if defined(STM8S105) || defined(STM8S005) || defined (STM8AF626x) + INTERRUPT void UART2_RX_IRQHandler(void); /* UART2 RX */ + INTERRUPT void UART2_TX_IRQHandler(void); /* UART2 TX */ +#endif /* (STM8S105) || (STM8S005) || (STM8AF626x) */ + +#if defined(STM8S207) || defined(STM8S007) || defined(STM8S208) || defined (STM8AF52Ax) || defined (STM8AF62Ax) + INTERRUPT void UART3_RX_IRQHandler(void); /* UART3 RX */ + INTERRUPT void UART3_TX_IRQHandler(void); /* UART3 TX */ +#endif /* (STM8S207) || (STM8S007) || (STM8S208) || (STM8AF52Ax) || (STM8AF62Ax) */ + +#if defined(STM8S207) || defined(STM8S007) || defined(STM8S208) || defined (STM8AF52Ax) || defined (STM8AF62Ax) + INTERRUPT void ADC2_IRQHandler(void); /* ADC2 */ +#else /* (STM8S105) || (STM8S103) || (STM8S903) || (STM8AF622x) */ + INTERRUPT void ADC1_IRQHandler(void); /* ADC1 */ +#endif /* (STM8S207) || (STM8S007) || (STM8S208) || (STM8AF52Ax) || (STM8AF62Ax) */ + +#if defined(STM8S903) || defined(STM8AF622x) // SDCC patch: add STM8AF622x + INTERRUPT void TIM6_UPD_OVF_TRG_IRQHandler(void); /* TIM6 UPD/OVF/TRG */ +#else /*STM8S208, STM8S207, STM8S105 or STM8S103 or STM8AF62Ax or STM8AF52Ax or STM8AF626x */ + INTERRUPT void TIM4_UPD_OVF_IRQHandler(void); /* TIM4 UPD/OVF */ +#endif /* (STM8S903) || (STM8AF622x) */ + INTERRUPT void EEPROM_EEC_IRQHandler(void); /* EEPROM ECC CORRECTION */ + + +// SDCC patch: __interrupt keyword required after function name --> requires new block +#elif defined (_SDCC_) + + INTERRUPT_HANDLER_TRAP(TRAP_IRQHandler); /* TRAP */ + INTERRUPT_HANDLER(TLI_IRQHandler, 0); /* TLI */ + INTERRUPT_HANDLER(AWU_IRQHandler, 1); /* AWU */ + INTERRUPT_HANDLER(CLK_IRQHandler, 2); /* CLOCK */ + INTERRUPT_HANDLER(EXTI_PORTA_IRQHandler, 3); /* EXTI PORTA */ + INTERRUPT_HANDLER(EXTI_PORTB_IRQHandler, 4); /* EXTI PORTB */ + INTERRUPT_HANDLER(EXTI_PORTC_IRQHandler, 5); /* EXTI PORTC */ + INTERRUPT_HANDLER(EXTI_PORTD_IRQHandler, 6); /* EXTI PORTD */ + INTERRUPT_HANDLER(EXTI_PORTE_IRQHandler, 7); /* EXTI PORTE */ + +#if defined(STM8S903) || defined(STM8AF622x) + INTERRUPT_HANDLER(EXTI_PORTF_IRQHandler, 8); /* EXTI PORTF */ +#endif /* (STM8S903) || (STM8AF622x) */ + +#if defined (STM8S208) || defined (STM8AF52Ax) + INTERRUPT_HANDLER(CAN_RX_IRQHandler, 8); /* CAN RX */ + INTERRUPT_HANDLER(CAN_TX_IRQHandler, 9); /* CAN TX/ER/SC */ +#endif /* (STM8S208) || (STM8AF52Ax) */ + + INTERRUPT_HANDLER(SPI_IRQHandler, 10); /* SPI */ + INTERRUPT_HANDLER(TIM1_UPD_OVF_TRG_BRK_IRQHandler, 11); /* TIM1 UPD/OVF/TRG/BRK */ + INTERRUPT_HANDLER(TIM1_CAP_COM_IRQHandler, 12); /* TIM1 CAP/COM */ + +#if defined(STM8S903) || defined(STM8AF622x) + INTERRUPT_HANDLER(TIM5_UPD_OVF_BRK_TRG_IRQHandler, 13); /* TIM5 UPD/OVF/BRK/TRG */ + INTERRUPT_HANDLER(TIM5_CAP_COM_IRQHandler, 14); /* TIM5 CAP/COM */ +#else /* (STM8S208) || (STM8S207) || (STM8S105) || (STM8S103) || (STM8S001) || (STM8AF52Ax) || (STM8AF62Ax) || (STM8A626x) */ + INTERRUPT_HANDLER(TIM2_UPD_OVF_BRK_IRQHandler, 13); /* TIM2 UPD/OVF/BRK */ + INTERRUPT_HANDLER(TIM2_CAP_COM_IRQHandler, 14); /* TIM2 CAP/COM */ +#endif /* (STM8S903) || (STM8AF622x) */ + +#if defined (STM8S208) || defined(STM8S207) || defined(STM8S007) || defined(STM8S105) || \ + defined(STM8S005) || defined (STM8AF52Ax) || defined (STM8AF62Ax) || defined (STM8AF626x) + INTERRUPT_HANDLER(TIM3_UPD_OVF_BRK_IRQHandler, 15); /* TIM3 UPD/OVF/BRK */ + INTERRUPT_HANDLER(TIM3_CAP_COM_IRQHandler, 16); /* TIM3 CAP/COM */ +#endif /* (STM8S208) || (STM8S207) || (STM8S105) || (STM8AF52Ax) || (STM8AF62Ax) || (STM8A626x) */ + +#if defined (STM8S208) || defined(STM8S207) || defined(STM8S007) || defined(STM8S103) || \ + defined(STM8S003) || defined(STM8S001) || defined (STM8AF52Ax) || defined (STM8AF62Ax) || defined (STM8S903) + INTERRUPT_HANDLER(UART1_TX_IRQHandler, 17); /* UART1 TX */ + INTERRUPT_HANDLER(UART1_RX_IRQHandler, 18); /* UART1 RX */ +#endif /* (STM8S208) || (STM8S207) || (STM8S903) || (STM8S103) || (STM8S001) || (STM8AF52Ax) || (STM8AF62Ax) */ + +#if defined (STM8AF622x) + INTERRUPT_HANDLER(UART4_TX_IRQHandler, 17); /* UART4 TX */ + INTERRUPT_HANDLER(UART4_RX_IRQHandler, 18); /* UART4 RX */ +#endif /* (STM8AF622x) */ + + INTERRUPT_HANDLER(I2C_IRQHandler, 19); /* I2C */ + +#if defined(STM8S105) || defined(STM8S005) || defined (STM8AF626x) + INTERRUPT_HANDLER(UART2_TX_IRQHandler, 20); /* UART2 TX */ + INTERRUPT_HANDLER(UART2_RX_IRQHandler, 21); /* UART2 RX */ +#endif /* (STM8S105) || (STM8AF626x) */ + +#if defined(STM8S207) || defined(STM8S007) || defined(STM8S208) || defined (STM8AF52Ax) || defined (STM8AF62Ax) + INTERRUPT_HANDLER(UART3_RX_IRQHandler, 20); /* UART3 RX */ + INTERRUPT_HANDLER(UART3_TX_IRQHandler, 21); /* UART3 TX */ +#endif /* (STM8S207) || (STM8S208) || (STM8AF62Ax) || (STM8AF52Ax) */ + +#if defined(STM8S207) || defined(STM8S007) || defined(STM8S208) || defined (STM8AF52Ax) || defined (STM8AF62Ax) + INTERRUPT_HANDLER(ADC2_IRQHandler, 22); /* ADC2 */ +#else /* (STM8S105) || (STM8S103) || (STM8S903) || (STM8AF622x) */ + INTERRUPT_HANDLER(ADC1_IRQHandler, 22); /* ADC1 */ +#endif /* (STM8S207) || (STM8S208) || (STM8AF62Ax) || (STM8AF52Ax) */ + +#if defined(STM8S903) || defined(STM8AF622x) + INTERRUPT_HANDLER(TIM6_UPD_OVF_TRG_IRQHandler, 23); /* TIM6 UPD/OVF/TRG */ +#else /* (STM8S208) || (STM8S207) || (STM8S105) || (STM8S103) || (STM8AF62Ax) || (STM8AF52Ax) || (STM8AF626x) */ + INTERRUPT_HANDLER(TIM4_UPD_OVF_IRQHandler, 23); /* TIM4 UPD/OVF */ +#endif /* (STM8S903) || (STM8AF622x) */ + INTERRUPT_HANDLER(EEPROM_EEC_IRQHandler, 24); /* EEPROM ECC CORRECTION */ + +#endif /* !(_RAISONANCE_) && !(_SDCC_) */ + +#endif /* __STM8S_IT_H */ + + +/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/ diff --git a/oldtest/main.c b/oldtest/main.c new file mode 100644 index 0000000..7b69923 --- /dev/null +++ b/oldtest/main.c @@ -0,0 +1,129 @@ +#include "main.h" +//#include "stdio.h" + +uint32_t ms_passed = 0; + +PUTCHAR_PROTOTYPE; + +void puts(const char *s) { + const char* p = s; + while (*p != '\0') putchar(*p++); +} + +void main(void) +{ + /*High speed internal clock prescaler: 1*/ + CLK_HSIPrescalerConfig(CLK_PRESCALER_HSIDIV1); + + UART1_DeInit(); + /* UART1 configuration ------------------------------------------------------*/ + /* UART1 configured as follow: + - BaudRate = 115200 baud + - Word Length = 8 Bits + - One Stop Bit + - No parity + - Receive and transmit enabled + - UART1 Clock disabled + */ + UART1_Init((uint32_t)115200, UART1_WORDLENGTH_8D, UART1_STOPBITS_1, UART1_PARITY_NO, + UART1_SYNCMODE_CLOCK_DISABLE, UART1_MODE_TXRX_ENABLE); + + puts("Demotest\n\r"); + // uint8_t *uniqueid = (uint8_t*)0x4865; + + // puts("\n\rUnique ID: "); + // for (int i = 0; i < 12; i++) { + // if(i > 0) printf(":"); + // printf("%02X", uniqueid[i]); + // } + // puts("\n\r"); + + /* Initialize Interrupt*/ + GPIO_Init(GPIOB, GPIO_PIN_4, GPIO_MODE_IN_PU_IT); + EXTI_SetExtIntSensitivity(EXTI_PORT_GPIOB, EXTI_SENSITIVITY_FALL_ONLY); + EXTI_SetTLISensitivity(EXTI_TLISENSITIVITY_FALL_ONLY); + enableInterrupts(); + + /* Initialize I/Os in Output Mode */ + GPIO_Init(LED_GPIO_PORT, (GPIO_Pin_TypeDef)LED_GPIO_PINS, GPIO_MODE_OUT_PP_LOW_FAST); + /* Show the system is working properly */ + GPIO_WriteHigh(LED_GPIO_PORT, LED_GPIO_PINS); + delay_ms(200); + GPIO_WriteLow(LED_GPIO_PORT, LED_GPIO_PINS); + delay_ms(100); + GPIO_WriteHigh(LED_GPIO_PORT, LED_GPIO_PINS); + delay_ms(200); + GPIO_WriteLow(LED_GPIO_PORT, LED_GPIO_PINS); + delay_ms(100); + GPIO_WriteHigh(LED_GPIO_PORT, LED_GPIO_PINS); + delay_ms(200); + GPIO_WriteLow(LED_GPIO_PORT, LED_GPIO_PINS); + + while (1) { + /* Toggles LEDs */ + delay_ms(10); + ms_passed += 10; + if(ms_passed % 1000 == 0) { + GPIO_WriteReverse(LED_GPIO_PORT, (GPIO_Pin_TypeDef)LED_GPIO_PINS); + uint32_t ntick = ms_passed / 1000; + char x = ntick % 58 + 65; + putchar(8); //backspace + putchar(x); + } + } +} + +/** + * @brief Retargets the C library printf function to the UART. + * @param c Character to send + * @retval char Character sent + */ +PUTCHAR_PROTOTYPE +{ + /* Write a character to the UART1 */ + UART1_SendData8(c); + /* Loop until the end of transmission */ + while (UART1_GetFlagStatus(UART1_FLAG_TXE) == RESET); + + return (c); +} + +/** + * @brief Retargets the C library scanf function to the USART. + * @param None + * @retval char Character to Read + */ +GETCHAR_PROTOTYPE +{ +#ifdef _COSMIC_ + char c = 0; +#else + int c = 0; +#endif + /* Loop until the Read data register flag is SET */ + while (UART1_GetFlagStatus(UART1_FLAG_RXNE) == RESET); + c = UART1_ReceiveData8(); + return (c); +} + + +#ifdef USE_FULL_ASSERT + +/** + * @brief Reports the name of the source file and the source line number + * where the assert_param error has occurred. + * @param file: pointer to the source file name + * @param line: assert_param error line source number + * @retval None + */ +void assert_failed(uint8_t* file, uint32_t line) +{ + /* User can add his own implementation to report the file name and line number, + ex: printf("Wrong parameters value: file %s on line %d\r\n", file, line) */ + + /* Infinite loop */ + while (1) + { + } +} +#endif diff --git a/oldtest/main.h b/oldtest/main.h new file mode 100644 index 0000000..dfb41d6 --- /dev/null +++ b/oldtest/main.h @@ -0,0 +1,50 @@ +#ifndef __MAIN_H +#define __MAIN_H + +#include "stm8s.h" +#include "stm8s_it.h" /* SDCC patch: required by SDCC for interrupts */ + +/* automatically use built-in LED for known nucleo boards */ +#if defined(STM8S_NUCLEO_208RB) || defined(STM8S_NUCLEO_207K8) +#define LED_GPIO_PORT (GPIOC) +#define LED_GPIO_PINS (GPIO_PIN_5) +#elif defined(STM8S103) +/* for STM8S103F3 breakout board. building with GPIOG would result in failure (chip + * does not have that GPIO peripheral) */ +#define LED_GPIO_PORT (GPIOB) +#define LED_GPIO_PINS (GPIO_PIN_5) +#else +#define LED_GPIO_PORT (GPIOG) +#define LED_GPIO_PINS (GPIO_PIN_3 | GPIO_PIN_2 | GPIO_PIN_1 | GPIO_PIN_0) +#endif + +#ifdef _RAISONANCE_ +#define PUTCHAR_PROTOTYPE int putchar (char c) +#define GETCHAR_PROTOTYPE int getchar (void) +#elif defined (_COSMIC_) +#define PUTCHAR_PROTOTYPE char putchar (char c) +#define GETCHAR_PROTOTYPE char getchar (void) +#else /* _IAR_ */ +#define PUTCHAR_PROTOTYPE int putchar (int c) +#define GETCHAR_PROTOTYPE int getchar (void) +#endif /* _RAISONANCE_ */ + +#define US(us) ( F_CPU / 6000000.0 * us ) + +inline void delay_count (uint16_t nCount) { + /* Decrement nCount value */ + while (nCount != 0) + { + nCount--; + } +} + +inline void delay_ms(uint32_t ms) { + while (ms != 0) { + ms--; + delay_count(US(1000)); + } +} + +extern uint32_t ms_passed; +#endif diff --git a/oldtest/stm8s_conf.h b/oldtest/stm8s_conf.h new file mode 100644 index 0000000..d2a852f --- /dev/null +++ b/oldtest/stm8s_conf.h @@ -0,0 +1,118 @@ +/** + ****************************************************************************** + * @file stm8s_conf.h + * @author MCD Application Team + * @version V2.0.4 + * @date 26-April-2018 + * @brief This file is used to configure the Library. + ****************************************************************************** + * @attention + * + *

© COPYRIGHT 2014 STMicroelectronics

+ * + * Licensed under MCD-ST Liberty SW License Agreement V2, (the "License"); + * You may not use this file except in compliance with the License. + * You may obtain a copy of the License at: + * + * http://www.st.com/software_license_agreement_liberty_v2 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + ****************************************************************************** + */ + +/* SDCC patch: include "STM8AF622x" defined in "STM8S_StdPeriph_Tempate" */ + +/* Define to prevent recursive inclusion -------------------------------------*/ +#ifndef __STM8S_CONF_H +#define __STM8S_CONF_H + +/* Includes ------------------------------------------------------------------*/ +#include "stm8s.h" + +/* Uncomment the line below to enable peripheral header file inclusion */ +#if defined(STM8S105) || defined(STM8S005) || defined(STM8S103) || defined(STM8S003) ||\ + defined(STM8S001) || defined(STM8S903) || defined (STM8AF626x) || defined (STM8AF622x) +//#include "stm8s_adc1.h" +#endif /* (STM8S105) ||(STM8S103) || (STM8S001) || (STM8S903) || (STM8AF626x) */ +#if defined(STM8S208) || defined(STM8S207) || defined(STM8S007) || defined (STM8AF52Ax) ||\ + defined (STM8AF62Ax) +// #include "stm8s_adc2.h" +#endif /* (STM8S208) || (STM8S207) || (STM8AF62Ax) || (STM8AF52Ax) */ +//#include "stm8s_awu.h" +//#include "stm8s_beep.h" +#if defined (STM8S208) || defined (STM8AF52Ax) +// #include "stm8s_can.h" +#endif /* (STM8S208) || (STM8AF52Ax) */ +#include "stm8s_clk.h" +#include "stm8s_exti.h" +//#include "stm8s_flash.h" +#include "stm8s_gpio.h" +//#include "stm8s_i2c.h" +#include "stm8s_itc.h" +//#include "stm8s_iwdg.h" +//#include "stm8s_rst.h" +//#include "stm8s_spi.h" +//#include "stm8s_tim1.h" +#if !defined(STM8S903) && !defined(STM8AF622x) /* SDCC patch: see https://github.com/tenbaht/sduino/tree/master/STM8S_StdPeriph_Driver */ +// #include "stm8s_tim2.h" +#endif /* (STM8S903) || (STM8AF622x) */ +#if defined(STM8S208) || defined(STM8S207) || defined(STM8S007) ||defined(STM8S105) ||\ + defined(STM8S005) || defined (STM8AF52Ax) || defined (STM8AF62Ax) || defined (STM8AF626x) +// #include "stm8s_tim3.h" +#endif /* (STM8S208) || (STM8S207) || (STM8S007) || (STM8S105) */ +#if !defined(STM8S903) && !defined(STM8AF622x) /* SDCC patch: see https://github.com/tenbaht/sduino/tree/master/STM8S_StdPeriph_Driver */ +// #include "stm8s_tim4.h" +#endif /* (STM8S903) || (STM8AF622x) */ +#if defined(STM8S903) || defined(STM8AF622x) /* SDCC patch: see https://github.com/tenbaht/sduino/tree/master/STM8S_StdPeriph_Driver */ +// #include "stm8s_tim5.h" +// #include "stm8s_tim6.h" +#endif /* (STM8S903) || (STM8AF622x) */ +#if defined(STM8S208) || defined(STM8S207) || defined(STM8S007) || defined(STM8S103) ||\ + defined(STM8S003) || defined(STM8S001) || defined(STM8S903) || defined (STM8AF52Ax) || defined (STM8AF62Ax) +#include "stm8s_uart1.h" +#endif /* (STM8S208) || (STM8S207) || (STM8S103) || (STM8S001) || (STM8S903) || (STM8AF52Ax) || (STM8AF62Ax) */ +#if defined(STM8S105) || defined(STM8S005) || defined (STM8AF626x) +// #include "stm8s_uart2.h" +#endif /* (STM8S105) || (STM8AF626x) */ +#if defined(STM8S208) ||defined(STM8S207) || defined(STM8S007) || defined (STM8AF52Ax) ||\ + defined (STM8AF62Ax) +// #include "stm8s_uart3.h" +#endif /* (STM8S208) || (STM8S207) || (STM8AF52Ax) || (STM8AF62Ax) */ +#if defined(STM8AF622x) /* SDCC patch: see https://github.com/tenbaht/sduino/tree/master/STM8S_StdPeriph_Driver */ +// #include "stm8s_uart4.h" +#endif /* (STM8AF622x) */ +//#include "stm8s_wwdg.h" + +/* Exported types ------------------------------------------------------------*/ +/* Exported constants --------------------------------------------------------*/ +/* Uncomment the line below to expanse the "assert_param" macro in the + Standard Peripheral Library drivers code */ +// #define USE_FULL_ASSERT (1) + +/* Exported macro ------------------------------------------------------------*/ +#ifdef USE_FULL_ASSERT + +/** + * @brief The assert_param macro is used for function's parameters check. + * @param expr: If expr is false, it calls assert_failed function + * which reports the name of the source file and the source + * line number of the call that failed. + * If expr is true, it returns no value. + * @retval : None + */ +#define assert_param(expr) ((expr) ? (void)0 : assert_failed((uint8_t *)__FILE__, __LINE__)) +/* Exported functions ------------------------------------------------------- */ +void assert_failed(uint8_t* file, uint32_t line); +#else +#define assert_param(expr) ((void)0) +#endif /* USE_FULL_ASSERT */ + +#endif /* __STM8S_CONF_H */ + + +/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/ diff --git a/oldtest/stm8s_it.c b/oldtest/stm8s_it.c new file mode 100644 index 0000000..da5357e --- /dev/null +++ b/oldtest/stm8s_it.c @@ -0,0 +1,488 @@ +/** + ****************************************************************************** + * @file stm8s_it.c + * @author MCD Application Team + * @version V2.0.4 + * @date 26-April-2018 + * @brief Main Interrupt Service Routines. + ****************************************************************************** + * @attention + * + *

© COPYRIGHT 2014 STMicroelectronics

+ * + * Licensed under MCD-ST Liberty SW License Agreement V2, (the "License"); + * You may not use this file except in compliance with the License. + * You may obtain a copy of the License at: + * + * http://www.st.com/software_license_agreement_liberty_v2 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + ****************************************************************************** + */ + +/* Includes ------------------------------------------------------------------*/ +#include "stm8s_it.h" +#include "main.h" + + +/* Private typedef -----------------------------------------------------------*/ +/* Private define ------------------------------------------------------------*/ +/* Private macro -------------------------------------------------------------*/ +/* Private variables ---------------------------------------------------------*/ +/* Private function prototypes -----------------------------------------------*/ +/* Private functions ---------------------------------------------------------*/ + +/* Public functions ----------------------------------------------------------*/ + +/** @addtogroup GPIO_Toggle + * @{ + */ +#ifdef _COSMIC_ +/** + * @brief Dummy interrupt routine + * @param None + * @retval None + */ +INTERRUPT_HANDLER(NonHandledInterrupt, 25) +{ + /* In order to detect unexpected events during development, + it is recommended to set a breakpoint on the following instruction. + */ +} +#endif /*_COSMIC_*/ + +/** + * @brief TRAP interrupt routine + * @param None + * @retval None + */ +INTERRUPT_HANDLER_TRAP(TRAP_IRQHandler) +{ + /* In order to detect unexpected events during development, + it is recommended to set a breakpoint on the following instruction. + */ +} +/** + * @brief Top Level Interrupt routine + * @param None + * @retval None + */ +INTERRUPT_HANDLER(TLI_IRQHandler, 0) +{ + /* In order to detect unexpected events during development, + it is recommended to set a breakpoint on the following instruction. + */ +} + +/** + * @brief Auto Wake Up Interrupt routine + * @param None + * @retval None + */ +INTERRUPT_HANDLER(AWU_IRQHandler, 1) +{ + /* In order to detect unexpected events during development, + it is recommended to set a breakpoint on the following instruction. + */ +} + +/** + * @brief Clock Controller Interrupt routine + * @param None + * @retval None + */ +INTERRUPT_HANDLER(CLK_IRQHandler, 2) +{ + /* In order to detect unexpected events during development, + it is recommended to set a breakpoint on the following instruction. + */ +} + +/** + * @brief External Interrupt PORTA Interrupt routine + * @param None + * @retval None + */ +INTERRUPT_HANDLER(EXTI_PORTA_IRQHandler, 3) +{ + /* In order to detect unexpected events during development, + it is recommended to set a breakpoint on the following instruction. + */ +} + +/** + * @brief External Interrupt PORTB Interrupt routine + * @param None + * @retval None + */ +INTERRUPT_HANDLER(EXTI_PORTB_IRQHandler, 4) +{ + /* In order to detect unexpected events during development, + it is recommended to set a breakpoint on the following instruction. + */ + ms_passed = 0; + // GPIO_WriteHigh(LED_GPIO_PORT, LED_GPIO_PINS); + // delay_ms(100); + // GPIO_WriteLow(LED_GPIO_PORT, LED_GPIO_PINS); +} + +/** + * @brief External Interrupt PORTC Interrupt routine + * @param None + * @retval None + */ +INTERRUPT_HANDLER(EXTI_PORTC_IRQHandler, 5) +{ + /* In order to detect unexpected events during development, + it is recommended to set a breakpoint on the following instruction. + */ +} + +/** + * @brief External Interrupt PORTD Interrupt routine + * @param None + * @retval None + */ +INTERRUPT_HANDLER(EXTI_PORTD_IRQHandler, 6) +{ + /* In order to detect unexpected events during development, + it is recommended to set a breakpoint on the following instruction. + */ +} + +/** + * @brief External Interrupt PORTE Interrupt routine + * @param None + * @retval None + */ +INTERRUPT_HANDLER(EXTI_PORTE_IRQHandler, 7) +{ + /* In order to detect unexpected events during development, + it is recommended to set a breakpoint on the following instruction. + */ +} +#ifdef STM8S903 +/** + * @brief External Interrupt PORTF Interrupt routine + * @param None + * @retval None + */ + INTERRUPT_HANDLER(EXTI_PORTF_IRQHandler, 8) +{ + /* In order to detect unexpected events during development, + it is recommended to set a breakpoint on the following instruction. + */ +} +#endif /*STM8S903*/ + +#if defined (STM8S208) || defined (STM8AF52Ax) +/** + * @brief CAN RX Interrupt routine. + * @param None + * @retval None + */ + INTERRUPT_HANDLER(CAN_RX_IRQHandler, 8) +{ + /* In order to detect unexpected events during development, + it is recommended to set a breakpoint on the following instruction. + */ +} + +/** + * @brief CAN TX Interrupt routine + * @param None + * @retval None + */ + INTERRUPT_HANDLER(CAN_TX_IRQHandler, 9) +{ + /* In order to detect unexpected events during development, + it is recommended to set a breakpoint on the following instruction. + */ +} +#endif /*STM8S208 || STM8AF52Ax */ + +/** + * @brief SPI Interrupt routine + * @param None + * @retval None + */ +INTERRUPT_HANDLER(SPI_IRQHandler, 10) +{ + /* In order to detect unexpected events during development, + it is recommended to set a breakpoint on the following instruction. + */ +} + +/** + * @brief Timer1 Update/Overflow/Trigger/Break Interrupt routine + * @param None + * @retval None + */ +INTERRUPT_HANDLER(TIM1_UPD_OVF_TRG_BRK_IRQHandler, 11) +{ + /* In order to detect unexpected events during development, + it is recommended to set a breakpoint on the following instruction. + */ +} + +/** + * @brief Timer1 Capture/Compare Interrupt routine + * @param None + * @retval None + */ +INTERRUPT_HANDLER(TIM1_CAP_COM_IRQHandler, 12) +{ + /* In order to detect unexpected events during development, + it is recommended to set a breakpoint on the following instruction. + */ +} + +#ifdef STM8S903 +/** + * @brief Timer5 Update/Overflow/Break/Trigger Interrupt routine + * @param None + * @retval None + */ + INTERRUPT_HANDLER(TIM5_UPD_OVF_BRK_TRG_IRQHandler, 13) +{ + /* In order to detect unexpected events during development, + it is recommended to set a breakpoint on the following instruction. + */ +} +/** + * @brief Timer5 Capture/Compare Interrupt routine + * @param None + * @retval None + */ + INTERRUPT_HANDLER(TIM5_CAP_COM_IRQHandler, 14) +{ + /* In order to detect unexpected events during development, + it is recommended to set a breakpoint on the following instruction. + */ +} + +#else /*STM8S208, STM8S207, STM8S105 or STM8S103 or STM8S001 or STM8AF62Ax or STM8AF52Ax or STM8AF626x */ +/** + * @brief Timer2 Update/Overflow/Break Interrupt routine + * @param None + * @retval None + */ + INTERRUPT_HANDLER(TIM2_UPD_OVF_BRK_IRQHandler, 13) +{ + /* In order to detect unexpected events during development, + it is recommended to set a breakpoint on the following instruction. + */ +} + +/** + * @brief Timer2 Capture/Compare Interrupt routine + * @param None + * @retval None + */ + INTERRUPT_HANDLER(TIM2_CAP_COM_IRQHandler, 14) +{ + /* In order to detect unexpected events during development, + it is recommended to set a breakpoint on the following instruction. + */ +} +#endif /*STM8S903*/ + +#if defined(STM8S208) || defined(STM8S207) || defined(STM8S007) || defined(STM8S105) || \ + defined(STM8S005) || defined(STM8AF62Ax) || defined(STM8AF52Ax) || defined(STM8AF626x) +/** + * @brief Timer3 Update/Overflow/Break Interrupt routine. + * @param None + * @retval None + */ + INTERRUPT_HANDLER(TIM3_UPD_OVF_BRK_IRQHandler, 15) +{ + /* In order to detect unexpected events during development, + it is recommended to set a breakpoint on the following instruction. + */ +} + +/** + * @brief Timer3 Capture/Compare Interrupt routine + * @param None + * @retval None + */ + INTERRUPT_HANDLER(TIM3_CAP_COM_IRQHandler, 16) +{ + /* In order to detect unexpected events during development, + it is recommended to set a breakpoint on the following instruction. + */ +} +#endif /*STM8S208, STM8S207 or STM8S105 or STM8AF62Ax or STM8AF52Ax or STM8AF626x */ + +#if defined(STM8S208) || defined(STM8S207) || defined(STM8S007) || defined(STM8S103) || \ + defined(STM8S003) || defined(STM8S001) || defined(STM8AF62Ax) || defined(STM8AF52Ax) || defined(STM8S903) +/** + * @brief UART1 TX Interrupt routine + * @param None + * @retval None + */ + INTERRUPT_HANDLER(UART1_TX_IRQHandler, 17) +{ + /* In order to detect unexpected events during development, + it is recommended to set a breakpoint on the following instruction. + */ +} + +/** + * @brief UART1 RX Interrupt routine + * @param None + * @retval None + */ + INTERRUPT_HANDLER(UART1_RX_IRQHandler, 18) +{ + /* In order to detect unexpected events during development, + it is recommended to set a breakpoint on the following instruction. + */ +} +#endif /*STM8S105 || STM8S001 */ + +/** + * @brief I2C Interrupt routine + * @param None + * @retval None + */ +INTERRUPT_HANDLER(I2C_IRQHandler, 19) +{ + /* In order to detect unexpected events during development, + it is recommended to set a breakpoint on the following instruction. + */ +} + +#if defined(STM8S105) || defined(STM8S005) || defined (STM8AF626x) +/** + * @brief UART2 TX interrupt routine. + * @param None + * @retval None + */ + INTERRUPT_HANDLER(UART2_TX_IRQHandler, 20) +{ + /* In order to detect unexpected events during development, + it is recommended to set a breakpoint on the following instruction. + */ + } + +/** + * @brief UART2 RX interrupt routine. + * @param None + * @retval None + */ + INTERRUPT_HANDLER(UART2_RX_IRQHandler, 21) +{ + /* In order to detect unexpected events during development, + it is recommended to set a breakpoint on the following instruction. + */ + } +#endif /* STM8S105*/ + +#if defined(STM8S207) || defined(STM8S007) || defined(STM8S208) || defined (STM8AF52Ax) || defined (STM8AF62Ax) +/** + * @brief UART3 TX interrupt routine. + * @param None + * @retval None + */ + INTERRUPT_HANDLER(UART3_TX_IRQHandler, 20) +{ + /* In order to detect unexpected events during development, + it is recommended to set a breakpoint on the following instruction. + */ + } + +/** + * @brief UART3 RX interrupt routine. + * @param None + * @retval None + */ + INTERRUPT_HANDLER(UART3_RX_IRQHandler, 21) +{ + /* In order to detect unexpected events during development, + it is recommended to set a breakpoint on the following instruction. + */ + } +#endif /*STM8S208 or STM8S207 or STM8AF52Ax or STM8AF62Ax */ + +#if defined(STM8S207) || defined(STM8S007) || defined(STM8S208) || defined (STM8AF52Ax) || defined (STM8AF62Ax) +/** + * @brief ADC2 interrupt routine. + * @param None + * @retval None + */ + INTERRUPT_HANDLER(ADC2_IRQHandler, 22) +{ + + /* In order to detect unexpected events during development, + it is recommended to set a breakpoint on the following instruction. + */ + return; + +} +#else /*STM8S105, STM8S103 or STM8S903 or STM8AF626x */ +/** + * @brief ADC1 interrupt routine. + * @param None + * @retval None + */ + INTERRUPT_HANDLER(ADC1_IRQHandler, 22) +{ + + /* In order to detect unexpected events during development, + it is recommended to set a breakpoint on the following instruction. + */ + return; + +} +#endif /*STM8S208 or STM8S207 or STM8AF52Ax or STM8AF62Ax */ + +#ifdef STM8S903 +/** + * @brief Timer6 Update/Overflow/Trigger Interrupt routine + * @param None + * @retval None + */ +INTERRUPT_HANDLER(TIM6_UPD_OVF_TRG_IRQHandler, 23) +{ + /* In order to detect unexpected events during development, + it is recommended to set a breakpoint on the following instruction. + */ +} +#else /*STM8S208, STM8S207, STM8S105 or STM8S103 or STM8S001 or STM8AF62Ax or STM8AF52Ax or STM8AF626x */ +/** + * @brief Timer4 Update/Overflow Interrupt routine + * @param None + * @retval None + */ + INTERRUPT_HANDLER(TIM4_UPD_OVF_IRQHandler, 23) +{ + /* In order to detect unexpected events during development, + it is recommended to set a breakpoint on the following instruction. + */ +} +#endif /*STM8S903*/ + +/** + * @brief Eeprom EEC Interrupt routine + * @param None + * @retval None + */ +INTERRUPT_HANDLER(EEPROM_EEC_IRQHandler, 24) +{ + /* In order to detect unexpected events during development, + it is recommended to set a breakpoint on the following instruction. + */ +} + +/** + * @} + */ + + +/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/ diff --git a/oldtest/stm8s_it.h b/oldtest/stm8s_it.h new file mode 100644 index 0000000..46aac46 --- /dev/null +++ b/oldtest/stm8s_it.h @@ -0,0 +1,201 @@ +/** + ****************************************************************************** + * @file stm8s_it.h + * @author MCD Application Team + * @version V2.0.4 + * @date 26-April-2018 + * @brief This file contains the headers of the interrupt handlers + ****************************************************************************** + * @attention + * + *

© COPYRIGHT 2014 STMicroelectronics

+ * + * Licensed under MCD-ST Liberty SW License Agreement V2, (the "License"); + * You may not use this file except in compliance with the License. + * You may obtain a copy of the License at: + * + * http://www.st.com/software_license_agreement_liberty_v2 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + ****************************************************************************** + */ + +/* Define to prevent recursive inclusion -------------------------------------*/ +#ifndef __STM8S_IT_H +#define __STM8S_IT_H + +/* Includes ------------------------------------------------------------------*/ +#include "stm8s.h" + +/* Exported types ------------------------------------------------------------*/ +/* Exported constants --------------------------------------------------------*/ +/* Exported macro ------------------------------------------------------------*/ +/* Exported functions ------------------------------------------------------- */ +#ifdef _COSMIC_ + void _stext(void); /* RESET startup routine */ + INTERRUPT void NonHandledInterrupt(void); +#endif /* _COSMIC_ */ + +// SDCC patch: requires separate handling for SDCC (see below) +#if !defined(_RAISONANCE_) && !defined(_SDCC_) + INTERRUPT void TRAP_IRQHandler(void); /* TRAP */ + INTERRUPT void TLI_IRQHandler(void); /* TLI */ + INTERRUPT void AWU_IRQHandler(void); /* AWU */ + INTERRUPT void CLK_IRQHandler(void); /* CLOCK */ + INTERRUPT void EXTI_PORTA_IRQHandler(void); /* EXTI PORTA */ + INTERRUPT void EXTI_PORTB_IRQHandler(void); /* EXTI PORTB */ + INTERRUPT void EXTI_PORTC_IRQHandler(void); /* EXTI PORTC */ + INTERRUPT void EXTI_PORTD_IRQHandler(void); /* EXTI PORTD */ + INTERRUPT void EXTI_PORTE_IRQHandler(void); /* EXTI PORTE */ + +#if defined(STM8S903) || defined(STM8AF622x) // SDCC patch: add STM8AF622x + INTERRUPT void EXTI_PORTF_IRQHandler(void); /* EXTI PORTF */ +#endif /* (STM8S903) || (STM8AF622x) */ + +#if defined (STM8S208) || defined (STM8AF52Ax) + INTERRUPT void CAN_RX_IRQHandler(void); /* CAN RX */ + INTERRUPT void CAN_TX_IRQHandler(void); /* CAN TX/ER/SC */ +#endif /* (STM8S208) || (STM8AF52Ax) */ + + INTERRUPT void SPI_IRQHandler(void); /* SPI */ + INTERRUPT void TIM1_CAP_COM_IRQHandler(void); /* TIM1 CAP/COM */ + INTERRUPT void TIM1_UPD_OVF_TRG_BRK_IRQHandler(void); /* TIM1 UPD/OVF/TRG/BRK */ + +#if defined(STM8S903) || defined(STM8AF622x) // SDCC patch: add STM8AF622x + INTERRUPT void TIM5_UPD_OVF_BRK_TRG_IRQHandler(void); /* TIM5 UPD/OVF/BRK/TRG */ + INTERRUPT void TIM5_CAP_COM_IRQHandler(void); /* TIM5 CAP/COM */ +#else /* (STM8S208) || (STM8S207) || (STM8S105) || (STM8S103) || (STM8S001) || (STM8AF52Ax) || (STM8AF62Ax) || (STM8A626x) */ + INTERRUPT void TIM2_UPD_OVF_BRK_IRQHandler(void); /* TIM2 UPD/OVF/BRK */ + INTERRUPT void TIM2_CAP_COM_IRQHandler(void); /* TIM2 CAP/COM */ +#endif /* (STM8S903) || (STM8AF622x) */ + +#if defined (STM8S208) || defined(STM8S207) || defined(STM8S007) || defined(STM8S105) || \ + defined(STM8S005) || defined (STM8AF52Ax) || defined (STM8AF62Ax) || defined (STM8AF626x) + INTERRUPT void TIM3_UPD_OVF_BRK_IRQHandler(void); /* TIM3 UPD/OVF/BRK */ + INTERRUPT void TIM3_CAP_COM_IRQHandler(void); /* TIM3 CAP/COM */ +#endif /* (STM8S208) || (STM8S207) || (STM8S105) || (STM8AF52Ax) || (STM8AF62Ax) || (STM8A626x) */ + +#if defined(STM8S208) || defined(STM8S207) || defined(STM8S007) || defined(STM8S103) || \ + defined(STM8S003) || defined(STM8S001) || defined(STM8AF52Ax) || defined(STM8AF62Ax) || defined(STM8S903) + INTERRUPT void UART1_TX_IRQHandler(void); /* UART1 TX */ + INTERRUPT void UART1_RX_IRQHandler(void); /* UART1 RX */ +#endif /* (STM8S208) || (STM8S207) || (STM8S007) || (STM8S103) || (STM8S003) || (STM8S001) || (STM8AF52Ax) || (STM8AF62Ax) || (STM8S903) */ + +#if defined (STM8AF622x) // SDCC patch: add STM8AF622x + INTERRUPT void UART4_TX_IRQHandler(void); /* UART4 TX */ + INTERRUPT void UART4_RX_IRQHandler(void); /* UART4 RX */ +#endif /* (STM8AF622x) */ + + INTERRUPT void I2C_IRQHandler(void); /* I2C */ + +#if defined(STM8S105) || defined(STM8S005) || defined (STM8AF626x) + INTERRUPT void UART2_RX_IRQHandler(void); /* UART2 RX */ + INTERRUPT void UART2_TX_IRQHandler(void); /* UART2 TX */ +#endif /* (STM8S105) || (STM8S005) || (STM8AF626x) */ + +#if defined(STM8S207) || defined(STM8S007) || defined(STM8S208) || defined (STM8AF52Ax) || defined (STM8AF62Ax) + INTERRUPT void UART3_RX_IRQHandler(void); /* UART3 RX */ + INTERRUPT void UART3_TX_IRQHandler(void); /* UART3 TX */ +#endif /* (STM8S207) || (STM8S007) || (STM8S208) || (STM8AF52Ax) || (STM8AF62Ax) */ + +#if defined(STM8S207) || defined(STM8S007) || defined(STM8S208) || defined (STM8AF52Ax) || defined (STM8AF62Ax) + INTERRUPT void ADC2_IRQHandler(void); /* ADC2 */ +#else /* (STM8S105) || (STM8S103) || (STM8S903) || (STM8AF622x) */ + INTERRUPT void ADC1_IRQHandler(void); /* ADC1 */ +#endif /* (STM8S207) || (STM8S007) || (STM8S208) || (STM8AF52Ax) || (STM8AF62Ax) */ + +#if defined(STM8S903) || defined(STM8AF622x) // SDCC patch: add STM8AF622x + INTERRUPT void TIM6_UPD_OVF_TRG_IRQHandler(void); /* TIM6 UPD/OVF/TRG */ +#else /*STM8S208, STM8S207, STM8S105 or STM8S103 or STM8AF62Ax or STM8AF52Ax or STM8AF626x */ + INTERRUPT void TIM4_UPD_OVF_IRQHandler(void); /* TIM4 UPD/OVF */ +#endif /* (STM8S903) || (STM8AF622x) */ + INTERRUPT void EEPROM_EEC_IRQHandler(void); /* EEPROM ECC CORRECTION */ + + +// SDCC patch: __interrupt keyword required after function name --> requires new block +#elif defined (_SDCC_) + + INTERRUPT_HANDLER_TRAP(TRAP_IRQHandler); /* TRAP */ + INTERRUPT_HANDLER(TLI_IRQHandler, 0); /* TLI */ + INTERRUPT_HANDLER(AWU_IRQHandler, 1); /* AWU */ + INTERRUPT_HANDLER(CLK_IRQHandler, 2); /* CLOCK */ + INTERRUPT_HANDLER(EXTI_PORTA_IRQHandler, 3); /* EXTI PORTA */ + INTERRUPT_HANDLER(EXTI_PORTB_IRQHandler, 4); /* EXTI PORTB */ + INTERRUPT_HANDLER(EXTI_PORTC_IRQHandler, 5); /* EXTI PORTC */ + INTERRUPT_HANDLER(EXTI_PORTD_IRQHandler, 6); /* EXTI PORTD */ + INTERRUPT_HANDLER(EXTI_PORTE_IRQHandler, 7); /* EXTI PORTE */ + +#if defined(STM8S903) || defined(STM8AF622x) + INTERRUPT_HANDLER(EXTI_PORTF_IRQHandler, 8); /* EXTI PORTF */ +#endif /* (STM8S903) || (STM8AF622x) */ + +#if defined (STM8S208) || defined (STM8AF52Ax) + INTERRUPT_HANDLER(CAN_RX_IRQHandler, 8); /* CAN RX */ + INTERRUPT_HANDLER(CAN_TX_IRQHandler, 9); /* CAN TX/ER/SC */ +#endif /* (STM8S208) || (STM8AF52Ax) */ + + INTERRUPT_HANDLER(SPI_IRQHandler, 10); /* SPI */ + INTERRUPT_HANDLER(TIM1_UPD_OVF_TRG_BRK_IRQHandler, 11); /* TIM1 UPD/OVF/TRG/BRK */ + INTERRUPT_HANDLER(TIM1_CAP_COM_IRQHandler, 12); /* TIM1 CAP/COM */ + +#if defined(STM8S903) || defined(STM8AF622x) + INTERRUPT_HANDLER(TIM5_UPD_OVF_BRK_TRG_IRQHandler, 13); /* TIM5 UPD/OVF/BRK/TRG */ + INTERRUPT_HANDLER(TIM5_CAP_COM_IRQHandler, 14); /* TIM5 CAP/COM */ +#else /* (STM8S208) || (STM8S207) || (STM8S105) || (STM8S103) || (STM8S001) || (STM8AF52Ax) || (STM8AF62Ax) || (STM8A626x) */ + INTERRUPT_HANDLER(TIM2_UPD_OVF_BRK_IRQHandler, 13); /* TIM2 UPD/OVF/BRK */ + INTERRUPT_HANDLER(TIM2_CAP_COM_IRQHandler, 14); /* TIM2 CAP/COM */ +#endif /* (STM8S903) || (STM8AF622x) */ + +#if defined (STM8S208) || defined(STM8S207) || defined(STM8S007) || defined(STM8S105) || \ + defined(STM8S005) || defined (STM8AF52Ax) || defined (STM8AF62Ax) || defined (STM8AF626x) + INTERRUPT_HANDLER(TIM3_UPD_OVF_BRK_IRQHandler, 15); /* TIM3 UPD/OVF/BRK */ + INTERRUPT_HANDLER(TIM3_CAP_COM_IRQHandler, 16); /* TIM3 CAP/COM */ +#endif /* (STM8S208) || (STM8S207) || (STM8S105) || (STM8AF52Ax) || (STM8AF62Ax) || (STM8A626x) */ + +#if defined (STM8S208) || defined(STM8S207) || defined(STM8S007) || defined(STM8S103) || \ + defined(STM8S003) || defined(STM8S001) || defined (STM8AF52Ax) || defined (STM8AF62Ax) || defined (STM8S903) + INTERRUPT_HANDLER(UART1_TX_IRQHandler, 17); /* UART1 TX */ + INTERRUPT_HANDLER(UART1_RX_IRQHandler, 18); /* UART1 RX */ +#endif /* (STM8S208) || (STM8S207) || (STM8S903) || (STM8S103) || (STM8S001) || (STM8AF52Ax) || (STM8AF62Ax) */ + +#if defined (STM8AF622x) + INTERRUPT_HANDLER(UART4_TX_IRQHandler, 17); /* UART4 TX */ + INTERRUPT_HANDLER(UART4_RX_IRQHandler, 18); /* UART4 RX */ +#endif /* (STM8AF622x) */ + + INTERRUPT_HANDLER(I2C_IRQHandler, 19); /* I2C */ + +#if defined(STM8S105) || defined(STM8S005) || defined (STM8AF626x) + INTERRUPT_HANDLER(UART2_TX_IRQHandler, 20); /* UART2 TX */ + INTERRUPT_HANDLER(UART2_RX_IRQHandler, 21); /* UART2 RX */ +#endif /* (STM8S105) || (STM8AF626x) */ + +#if defined(STM8S207) || defined(STM8S007) || defined(STM8S208) || defined (STM8AF52Ax) || defined (STM8AF62Ax) + INTERRUPT_HANDLER(UART3_RX_IRQHandler, 20); /* UART3 RX */ + INTERRUPT_HANDLER(UART3_TX_IRQHandler, 21); /* UART3 TX */ +#endif /* (STM8S207) || (STM8S208) || (STM8AF62Ax) || (STM8AF52Ax) */ + +#if defined(STM8S207) || defined(STM8S007) || defined(STM8S208) || defined (STM8AF52Ax) || defined (STM8AF62Ax) + INTERRUPT_HANDLER(ADC2_IRQHandler, 22); /* ADC2 */ +#else /* (STM8S105) || (STM8S103) || (STM8S903) || (STM8AF622x) */ + INTERRUPT_HANDLER(ADC1_IRQHandler, 22); /* ADC1 */ +#endif /* (STM8S207) || (STM8S208) || (STM8AF62Ax) || (STM8AF52Ax) */ + +#if defined(STM8S903) || defined(STM8AF622x) + INTERRUPT_HANDLER(TIM6_UPD_OVF_TRG_IRQHandler, 23); /* TIM6 UPD/OVF/TRG */ +#else /* (STM8S208) || (STM8S207) || (STM8S105) || (STM8S103) || (STM8AF62Ax) || (STM8AF52Ax) || (STM8AF626x) */ + INTERRUPT_HANDLER(TIM4_UPD_OVF_IRQHandler, 23); /* TIM4 UPD/OVF */ +#endif /* (STM8S903) || (STM8AF622x) */ + INTERRUPT_HANDLER(EEPROM_EEC_IRQHandler, 24); /* EEPROM ECC CORRECTION */ + +#endif /* !(_RAISONANCE_) && !(_SDCC_) */ + +#endif /* __STM8S_IT_H */ + + +/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/ diff --git a/platformio.ini b/platformio.ini new file mode 100644 index 0000000..06a62f9 --- /dev/null +++ b/platformio.ini @@ -0,0 +1,24 @@ +; PlatformIO Project Configuration File +; +; Build options: build flags, source filter +; Upload options: custom upload port, speed and extra flags +; Library options: dependencies, extra library storages +; Advanced options: extra scripting +; +; Please visit documentation for the other options and examples +; https://docs.platformio.org/page/projectconf.html + +[env:stm8sblue] +platform = ststm8 +board = stm8sblue +framework = spl +extra_scripts = pre:extra_script.py +upload_protocol = stlinkv2 +board_build.mcu = stm8s103f3p6 +board_build.f_cpu = 16000000L +; serial monitor options +monitor_speed = 115200 +;build_unflags = --nostdlib +;build_flags = +; -I$PROJECT_PACKAGES_DIR/toolchain-sdcc/include/ + diff --git a/src/main.c b/src/main.c new file mode 100644 index 0000000..077a9c0 --- /dev/null +++ b/src/main.c @@ -0,0 +1,284 @@ +#include "main.h" +#include "stm8s_i2c.h" +// #include "stm8s_i2c.h" +// #include "stm8s_uart1.h" + +/* Private macro -------------------------------------------------------------*/ +// extern uint8_t HEADER_ADDRESS_Read = (((SLAVE_ADDRESS & 0xFF00) >> 7) | 0xF1); +// extern uint8_t HEADER_ADDRESS_Write; +/* Private variables ---------------------------------------------------------*/ +uint8_t i = 0; +TestStatus TransferStatus1 = FAILED; +extern __IO uint8_t SlaveAddress; +extern __IO uint8_t TxByte; +extern __IO uint8_t RxByte; + +extern __IO uint8_t State; +/* Private function prototypes -----------------------------------------------*/ +TestStatus Buffercmp(uint8_t* pBuffer1, uint8_t* pBuffer2, uint16_t BufferLength); +PUTCHAR_PROTOTYPE; + +void main(void) +{ + UART1_DeInit(); + I2C_DeInit(); +#ifdef FAST_I2C_MODE + /* system_clock / 1 */ + CLK_HSIPrescalerConfig(CLK_PRESCALER_HSIDIV1); +#else + /* system_clock / 2 */ + CLK_HSIPrescalerConfig(CLK_PRESCALER_HSIDIV2); +#endif + + UART1_Init((uint32_t)115200, UART1_WORDLENGTH_8D, UART1_STOPBITS_1, UART1_PARITY_NO, + UART1_SYNCMODE_CLOCK_DISABLE, UART1_MODE_TXRX_ENABLE); + + puts("Demotest\n\r"); + delay_ms(1000); + + /* I2C Initialize */ + I2C_Init(I2C_SPEED, 0xA0, I2C_DUTYCYCLE_2, I2C_ACK_CURR, I2C_ADDMODE_7BIT, 16); + + /* Enable Buffer and Event Interrupt*/ + I2C_ITConfig((I2C_IT_TypeDef)(I2C_IT_EVT | I2C_IT_BUF | I2C_IT_ERR) , ENABLE); + + enableInterrupts(); + + // /* Initialize LED in Output Mode */ + // GPIO_Init(LED_GPIO_PORT, (GPIO_Pin_TypeDef)LED_GPIO_PINS, GPIO_MODE_OUT_PP_LOW_FAST); + // /* Show the system is working properly */ + // GPIO_WriteHigh(LED_GPIO_PORT, LED_GPIO_PINS); + // delay_ms(200); + // GPIO_WriteLow(LED_GPIO_PORT, LED_GPIO_PINS); + // delay_ms(100); + // GPIO_WriteHigh(LED_GPIO_PORT, LED_GPIO_PINS); + // delay_ms(200); + // GPIO_WriteLow(LED_GPIO_PORT, LED_GPIO_PINS); + // delay_ms(100); + // GPIO_WriteHigh(LED_GPIO_PORT, LED_GPIO_PINS); + // delay_ms(200); + // GPIO_WriteLow(LED_GPIO_PORT, LED_GPIO_PINS); + + SlaveAddress = SLAVE_ACCGYR_ADDR; + State = 0; + TxByte = 0x0F; + puts("START I2C\n"); + + /* Send START condition */ + I2C_GenerateSTART(ENABLE); + // I2C_SendData(0x0F); + // I2C_GenerateSTART(ENABLE); + // I2C_Send7bitAddress(SLAVE_MAG_ADDR, I2C_DIRECTION_RX); + // uint8_t r = I2C_ReceiveData(); + // // I2C_GenerateSTOP(ENABLE); + // putchar(r); + // puts("\nSOTNKS\n"); + while (I2C_GetFlagStatus(I2C_FLAG_BUSBUSY)); + puts("NOBUSY\n"); + RxByte = I2C_ReceiveData(); + putchar(RxByte); + while(1){} + + /* Add a delay to be sure that communication is finished */ + delay_count(0xFFFF); + + /***** reception phase ***/ + puts("RECEPTION PHASE\n"); + /* Wait while the bus is busy */ + while (I2C_GetFlagStatus(I2C_FLAG_BUSBUSY)); + + /* Send START condition */ + I2C_GenerateSTART(ENABLE); + + /* Test on EV5 and clear it */ + while (!I2C_CheckEvent(I2C_EVENT_MASTER_MODE_SELECT)); + + /* Send slave Address for write */ + I2C_Send7bitAddress(SlaveAddress, I2C_DIRECTION_RX); + + /* Test on EV6 and clear it */ + while (!I2C_CheckEvent(I2C_EVENT_MASTER_RECEIVER_MODE_SELECTED)); + +// /* While there is data to be read */ +// while (NumByteToRead) +// { +// #ifdef SAFE_PROCEDURE +// if (NumByteToRead != 3) /* Receive bytes from first byte until byte N-3 */ +// { +// while ((I2C_GetFlagStatus(I2C_FLAG_TRANSFERFINISHED) == RESET)); /* Poll on BTF */ +// +// /* Read a byte from the Slave */ +// RxBuffer[Rx_Idx] = I2C_ReceiveData(); +// +// /* Point to the next location where the byte read will be saved */ +// Rx_Idx++; +// +// /* Decrement the read bytes counter */ +// NumByteToRead--; +// } +// +// if (NumByteToRead == 3) /* it remains to read three data: data N-2, data N-1, Data N */ +// { +// /* Data N-2 in DR and data N -1 in shift register */ +// while ((I2C_GetFlagStatus(I2C_FLAG_TRANSFERFINISHED) == RESET)); /* Poll on BTF */ +// +// /* Clear ACK */ +// I2C_AcknowledgeConfig(I2C_ACK_NONE); +// +// /* Disable general interrupts */ +// disableInterrupts(); +// +// /* Read Data N-2 */ +// RxBuffer[Rx_Idx] = I2C_ReceiveData(); +// +// /* Point to the next location where the byte read will be saved */ +// Rx_Idx++; +// +// /* Program the STOP */ +// I2C_GenerateSTOP(ENABLE); +// +// /* Read DataN-1 */ +// RxBuffer[Rx_Idx] = I2C_ReceiveData(); +// +// /* Enable General interrupts */ +// enableInterrupts(); +// +// /* Point to the next location where the byte read will be saved */ +// Rx_Idx++; +// +// while ((I2C_GetFlagStatus(I2C_FLAG_RXNOTEMPTY) == RESET)); /* Poll on RxNE */ +// +// /* Read DataN */ +// RxBuffer[Rx_Idx] = I2C_ReceiveData(); +// +// /* Reset the number of bytes to be read by master */ +// NumByteToRead = 0; +// +// } +// #else +// if (NumByteToRead == 1) +// { +// /* Disable Acknowledgement */ +// I2C_AcknowledgeConfig(I2C_ACK_NONE); +// +// /* Send STOP Condition */ +// I2C_GenerateSTOP(ENABLE); +// +// /* Poll on RxNE Flag */ +// while ((I2C_GetFlagStatus(I2C_FLAG_RXNOTEMPTY) == RESET)); +// /* Read a byte from the Slave */ +// RxBuffer[Rx_Idx] = I2C_ReceiveData(); +// +// /* Point to the next location where the byte read will be saved */ +// Rx_Idx++; +// +// /* Decrement the read bytes counter */ +// NumByteToRead--; +// } +// +// /* Test on EV7 and clear it */ +// if (I2C_CheckEvent(I2C_EVENT_MASTER_BYTE_RECEIVED) ) +// { +// /* Read a byte from the EEPROM */ +// RxBuffer[Rx_Idx] = I2C_ReceiveData(); +// +// /* Point to the next location where the byte read will be saved */ +// Rx_Idx++; +// +// /* Decrement the read bytes counter */ +// NumByteToRead--; +// } +// #endif /* SAFE_PROCEDURE */ +// } +// +// /* check if sent and received data are not corrupted */ +// TransferStatus1 = Buffercmp((uint8_t*)TxBuffer, (uint8_t*) RxBuffer, BUFFERSIZE); + + if (TransferStatus1 != FAILED) + { + puts("FAILED\n"); + while (1) + { + /* Toggle LED*/ + GPIO_WriteReverse(LED_GPIO_PORT, LED_GPIO_PINS); + /* Insert delay */ + delay_count(0x7FFF); + } + } + else + { + puts("OK!\n"); + while (1) + { + /* Toggle LED*/ + GPIO_WriteReverse(LED_GPIO_PORT, LED_GPIO_PINS); + /* Insert delay */ + delay_count(0xFFFF); + } + } +} + +/** + * @brief Compares two buffers. + * @param pBuffer1, pBuffer2: buffers to be compared. + * @param BufferLength: buffer's length + * @retval PASSED: pBuffer1 identical to pBuffer2 + * FAILED: pBuffer1 differs from pBuffer2 + */ +TestStatus Buffercmp(uint8_t* pBuffer1, uint8_t* pBuffer2, uint16_t BufferLength) +{ + while (BufferLength--) + { + if (*pBuffer1 != *pBuffer2) + { + return FAILED; + } + + pBuffer1++; + pBuffer2++; + } + + return PASSED; +} + + + +void puts(const char *s) { + const char* p = s; + while (*p != '\0') putchar(*p++); +} + +/** + * @brief Retargets the C library printf function to the UART. + * @param c Character to send + * @retval char Character sent + */ +PUTCHAR_PROTOTYPE { + /* Write a character to the UART1 */ + UART1_SendData8(c); + /* Loop until the end of transmission */ + while (UART1_GetFlagStatus(UART1_FLAG_TXE) == RESET); + + return (c); +} + +#ifdef USE_FULL_ASSERT + +/** + * @brief Reports the name of the source file and the source line number + * where the assert_param error has occurred. + * @param file: pointer to the source file name + * @param line: assert_param error line source number + * @retval None + */ +void assert_failed(uint8_t* file, uint32_t line) +{ + /* User can add his own implementation to report the file name and line number, + ex: printf("Wrong parameters value: file %s on line %d\r\n", file, line) */ + + /* Infinite loop */ + while (1) + { + } +} +#endif diff --git a/src/main.h b/src/main.h new file mode 100644 index 0000000..98cc25f --- /dev/null +++ b/src/main.h @@ -0,0 +1,67 @@ +#ifndef __MAIN_H +#define __MAIN_H + +#include "stm8s.h" +#include "stm8s_it.h" /* SDCC patch: required by SDCC for interrupts */ + +/* automatically use built-in LED for known nucleo boards */ +#if defined(STM8S_NUCLEO_208RB) || defined(STM8S_NUCLEO_207K8) +#define LED_GPIO_PORT (GPIOC) +#define LED_GPIO_PINS (GPIO_PIN_5) +#elif defined(STM8S103) +/* for STM8S103F3 breakout board. building with GPIOG would result in failure (chip + * does not have that GPIO peripheral) */ +#define LED_GPIO_PORT (GPIOB) +#define LED_GPIO_PINS (GPIO_PIN_5) +#else +#define LED_GPIO_PORT (GPIOG) +#define LED_GPIO_PINS (GPIO_PIN_3 | GPIO_PIN_2 | GPIO_PIN_1 | GPIO_PIN_0) +#endif + +/* stdio Prototypes */ +#define PUTCHAR_PROTOTYPE int putchar (int c) +#define GETCHAR_PROTOTYPE int getchar (void) +void puts(const char* s); + +/* Delay functions */ +#define US(us) ( F_CPU / 6000000.0 * us ) + +inline void delay_count (uint16_t nCount) { + /* Decrement nCount value */ + while (nCount != 0) + { + nCount--; + } +} + +inline void delay_ms(uint32_t ms) { + while (ms != 0) { + ms--; + delay_count(US(1000)); + } +} + +/* definition of fast or default standard mode (bus speed up to 400 or 100 kHz) */ +// #define FAST_I2C_MODE + +#ifdef FAST_I2C_MODE +#define I2C_SPEED 300000 +#else +#define I2C_SPEED 100000 +#endif + +/* 7-bit slave addresses */ +#define SLAVE_ACCGYR_ADDR 0b11010100 +#define SLAVE_MAG_ADDR 0b00111000 + +/* This define is used in master receiver */ +/* Uncomment the line below if you want to use the safe procedure */ +#define SAFE_PROCEDURE + + +#define BUFFERSIZE 10 + + +typedef enum {FAILED = 0, PASSED = !FAILED} TestStatus; + +#endif diff --git a/src/stm8s_conf.h b/src/stm8s_conf.h new file mode 100644 index 0000000..8c4956f --- /dev/null +++ b/src/stm8s_conf.h @@ -0,0 +1,118 @@ +/** + ****************************************************************************** + * @file stm8s_conf.h + * @author MCD Application Team + * @version V2.0.4 + * @date 26-April-2018 + * @brief This file is used to configure the Library. + ****************************************************************************** + * @attention + * + *

© COPYRIGHT 2014 STMicroelectronics

+ * + * Licensed under MCD-ST Liberty SW License Agreement V2, (the "License"); + * You may not use this file except in compliance with the License. + * You may obtain a copy of the License at: + * + * http://www.st.com/software_license_agreement_liberty_v2 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + ****************************************************************************** + */ + +/* SDCC patch: include "STM8AF622x" defined in "STM8S_StdPeriph_Tempate" */ + +/* Define to prevent recursive inclusion -------------------------------------*/ +#ifndef __STM8S_CONF_H +#define __STM8S_CONF_H + +/* Includes ------------------------------------------------------------------*/ +#include "stm8s.h" + +/* Uncomment the line below to enable peripheral header file inclusion */ +#if defined(STM8S105) || defined(STM8S005) || defined(STM8S103) || defined(STM8S003) ||\ + defined(STM8S001) || defined(STM8S903) || defined (STM8AF626x) || defined (STM8AF622x) +//#include "stm8s_adc1.h" +#endif /* (STM8S105) ||(STM8S103) || (STM8S001) || (STM8S903) || (STM8AF626x) */ +#if defined(STM8S208) || defined(STM8S207) || defined(STM8S007) || defined (STM8AF52Ax) ||\ + defined (STM8AF62Ax) +// #include "stm8s_adc2.h" +#endif /* (STM8S208) || (STM8S207) || (STM8AF62Ax) || (STM8AF52Ax) */ +//#include "stm8s_awu.h" +//#include "stm8s_beep.h" +#if defined (STM8S208) || defined (STM8AF52Ax) +// #include "stm8s_can.h" +#endif /* (STM8S208) || (STM8AF52Ax) */ +#include "stm8s_clk.h" +#include "stm8s_exti.h" +//#include "stm8s_flash.h" +#include "stm8s_gpio.h" +#include "stm8s_i2c.h" +#include "stm8s_itc.h" +//#include "stm8s_iwdg.h" +//#include "stm8s_rst.h" +//#include "stm8s_spi.h" +//#include "stm8s_tim1.h" +#if !defined(STM8S903) && !defined(STM8AF622x) /* SDCC patch: see https://github.com/tenbaht/sduino/tree/master/STM8S_StdPeriph_Driver */ +// #include "stm8s_tim2.h" +#endif /* (STM8S903) || (STM8AF622x) */ +#if defined(STM8S208) || defined(STM8S207) || defined(STM8S007) ||defined(STM8S105) ||\ + defined(STM8S005) || defined (STM8AF52Ax) || defined (STM8AF62Ax) || defined (STM8AF626x) +// #include "stm8s_tim3.h" +#endif /* (STM8S208) || (STM8S207) || (STM8S007) || (STM8S105) */ +#if !defined(STM8S903) && !defined(STM8AF622x) /* SDCC patch: see https://github.com/tenbaht/sduino/tree/master/STM8S_StdPeriph_Driver */ +// #include "stm8s_tim4.h" +#endif /* (STM8S903) || (STM8AF622x) */ +#if defined(STM8S903) || defined(STM8AF622x) /* SDCC patch: see https://github.com/tenbaht/sduino/tree/master/STM8S_StdPeriph_Driver */ +// #include "stm8s_tim5.h" +// #include "stm8s_tim6.h" +#endif /* (STM8S903) || (STM8AF622x) */ +#if defined(STM8S208) || defined(STM8S207) || defined(STM8S007) || defined(STM8S103) ||\ + defined(STM8S003) || defined(STM8S001) || defined(STM8S903) || defined (STM8AF52Ax) || defined (STM8AF62Ax) +#include "stm8s_uart1.h" +#endif /* (STM8S208) || (STM8S207) || (STM8S103) || (STM8S001) || (STM8S903) || (STM8AF52Ax) || (STM8AF62Ax) */ +#if defined(STM8S105) || defined(STM8S005) || defined (STM8AF626x) +// #include "stm8s_uart2.h" +#endif /* (STM8S105) || (STM8AF626x) */ +#if defined(STM8S208) ||defined(STM8S207) || defined(STM8S007) || defined (STM8AF52Ax) ||\ + defined (STM8AF62Ax) +// #include "stm8s_uart3.h" +#endif /* (STM8S208) || (STM8S207) || (STM8AF52Ax) || (STM8AF62Ax) */ +#if defined(STM8AF622x) /* SDCC patch: see https://github.com/tenbaht/sduino/tree/master/STM8S_StdPeriph_Driver */ +// #include "stm8s_uart4.h" +#endif /* (STM8AF622x) */ +//#include "stm8s_wwdg.h" + +/* Exported types ------------------------------------------------------------*/ +/* Exported constants --------------------------------------------------------*/ +/* Uncomment the line below to expanse the "assert_param" macro in the + Standard Peripheral Library drivers code */ +// #define USE_FULL_ASSERT (1) + +/* Exported macro ------------------------------------------------------------*/ +#ifdef USE_FULL_ASSERT + +/** + * @brief The assert_param macro is used for function's parameters check. + * @param expr: If expr is false, it calls assert_failed function + * which reports the name of the source file and the source + * line number of the call that failed. + * If expr is true, it returns no value. + * @retval : None + */ +#define assert_param(expr) ((expr) ? (void)0 : assert_failed((uint8_t *)__FILE__, __LINE__)) +/* Exported functions ------------------------------------------------------- */ +void assert_failed(uint8_t* file, uint32_t line); +#else +#define assert_param(expr) ((void)0) +#endif /* USE_FULL_ASSERT */ + +#endif /* __STM8S_CONF_H */ + + +/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/ diff --git a/src/stm8s_it.c b/src/stm8s_it.c new file mode 100644 index 0000000..a07937b --- /dev/null +++ b/src/stm8s_it.c @@ -0,0 +1,541 @@ +/** + ****************************************************************************** + * @file stm8s_it.c + * @author MCD Application Team + * @version V2.0.4 + * @date 26-April-2018 + * @brief Main Interrupt Service Routines. + ****************************************************************************** + * @attention + * + *

© COPYRIGHT 2014 STMicroelectronics

+ * + * Licensed under MCD-ST Liberty SW License Agreement V2, (the "License"); + * You may not use this file except in compliance with the License. + * You may obtain a copy of the License at: + * + * http://www.st.com/software_license_agreement_liberty_v2 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + ****************************************************************************** + */ + +/* Includes ------------------------------------------------------------------*/ +#include "stm8s_it.h" +#include "main.h" +#include "stm8s.h" +#include "stm8s_i2c.h" + +/* Private typedef -----------------------------------------------------------*/ +/* Private define ------------------------------------------------------------*/ +/* Private macro -------------------------------------------------------------*/ +// extern uint8_t HEADER_ADDRESS_Write = (((SLAVE_ADDRESS & 0xFF00) >> 7) | 0xF0); +// extern uint8_t HEADER_ADDRESS_Read; +/* Private variables ---------------------------------------------------------*/ +__IO uint8_t SlaveAddress; +__IO uint8_t TxByte; +__IO uint8_t RxByte; + +__IO uint8_t State; +/* Private function prototypes -----------------------------------------------*/ +/* Private functions ---------------------------------------------------------*/ + +/* Public functions ----------------------------------------------------------*/ + +/** @addtogroup GPIO_Toggle + * @{ + */ +#ifdef _COSMIC_ +/** + * @brief Dummy interrupt routine + * @param None + * @retval None + */ +INTERRUPT_HANDLER(NonHandledInterrupt, 25) +{ + /* In order to detect unexpected events during development, + it is recommended to set a breakpoint on the following instruction. + */ +} +#endif /*_COSMIC_*/ + +/** + * @brief TRAP interrupt routine + * @param None + * @retval None + */ +INTERRUPT_HANDLER_TRAP(TRAP_IRQHandler) +{ + /* In order to detect unexpected events during development, + it is recommended to set a breakpoint on the following instruction. + */ +} +/** + * @brief Top Level Interrupt routine + * @param None + * @retval None + */ +INTERRUPT_HANDLER(TLI_IRQHandler, 0) +{ + /* In order to detect unexpected events during development, + it is recommended to set a breakpoint on the following instruction. + */ +} + +/** + * @brief Auto Wake Up Interrupt routine + * @param None + * @retval None + */ +INTERRUPT_HANDLER(AWU_IRQHandler, 1) +{ + /* In order to detect unexpected events during development, + it is recommended to set a breakpoint on the following instruction. + */ +} + +/** + * @brief Clock Controller Interrupt routine + * @param None + * @retval None + */ +INTERRUPT_HANDLER(CLK_IRQHandler, 2) +{ + /* In order to detect unexpected events during development, + it is recommended to set a breakpoint on the following instruction. + */ +} + +/** + * @brief External Interrupt PORTA Interrupt routine + * @param None + * @retval None + */ +INTERRUPT_HANDLER(EXTI_PORTA_IRQHandler, 3) +{ + /* In order to detect unexpected events during development, + it is recommended to set a breakpoint on the following instruction. + */ +} + +/** + * @brief External Interrupt PORTB Interrupt routine + * @param None + * @retval None + */ +INTERRUPT_HANDLER(EXTI_PORTB_IRQHandler, 4) +{ + /* In order to detect unexpected events during development, + it is recommended to set a breakpoint on the following instruction. + */ +} + +/** + * @brief External Interrupt PORTC Interrupt routine + * @param None + * @retval None + */ +INTERRUPT_HANDLER(EXTI_PORTC_IRQHandler, 5) +{ + /* In order to detect unexpected events during development, + it is recommended to set a breakpoint on the following instruction. + */ +} + +/** + * @brief External Interrupt PORTD Interrupt routine + * @param None + * @retval None + */ +INTERRUPT_HANDLER(EXTI_PORTD_IRQHandler, 6) +{ + /* In order to detect unexpected events during development, + it is recommended to set a breakpoint on the following instruction. + */ +} + +/** + * @brief External Interrupt PORTE Interrupt routine + * @param None + * @retval None + */ +INTERRUPT_HANDLER(EXTI_PORTE_IRQHandler, 7) +{ + /* In order to detect unexpected events during development, + it is recommended to set a breakpoint on the following instruction. + */ +} +#ifdef STM8S903 +/** + * @brief External Interrupt PORTF Interrupt routine + * @param None + * @retval None + */ + INTERRUPT_HANDLER(EXTI_PORTF_IRQHandler, 8) +{ + /* In order to detect unexpected events during development, + it is recommended to set a breakpoint on the following instruction. + */ +} +#endif /*STM8S903*/ + +#if defined (STM8S208) || defined (STM8AF52Ax) +/** + * @brief CAN RX Interrupt routine. + * @param None + * @retval None + */ + INTERRUPT_HANDLER(CAN_RX_IRQHandler, 8) +{ + /* In order to detect unexpected events during development, + it is recommended to set a breakpoint on the following instruction. + */ +} + +/** + * @brief CAN TX Interrupt routine + * @param None + * @retval None + */ + INTERRUPT_HANDLER(CAN_TX_IRQHandler, 9) +{ + /* In order to detect unexpected events during development, + it is recommended to set a breakpoint on the following instruction. + */ +} +#endif /*STM8S208 || STM8AF52Ax */ + +/** + * @brief SPI Interrupt routine + * @param None + * @retval None + */ +INTERRUPT_HANDLER(SPI_IRQHandler, 10) +{ + /* In order to detect unexpected events during development, + it is recommended to set a breakpoint on the following instruction. + */ +} + +/** + * @brief Timer1 Update/Overflow/Trigger/Break Interrupt routine + * @param None + * @retval None + */ +INTERRUPT_HANDLER(TIM1_UPD_OVF_TRG_BRK_IRQHandler, 11) +{ + /* In order to detect unexpected events during development, + it is recommended to set a breakpoint on the following instruction. + */ +} + +/** + * @brief Timer1 Capture/Compare Interrupt routine + * @param None + * @retval None + */ +INTERRUPT_HANDLER(TIM1_CAP_COM_IRQHandler, 12) +{ + /* In order to detect unexpected events during development, + it is recommended to set a breakpoint on the following instruction. + */ +} + +#ifdef STM8S903 +/** + * @brief Timer5 Update/Overflow/Break/Trigger Interrupt routine + * @param None + * @retval None + */ + INTERRUPT_HANDLER(TIM5_UPD_OVF_BRK_TRG_IRQHandler, 13) +{ + /* In order to detect unexpected events during development, + it is recommended to set a breakpoint on the following instruction. + */ +} +/** + * @brief Timer5 Capture/Compare Interrupt routine + * @param None + * @retval None + */ + INTERRUPT_HANDLER(TIM5_CAP_COM_IRQHandler, 14) +{ + /* In order to detect unexpected events during development, + it is recommended to set a breakpoint on the following instruction. + */ +} + +#else /*STM8S208, STM8S207, STM8S105 or STM8S103 or STM8S001 or STM8AF62Ax or STM8AF52Ax or STM8AF626x */ +/** + * @brief Timer2 Update/Overflow/Break Interrupt routine + * @param None + * @retval None + */ + INTERRUPT_HANDLER(TIM2_UPD_OVF_BRK_IRQHandler, 13) +{ + /* In order to detect unexpected events during development, + it is recommended to set a breakpoint on the following instruction. + */ +} + +/** + * @brief Timer2 Capture/Compare Interrupt routine + * @param None + * @retval None + */ + INTERRUPT_HANDLER(TIM2_CAP_COM_IRQHandler, 14) +{ + /* In order to detect unexpected events during development, + it is recommended to set a breakpoint on the following instruction. + */ +} +#endif /*STM8S903*/ + +#if defined(STM8S208) || defined(STM8S207) || defined(STM8S007) || defined(STM8S105) || \ + defined(STM8S005) || defined(STM8AF62Ax) || defined(STM8AF52Ax) || defined(STM8AF626x) +/** + * @brief Timer3 Update/Overflow/Break Interrupt routine. + * @param None + * @retval None + */ + INTERRUPT_HANDLER(TIM3_UPD_OVF_BRK_IRQHandler, 15) +{ + /* In order to detect unexpected events during development, + it is recommended to set a breakpoint on the following instruction. + */ +} + +/** + * @brief Timer3 Capture/Compare Interrupt routine + * @param None + * @retval None + */ + INTERRUPT_HANDLER(TIM3_CAP_COM_IRQHandler, 16) +{ + /* In order to detect unexpected events during development, + it is recommended to set a breakpoint on the following instruction. + */ +} +#endif /*STM8S208, STM8S207 or STM8S105 or STM8AF62Ax or STM8AF52Ax or STM8AF626x */ + +#if defined(STM8S208) || defined(STM8S207) || defined(STM8S007) || defined(STM8S103) || \ + defined(STM8S003) || defined(STM8S001) || defined(STM8AF62Ax) || defined(STM8AF52Ax) || defined(STM8S903) +/** + * @brief UART1 TX Interrupt routine + * @param None + * @retval None + */ + INTERRUPT_HANDLER(UART1_TX_IRQHandler, 17) +{ + /* In order to detect unexpected events during development, + it is recommended to set a breakpoint on the following instruction. + */ +} + +/** + * @brief UART1 RX Interrupt routine + * @param None + * @retval None + */ + INTERRUPT_HANDLER(UART1_RX_IRQHandler, 18) +{ + /* In order to detect unexpected events during development, + it is recommended to set a breakpoint on the following instruction. + */ +} +#endif /*STM8S105 || STM8S001 */ + +/** + * @brief I2C Interrupt routine + * @param None + * @retval None + */ +INTERRUPT_HANDLER(I2C_IRQHandler, 19) +{ + /* In order to detect unexpected events during development, + it is recommended to set a breakpoint on the following instruction. + */ + // puts("I2C "); + switch (I2C_GetLastEvent()) { + /* EV5 */ + case I2C_EVENT_MASTER_MODE_SELECT : + if (State == 0) { + /* Send slave Address for write */ + I2C_Send7bitAddress(SlaveAddress, I2C_DIRECTION_TX); + puts("EV5_TX\n"); + } else { + I2C_Send7bitAddress(SlaveAddress, I2C_DIRECTION_RX); + puts("EV5_RX\n"); + } + break; + + /* EV6 */ + case I2C_EVENT_MASTER_TRANSMITTER_MODE_SELECTED: + I2C_SendData(TxByte); + // I2C_ITConfig(I2C_IT_BUF, DISABLE); + State = 1; + puts("EV6_TX\n"); + break; + + case I2C_EVENT_MASTER_RECEIVER_MODE_SELECTED: + I2C_AcknowledgeConfig(I2C_ACK_NONE); + puts("EV6_RX\n"); + break; + + /* EV7 */ + case I2C_EVENT_MASTER_BYTE_RECEIVED: + I2C_GenerateSTOP(ENABLE); + puts("EV7\n"); + break; + + /* EV8 */ + case I2C_EVENT_MASTER_BYTE_TRANSMITTING: + /* Transmit Data */ + I2C_GenerateSTART(ENABLE); + puts("EV8\n"); + break; + + default: + if(I2C_GetFlagStatus(I2C_FLAG_ACKNOWLEDGEFAILURE) == SET) { + puts("ACK FAILURE\n"); + I2C_ClearFlag(I2C_FLAG_ACKNOWLEDGEFAILURE); + } else { + puts("BOH FAILURE\n"); + } + break; + } +} + +#if defined(STM8S105) || defined(STM8S005) || defined (STM8AF626x) +/** + * @brief UART2 TX interrupt routine. + * @param None + * @retval None + */ + INTERRUPT_HANDLER(UART2_TX_IRQHandler, 20) +{ + /* In order to detect unexpected events during development, + it is recommended to set a breakpoint on the following instruction. + */ + } + +/** + * @brief UART2 RX interrupt routine. + * @param None + * @retval None + */ + INTERRUPT_HANDLER(UART2_RX_IRQHandler, 21) +{ + /* In order to detect unexpected events during development, + it is recommended to set a breakpoint on the following instruction. + */ + } +#endif /* STM8S105*/ + +#if defined(STM8S207) || defined(STM8S007) || defined(STM8S208) || defined (STM8AF52Ax) || defined (STM8AF62Ax) +/** + * @brief UART3 TX interrupt routine. + * @param None + * @retval None + */ + INTERRUPT_HANDLER(UART3_TX_IRQHandler, 20) +{ + /* In order to detect unexpected events during development, + it is recommended to set a breakpoint on the following instruction. + */ + } + +/** + * @brief UART3 RX interrupt routine. + * @param None + * @retval None + */ + INTERRUPT_HANDLER(UART3_RX_IRQHandler, 21) +{ + /* In order to detect unexpected events during development, + it is recommended to set a breakpoint on the following instruction. + */ + } +#endif /*STM8S208 or STM8S207 or STM8AF52Ax or STM8AF62Ax */ + +#if defined(STM8S207) || defined(STM8S007) || defined(STM8S208) || defined (STM8AF52Ax) || defined (STM8AF62Ax) +/** + * @brief ADC2 interrupt routine. + * @param None + * @retval None + */ + INTERRUPT_HANDLER(ADC2_IRQHandler, 22) +{ + + /* In order to detect unexpected events during development, + it is recommended to set a breakpoint on the following instruction. + */ + return; + +} +#else /*STM8S105, STM8S103 or STM8S903 or STM8AF626x */ +/** + * @brief ADC1 interrupt routine. + * @param None + * @retval None + */ + INTERRUPT_HANDLER(ADC1_IRQHandler, 22) +{ + + /* In order to detect unexpected events during development, + it is recommended to set a breakpoint on the following instruction. + */ + return; + +} +#endif /*STM8S208 or STM8S207 or STM8AF52Ax or STM8AF62Ax */ + +#ifdef STM8S903 +/** + * @brief Timer6 Update/Overflow/Trigger Interrupt routine + * @param None + * @retval None + */ +INTERRUPT_HANDLER(TIM6_UPD_OVF_TRG_IRQHandler, 23) +{ + /* In order to detect unexpected events during development, + it is recommended to set a breakpoint on the following instruction. + */ +} +#else /*STM8S208, STM8S207, STM8S105 or STM8S103 or STM8S001 or STM8AF62Ax or STM8AF52Ax or STM8AF626x */ +/** + * @brief Timer4 Update/Overflow Interrupt routine + * @param None + * @retval None + */ + INTERRUPT_HANDLER(TIM4_UPD_OVF_IRQHandler, 23) +{ + /* In order to detect unexpected events during development, + it is recommended to set a breakpoint on the following instruction. + */ +} +#endif /*STM8S903*/ + +/** + * @brief Eeprom EEC Interrupt routine + * @param None + * @retval None + */ +INTERRUPT_HANDLER(EEPROM_EEC_IRQHandler, 24) +{ + /* In order to detect unexpected events during development, + it is recommended to set a breakpoint on the following instruction. + */ +} + +/** + * @} + */ + + +/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/ diff --git a/src/stm8s_it.h b/src/stm8s_it.h new file mode 100644 index 0000000..46aac46 --- /dev/null +++ b/src/stm8s_it.h @@ -0,0 +1,201 @@ +/** + ****************************************************************************** + * @file stm8s_it.h + * @author MCD Application Team + * @version V2.0.4 + * @date 26-April-2018 + * @brief This file contains the headers of the interrupt handlers + ****************************************************************************** + * @attention + * + *

© COPYRIGHT 2014 STMicroelectronics

+ * + * Licensed under MCD-ST Liberty SW License Agreement V2, (the "License"); + * You may not use this file except in compliance with the License. + * You may obtain a copy of the License at: + * + * http://www.st.com/software_license_agreement_liberty_v2 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + ****************************************************************************** + */ + +/* Define to prevent recursive inclusion -------------------------------------*/ +#ifndef __STM8S_IT_H +#define __STM8S_IT_H + +/* Includes ------------------------------------------------------------------*/ +#include "stm8s.h" + +/* Exported types ------------------------------------------------------------*/ +/* Exported constants --------------------------------------------------------*/ +/* Exported macro ------------------------------------------------------------*/ +/* Exported functions ------------------------------------------------------- */ +#ifdef _COSMIC_ + void _stext(void); /* RESET startup routine */ + INTERRUPT void NonHandledInterrupt(void); +#endif /* _COSMIC_ */ + +// SDCC patch: requires separate handling for SDCC (see below) +#if !defined(_RAISONANCE_) && !defined(_SDCC_) + INTERRUPT void TRAP_IRQHandler(void); /* TRAP */ + INTERRUPT void TLI_IRQHandler(void); /* TLI */ + INTERRUPT void AWU_IRQHandler(void); /* AWU */ + INTERRUPT void CLK_IRQHandler(void); /* CLOCK */ + INTERRUPT void EXTI_PORTA_IRQHandler(void); /* EXTI PORTA */ + INTERRUPT void EXTI_PORTB_IRQHandler(void); /* EXTI PORTB */ + INTERRUPT void EXTI_PORTC_IRQHandler(void); /* EXTI PORTC */ + INTERRUPT void EXTI_PORTD_IRQHandler(void); /* EXTI PORTD */ + INTERRUPT void EXTI_PORTE_IRQHandler(void); /* EXTI PORTE */ + +#if defined(STM8S903) || defined(STM8AF622x) // SDCC patch: add STM8AF622x + INTERRUPT void EXTI_PORTF_IRQHandler(void); /* EXTI PORTF */ +#endif /* (STM8S903) || (STM8AF622x) */ + +#if defined (STM8S208) || defined (STM8AF52Ax) + INTERRUPT void CAN_RX_IRQHandler(void); /* CAN RX */ + INTERRUPT void CAN_TX_IRQHandler(void); /* CAN TX/ER/SC */ +#endif /* (STM8S208) || (STM8AF52Ax) */ + + INTERRUPT void SPI_IRQHandler(void); /* SPI */ + INTERRUPT void TIM1_CAP_COM_IRQHandler(void); /* TIM1 CAP/COM */ + INTERRUPT void TIM1_UPD_OVF_TRG_BRK_IRQHandler(void); /* TIM1 UPD/OVF/TRG/BRK */ + +#if defined(STM8S903) || defined(STM8AF622x) // SDCC patch: add STM8AF622x + INTERRUPT void TIM5_UPD_OVF_BRK_TRG_IRQHandler(void); /* TIM5 UPD/OVF/BRK/TRG */ + INTERRUPT void TIM5_CAP_COM_IRQHandler(void); /* TIM5 CAP/COM */ +#else /* (STM8S208) || (STM8S207) || (STM8S105) || (STM8S103) || (STM8S001) || (STM8AF52Ax) || (STM8AF62Ax) || (STM8A626x) */ + INTERRUPT void TIM2_UPD_OVF_BRK_IRQHandler(void); /* TIM2 UPD/OVF/BRK */ + INTERRUPT void TIM2_CAP_COM_IRQHandler(void); /* TIM2 CAP/COM */ +#endif /* (STM8S903) || (STM8AF622x) */ + +#if defined (STM8S208) || defined(STM8S207) || defined(STM8S007) || defined(STM8S105) || \ + defined(STM8S005) || defined (STM8AF52Ax) || defined (STM8AF62Ax) || defined (STM8AF626x) + INTERRUPT void TIM3_UPD_OVF_BRK_IRQHandler(void); /* TIM3 UPD/OVF/BRK */ + INTERRUPT void TIM3_CAP_COM_IRQHandler(void); /* TIM3 CAP/COM */ +#endif /* (STM8S208) || (STM8S207) || (STM8S105) || (STM8AF52Ax) || (STM8AF62Ax) || (STM8A626x) */ + +#if defined(STM8S208) || defined(STM8S207) || defined(STM8S007) || defined(STM8S103) || \ + defined(STM8S003) || defined(STM8S001) || defined(STM8AF52Ax) || defined(STM8AF62Ax) || defined(STM8S903) + INTERRUPT void UART1_TX_IRQHandler(void); /* UART1 TX */ + INTERRUPT void UART1_RX_IRQHandler(void); /* UART1 RX */ +#endif /* (STM8S208) || (STM8S207) || (STM8S007) || (STM8S103) || (STM8S003) || (STM8S001) || (STM8AF52Ax) || (STM8AF62Ax) || (STM8S903) */ + +#if defined (STM8AF622x) // SDCC patch: add STM8AF622x + INTERRUPT void UART4_TX_IRQHandler(void); /* UART4 TX */ + INTERRUPT void UART4_RX_IRQHandler(void); /* UART4 RX */ +#endif /* (STM8AF622x) */ + + INTERRUPT void I2C_IRQHandler(void); /* I2C */ + +#if defined(STM8S105) || defined(STM8S005) || defined (STM8AF626x) + INTERRUPT void UART2_RX_IRQHandler(void); /* UART2 RX */ + INTERRUPT void UART2_TX_IRQHandler(void); /* UART2 TX */ +#endif /* (STM8S105) || (STM8S005) || (STM8AF626x) */ + +#if defined(STM8S207) || defined(STM8S007) || defined(STM8S208) || defined (STM8AF52Ax) || defined (STM8AF62Ax) + INTERRUPT void UART3_RX_IRQHandler(void); /* UART3 RX */ + INTERRUPT void UART3_TX_IRQHandler(void); /* UART3 TX */ +#endif /* (STM8S207) || (STM8S007) || (STM8S208) || (STM8AF52Ax) || (STM8AF62Ax) */ + +#if defined(STM8S207) || defined(STM8S007) || defined(STM8S208) || defined (STM8AF52Ax) || defined (STM8AF62Ax) + INTERRUPT void ADC2_IRQHandler(void); /* ADC2 */ +#else /* (STM8S105) || (STM8S103) || (STM8S903) || (STM8AF622x) */ + INTERRUPT void ADC1_IRQHandler(void); /* ADC1 */ +#endif /* (STM8S207) || (STM8S007) || (STM8S208) || (STM8AF52Ax) || (STM8AF62Ax) */ + +#if defined(STM8S903) || defined(STM8AF622x) // SDCC patch: add STM8AF622x + INTERRUPT void TIM6_UPD_OVF_TRG_IRQHandler(void); /* TIM6 UPD/OVF/TRG */ +#else /*STM8S208, STM8S207, STM8S105 or STM8S103 or STM8AF62Ax or STM8AF52Ax or STM8AF626x */ + INTERRUPT void TIM4_UPD_OVF_IRQHandler(void); /* TIM4 UPD/OVF */ +#endif /* (STM8S903) || (STM8AF622x) */ + INTERRUPT void EEPROM_EEC_IRQHandler(void); /* EEPROM ECC CORRECTION */ + + +// SDCC patch: __interrupt keyword required after function name --> requires new block +#elif defined (_SDCC_) + + INTERRUPT_HANDLER_TRAP(TRAP_IRQHandler); /* TRAP */ + INTERRUPT_HANDLER(TLI_IRQHandler, 0); /* TLI */ + INTERRUPT_HANDLER(AWU_IRQHandler, 1); /* AWU */ + INTERRUPT_HANDLER(CLK_IRQHandler, 2); /* CLOCK */ + INTERRUPT_HANDLER(EXTI_PORTA_IRQHandler, 3); /* EXTI PORTA */ + INTERRUPT_HANDLER(EXTI_PORTB_IRQHandler, 4); /* EXTI PORTB */ + INTERRUPT_HANDLER(EXTI_PORTC_IRQHandler, 5); /* EXTI PORTC */ + INTERRUPT_HANDLER(EXTI_PORTD_IRQHandler, 6); /* EXTI PORTD */ + INTERRUPT_HANDLER(EXTI_PORTE_IRQHandler, 7); /* EXTI PORTE */ + +#if defined(STM8S903) || defined(STM8AF622x) + INTERRUPT_HANDLER(EXTI_PORTF_IRQHandler, 8); /* EXTI PORTF */ +#endif /* (STM8S903) || (STM8AF622x) */ + +#if defined (STM8S208) || defined (STM8AF52Ax) + INTERRUPT_HANDLER(CAN_RX_IRQHandler, 8); /* CAN RX */ + INTERRUPT_HANDLER(CAN_TX_IRQHandler, 9); /* CAN TX/ER/SC */ +#endif /* (STM8S208) || (STM8AF52Ax) */ + + INTERRUPT_HANDLER(SPI_IRQHandler, 10); /* SPI */ + INTERRUPT_HANDLER(TIM1_UPD_OVF_TRG_BRK_IRQHandler, 11); /* TIM1 UPD/OVF/TRG/BRK */ + INTERRUPT_HANDLER(TIM1_CAP_COM_IRQHandler, 12); /* TIM1 CAP/COM */ + +#if defined(STM8S903) || defined(STM8AF622x) + INTERRUPT_HANDLER(TIM5_UPD_OVF_BRK_TRG_IRQHandler, 13); /* TIM5 UPD/OVF/BRK/TRG */ + INTERRUPT_HANDLER(TIM5_CAP_COM_IRQHandler, 14); /* TIM5 CAP/COM */ +#else /* (STM8S208) || (STM8S207) || (STM8S105) || (STM8S103) || (STM8S001) || (STM8AF52Ax) || (STM8AF62Ax) || (STM8A626x) */ + INTERRUPT_HANDLER(TIM2_UPD_OVF_BRK_IRQHandler, 13); /* TIM2 UPD/OVF/BRK */ + INTERRUPT_HANDLER(TIM2_CAP_COM_IRQHandler, 14); /* TIM2 CAP/COM */ +#endif /* (STM8S903) || (STM8AF622x) */ + +#if defined (STM8S208) || defined(STM8S207) || defined(STM8S007) || defined(STM8S105) || \ + defined(STM8S005) || defined (STM8AF52Ax) || defined (STM8AF62Ax) || defined (STM8AF626x) + INTERRUPT_HANDLER(TIM3_UPD_OVF_BRK_IRQHandler, 15); /* TIM3 UPD/OVF/BRK */ + INTERRUPT_HANDLER(TIM3_CAP_COM_IRQHandler, 16); /* TIM3 CAP/COM */ +#endif /* (STM8S208) || (STM8S207) || (STM8S105) || (STM8AF52Ax) || (STM8AF62Ax) || (STM8A626x) */ + +#if defined (STM8S208) || defined(STM8S207) || defined(STM8S007) || defined(STM8S103) || \ + defined(STM8S003) || defined(STM8S001) || defined (STM8AF52Ax) || defined (STM8AF62Ax) || defined (STM8S903) + INTERRUPT_HANDLER(UART1_TX_IRQHandler, 17); /* UART1 TX */ + INTERRUPT_HANDLER(UART1_RX_IRQHandler, 18); /* UART1 RX */ +#endif /* (STM8S208) || (STM8S207) || (STM8S903) || (STM8S103) || (STM8S001) || (STM8AF52Ax) || (STM8AF62Ax) */ + +#if defined (STM8AF622x) + INTERRUPT_HANDLER(UART4_TX_IRQHandler, 17); /* UART4 TX */ + INTERRUPT_HANDLER(UART4_RX_IRQHandler, 18); /* UART4 RX */ +#endif /* (STM8AF622x) */ + + INTERRUPT_HANDLER(I2C_IRQHandler, 19); /* I2C */ + +#if defined(STM8S105) || defined(STM8S005) || defined (STM8AF626x) + INTERRUPT_HANDLER(UART2_TX_IRQHandler, 20); /* UART2 TX */ + INTERRUPT_HANDLER(UART2_RX_IRQHandler, 21); /* UART2 RX */ +#endif /* (STM8S105) || (STM8AF626x) */ + +#if defined(STM8S207) || defined(STM8S007) || defined(STM8S208) || defined (STM8AF52Ax) || defined (STM8AF62Ax) + INTERRUPT_HANDLER(UART3_RX_IRQHandler, 20); /* UART3 RX */ + INTERRUPT_HANDLER(UART3_TX_IRQHandler, 21); /* UART3 TX */ +#endif /* (STM8S207) || (STM8S208) || (STM8AF62Ax) || (STM8AF52Ax) */ + +#if defined(STM8S207) || defined(STM8S007) || defined(STM8S208) || defined (STM8AF52Ax) || defined (STM8AF62Ax) + INTERRUPT_HANDLER(ADC2_IRQHandler, 22); /* ADC2 */ +#else /* (STM8S105) || (STM8S103) || (STM8S903) || (STM8AF622x) */ + INTERRUPT_HANDLER(ADC1_IRQHandler, 22); /* ADC1 */ +#endif /* (STM8S207) || (STM8S208) || (STM8AF62Ax) || (STM8AF52Ax) */ + +#if defined(STM8S903) || defined(STM8AF622x) + INTERRUPT_HANDLER(TIM6_UPD_OVF_TRG_IRQHandler, 23); /* TIM6 UPD/OVF/TRG */ +#else /* (STM8S208) || (STM8S207) || (STM8S105) || (STM8S103) || (STM8AF62Ax) || (STM8AF52Ax) || (STM8AF626x) */ + INTERRUPT_HANDLER(TIM4_UPD_OVF_IRQHandler, 23); /* TIM4 UPD/OVF */ +#endif /* (STM8S903) || (STM8AF622x) */ + INTERRUPT_HANDLER(EEPROM_EEC_IRQHandler, 24); /* EEPROM ECC CORRECTION */ + +#endif /* !(_RAISONANCE_) && !(_SDCC_) */ + +#endif /* __STM8S_IT_H */ + + +/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/ diff --git a/test/README b/test/README new file mode 100644 index 0000000..9b1e87b --- /dev/null +++ b/test/README @@ -0,0 +1,11 @@ + +This directory is intended for PlatformIO Test Runner and project tests. + +Unit Testing is a software testing method by which individual units of +source code, sets of one or more MCU program modules together with associated +control data, usage procedures, and operating procedures, are tested to +determine whether they are fit for use. Unit testing finds problems early +in the development cycle. + +More information about PlatformIO Unit Testing: +- https://docs.platformio.org/en/latest/advanced/unit-testing/index.html