diff --git a/src/boards/include/boards/0xcb_helios.h b/src/boards/include/boards/0xcb_helios.h new file mode 100644 index 00000000..e9df358e --- /dev/null +++ b/src/boards/include/boards/0xcb_helios.h @@ -0,0 +1,84 @@ +/* + * Copyright (c) 2020 Raspberry Pi (Trading) Ltd. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +// ----------------------------------------------------- +// NOTE: THIS HEADER IS ALSO INCLUDED BY ASSEMBLER SO +// SHOULD ONLY CONSIST OF PREPROCESSOR DIRECTIVES +// ----------------------------------------------------- +// +//------------------------------------------------------------------------------------------ +// Board definition for the 0xCB Helios + +#ifndef _BOARDS_0XCB_HELIOS_H +#define _BOARDS_0XCB_HELIOS_H + +// For board detection +#define _0XCB_HELIOS + +#ifndef PICO_DEFAULT_UART +#define PICO_DEFAULT_UART 0 +#endif +#ifndef PICO_DEFAULT_UART_TX_PIN +#define PICO_DEFAULT_UART_TX_PIN 0 +#endif +#ifndef PICO_DEFAULT_UART_RX_PIN +#define PICO_DEFAULT_UART_RX_PIN 1 +#endif + +// User LED and level shifted PIN +#ifndef PICO_DEFAULT_LED_PIN +#define PICO_DEFAULT_LED_PIN 17 +#endif +#ifndef PICO_DEFAULT_WS2812_PIN +#define PICO_DEFAULT_WS2812_PIN 25 +#endif + +// --- I2C --- +#ifndef PICO_DEFAULT_I2C +#define PICO_DEFAULT_I2C 1 +#endif +#ifndef PICO_DEFAULT_I2C_SDA_PIN +#define PICO_DEFAULT_I2C_SDA_PIN 2 +#endif +#ifndef PICO_DEFAULT_I2C_SCL_PIN +#define PICO_DEFAULT_I2C_SCL_PIN 3 +#endif + +// --- SPI --- +#ifndef PICO_DEFAULT_SPI +#define PICO_DEFAULT_SPI 0 +#endif +#ifndef PICO_DEFAULT_SPI_SCK_PIN +#define PICO_DEFAULT_SPI_SCK_PIN 22 +#endif +#ifndef PICO_DEFAULT_SPI_TX_PIN +#define PICO_DEFAULT_SPI_TX_PIN 23 +#endif +#ifndef PICO_DEFAULT_SPI_RX_PIN +#define PICO_DEFAULT_SPI_RX_PIN 20 +#endif +#ifndef PICO_DEFAULT_SPI_CSN_PIN +#define PICO_DEFAULT_SPI_CSN_PIN 21 +#endif + +#define PICO_BOOT_STAGE2_CHOOSE_W25Q080 1 + +#ifndef PICO_FLASH_SPI_CLKDIV +#define PICO_FLASH_SPI_CLKDIV 2 +#endif + +// board has 16M onboard flash +#ifndef PICO_FLASH_SIZE_BYTES +#define PICO_FLASH_SIZE_BYTES (16 * 1024 * 1024) +#endif + +// All boards have B1 RP2040 + +#ifndef PICO_RP2040_B0_SUPPORTED +#define PICO_RP2040_B0_SUPPORTED 0 +#endif + +#endif diff --git a/src/boards/include/boards/cytron_maker_pi_rp2040.h b/src/boards/include/boards/cytron_maker_pi_rp2040.h index 72ed4be9..77dd424c 100644 --- a/src/boards/include/boards/cytron_maker_pi_rp2040.h +++ b/src/boards/include/boards/cytron_maker_pi_rp2040.h @@ -26,8 +26,8 @@ #define MAKER_PI_RP2040_M1B_PIN 9 #endif -#ifndef MAKER_PI_RP2040_M2B_PIN -#define MAKER_PI_RP2040_M2B_PIN 10 +#ifndef MAKER_PI_RP2040_M2A_PIN +#define MAKER_PI_RP2040_M2A_PIN 10 #endif #ifndef MAKER_PI_RP2040_M2B_PIN @@ -186,4 +186,4 @@ #define PICO_RP2040_B0_SUPPORTED 0 #endif -#endif \ No newline at end of file +#endif diff --git a/src/boards/include/boards/nullbits_bit_c_pro.h b/src/boards/include/boards/nullbits_bit_c_pro.h index cbc287d0..169e0c19 100644 --- a/src/boards/include/boards/nullbits_bit_c_pro.h +++ b/src/boards/include/boards/nullbits_bit_c_pro.h @@ -56,7 +56,7 @@ //------------- I2C -------------// #ifndef PICO_DEFAULT_I2C -#define PICO_DEFAULT_I2C 0 +#define PICO_DEFAULT_I2C 1 #endif #ifndef PICO_DEFAULT_I2C_SDA_PIN diff --git a/src/boards/include/boards/pico_w.h b/src/boards/include/boards/pico_w.h index 3109c78a..ba80a49b 100644 --- a/src/boards/include/boards/pico_w.h +++ b/src/boards/include/boards/pico_w.h @@ -9,7 +9,7 @@ // SHOULD ONLY CONSIST OF PREPROCESSOR DIRECTIVES // ----------------------------------------------------- -// This header may be included by other board headers as "boards/pico.h" +// This header may be included by other board headers as "boards/pico_w.h" #ifndef _BOARDS_PICO_W_H #define _BOARDS_PICO_W_H diff --git a/src/boards/include/boards/pimoroni_tiny2040_2mb.h b/src/boards/include/boards/pimoroni_tiny2040_2mb.h index e32d3703..7aa07b2f 100644 --- a/src/boards/include/boards/pimoroni_tiny2040_2mb.h +++ b/src/boards/include/boards/pimoroni_tiny2040_2mb.h @@ -13,8 +13,8 @@ #define _BOARDS_PIMORONI_TINY2040_2MB_H // For board detection -#define PIMORONI_TINY2040 #define PIMORONI_TINY2040_2MB +#define PIMORONI_TINY2040 // --- BOARD SPECIFIC --- #define TINY2040_LED_R_PIN 18 diff --git a/src/boards/include/boards/pololu_3pi_2040_robot.h b/src/boards/include/boards/pololu_3pi_2040_robot.h index a3110cc2..94be451a 100644 --- a/src/boards/include/boards/pololu_3pi_2040_robot.h +++ b/src/boards/include/boards/pololu_3pi_2040_robot.h @@ -9,8 +9,8 @@ // SHOULD ONLY CONSIST OF PREPROCESSOR DIRECTIVES // ----------------------------------------------------- -#ifndef _POLOLU_3PI_2040_ROBOT_H -#define _POLOLU_3PI_2040_ROBOT_H +#ifndef _BOARDS_POLOLU_3PI_2040_ROBOT_H +#define _BOARDS_POLOLU_3PI_2040_ROBOT_H // For board detection #define POLOLU_3PI_2040_ROBOT diff --git a/src/boards/include/boards/pololu_zumo_2040_robot.h b/src/boards/include/boards/pololu_zumo_2040_robot.h index 252cea98..7eb1cf0e 100644 --- a/src/boards/include/boards/pololu_zumo_2040_robot.h +++ b/src/boards/include/boards/pololu_zumo_2040_robot.h @@ -9,8 +9,8 @@ // SHOULD ONLY CONSIST OF PREPROCESSOR DIRECTIVES // ----------------------------------------------------- -#ifndef _POLOLU_ZUMO_2040_ROBOT_H -#define _POLOLU_ZUMO_2040_ROBOT_H +#ifndef _BOARDS_POLOLU_ZUMO_2040_ROBOT_H +#define _BOARDS_POLOLU_ZUMO_2040_ROBOT_H // For board detection #define POLOLU_ZUMO_2040_ROBOT diff --git a/src/boards/include/boards/weact_studio_rp2040_2mb.h b/src/boards/include/boards/weact_studio_rp2040_2mb.h index 34667eb2..d058ce34 100644 --- a/src/boards/include/boards/weact_studio_rp2040_2mb.h +++ b/src/boards/include/boards/weact_studio_rp2040_2mb.h @@ -9,13 +9,13 @@ // SHOULD ONLY CONSIST OF PREPROCESSOR DIRECTIVES // ----------------------------------------------------- -// This header may be included by other board headers as "boards/weact_studio_rp2040_16mb.h" +// This header may be included by other board headers as "boards/weact_studio_rp2040_2mb.h" -#ifndef _BOARDS_WEACT_STUDIO_RP2040_16MB_H -#define _BOARDS_WEACT_STUDIO_RP2040_16MB_H +#ifndef _BOARDS_WEACT_STUDIO_RP2040_2MB_H +#define _BOARDS_WEACT_STUDIO_RP2040_2MB_H // For board detection -#define WEACT_STUDIO_RP2040_16MB +#define WEACT_STUDIO_RP2040_2MB // --- UART --- #ifndef PICO_DEFAULT_UART diff --git a/src/boards/include/boards/weact_studio_rp2040_4mb.h b/src/boards/include/boards/weact_studio_rp2040_4mb.h index 98f10a1d..6b49a4f3 100644 --- a/src/boards/include/boards/weact_studio_rp2040_4mb.h +++ b/src/boards/include/boards/weact_studio_rp2040_4mb.h @@ -9,13 +9,13 @@ // SHOULD ONLY CONSIST OF PREPROCESSOR DIRECTIVES // ----------------------------------------------------- -// This header may be included by other board headers as "boards/weact_studio_rp2040_16mb.h" +// This header may be included by other board headers as "boards/weact_studio_rp2040_4mb.h" -#ifndef _BOARDS_WEACT_STUDIO_RP2040_16MB_H -#define _BOARDS_WEACT_STUDIO_RP2040_16MB_H +#ifndef _BOARDS_WEACT_STUDIO_RP2040_4MB_H +#define _BOARDS_WEACT_STUDIO_RP2040_4MB_H // For board detection -#define WEACT_STUDIO_RP2040_16MB +#define WEACT_STUDIO_RP2040_4MB // --- UART --- #ifndef PICO_DEFAULT_UART diff --git a/src/boards/include/boards/weact_studio_rp2040_8mb.h b/src/boards/include/boards/weact_studio_rp2040_8mb.h index 5d28e7b5..bdddd227 100644 --- a/src/boards/include/boards/weact_studio_rp2040_8mb.h +++ b/src/boards/include/boards/weact_studio_rp2040_8mb.h @@ -9,13 +9,13 @@ // SHOULD ONLY CONSIST OF PREPROCESSOR DIRECTIVES // ----------------------------------------------------- -// This header may be included by other board headers as "boards/weact_studio_rp2040_16mb.h" +// This header may be included by other board headers as "boards/weact_studio_rp2040_8mb.h" -#ifndef _BOARDS_WEACT_STUDIO_RP2040_16MB_H -#define _BOARDS_WEACT_STUDIO_RP2040_16MB_H +#ifndef _BOARDS_WEACT_STUDIO_RP2040_8MB_H +#define _BOARDS_WEACT_STUDIO_RP2040_8MB_H // For board detection -#define WEACT_STUDIO_RP2040_16MB +#define WEACT_STUDIO_RP2040_8MB // --- UART --- #ifndef PICO_DEFAULT_UART diff --git a/src/rp2040/rp2040_interface_pins.json b/src/rp2040/rp2040_interface_pins.json new file mode 100644 index 00000000..35dd8234 --- /dev/null +++ b/src/rp2040/rp2040_interface_pins.json @@ -0,0 +1,74 @@ +{ + "UART": { + "0": { + "TX": [0, 12, 16, 28], + "RX": [1, 13, 17, 29], + "CTS": [2, 14, 18], + "RTS": [3, 15, 19] + }, + "1": { + "TX": [4, 8, 20, 24], + "RX": [5, 9, 21, 25], + "CTS": [6, 10, 22, 26], + "RTS": [7, 11, 23, 27] + } + }, + "I2C": { + "0": { + "SDA": [0, 4, 8, 12, 16, 20, 24, 28], + "SCL": [1, 5, 9, 13, 17, 21, 25, 29] + }, + "1": { + "SDA": [2, 6, 10, 14, 18, 22, 26], + "SCL": [3, 7, 11, 15, 19, 23, 27] + } + }, + "SPI": { + "0": { + "RX": [0, 4, 16, 20], + "CSN": [1, 5, 17, 21], + "SCK": [2, 6, 18, 22], + "TX": [3, 7, 19, 23] + }, + "1": { + "RX": [8, 12, 24, 28], + "CSN": [9, 13, 25, 29], + "SCK": [10, 14, 26], + "TX": [11, 15, 27] + } + }, + "PWM": { + "0": { + "A": [0, 16], + "B": [1, 17] + }, + "1": { + "A": [2, 18], + "B": [3, 19] + }, + "2": { + "A": [4, 20], + "B": [5, 21] + }, + "3": { + "A": [6, 22], + "B": [7, 23] + }, + "4": { + "A": [8, 24], + "B": [9, 25] + }, + "5": { + "A": [10, 26], + "B": [11, 27] + }, + "6": { + "A": [12, 28], + "B": [13, 29] + }, + "7": { + "A": [14], + "B": [15] + } + } +} diff --git a/tools/check_all_board_headers.sh b/tools/check_all_board_headers.sh new file mode 100755 index 00000000..bdbe3f77 --- /dev/null +++ b/tools/check_all_board_headers.sh @@ -0,0 +1,7 @@ +#!/bin/bash +for HEADER in src/boards/include/boards/*.h; do + tools/check_board_header.py $HEADER + if [[ $? -ne 0 ]]; then + break + fi +done diff --git a/tools/check_board_header.py b/tools/check_board_header.py new file mode 100755 index 00000000..23176aa0 --- /dev/null +++ b/tools/check_board_header.py @@ -0,0 +1,183 @@ +#!/usr/bin/env python3 +# +# Copyright (c) 2024 Raspberry Pi Ltd. +# +# SPDX-License-Identifier: BSD-3-Clause +# +# +# Simple script to check basic validity of a board-header-file +# +# Usage: +# +# tools/check_board_header.py src/boards/include/boards/ + + +import re +import sys +import os.path +import json +import warnings + +from collections import namedtuple + +# warnings off by default, because some boards use the same pin for multiple purposes +show_warnings = False + +interfaces_json = "src/rp2040/rp2040_interface_pins.json" +if not os.path.isfile(interfaces_json): + raise Exception("{} doesn't exist".format(interfaces_json)) + +board_header = sys.argv[1] +if not os.path.isfile(board_header): + raise Exception("{} doesn't exist".format(board_header)) + +with open(interfaces_json) as interfaces_fh: + interfaces = json.load(interfaces_fh) + # convert instance-keys to integers (allowed by Python but not by JSON) + for interface in interfaces: + for instance in list(interfaces[interface]): + interfaces[interface][int(instance)] = interfaces[interface].pop(instance) + +DefineType = namedtuple("DefineType", ["name", "value", "resolved_value", "lineno"]) + +defines = dict() +pins = dict() # dict of lists +has_include_guard = False +has_board_detection = False +has_include_suggestion = False +expected_include_suggestion = "/".join(board_header.split("/")[-2:]) +expected_include_guard = "_" + re.sub(r"\W", "_", expected_include_suggestion.upper()) +expected_board_detection = re.sub(r"\W", "_", expected_include_suggestion.split("/")[-1].upper()[:-2]) + +with open(board_header) as header_fh: + last_ifndef = None + last_ifndef_lineno = -1 + board_detection_is_next = False + for lineno, line in enumerate(header_fh.readlines()): + lineno += 1 + # strip trailing comments + line = re.sub(r"(?<=\S)\s*//.*$", "", line) + + # look for board-detection comment + if re.match("// For board detection", line): + board_detection_is_next = True + continue + # check include-suggestion + m = re.match(r"^// This header may be included by other board headers as \"(.+?)\"", line) + if m: + include_suggestion = m.group(1) + if include_suggestion == expected_include_suggestion: + has_include_suggestion = True + else: + raise Exception("{}:{} Suggests including \"{}\" but file is named \"{}\"".format(board_header, lineno, include_suggestion, expected_include_suggestion)) + # look for "#ifndef BLAH_BLAH" + m = re.match(r"^#ifndef (\w+)\s*$", line) + if m: + last_ifndef = m.group(1) + last_ifndef_lineno = lineno + # look for "#define BLAH_BLAH" or "#define BLAH_BLAH 42" + m = re.match(r"^#define (\w+)(?:\s+(.+?))?\s*$", line) + if m: + #print(m.groups()) + name = m.group(1) + value = m.group(2) + # check all uppercase + if name != name.upper(): + raise Exception("{}:{} Expected \"{}\" to be all uppercase".format(board_header, lineno, name)) + # check that adjacent #ifndef and #define lines match up + if last_ifndef_lineno + 1 == lineno: + if last_ifndef != name: + raise Exception("{}:{} #ifndef {} / #define {} mismatch".format(board_header, last_ifndef_lineno, last_ifndef, name)) + if value: + try: + # most board-defines are integer values + value = int(value, 0) + except ValueError: + pass + + # resolve nested defines + resolved_value = value + while resolved_value in defines: + resolved_value = defines[resolved_value].resolved_value + else: + resolved_value = None + + define = DefineType(name, value, resolved_value, lineno) + + # check the include-guard define + if re.match(r"^_BOARDS_(\w+)_H$", name): + # check it has an #ifndef + if last_ifndef_lineno +1 != lineno: + raise Exception("{}:{} Include-guard #define {} is missing an #ifndef".format(board_header, lineno, name)) + if value: + raise Exception("{}:{} Include-guard #define {} shouldn't have a value".format(board_header, lineno, name)) + if len(defines): + raise Exception("{}:{} Include-guard #define {} should be the first define".format(board_header, lineno, name)) + if name == expected_include_guard: + has_include_guard = True + else: + raise Exception("{}:{} Found include-guard #define {} but expected {}".format(board_header, lineno, name, expected_include_guard)) + # check board-detection define + if board_detection_is_next: + board_detection_is_next = False + if value: + raise Exception("{}:{} Board-detection #define {} shouldn't have a value".format(board_header, lineno, name)) + # this is a bit messy because pico.h does "#define RASPBERRYPI_PICO" and metrotech_xerxes_rp2040.h does "#define XERXES_RP2040" + if name.endswith(expected_board_detection) or expected_board_detection.endswith(name): + has_board_detection = True + else: + raise Exception("{}:{} Board-detection #define {} should end with {}".format(board_header, lineno, name, expected_board_detection)) + # check for multiply-defined values + if name in defines: + raise Exception("{}:{} Multiple definitions for {} ({} and {})".format(board_header, lineno, name, defines[name].value, value)) + else: + defines[name] = define + + # check for pin-conflicts + if name.endswith("_PIN"): + if resolved_value is None: + raise Exception("{}:{} {} is set to an undefined value".format(board_header, lineno, name)) + elif not isinstance(resolved_value, int): + raise Exception("{}:{} {} resolves to a non-integer value {}".format(board_header, lineno, name, resolved_value)) + else: + if resolved_value in pins and resolved_value == value: + if show_warnings: + warnings.warn("{}:{} Both {} and {} claim to be pin {}".format(board_header, lineno, pins[resolved_value][0].name, name, resolved_value)) + pins[resolved_value].append(define) + else: + if not (0 <= resolved_value <= 29): + raise Exception("{}:{} Pin {} for {} is outside of the allowed range".foramt(board_header, lineno, resolved_value, name)) + pins[resolved_value] = [define] + +#import pprint; pprint.pprint(dict(sorted(defines.items(), key=lambda x: x[1].lineno))) + +# check for invalid DEFAULT mappings +for name, define in defines.items(): + m = re.match(r"^(PICO_DEFAULT_(\w+))_(\w+)_PIN$", name) + if m: + instance_name = m.group(1) + interface = m.group(2) + function = m.group(3) + if interface == "WS2812": + continue + if interface not in interfaces: + raise Exception("{}:{} {} is defined but {} isn't in {}".format(board_header, define.lineno, name, interface, interfaces_json)) + if instance_name not in defines: + raise Exception("{}:{} {} is defined but {} isn't defined".format(board_header, define.lineno, name, instance_name)) + instance_define = defines[instance_name] + instance = instance_define.resolved_value + if instance not in interfaces[interface]: + raise Exception("{}:{} {} is set to an invalid instance {}".format(board_header, instance_define.lineno, instance_define, instance)) + if function not in interfaces[interface][instance]: + raise Exception("{}:{} {} is defined but {} isn't a valid function for {}".format(board_header, define.lineno, name, function, instance_define)) + if define.resolved_value not in interfaces[interface][instance][function]: + raise Exception("{}:{} {} is set to {} which isn't a valid pin for {} on {} {}".format(board_header, define.lineno, name, define.resolved_value, function, interface, instance)) + +if not has_include_guard: + raise Exception("{} has no include-guard (expected {})".format(board_header, expected_include_guard)) +if not has_board_detection and expected_board_detection != "NONE": + raise Exception("{} has no board-detection #define (expected {})".format(board_header, expected_board_detection)) +# lots of headers don't have this +#if not has_include_suggestion: +# raise Exception("{} has no include-suggestion (expected {})".format(board_header, expected_include_suggestion)) +