From 3e8a5e889453a4cf786e808f9b38ef39308ef159 Mon Sep 17 00:00:00 2001 From: Niklas Hauser Date: Sat, 3 Apr 2021 21:23:19 +0200 Subject: [PATCH 01/12] [cmsis] Add query about STM32 header information --- ext/st/module.lb | 76 +++++++++++++++++++++++++++++++----------------- 1 file changed, 49 insertions(+), 27 deletions(-) diff --git a/ext/st/module.lb b/ext/st/module.lb index e90bb805e0..92405dbccd 100644 --- a/ext/st/module.lb +++ b/ext/st/module.lb @@ -67,27 +67,11 @@ def common_rcc_map(env): :returns: a 2D-dictionary: `map[PERIPHERAL][TYPE] = REGISTER` """ - device = env[":target"] - - core = device.get_driver("core")["type"] - core = core.replace("cortex-m", "").replace("+", "plus").replace("f", "").replace("d", "") - core_header = "core_cm{}.h".format(core) - core_header = repopath("ext/arm/cmsis/CMSIS/Core/Include", core_header) - - folder = "stm32{}xx".format(device.identifier.family) - family_header = folder + ".h" - folder = "stm32/{}/Include".format(folder) - define = None - - content = Path(localpath(folder, family_header)).read_text(encoding="utf-8", errors="replace") - match = re.findall(r"if defined\((?PSTM32[F|L|G][\w\d]+)\)", content) - define = getDefineForDevice(device.identifier, match) - if define is None or match is None: - raise ValidateException("No device define found for '{}'!".format(device.partname)) - device_header = define.lower() + ".h" + headers = env.query("headers") + core_header = repopath("ext/arm/cmsis/CMSIS/Core/Include", headers["core_header"]) content = "" - for header_path in [core_header, localpath(folder, device_header)]: + for header_path in [core_header, localpath(bprops["folder"], headers["device_header"])]: content += Path(header_path).read_text(encoding="utf-8", errors="replace") # find mpu and fpu features @@ -108,16 +92,52 @@ def common_rcc_map(env): for (reg, per, typ) in match: rcc_map[per][typ] = reg - bprops.update({ - "folder": folder, + bprops["peripherals"] = peripherals + return rcc_map + +def common_header_file(env): + """ + Gives information about the STM32 header files. For example the STM32F469: + + - family_define: `STM32F4` + - define: `STM32F469xx` + - core_header: `core_cm4.h` + - system_header: `system_stm32f4xx.h` + - family_header: `stm32f4xx.h` + - device_header: `stm32f469xx.h` + + :returns: a dictionary with the above keys + """ + device = env[":target"] + + core = device.get_driver("core")["type"] + core = core.replace("cortex-m", "").replace("+", "plus").replace("f", "").replace("d", "") + core_header = "core_cm{}.h".format(core) + + folder = "stm32{}xx".format(device.identifier.family) + family_header = folder + ".h" + folder = "stm32/{}/Include".format(folder) + define = None + + content = Path(localpath(folder, family_header)).read_text(encoding="utf-8", errors="replace") + match = re.findall(r"if defined\((?PSTM32[F|L|G][\w\d]+)\)", content) + define = getDefineForDevice(device.identifier, match) + if define is None or match is None: + raise ValidateException("No device define found for '{}'!".format(device.partname)) + device_header = define.lower() + ".h" + family_define = "STM32{}".format(device.identifier.family.upper()) + + headers = { "define": define, + "family_define": family_define, + "core_header": core_header, "device_header": device_header, "family_header": family_header, "system_header": "system_" + family_header, - "peripherals": peripherals, - }) - return rcc_map - + } + bprops.update(headers) + bprops["folder"] = folder + return headers # ----------------------------------------------------------------------------- def init(module): @@ -131,6 +151,8 @@ def prepare(module, options): module.add_query( EnvironmentQuery(name="rcc-map", factory=common_rcc_map)) + module.add_query( + EnvironmentQuery(name="headers", factory=common_header_file)) module.depends(":cmsis:core") return True @@ -141,12 +163,12 @@ def validate(env): def build(env): env.collect(":build:path.include", "modm/ext") env.collect(":build:path.include", "modm/ext/cmsis/device") + env.collect(":build:cppdefines", bprops["family_define"]) env.outbasepath = "modm/ext/cmsis/device" env.copy(localpath(bprops["folder"], bprops["device_header"]), bprops["device_header"]) env.copy(localpath(bprops["folder"], bprops["system_header"]), bprops["system_header"]) - if env.has_module(":tinyusb"): # Requires the family header - env.copy(localpath(bprops["folder"], bprops["family_header"]), bprops["family_header"]) + env.copy(localpath(bprops["folder"], bprops["family_header"]), bprops["family_header"]) env.substitutions = bprops env.substitutions.update({ From b85d04e32122d6ccf6d554455ebbf9aa7c9c28e6 Mon Sep 17 00:00:00 2001 From: Niklas Hauser Date: Tue, 30 Mar 2021 06:24:06 +0200 Subject: [PATCH 02/12] [ext] Update ros-lib --- ext/ros/ros-lib | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ext/ros/ros-lib b/ext/ros/ros-lib index 27b110a8e1..a53267bb7f 160000 --- a/ext/ros/ros-lib +++ b/ext/ros/ros-lib @@ -1 +1 @@ -Subproject commit 27b110a8e1a2fcc0dfda4110d3388ab3b06ebf26 +Subproject commit a53267bb7f120ef5299a9435aee82907a3c4deff From 1e934b7d91976ef707924134a04f4ee684e41da9 Mon Sep 17 00:00:00 2001 From: Niklas Hauser Date: Sat, 3 Apr 2021 12:01:39 +0200 Subject: [PATCH 03/12] [examples] Fix Black Pill F411 USB FatFs docs --- examples/black_pill_f411/usbfatfs/main.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/examples/black_pill_f411/usbfatfs/main.cpp b/examples/black_pill_f411/usbfatfs/main.cpp index 756efdad6c..0747979138 100644 --- a/examples/black_pill_f411/usbfatfs/main.cpp +++ b/examples/black_pill_f411/usbfatfs/main.cpp @@ -20,7 +20,7 @@ If you want to use the sanity check: scons bin && \ - cp ../../../build/stm32f411ceu_mini_f411/usb_fatfs/release/usbfatfs.bin . && \ + cp ../../../build/black_pill_f411/usb_fatfs/scons-release/usbfatfs.bin . && \ echo -n "F411" >> usbfatfs.bin && \ crc32 usbfatfs.bin | xxd -r -p - >> usbfatfs.bin && \ mv usbfatfs.bin /Volumes/MODM_USB @@ -28,7 +28,7 @@ If you want to use the sanity check: Otherwise just copy the file as is and `#define WITH_SANITY_CHECK 0` scons bin && \ - cp ../../../build/stm32f411ceu_mini_f411/usb_fatfs/release/usbfatfs.bin /Volumes/MODM_USB + cp ../../../build/black_pill_f411/usb_fatfs/scons-release/usbfatfs.bin /Volumes/MODM_USB */ From 6a9b7f00b2bc2b532506e43198a8f8d029fde19f Mon Sep 17 00:00:00 2001 From: Niklas Hauser Date: Sun, 4 Apr 2021 01:34:27 +0200 Subject: [PATCH 04/12] [build] Add delay=seconds argument to program-dfu --- tools/build_script_generator/make/module.md | 5 ++++- tools/build_script_generator/make/resources/Makefile.in | 3 ++- tools/build_script_generator/scons/module.md | 5 ++++- tools/build_script_generator/scons/site_tools/dfu.py | 4 ++-- 4 files changed, 12 insertions(+), 5 deletions(-) diff --git a/tools/build_script_generator/make/module.md b/tools/build_script_generator/make/module.md index 935fb90c8c..c5628d209d 100644 --- a/tools/build_script_generator/make/module.md +++ b/tools/build_script_generator/make/module.md @@ -169,12 +169,15 @@ Writes all fuses onto your target connected to avrdude. See the #### make program-dfu ``` -make program-dfu profile={debug|release} +make program-dfu profile={debug|release} [delay={seconds}] ``` Writes the executable onto your target via Device Firmware Update (DFU) over USB. A DFU bootloader is available on many STM32 microcontrollers and can be accessed by pressing the BOOT0-Button during startup. + +Some DFU devices require additional delay to re-enumerate, which you can specify +with the `delay` parameter (default is 5 seconds). (\* *only ARM Cortex-M targets*) ``` diff --git a/tools/build_script_generator/make/resources/Makefile.in b/tools/build_script_generator/make/resources/Makefile.in index 9505f1b39c..218c76de44 100644 --- a/tools/build_script_generator/make/resources/Makefile.in +++ b/tools/build_script_generator/make/resources/Makefile.in @@ -87,9 +87,10 @@ program: build program-bmp: build @python3 modm/modm_tools/bmp.py -p $(port) $(ELF_FILE) +delay?=5 .PHONY: program-dfu program-dfu: bin - @dfu-util -v -E2 -R -i 0 -a 0 -s 0x08000000:leave -D $(BIN_FILE) + @dfu-util -v -E$(delay) -R -i 0 -a 0 -s 0x08000000:leave -D $(BIN_FILE) %% if platform in ["sam"] .PHONY: program-bossac diff --git a/tools/build_script_generator/scons/module.md b/tools/build_script_generator/scons/module.md index 2322dacb33..ef02077119 100644 --- a/tools/build_script_generator/scons/module.md +++ b/tools/build_script_generator/scons/module.md @@ -179,12 +179,15 @@ Writes all fuses onto your target connected to avrdude. See the #### scons program-dfu ``` -scons program-dfu profile={debug|release} [firmware={hash or file}] +scons program-dfu profile={debug|release} [firmware={hash or file}] [delay={seconds}] ``` Writes the executable onto your target via Device Firmware Update (DFU) over USB. A DFU bootloader is available on many STM32 microcontrollers and can be accessed by pressing the BOOT0-Button during startup. + +Some DFU devices require additional delay to re-enumerate, which you can specify +with the `delay` parameter (default is 5 seconds). (\* *only ARM Cortex-M targets*) ``` diff --git a/tools/build_script_generator/scons/site_tools/dfu.py b/tools/build_script_generator/scons/site_tools/dfu.py index d8d28dee01..ca2dc5e0df 100644 --- a/tools/build_script_generator/scons/site_tools/dfu.py +++ b/tools/build_script_generator/scons/site_tools/dfu.py @@ -26,14 +26,14 @@ # ----------------------------------------------------------------------------- def program_dfu(env, source, alias='program_dfu'): - actionString = '$DFU_PROGRAMMER -v -E2 -R -i 0 -a 0 -s 0x08000000:leave -D $SOURCE' + delay = ARGUMENTS.get("delay", "5") + actionString = 'dfu-util -v -E{} -R -i 0 -a 0 -s 0x08000000:leave -D $SOURCE'.format(delay) action = Action(actionString, cmdstr="$PROGRAM_DFU_COMSTR") return env.AlwaysBuild(env.Alias(alias, source, action)) # ----------------------------------------------------------------------------- def generate(env, **kw): - env['DFU_PROGRAMMER'] = 'dfu-util' env.AddMethod(program_dfu, 'ProgramDFU') def exists(env): From acd41688852ce42ad013a9c137410e1be6a15978 Mon Sep 17 00:00:00 2001 From: Niklas Hauser Date: Tue, 30 Mar 2021 06:01:02 +0200 Subject: [PATCH 05/12] [ext] Update to TinyUSB v0.9.0 --- examples/generic/usb/main.cpp | 4 ++-- examples/generic/usb/project.xml | 6 +++--- examples/stm32f3_discovery/usb_dfu/main.cpp | 7 +++++-- ext/hathach/module.lb | 2 +- ext/hathach/module.md | 4 +++- ext/hathach/tinyusb | 2 +- ext/hathach/tusb_descriptors.c.in | 15 ++++++++------- 7 files changed, 23 insertions(+), 17 deletions(-) diff --git a/examples/generic/usb/main.cpp b/examples/generic/usb/main.cpp index b938f8233c..650c736035 100644 --- a/examples/generic/usb/main.cpp +++ b/examples/generic/usb/main.cpp @@ -92,10 +92,10 @@ void midi_task() if (previous < 0) previous = sizeof(note_sequence) - 1; // Send Note On for current position at full velocity (127) on channel 1. - tudi_midi_write24(0, 0x90, note_sequence[note_pos], 127); + tud_midi_write24(0, 0x90, note_sequence[note_pos], 127); // Send Note Off for previous note. - tudi_midi_write24(0, 0x80, note_sequence[previous], 0); + tud_midi_write24(0, 0x80, note_sequence[previous], 0); // Increment position note_pos++; diff --git a/examples/generic/usb/project.xml b/examples/generic/usb/project.xml index 8758f81907..18a8b42256 100644 --- a/examples/generic/usb/project.xml +++ b/examples/generic/usb/project.xml @@ -1,8 +1,8 @@ - modm:blue-pill + modm:blue-pill-f103 - - + + diff --git a/examples/stm32f3_discovery/usb_dfu/main.cpp b/examples/stm32f3_discovery/usb_dfu/main.cpp index eb6a1921c0..9b56f6e4d3 100644 --- a/examples/stm32f3_discovery/usb_dfu/main.cpp +++ b/examples/stm32f3_discovery/usb_dfu/main.cpp @@ -35,7 +35,10 @@ constexpr uint64_t DFU_MAGIC{0xf318ea89313f2be8}; /* 1. Do scons program once * 2. Power-cycle by disconnecting USB cable from ST-Link * 3. Force USB re-enumeration by connecting USB cable to UsbFs - * 3. Do scons program-dfu as many times as you want + * 4. Do `scons program-dfu delay=3` as many times as you want + * + * Rebooting the chip into DFU and enumerating USB again takes a few seconds. + * You may have to increase the `delay` argument. */ int main() @@ -72,7 +75,7 @@ int main() } // Invoked on DFU_DETACH request to reboot to the bootloader -void tud_dfu_rt_reboot_to_dfu(void) +void tud_dfu_runtime_reboot_to_dfu_cb(void) { dfu_mode = DFU_MAGIC; // You must delay SystemReset so that TinyUSB can finish!!! diff --git a/ext/hathach/module.lb b/ext/hathach/module.lb index f07a1a20b8..e16e3ffbd4 100644 --- a/ext/hathach/module.lb +++ b/ext/hathach/module.lb @@ -260,7 +260,7 @@ class TinyUsbClassModule(Module): global tusb_config cfg_name = "CFG_TU{}_{}".format(self.mode[0].upper(), self.name.upper()) - if "DFU" in cfg_name: cfg_name += "_RT"; + if "DFU" in cfg_name: cfg_name += "_RUNTIME"; tusb_config[cfg_name] = env[":tinyusb:config"].count("{}.{}".format(self.mode, self.name)) speed = env.get(":tinyusb:speed", 0) diff --git a/ext/hathach/module.md b/ext/hathach/module.md index 38f1df368d..12244165f4 100644 --- a/ext/hathach/module.md +++ b/ext/hathach/module.md @@ -42,8 +42,10 @@ generated, so you can implement them yourself. Note that you must also manually depend on the device classes you want to implement: ```xml -modm:tinyusb:device:net +modm:tinyusb:device:audio +modm:tinyusb:device:bth modm:tinyusb:device:hid +modm:tinyusb:device:net modm:tinyusb:device:usbtmc ``` diff --git a/ext/hathach/tinyusb b/ext/hathach/tinyusb index 7d00820dcb..29262abd18 160000 --- a/ext/hathach/tinyusb +++ b/ext/hathach/tinyusb @@ -1 +1 @@ -Subproject commit 7d00820dcb9909fd4089d94077f45838006ee34e +Subproject commit 29262abd18096d982f806cb43921af6b8002f88c diff --git a/ext/hathach/tusb_descriptors.c.in b/ext/hathach/tusb_descriptors.c.in index 6dc2498457..43994e6196 100644 --- a/ext/hathach/tusb_descriptors.c.in +++ b/ext/hathach/tusb_descriptors.c.in @@ -35,7 +35,7 @@ #define _PID_MAP(itf, n) ((CFG_TUD_##itf) << (n)) #define USB_PID \ (0x4000 | _PID_MAP(CDC, 0) | _PID_MAP(MSC, 2) | _PID_MAP(HID, 3) | \ - _PID_MAP(MIDI, 4) | _PID_MAP(VENDOR, 5)) + _PID_MAP(MIDI, 4) | _PID_MAP(AUDIO, 5) | _PID_MAP(VENDOR, 6)) //--------------------------------------------------------------------+ // Device Descriptors @@ -90,12 +90,13 @@ enum }; #define CONFIG_TOTAL_LEN (TUD_CONFIG_DESC_LEN + \ - CFG_TUD_CDC * TUD_CDC_DESC_LEN + \ - CFG_TUD_MSC * TUD_MSC_DESC_LEN + \ - CFG_TUD_HID * TUD_HID_DESC_LEN + \ - CFG_TUD_MIDI * TUD_MIDI_DESC_LEN + \ - CFG_TUD_DFU_RT * TUD_DFU_RT_DESC_LEN + \ - CFG_TUD_VENDOR * TUD_VENDOR_DESC_LEN) + CFG_TUD_CDC * TUD_CDC_DESC_LEN + \ + CFG_TUD_MSC * TUD_MSC_DESC_LEN + \ + CFG_TUD_HID * TUD_HID_DESC_LEN + \ + CFG_TUD_AUDIO * TUD_AUDIO_MIC_DESC_LEN + \ + CFG_TUD_MIDI * TUD_MIDI_DESC_LEN + \ + CFG_TUD_DFU_RUNTIME * TUD_DFU_RT_DESC_LEN + \ + CFG_TUD_VENDOR * TUD_VENDOR_DESC_LEN) %% for endpoint, value in endpoints.items() #define EPNUM_{{ endpoint }} {{ value }} From 1f5d06e4f8a20c77269fb8d063a7a5bdad94ade2 Mon Sep 17 00:00:00 2001 From: Niklas Hauser Date: Sun, 4 Apr 2021 06:29:38 +0200 Subject: [PATCH 06/12] [tinyusb] Add better customization options --- ext/hathach/module.lb | 141 ++++++++++++++++++------------ ext/hathach/module.md | 28 ++++++ ext/hathach/tusb_config.h.in | 8 +- ext/hathach/tusb_descriptors.c.in | 12 ++- 4 files changed, 128 insertions(+), 61 deletions(-) diff --git a/ext/hathach/module.lb b/ext/hathach/module.lb index e16e3ffbd4..ef76b769a8 100644 --- a/ext/hathach/module.lb +++ b/ext/hathach/module.lb @@ -181,7 +181,14 @@ def build(env): class TinyUsbDeviceModule(Module): def init(self, module): module.name = ":tinyusb:device" - module.description = "TinyUSB in Device Mode" + module.description = """ +# TinyUSB in Device Mode + +Configuration options: + +- `CFG_TUD_ENDPOINT0_SIZE` = 64 +- `CFG_TUD_TASK_QUEUE_SZ` = 16 +""" def prepare(self, module, options): paths = {p.parent for p in Path(localpath("tinyusb/src/class/")).glob("*/*_device.h")} @@ -193,11 +200,6 @@ class TinyUsbDeviceModule(Module): env.outbasepath = "modm/ext/tinyusb" env.copy("tinyusb/src/device/", "device/") - """ Device config defaults: - - CFG_TUD_ENDPOINT0_SIZE = 64 - - CFG_TUD_TASK_QUEUE_SZ = 16 - """ - # ----------------------------------------------------------------------------- class TinyUsbHostModule(Module): @@ -206,7 +208,14 @@ class TinyUsbHostModule(Module): def init(self, module): module.name = ":tinyusb:host" - module.description = "TinyUSB in Host Mode" + module.description = """ +# TinyUSB in Host Mode + +Configuration options: + +- `CFG_TUH_EP_MAX` = 9 +- `CFG_TUH_TASK_QUEUE_SZ` = 16 +""" def prepare(self, module, options): # Only OTG has Host Mode @@ -223,12 +232,68 @@ class TinyUsbHostModule(Module): env.outbasepath = "modm/ext/tinyusb" env.copy("tinyusb/src/host/", "host/") - """ Host config defaults: - - CFG_TUH_TASK_QUEUE_SZ = 16 - """ - # ----------------------------------------------------------------------------- +tu_config_descr = {"device": { + "audio": """ +- `CFG_TUD_AUDIO_CTRL_BUF_SIZE` = [undef] +- `CFG_TUD_AUDIO_ENABLE_FEEDBACK_EP` = 0 +- `CFG_TUD_AUDIO_EPSIZE_IN` = 0 +- `CFG_TUD_AUDIO_EPSIZE_OUT` = 0 +- `CFG_TUD_AUDIO_FORMAT_TYPE_I_RX` = `AUDIO_DATA_FORMAT_TYPE_I_PCM` +- `CFG_TUD_AUDIO_FORMAT_TYPE_I_TX` = `AUDIO_DATA_FORMAT_TYPE_I_PCM` +- `CFG_TUD_AUDIO_FORMAT_TYPE_RX` = `AUDIO_FORMAT_TYPE_UNDEFINED` +- `CFG_TUD_AUDIO_FORMAT_TYPE_TX` = `AUDIO_FORMAT_TYPE_UNDEFINED` +- `CFG_TUD_AUDIO_INT_CTR_BUFSIZE` = 6 +- `CFG_TUD_AUDIO_INT_CTR_EPSIZE_IN` = 0 +- `CFG_TUD_AUDIO_N_AS_INT` = 0 +- `CFG_TUD_AUDIO_N_BYTES_PER_SAMPLE_RX` = 1 +- `CFG_TUD_AUDIO_N_BYTES_PER_SAMPLE_TX` = 1 +- `CFG_TUD_AUDIO_N_CHANNELS_RX` = 1 +- `CFG_TUD_AUDIO_N_CHANNELS_TX` = 1 +- `CFG_TUD_AUDIO_RX_FIFO_COUNT` = `CFG_TUD_AUDIO_N_CHANNELS_RX` +- `CFG_TUD_AUDIO_RX_FIFO_SIZE` = 0 +- `CFG_TUD_AUDIO_TX_FIFO_COUNT` = `CFG_TUD_AUDIO_N_CHANNELS_TX` +- `CFG_TUD_AUDIO_TX_FIFO_SIZE` = 0 +""", + "bth": """ +- `CFG_TUD_BTH_DATA_EPSIZE` = 64 +- `CFG_TUD_BTH_EVENT_EPSIZE` = 16 +- `CFG_TUD_BTH_ISO_ALT_COUNT` = 0 +""", + "cdc": """ +- `CFG_TUD_CDC_EP_BUFSIZE` = 64/512 (fs/hs) +- `CFG_TUD_CDC_RX_BUFSIZE` = [undef] modm default: 512 +- `CFG_TUD_CDC_TX_BUFSIZE` = [undef] modm default: 512 +""", + "hid": """ +- `CFG_TUD_HID_EP_BUFSIZE` = 16 +""", + "midi": """ +- `CFG_TUD_MIDI_EP_BUFSIZE` = 64/512 (fs/hs) +- `CFG_TUD_MIDI_RX_BUFSIZE` = [undef] modm default: 64/512 (fs/hs) +- `CFG_TUD_MIDI_TX_BUFSIZE` = [undef] modm default: 64/512 (fs/hs) +""", + "msc": """ +- `CFG_TUD_MSC_EP_BUFSIZE` = [undef] modm default: 512 +""", + "net": """ +- `CFG_TUD_NET_ENDPOINT_SIZE` = 64/512 (fs/hs) +- `CFG_TUD_NET_MTU` = 1514 +""", + "usbtmc": """ +- `CFG_TUD_USBTMC_ENABLE_488` = 1 +""", + "vendor": """ +- `CFG_TUD_VENDOR_EPSIZE` = 64 +- `CFG_TUD_VENDOR_RX_BUFSIZE` = [undef] modm default: 64/512 (fs/hs) +- `CFG_TUD_VENDOR_TX_BUFSIZE` = [undef] modm default: 64/512 (fs/hs) +""" +}, "host": { + "msc": """ +- `CFG_TUH_MSC_MAXLUN` = 4 +""" +}} class TinyUsbClassModule(Module): def __init__(self, path, mode): self.mode = mode @@ -236,20 +301,17 @@ class TinyUsbClassModule(Module): def init(self, module): module.name = ":tinyusb:{}:{}".format(self.mode, self.name) - module.description = "{} class {}".format(self.mode.capitalize(), self.name.upper()) + descr = "# {} class {}".format(self.mode.capitalize(), self.name.upper()) + conf = tu_config_descr[self.mode].get(self.name, "") + if conf: descr += "\n\nConfiguration options:\n" + conf + module.description = descr def prepare(self, module, options): if self.mode == "device": - # FIXME: Changing these defaults seems to crash TinyUSB in weird ways. - # Since all of the TinyUSB examples leave them at these default values - # I think they are not supposed to be changed? -Niklas - # if self.name in ["cdc", "midi", "vendor"]: - # module.add_option(NumericOption("buffer.rx", description="", minimum=64, default=64)) - # module.add_option(NumericOption("buffer.tx", description="", minimum=64, default=64)) - # if self.name in ["msc"]: - # module.add_option(NumericOption("buffer.ep", description="", minimum=512, default=512)) if self.name == "cdc": module.depends(":architecture:uart") + if self.name == "midi": + module.depends(":tinyusb:device:audio") module.depends(":tinyusb") return True @@ -267,40 +329,7 @@ class TinyUsbClassModule(Module): if self.mode == "device": # These are the defaults that don't crash TinyUSB. if self.name in ["cdc", "midi", "vendor"]: - tusb_config[cfg_name+"_RX_BUFSIZE"] = 512 if speed else 64 #env["buffer.rx"] - tusb_config[cfg_name+"_TX_BUFSIZE"] = 512 if speed else 64 #env["buffer.tx"] + tusb_config[cfg_name+"_RX_BUFSIZE"] = 512 if speed else 64 + tusb_config[cfg_name+"_TX_BUFSIZE"] = 512 if speed else 64 if self.name in ["msc"]: - tusb_config[cfg_name+"_EP_BUFSIZE"] = 512 #env["buffer.ep"] - - - """ Device class defaults: - - CFG_TUD_BTH_DATA_EPSIZE = 64 - - CFG_TUD_BTH_EVENT_EPSIZE = 16 - - CFG_TUD_BTH_ISO_ALT_COUNT = 0 - - - CFG_TUD_CDC_EP_BUFSIZE = 64 or 512 (hs) - - CFG_TUD_CDC_RX_BUFSIZE = [undef] - - CFG_TUD_CDC_TX_BUFSIZE = [undef] - - - CFG_TUD_HID_EP_BUFSIZE = 16 - - - CFG_TUD_MIDI_EP_BUFSIZE = 64 or 512 (hs) - - CFG_TUD_MIDI_RX_BUFSIZE = [undef] - - CFG_TUD_MIDI_TX_BUFSIZE = [undef] - - - CFG_TUD_MSC_EP_BUFSIZE = [undef] - - - CFG_TUD_NET_ENDPOINT_SIZE = 64 or 512 (hs) - - - CFG_TUD_USBTMC_ENABLE_488 = 1 - - - CFG_TUD_VENDOR_EPSIZE = 64 - - CFG_TUD_VENDOR_RX_BUFSIZE = [undef] - - CFG_TUD_VENDOR_TX_BUFSIZE = [undef] - """ - - """ Host config defaults: - - CFG_TUH_CDC_RNDIS - - CFG_TUH_HID_KEYBOARD - - CFG_TUH_HID_MOUSE - """ + tusb_config[cfg_name+"_EP_BUFSIZE"] = 512 diff --git a/ext/hathach/module.md b/ext/hathach/module.md index 12244165f4..0e96cb4a78 100644 --- a/ext/hathach/module.md +++ b/ext/hathach/module.md @@ -35,6 +35,30 @@ modm will generate the USB descriptors automatically for the set of device classes you've chosen. You can then implement your app via TinyUSB callbacks. +### Partial Customization + +You can overwrite or add configurations via a `` file, +which will be included at the very *beginning* of the modm-generated +`tusb_config.h` file: + +```c +// Overwrite the modm default +#define CFG_TUD_CDC_TX_BUFSIZE 1024 +// Overwrite the TinyUSB default +#define CFG_TUD_CDC_EP_BUFSIZE 1024 +``` + +You can also replace the following weakly linked descriptor functions and +objects in case you want to update only a small part of the autogenerated +descriptors: + +- `const uint8_t* tud_descriptor_device_cb(void)` to replace the autogenerated + `tusb_desc_device_t` descriptor. +- `const uint8_t* tud_descriptor_configuration_cb(uint8_t index)` to replace + the endpoint descriptions. +- `const char* string_desc_arr[]` to replace the string descriptors. + + ## Manual USB Descriptors If you leave the `modm:tinyusb:config` option empty, no descriptors are @@ -49,6 +73,10 @@ manually depend on the device classes you want to implement: modm:tinyusb:device:usbtmc ``` +Some of these classes require a lot of configuration that you must provide via +the `` file. See the class module descriptions for these +configurations and consult the TinyUSB documentation for their purpose. + ## Initializing USB diff --git a/ext/hathach/tusb_config.h.in b/ext/hathach/tusb_config.h.in index 8f07eb8ac6..c94ff4829c 100644 --- a/ext/hathach/tusb_config.h.in +++ b/ext/hathach/tusb_config.h.in @@ -13,8 +13,14 @@ #include +#if __has_include() +# include +#endif + %% for name, value in config.items() | sort -#define {{name}} {{value}} +#ifndef {{name}} +# define {{name}} {{value}} +#endif %% endfor diff --git a/ext/hathach/tusb_descriptors.c.in b/ext/hathach/tusb_descriptors.c.in index 43994e6196..4cb6e42efc 100644 --- a/ext/hathach/tusb_descriptors.c.in +++ b/ext/hathach/tusb_descriptors.c.in @@ -73,7 +73,8 @@ const tusb_desc_device_t desc_device = // Invoked when received GET DEVICE DESCRIPTOR // Application return pointer to descriptor -uint8_t const * tud_descriptor_device_cb(void) +modm_weak const uint8_t* +tud_descriptor_device_cb(void) { return (uint8_t const *) &desc_device; } @@ -133,7 +134,8 @@ const uint8_t desc_{{"hs" if hs else "fs"}}_configuration[] = // Invoked when received GET CONFIGURATION DESCRIPTOR // Application return pointer to descriptor // Descriptor contents must exist long enough for transfer to complete -const uint8_t* tud_descriptor_configuration_cb(uint8_t index) +modm_weak const uint8_t* +tud_descriptor_configuration_cb(uint8_t index) { (void)index; // for multiple configurations %% if port @@ -149,7 +151,8 @@ const uint8_t* tud_descriptor_configuration_cb(uint8_t index) //--------------------------------------------------------------------+ // array of pointer to string descriptors -const char* string_desc_arr[] = +modm_weak const char* +string_desc_arr[] = { NULL, // 0: Language "TinyUSB", // 1: Manufacturer @@ -165,7 +168,8 @@ static uint16_t _desc_str[32]; // Invoked when received GET STRING DESCRIPTOR request // Application return pointer to descriptor, whose contents must exist long // enough for transfer to complete -const uint16_t* tud_descriptor_string_cb(uint8_t index, uint16_t langid) +const uint16_t* +tud_descriptor_string_cb(uint8_t index, uint16_t langid) { (void)langid; uint8_t chr_count = 1; From ebeeaae32f8bbfade2b7143ec9c93baeef988d30 Mon Sep 17 00:00:00 2001 From: Niklas Hauser Date: Tue, 30 Mar 2021 06:23:54 +0200 Subject: [PATCH 07/12] [ext] Update FatFs to v0.14a --- ext/chan/fatfs | 2 +- ext/chan/ffconf.h | 6 +++--- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/ext/chan/fatfs b/ext/chan/fatfs index 4680e88580..4f32429286 160000 --- a/ext/chan/fatfs +++ b/ext/chan/fatfs @@ -1 +1 @@ -Subproject commit 4680e88580d3d67db2c212c8b7753dd43abdd1d3 +Subproject commit 4f32429286759ad61fa05832840a4b056d5d618a diff --git a/ext/chan/ffconf.h b/ext/chan/ffconf.h index e8800a203e..0d20a9b059 100644 --- a/ext/chan/ffconf.h +++ b/ext/chan/ffconf.h @@ -2,7 +2,7 @@ / FatFs Functional Configurations /---------------------------------------------------------------------------*/ -#define FFCONF_DEF 86606 /* Revision ID */ +#define FFCONF_DEF 80196 /* Revision ID */ /*---------------------------------------------------------------------------/ / Function Configurations @@ -205,8 +205,8 @@ / To enable the 64-bit LBA, also exFAT needs to be enabled. (FF_FS_EXFAT == 1) */ -#define FF_MIN_GPT 0x100000000 -/* Minimum number of sectors to switch GPT format to create partition in f_mkfs and +#define FF_MIN_GPT 0x10000000 +/* Minimum number of sectors to switch GPT as partitioning format in f_mkfs and / f_fdisk function. 0x100000000 max. This option has no effect when FF_LBA64 == 0. */ From 37abc036821c6bbd2eb7b5fa63c3dd6457b40f6e Mon Sep 17 00:00:00 2001 From: Niklas Hauser Date: Tue, 6 Apr 2021 02:53:32 +0200 Subject: [PATCH 08/12] [fatfs] Add better configuration options --- .../black_pill_f411/usbfatfs/ffconf_local.h | 25 +++ ext/chan/ffconf.h | 174 +++++++++++++----- ext/chan/module.lb | 40 +++- 3 files changed, 183 insertions(+), 56 deletions(-) create mode 100644 examples/black_pill_f411/usbfatfs/ffconf_local.h diff --git a/examples/black_pill_f411/usbfatfs/ffconf_local.h b/examples/black_pill_f411/usbfatfs/ffconf_local.h new file mode 100644 index 0000000000..f68a42ef41 --- /dev/null +++ b/examples/black_pill_f411/usbfatfs/ffconf_local.h @@ -0,0 +1,25 @@ +/* + * Copyright (c) 2021, Niklas Hauser + * + * This file is part of the modm project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ + +#ifndef FFCONF_DEF +# error "Don't include this file directly, use 'ffconf.h' instead!" +#endif + +// Enable directory filtering: f_findfirst(), f_findnext() +#define FF_USE_FIND 1 + +// Enable Volume Formatting: f_mkfs() +#define FF_USE_MKFS 1 + +// Enable Volume Label: f_setlabel(), f_getlabel() +#define FF_USE_LABEL 1 + +// Enable tiny sector buffers +#define FF_FS_TINY 1 diff --git a/ext/chan/ffconf.h b/ext/chan/ffconf.h index 0d20a9b059..1a31f5f647 100644 --- a/ext/chan/ffconf.h +++ b/ext/chan/ffconf.h @@ -2,20 +2,34 @@ / FatFs Functional Configurations /---------------------------------------------------------------------------*/ +#ifndef FFCONF_DEF #define FFCONF_DEF 80196 /* Revision ID */ +// Simply forward +#define ff_memalloc malloc +#define ff_memfree free + +/* A header file that overwrites with local project settings. */ +#if __has_include() +# include +#endif + /*---------------------------------------------------------------------------/ / Function Configurations /---------------------------------------------------------------------------*/ -#define FF_FS_READONLY 0 +#ifndef FF_FS_READONLY +# define FF_FS_READONLY 0 +#endif /* This option switches read-only configuration. (0:Read/Write or 1:Read-only) / Read-only configuration removes writing API functions, f_write(), f_sync(), / f_unlink(), f_mkdir(), f_chmod(), f_rename(), f_truncate(), f_getfree() / and optional writing functions as well. */ -#define FF_FS_MINIMIZE 0 +#ifndef FF_FS_MINIMIZE +# define FF_FS_MINIMIZE 0 +#endif /* This option defines minimization level to remove some basic API functions. / / 0: Basic functions are fully enabled. @@ -25,7 +39,9 @@ / 3: f_lseek() function is removed in addition to 2. */ -#define FF_USE_STRFUNC 0 +#ifndef FF_USE_STRFUNC +# define FF_USE_STRFUNC 0 +#endif /* This option switches string functions, f_gets(), f_putc(), f_puts() and f_printf(). / / 0: Disable string functions. @@ -33,34 +49,48 @@ / 2: Enable with LF-CRLF conversion. */ -#define FF_USE_FIND 1 +#ifndef FF_USE_FIND +# define FF_USE_FIND 0 +#endif /* This option switches filtered directory read functions, f_findfirst() and / f_findnext(). (0:Disable, 1:Enable 2:Enable with matching altname[] too) */ -#define FF_USE_MKFS 1 +#ifndef FF_USE_MKFS +# define FF_USE_MKFS 0 +#endif /* This option switches f_mkfs() function. (0:Disable or 1:Enable) */ -#define FF_USE_FASTSEEK 0 +#ifndef FF_USE_FASTSEEK +# define FF_USE_FASTSEEK 0 +#endif /* This option switches fast seek function. (0:Disable or 1:Enable) */ -#define FF_USE_EXPAND 1 +#ifndef FF_USE_EXPAND +# define FF_USE_EXPAND 0 +#endif /* This option switches f_expand function. (0:Disable or 1:Enable) */ -#define FF_USE_CHMOD 1 +#ifndef FF_USE_CHMOD +# define FF_USE_CHMOD 0 +#endif /* This option switches attribute manipulation functions, f_chmod() and f_utime(). / (0:Disable or 1:Enable) Also FF_FS_READONLY needs to be 0 to enable this option. */ -#define FF_USE_LABEL 1 +#ifndef FF_USE_LABEL +# define FF_USE_LABEL 0 +#endif /* This option switches volume label functions, f_getlabel() and f_setlabel(). / (0:Disable or 1:Enable) */ -#define FF_USE_FORWARD 1 +#ifndef FF_USE_FORWARD +# define FF_USE_FORWARD 0 +#endif /* This option switches f_forward() function. (0:Disable or 1:Enable) */ @@ -68,7 +98,9 @@ / Locale and Namespace Configurations /---------------------------------------------------------------------------*/ -#define FF_CODE_PAGE 932 +#ifndef FF_CODE_PAGE +# define FF_CODE_PAGE 932 +#endif /* This option specifies the OEM code page to be used on the target system. / Incorrect code page setting can cause a file open failure. / @@ -97,8 +129,12 @@ */ -#define FF_USE_LFN 0 -#define FF_MAX_LFN 255 +#ifndef FF_USE_LFN +# define FF_USE_LFN 0 +#endif +#ifndef FF_MAX_LFN +# define FF_MAX_LFN 255 +#endif /* The FF_USE_LFN switches the support for LFN (long file name). / / 0: Disable LFN. FF_MAX_LFN has no effect. @@ -117,7 +153,9 @@ / ff_memfree() exemplified in ffsystem.c, need to be added to the project. */ -#define FF_LFN_UNICODE 0 +#ifndef FF_LFN_UNICODE +# define FF_LFN_UNICODE 0 +#endif /* This option switches the character encoding on the API when LFN is enabled. / / 0: ANSI/OEM in current CP (TCHAR = char) @@ -129,15 +167,21 @@ / When LFN is not enabled, this option has no effect. */ -#define FF_LFN_BUF 255 -#define FF_SFN_BUF 12 +#ifndef FF_LFN_BUF +# define FF_LFN_BUF 255 +#endif +#ifndef FF_SFN_BUF +# define FF_SFN_BUF 12 +#endif /* This set of options defines size of file name members in the FILINFO structure / which is used to read out directory items. These values should be suffcient for / the file names to read. The maximum possible length of the read file name depends / on character encoding. When LFN is not enabled, these options have no effect. */ -#define FF_STRF_ENCODE 3 +#ifndef FF_STRF_ENCODE +# define FF_STRF_ENCODE 3 +#endif /* When FF_LFN_UNICODE >= 1 with LFN enabled, string I/O functions, f_gets(), / f_putc(), f_puts and f_printf() convert the character encoding in it. / This option selects assumption of character encoding ON THE FILE to be @@ -150,7 +194,9 @@ */ -#define FF_FS_RPATH 0 +#ifndef FF_FS_RPATH +# define FF_FS_RPATH 0 +#endif /* This option configures support for relative path. / / 0: Disable relative path and remove related functions. @@ -163,12 +209,18 @@ / Drive/Volume Configurations /---------------------------------------------------------------------------*/ -#define FF_VOLUMES 1 +#ifndef FF_VOLUMES +# define FF_VOLUMES 1 +#endif /* Number of volumes (logical drives) to be used. (1-10) */ -#define FF_STR_VOLUME_ID 0 -#define FF_VOLUME_STRS "RAM","NAND","CF","SD","SD2","USB","USB2","USB3" +#ifndef FF_STR_VOLUME_ID +# define FF_STR_VOLUME_ID 0 +#endif +#ifndef FF_VOLUME_STRS +# define FF_VOLUME_STRS "RAM","NAND","CF","SD","SD2","USB","USB2","USB3" +#endif /* FF_STR_VOLUME_ID switches support for volume ID in arbitrary strings. / When FF_STR_VOLUME_ID is set to 1 or 2, arbitrary strings can be used as drive / number in the path name. FF_VOLUME_STRS defines the volume ID strings for each @@ -181,7 +233,9 @@ */ -#define FF_MULTI_PARTITION 0 +#ifndef FF_MULTI_PARTITION +# define FF_MULTI_PARTITION 0 +#endif /* This option switches support for multiple volumes on the physical drive. / By default (0), each logical drive number is bound to the same physical drive / number and only an FAT volume found on the physical drive will be mounted. @@ -190,8 +244,12 @@ / funciton will be available. */ -#define FF_MIN_SS 512 -#define FF_MAX_SS 512 +#ifndef FF_MIN_SS +# define FF_MIN_SS 512 +#endif +#ifndef FF_MAX_SS +# define FF_MAX_SS 512 +#endif /* This set of options configures the range of sector size to be supported. (512, / 1024, 2048 or 4096) Always set both 512 for most systems, generic memory card and / harddisk. But a larger value may be required for on-board flash memory and some @@ -200,17 +258,23 @@ / GET_SECTOR_SIZE command. */ -#define FF_LBA64 0 +#ifndef FF_LBA64 +# define FF_LBA64 0 +#endif /* This option switches support for 64-bit LBA. (0:Disable or 1:Enable) / To enable the 64-bit LBA, also exFAT needs to be enabled. (FF_FS_EXFAT == 1) */ -#define FF_MIN_GPT 0x10000000 -/* Minimum number of sectors to switch GPT as partitioning format in f_mkfs and +#ifndef FF_MIN_GPT +# define FF_MIN_GPT 0x100000000 +#endif +/* Minimum number of sectors to switch GPT format to create partition in f_mkfs and / f_fdisk function. 0x100000000 max. This option has no effect when FF_LBA64 == 0. */ -#define FF_USE_TRIM 0 +#ifndef FF_USE_TRIM +# define FF_USE_TRIM 0 +#endif /* This option switches support for ATA-TRIM. (0:Disable or 1:Enable) / To enable Trim function, also CTRL_TRIM command should be implemented to the / disk_ioctl() function. */ @@ -221,23 +285,35 @@ / System Configurations /---------------------------------------------------------------------------*/ -#define FF_FS_TINY 1 +#ifndef FF_FS_TINY +# define FF_FS_TINY 0 +#endif /* This option switches tiny buffer configuration. (0:Normal or 1:Tiny) / At the tiny configuration, size of file object (FIL) is shrinked FF_MAX_SS bytes. / Instead of private sector buffer eliminated from the file object, common sector / buffer in the filesystem object (FATFS) is used for the file data transfer. */ -#define FF_FS_EXFAT 0 +#ifndef FF_FS_EXFAT +# define FF_FS_EXFAT 0 +#endif /* This option switches support for exFAT filesystem. (0:Disable or 1:Enable) / To enable exFAT, also LFN needs to be enabled. (FF_USE_LFN >= 1) / Note that enabling exFAT discards ANSI C (C89) compatibility. */ -#define FF_FS_NORTC 1 -#define FF_NORTC_MON 1 -#define FF_NORTC_MDAY 1 -#define FF_NORTC_YEAR 2020 +#ifndef FF_FS_NORTC +# define FF_FS_NORTC 1 +#endif +#ifndef FF_NORTC_MON +# define FF_NORTC_MON 1 +#endif +#ifndef FF_NORTC_MDAY +# define FF_NORTC_MDAY 1 +#endif +#ifndef FF_NORTC_YEAR +# define FF_NORTC_YEAR 2019 +#endif /* The option FF_FS_NORTC switches timestamp functiton. If the system does not have / any RTC function or valid timestamp is not needed, set FF_FS_NORTC = 1 to disable / the timestamp function. Every object modified by FatFs will have a fixed timestamp @@ -248,7 +324,9 @@ / These options have no effect in read-only configuration (FF_FS_READONLY = 1). */ -#define FF_FS_NOFSINFO 0 +#ifndef FF_FS_NOFSINFO +# define FF_FS_NOFSINFO 0 +#endif /* If you need to know correct free space on the FAT32 volume, set bit 0 of this / option, and f_getfree() function at first time after volume mount will force / a full FAT scan. Bit 1 controls the use of last allocated cluster number. @@ -260,7 +338,9 @@ */ -#define FF_FS_LOCK 0 +#ifndef FF_FS_LOCK +# define FF_FS_LOCK 0 +#endif /* The option FF_FS_LOCK switches file lock function to control duplicated file open / and illegal operation to open objects. This option must be 0 when FF_FS_READONLY / is 1. @@ -273,9 +353,15 @@ /* #include // O/S definitions */ -#define FF_FS_REENTRANT 0 -#define FF_FS_TIMEOUT 1000 -#define FF_SYNC_t HANDLE +#ifndef FF_FS_REENTRANT +# define FF_FS_REENTRANT 0 +#endif +#ifndef FF_FS_TIMEOUT +# define FF_FS_TIMEOUT 1000 +#endif +#ifndef FF_SYNC_t +# define FF_SYNC_t HANDLE +#endif /* The option FF_FS_REENTRANT switches the re-entrancy (thread safe) of the FatFs / module itself. Note that regardless of this option, file access to different / volume is always re-entrant and volume control functions, f_mount(), f_mkfs() @@ -293,13 +379,7 @@ / SemaphoreHandle_t and etc. A header file for O/S definitions needs to be / included somewhere in the scope of ff.h. */ -// Simply forward -#define ff_memalloc malloc -#define ff_memfree free - -/* A header file that overwrites with local project settings. */ -#if __has_include() -#include -#endif /*--- End of configuration options ---*/ + +#endif /* FFCONF_DEF */ diff --git a/ext/chan/module.lb b/ext/chan/module.lb index c45c4100fc..2df00b235b 100644 --- a/ext/chan/module.lb +++ b/ext/chan/module.lb @@ -13,21 +13,43 @@ def init(module): module.name = ":fatfs" - module.description = """\ -# FatFs Generic FAT Filesystem Module + module.description = """ +# FatFs: FAT Filesystem + +FatFs is a generic FAT/exFAT filesystem module for small embedded systems. See http://elm-chan.org/fsw/ff/00index_e.html. -## Custom Configuration -This module defines a default `ffconf.h` config file. If you need to change a -configuration setting, then you can define a `ffconf_local.h` file, which -is included *after* at the end of the config. You must therefore first `#undef` -the config macros, then redefine them with your options, for example: +## Configuration + +This module generates a `ffconf.h` config file for modm integration with these +settings: + +- `FF_FS_NORTC = 1`: modm does not provide an accurate RTC timekeeping method, + you must implement that yourself. +- `ff_memalloc`/`ff_memfree`: Forwarded to `malloc` and `free` as implemented by + the `modm:platform:heap` module + +To configure FatFs for your project, create a `` file, which is +included at the *beginning* of the config, thus overwriting the default +settings. Please see the `modm/ext/fatfs/ffconf.h` file for the available +configuration options and their default values. + +Example `` configuration: ```c -#undef FF_USE_STRFUNC -#define FF_USE_STRFUNC 1 +// Enable directory filtering: f_findfirst(), f_findnext() +#define FF_USE_FIND 1 + +// Enable Volume Formatting: f_mkfs() +#define FF_USE_MKFS 1 + +// Enable Volume Label: f_setlabel(), f_getlabel() +#define FF_USE_LABEL 1 + +// Enable tiny sector buffers +#define FF_FS_TINY 1 ``` """ From 7416c1d577cd8ddaf4ec50f783d0eede38490beb Mon Sep 17 00:00:00 2001 From: Niklas Hauser Date: Tue, 6 Apr 2021 04:07:55 +0200 Subject: [PATCH 09/12] [fatfs] Add Petit FatFs v0.03a module --- ext/chan/module_petit.lb | 60 +++++++++++++++++++++++++++++ ext/chan/pffconf.h | 81 ++++++++++++++++++++++++++++++++++++++++ 2 files changed, 141 insertions(+) create mode 100644 ext/chan/module_petit.lb create mode 100644 ext/chan/pffconf.h diff --git a/ext/chan/module_petit.lb b/ext/chan/module_petit.lb new file mode 100644 index 0000000000..a8ada92dd8 --- /dev/null +++ b/ext/chan/module_petit.lb @@ -0,0 +1,60 @@ +#!/usr/bin/env python3 +# -*- coding: utf-8 -*- +# +# Copyright (c) 2021, Niklas Hauser +# +# This file is part of the modm project. +# +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. +# ----------------------------------------------------------------------------- + +def init(module): + module.name = ":fatfs.petit" + module.description = """ +# Petit FatFs: Tiny FAT Filesystem + +Petit FatFs is a sub-set of FatFs module for tiny 8-bit microcontrollers. It can +be incorporated into the tiny microcontrollers with limited memory even if the +RAM size is less than sector size. + +See http://elm-chan.org/fsw/ff/00index_p.html. + + +## Configuration + +To configure Petit FatFs for your project, create a `` file, +which is included at the *beginning* of the config, thus overwriting the default +settings. Please see the `modm/ext/fatfs-petit/pffconf.h` file for the available +configuration options and their default values. + +Example `` configuration: + +```c +// Enable directories: pf_opendir(), pf_readdir() +#define PF_USE_DIR 1 + +// Enabling writing: pf_write() +#define PF_USE_WRITE 1 + +// Use FAT12 file system +#define PF_FS_FAT12 1 +#define PF_FS_FAT16 0 +#define PF_FS_FAT32 0 +``` +""" + +def prepare(module, options): + return True + +def build(env): + env.collect(":build:path.include", "modm/ext") + env.outbasepath = "modm/ext/fatfs-petit" + + env.copy("fatfs/tiny/source/diskio.h", "diskio.h") + env.copy("fatfs/tiny/source/pff.h", "pff.h") + env.copy("fatfs/tiny/source/pff.c", "pff.c") + env.copy("fatfs/tiny/LICENSE.txt", "LICENSE.txt") + + env.copy("pffconf.h") diff --git a/ext/chan/pffconf.h b/ext/chan/pffconf.h new file mode 100644 index 0000000000..9590edc07f --- /dev/null +++ b/ext/chan/pffconf.h @@ -0,0 +1,81 @@ +/*---------------------------------------------------------------------------/ +/ Petit FatFs - Configuration file +/---------------------------------------------------------------------------*/ + +#ifndef PFCONF_DEF +#define PFCONF_DEF 8088 /* Revision ID */ + +/* A header file that overwrites with local project settings. */ +#if __has_include() +#include +#endif + +/*---------------------------------------------------------------------------/ +/ Function Configurations (0:Disable, 1:Enable) +/---------------------------------------------------------------------------*/ + +#ifndef PF_USE_READ +# define PF_USE_READ 1 /* pf_read() function */ +#endif +#ifndef PF_USE_DIR +# define PF_USE_DIR 0 /* pf_opendir() and pf_readdir() function */ +#endif +#ifndef PF_USE_LSEEK +# define PF_USE_LSEEK 0 /* pf_lseek() function */ +#endif +#ifndef PF_USE_WRITE +# define PF_USE_WRITE 0 /* pf_write() function */ +#endif + +#ifndef PF_FS_FAT12 +# define PF_FS_FAT12 0 /* FAT12 */ +#endif +#ifndef PF_FS_FAT16 +# define PF_FS_FAT16 1 /* FAT16 */ +#endif +#ifndef PF_FS_FAT32 +# define PF_FS_FAT32 0 /* FAT32 */ +#endif + + +/*---------------------------------------------------------------------------/ +/ Locale and Namespace Configurations +/---------------------------------------------------------------------------*/ + +#ifndef PF_USE_LCC +# define PF_USE_LCC 0 /* Allow lower case ASCII and non-ASCII chars */ +#endif + +#ifndef PF_CODE_PAGE +# define PF_CODE_PAGE 437 +#endif +/* The PF_CODE_PAGE specifies the code page to be used on the target system. +/ SBCS code pages with PF_USE_LCC == 1 requiers a 128 byte of case conversion +/ table. It might occupy RAM on some platforms, e.g. avr-gcc. +/ When PF_USE_LCC == 0, PF_CODE_PAGE has no effect. +/ +/ 437 - U.S. +/ 720 - Arabic +/ 737 - Greek +/ 771 - KBL +/ 775 - Baltic +/ 850 - Latin 1 +/ 852 - Latin 2 +/ 855 - Cyrillic +/ 857 - Turkish +/ 860 - Portuguese +/ 861 - Icelandic +/ 862 - Hebrew +/ 863 - Canadian French +/ 864 - Arabic +/ 865 - Nordic +/ 866 - Russian +/ 869 - Greek 2 +/ 932 - Japanese (DBCS) +/ 936 - Simplified Chinese (DBCS) +/ 949 - Korean (DBCS) +/ 950 - Traditional Chinese (DBCS) +*/ + + +#endif /* PF_CONF */ From ad2ef4b897d072ac2c016f0bf6be362717f322a3 Mon Sep 17 00:00:00 2001 From: Niklas Hauser Date: Tue, 30 Mar 2021 06:21:38 +0200 Subject: [PATCH 10/12] [ext] Update FreeRTOS to 202012 LTS version --- ext/aws/freertos | 2 +- ext/aws/module.lb | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/ext/aws/freertos b/ext/aws/freertos index a5317393d9..22cf84210c 160000 --- a/ext/aws/freertos +++ b/ext/aws/freertos @@ -1 +1 @@ -Subproject commit a5317393d92e283980f809c9fc7a6510c4a57a6e +Subproject commit 22cf84210cec4ddcd1e3665c8b986c5d194919b3 diff --git a/ext/aws/module.lb b/ext/aws/module.lb index 194b87300d..c293935ed4 100644 --- a/ext/aws/module.lb +++ b/ext/aws/module.lb @@ -65,6 +65,7 @@ the config macros, then redefine them with your options, for example: env.copy("freertos/FreeRTOS-Plus-TCP/portable/Compiler/GCC/pack_struct_end.h", "freertos_plus_tcp/include/pack_struct_end.h") env.collect(":build:path.include", "modm/ext/freertos_plus_tcp/include") + env.collect(":build:path.include", "modm/ext/freertos_plus_tcp/tools/tcp_utilities/include") env.template("FreeRTOSIPConfig.h.in", "freertos_plus_tcp/include/FreeRTOSIPConfig.h") # ----------------------------------------------------------------------------- From 0daed777f92eb7600de7c1067e904b1b8ee28722 Mon Sep 17 00:00:00 2001 From: Niklas Hauser Date: Tue, 6 Apr 2021 09:13:54 +0200 Subject: [PATCH 11/12] [freertos] Add better configuration management --- ext/aws/FreeRTOSConfig.h.in | 220 +++++++++++++--------- ext/aws/freertos.md | 70 +++++++ ext/aws/module.lb | 43 ++--- repo.lb | 2 +- src/modm/platform/clock/systick/module.lb | 4 - 5 files changed, 218 insertions(+), 121 deletions(-) create mode 100644 ext/aws/freertos.md diff --git a/ext/aws/FreeRTOSConfig.h.in b/ext/aws/FreeRTOSConfig.h.in index 209fbf50a8..63bb7f0cea 100644 --- a/ext/aws/FreeRTOSConfig.h.in +++ b/ext/aws/FreeRTOSConfig.h.in @@ -35,6 +35,9 @@ your application. */ #include #include +/* Define to trap errors during development. */ +#define configASSERT( x ) { modm_assert((x), "freertos", __FILE__, MODM_STRINGIFY(__LINE__)); } + // declared in modm:platform:clock #ifdef __cplusplus extern "C" uint32_t SystemCoreClock; @@ -42,112 +45,147 @@ your application. */ extern uint32_t SystemCoreClock; #endif -#define configUSE_PREEMPTION 1 -#define configUSE_PORT_OPTIMISED_TASK_SELECTION {{ ("m0" not in core) | int }} -#define configUSE_TICKLESS_IDLE 0 #define configCPU_CLOCK_HZ ( SystemCoreClock ) -#define configTICK_RATE_HZ ( {{ options["::frequency"] }} ) -#define configMAX_PRIORITIES 5 -#define configMINIMAL_STACK_SIZE 128 -#define configMAX_TASK_NAME_LEN 16 -#define configUSE_16_BIT_TICKS 0 -#define configIDLE_SHOULD_YIELD 1 -#define configUSE_TASK_NOTIFICATIONS 1 -#define configUSE_MUTEXES 1 -#define configUSE_RECURSIVE_MUTEXES 1 -#define configUSE_COUNTING_SEMAPHORES 1 -#define configQUEUE_REGISTRY_SIZE 10 -#define configUSE_QUEUE_SETS 0 -#define configUSE_TIME_SLICING 0 -#define configUSE_NEWLIB_REENTRANT 0 -#define configENABLE_BACKWARD_COMPATIBILITY 0 -#define configNUM_THREAD_LOCAL_STORAGE_POINTERS 5 - - +#define configTICK_RATE_HZ ( {{ frequency }} ) /* Memory allocation related definitions. */ #define configSUPPORT_STATIC_ALLOCATION 0 #define configSUPPORT_DYNAMIC_ALLOCATION 1 -#define configTOTAL_HEAP_SIZE 0 // modm provides heap -#define configAPPLICATION_ALLOCATED_HEAP 1 - -/* Hook function related definitions. */ -#define configUSE_IDLE_HOOK 0 // used by modm:platform:clock for modm::Clock::increment(): vApplicationTickHook() #define configUSE_TICK_HOOK 1 -#define configCHECK_FOR_STACK_OVERFLOW 1 -#define configUSE_MALLOC_FAILED_HOOK 0 // modm provides heap assertions -#define configUSE_DAEMON_TASK_STARTUP_HOOK 0 - -/* Run time and task stats gathering related definitions. */ -#define configGENERATE_RUN_TIME_STATS 0 -#define configUSE_TRACE_FACILITY 0 -#define configUSE_STATS_FORMATTING_FUNCTIONS 0 - -/* Co-routine related definitions. */ -#define configUSE_CO_ROUTINES 0 -#define configMAX_CO_ROUTINE_PRIORITIES 1 - -/* Software timer related definitions. */ -#define configUSE_TIMERS 1 -#define configTIMER_TASK_PRIORITY 3 -#define configTIMER_QUEUE_LENGTH 10 -#define configTIMER_TASK_STACK_DEPTH configMINIMAL_STACK_SIZE - -/* Define to trap errors during development. */ -#define configASSERT( x ) { modm_assert((x), "freertos.assert", __FILE__, MODM_STRINGIFY(__LINE__)); } - -/* FreeRTOS MPU specific definitions. */ -#define configINCLUDE_APPLICATION_DEFINED_PRIVILEGED_FUNCTIONS 0 - -/* Optional functions - most linkers will remove unused functions anyway. */ -#define INCLUDE_vTaskPrioritySet 1 -#define INCLUDE_uxTaskPriorityGet 1 -#define INCLUDE_vTaskDelete 1 -#define INCLUDE_vTaskSuspend 1 -#define INCLUDE_xResumeFromISR 1 -#define INCLUDE_vTaskDelayUntil 1 -#define INCLUDE_vTaskDelay 1 -#define INCLUDE_xTaskGetSchedulerState 1 -#define INCLUDE_xTaskGetCurrentTaskHandle 1 -#define INCLUDE_uxTaskGetStackHighWaterMark 0 -#define INCLUDE_xTaskGetIdleTaskHandle 0 -#define INCLUDE_eTaskGetState 0 -#define INCLUDE_xEventGroupSetBitFromISR 1 -#define INCLUDE_xTimerPendFunctionCall 0 -#define INCLUDE_xTaskAbortDelay 0 -#define INCLUDE_xTaskGetHandle 0 -#define INCLUDE_xTaskResumeFromISR 1 - - -/* __NVIC_PRIO_BITS will be specified when CMSIS is being used. */ -#define configPRIO_BITS __NVIC_PRIO_BITS - -/* The lowest interrupt priority that can be used in a call to a "set priority" -function. */ -#define configLIBRARY_LOWEST_INTERRUPT_PRIORITY 15 - -/* The highest interrupt priority that can be used by any interrupt service -routine that makes calls to interrupt safe FreeRTOS API functions. DO NOT CALL -INTERRUPT SAFE FREERTOS API FUNCTIONS FROM ANY INTERRUPT THAT HAS A HIGHER -PRIORITY THAN THIS! (higher priorities are lower numeric values. */ -#define configLIBRARY_MAX_SYSCALL_INTERRUPT_PRIORITY 4 /* Interrupt priorities used by the kernel port layer itself. These are generic to all Cortex-M ports, and do not rely on any particular library functions. */ -#define configKERNEL_INTERRUPT_PRIORITY ( configLIBRARY_LOWEST_INTERRUPT_PRIORITY << (8 - configPRIO_BITS) ) -/* !!!! configMAX_SYSCALL_INTERRUPT_PRIORITY must not be set to zero !!!! -See http://www.FreeRTOS.org/RTOS-Cortex-M3-M4.html. */ -#define configMAX_SYSCALL_INTERRUPT_PRIORITY ( configLIBRARY_MAX_SYSCALL_INTERRUPT_PRIORITY << (8 - configPRIO_BITS) ) +#define configKERNEL_INTERRUPT_PRIORITY (((1u << __NVIC_PRIO_BITS) - 1u) << (8u - __NVIC_PRIO_BITS)) /* Definitions that map the FreeRTOS port interrupt handlers to their CMSIS standard names. */ -#define xPortPendSVHandler PendSV_Handler -#define vPortSVCHandler SVC_Handler -#define xPortSysTickHandler SysTick_Handler +#define xPortPendSVHandler PendSV_Handler +#define vPortSVCHandler SVC_Handler +#define xPortSysTickHandler SysTick_Handler + /* A header file that overwrites with local project settings. */ #if __has_include() -#include +# include +#endif + + +/* Required config by FreeRTOS and defaulted by modm */ + +/* !!!! configMAX_SYSCALL_INTERRUPT_PRIORITY must not be set to zero !!!! +See http://www.FreeRTOS.org/RTOS-Cortex-M3-M4.html. */ +#ifndef configMAX_SYSCALL_INTERRUPT_PRIORITY +# define configMAX_SYSCALL_INTERRUPT_PRIORITY (__NVIC_PRIO_BITS << (8u - __NVIC_PRIO_BITS)) +#endif + +#ifndef configMINIMAL_STACK_SIZE +# define configMINIMAL_STACK_SIZE 128 +#endif +#ifndef configMAX_PRIORITIES +# define configMAX_PRIORITIES 5 +#endif +#ifndef configUSE_PREEMPTION +# define configUSE_PREEMPTION 1 +#endif +#ifndef configUSE_IDLE_HOOK +# define configUSE_IDLE_HOOK 0 +#endif +#ifndef configUSE_16_BIT_TICKS +# define configUSE_16_BIT_TICKS 0 +#endif + +/* Defaulted by FreeRTOS but changed by modm */ + +#ifndef configUSE_MUTEXES +# define configUSE_MUTEXES 1 +#endif +#ifndef configUSE_RECURSIVE_MUTEXES +# define configUSE_RECURSIVE_MUTEXES 1 +#endif +#ifndef configUSE_COUNTING_SEMAPHORES +# define configUSE_COUNTING_SEMAPHORES 1 +#endif +#ifndef configQUEUE_REGISTRY_SIZE +# define configQUEUE_REGISTRY_SIZE 10 +#endif +#ifndef configENABLE_BACKWARD_COMPATIBILITY +# define configENABLE_BACKWARD_COMPATIBILITY 0 +#endif +#ifndef configNUM_THREAD_LOCAL_STORAGE_POINTERS +# define configNUM_THREAD_LOCAL_STORAGE_POINTERS 5 +#endif +#ifndef configCHECK_FOR_STACK_OVERFLOW +# define configCHECK_FOR_STACK_OVERFLOW 1 +#endif + +/* The timers module relies on xTaskGetSchedulerState(). */ +#ifndef configUSE_TIMERS +# define configUSE_TIMERS 1 +#endif +#ifndef configTIMER_TASK_PRIORITY +# define configTIMER_TASK_PRIORITY 3 +#endif +#ifndef configTIMER_QUEUE_LENGTH +# define configTIMER_QUEUE_LENGTH 10 +#endif +#ifndef configTIMER_TASK_STACK_DEPTH +# define configTIMER_TASK_STACK_DEPTH configMINIMAL_STACK_SIZE +#endif + +/* Optional functions all enabled. */ +#ifndef INCLUDE_vTaskPrioritySet +# define INCLUDE_vTaskPrioritySet 1 +#endif +#ifndef INCLUDE_uxTaskPriorityGet +# define INCLUDE_uxTaskPriorityGet 1 +#endif +#ifndef INCLUDE_vTaskDelete +# define INCLUDE_vTaskDelete 1 +#endif +#ifndef INCLUDE_vTaskSuspend +# define INCLUDE_vTaskSuspend 1 +#endif +#ifndef INCLUDE_xTaskDelayUntil +# define INCLUDE_xTaskDelayUntil 1 +#endif +#ifndef INCLUDE_vTaskDelay +# define INCLUDE_vTaskDelay 1 +#endif +#ifndef INCLUDE_xTaskGetIdleTaskHandle +# define INCLUDE_xTaskGetIdleTaskHandle 1 +#endif +#ifndef INCLUDE_xTaskAbortDelay +# define INCLUDE_xTaskAbortDelay 1 +#endif +#ifndef INCLUDE_xQueueGetMutexHolder +# define INCLUDE_xQueueGetMutexHolder 1 +#endif +#ifndef INCLUDE_xSemaphoreGetMutexHolder +# define INCLUDE_xSemaphoreGetMutexHolder 1 +#endif +#ifndef INCLUDE_xTaskGetHandle +# define INCLUDE_xTaskGetHandle 1 +#endif +#ifndef INCLUDE_uxTaskGetStackHighWaterMark +# define INCLUDE_uxTaskGetStackHighWaterMark 1 +#endif +#ifndef INCLUDE_uxTaskGetStackHighWaterMark2 +# define INCLUDE_uxTaskGetStackHighWaterMark2 1 +#endif +#ifndef INCLUDE_eTaskGetState +# define INCLUDE_eTaskGetState 1 +#endif +#ifndef INCLUDE_xTaskResumeFromISR +# define INCLUDE_xTaskResumeFromISR 1 +#endif +#ifndef INCLUDE_xTimerPendFunctionCall +# define INCLUDE_xTimerPendFunctionCall 1 +#endif +#ifndef INCLUDE_xTaskGetSchedulerState +# define INCLUDE_xTaskGetSchedulerState 1 +#endif +#ifndef INCLUDE_xTaskGetCurrentTaskHandle +# define INCLUDE_xTaskGetCurrentTaskHandle 1 #endif #endif /* FREERTOS_CONFIG_H */ diff --git a/ext/aws/freertos.md b/ext/aws/freertos.md new file mode 100644 index 0000000000..2d83a7ee6c --- /dev/null +++ b/ext/aws/freertos.md @@ -0,0 +1,70 @@ +# FreeRTOS + +Amazon FreeRTOS is an open source, real-time operating system (RTOS) for +microcontrollers in small, low-power devices. + +This module provides the latest FreeRTOS LTS release integrated with modm: + +- Chooses the right Cortex-M port for the target. +- Variable tick rate integrated with `modm::Clock` via `modm:platform:clock`. +- Dynamic memory provided by the `modm:platform:heap` module with thread-safe + locking of Newlib's `malloc/free`. +- Assertions integrated into the `modm:architecture:assert` interface. +- Interrupt handling integrated with CMSIS NVIC functions. + +Note that we recommend using the FreeRTOS API directly and only if you write +threaded code that also runs on other platforms (x86 simulators for example) +should you consider using the API defined in `modm:processing:rtos` module. + + +## Configuration + +This module generates a `FreeRTOSConfig.h` config file for modm integration with +these settings: + +- `configASSERT(x)` implemented with `modm_assert(x, "freertos")`. +- `configCPU_CLOCK_HZ` implemented with CMSIS `SystemCoreClock`. +- `configTICK_RATE_HZ` set to `modm:freertos:frequency` or 1kHz on Cortex-M0. +- `configSUPPORT_DYNAMIC_ALLOCATION = 1` as implemented by `modm:platform:heap`. +- `configUSE_TICK_HOOK = 1` used by `modm:platform:clock` to provide `modm::Clock`. + +In addition we define these overwritable default settings: + +- `configMAX_SYSCALL_INTERRUPT_PRIORITY` = `(__NVIC_PRIO_BITS << (8u - __NVIC_PRIO_BITS))` + +- `configMINIMAL_STACK_SIZE` = 128 +- `configMAX_PRIORITIES` = 5 +- `configUSE_PREEMPTION` = 1 +- `configUSE_IDLE_HOOK` = 0 +- `configUSE_16_BIT_TICKS` = 0 + +- `configUSE_MUTEXES` = 1 +- `configUSE_RECURSIVE_MUTEXES` = 1 +- `configUSE_COUNTING_SEMAPHORES` = 1 +- `configQUEUE_REGISTRY_SIZE` = 10 +- `configNUM_THREAD_LOCAL_STORAGE_POINTERS` = 5 +- `configCHECK_FOR_STACK_OVERFLOW` = 1 + +- `configUSE_TIMERS` = 1 +- `configTIMER_TASK_PRIORITY` = 3 +- `configTIMER_QUEUE_LENGTH` = 10 +- `configTIMER_TASK_STACK_DEPTH` = `configMINIMAL_STACK_SIZE` + +All other config settings are unchanged by modm and are defaulted by FreeRTOS +itself, please refer to the [FreeRTOS Config documentation][config] to +understand what each of these do. + +To change a configuration setting, define a `` file, +which is included *before* the optional settings, so you can overwrite them +easily. + +An example `` file: + +```c +// Use a bigger minimal stack size +#define configMINIMAL_STACK_SIZE 256 +// Longer timer queue +#define configTIMER_QUEUE_LENGTH 20 +``` + +[config]: https://www.freertos.org/a00110.html diff --git a/ext/aws/module.lb b/ext/aws/module.lb index c293935ed4..b9fd4a4602 100644 --- a/ext/aws/module.lb +++ b/ext/aws/module.lb @@ -71,23 +71,7 @@ the config macros, then redefine them with your options, for example: def init(module): module.name = "freertos" - module.description = """\ -# a:FreeRTOS - -Amazon FreeRTOS port for modm to be used with via the `modm:processing:rtos` module. - -## Custom Configuration - -This module defines a default FreeRTOS config. If you need to change a -configuration setting, then you can define a `FreeRTOSConfigLocal.h` file, which -is included *after* at the end of the config. You must therefore first `#undef` -the config macros, then redefine them with your options, for example: - -```c -#undef configCHECK_FOR_STACK_OVERFLOW -#define configCHECK_FOR_STACK_OVERFLOW 0 -``` -""" + module.description = FileReader("freertos.md") def prepare(module, options): device = options[":target"] @@ -95,17 +79,23 @@ def prepare(module, options): if not (core and core["type"].startswith("cortex-m")): return False - module.add_option( - NumericOption( - name="frequency", - description="Context switch frequency in Hz", - minimum=1, maximum=1000, - default=1000)) + if "m0" not in core: + def validate_frequency(freq): + if (1000 % freq > 1): + raise ValueError("FreeRTOS frequency must cleanly divide 1kHz for modm::Clock!") + module.add_option( + NumericOption( + name="frequency", + description="Context switch frequency in Hz", + validate=validate_frequency, + minimum=4, maximum=1000, + default=1000)) module.depends( ":architecture:assert", ":cmsis:device", - ":platform:clock") + ":platform:clock", + ":platform:heap") module.add_submodule(FreeRTOS_TCP()) @@ -114,7 +104,10 @@ def prepare(module, options): def build(env): # Figure out the core and correct path in portable/ core = env[":target"].get_driver("core")["type"] - env.substitutions = {"core": core} + env.substitutions = { + "core": core, + "frequency": env.get("frequency", 1000) + } path = core.replace("cortex-m", "ARM_CM").replace("+", "").replace("fd", "f").upper() path = path.replace("CM7F", "CM7/r0p1") # use subfolder for M7 path = "freertos/FreeRTOS/Source/portable/GCC/{}".format(path) diff --git a/repo.lb b/repo.lb index 91fd4c27b2..b5af692f46 100644 --- a/repo.lb +++ b/repo.lb @@ -24,7 +24,7 @@ from os.path import normpath # Check for miminum required lbuild version import lbuild -min_lbuild_version = "1.16.1" +min_lbuild_version = "1.17.0" if StrictVersion(getattr(lbuild, "__version__", "0.1.0")) < StrictVersion(min_lbuild_version): print("modm requires at least lbuild v{}, please upgrade!\n" " pip3 install -U lbuild".format(min_lbuild_version)) diff --git a/src/modm/platform/clock/systick/module.lb b/src/modm/platform/clock/systick/module.lb index 7d5b584971..925a3b693e 100644 --- a/src/modm/platform/clock/systick/module.lb +++ b/src/modm/platform/clock/systick/module.lb @@ -29,10 +29,6 @@ def prepare(module, options): return True -def validate(env): - if (1000 % env.get(":freertos:frequency", 1000) != 0): - raise ValidateException("FreeRTOS frequency must cleanly divide 1kHz for modm::Clock!") - def build(env): core = env[":target"].get_driver("core")["type"] default = 1000 if "m0" in core else 4 From 1375ff15f569a8f21fa3c24bf57c1e25e2803eac Mon Sep 17 00:00:00 2001 From: Niklas Hauser Date: Sun, 11 Apr 2021 04:50:49 +0200 Subject: [PATCH 12/12] [freertos+tcp] Add better configuration management --- .../freertos_plus_tcp/project.xml | 1 - .../ethernet/FreeRTOSIPConfigLocal.h | 271 ++++++++++++++++ ext/aws/FreeRTOSIPConfig.h.in | 301 ++---------------- ext/aws/freertos_tcp.md | 41 +++ ext/aws/{modm_port.cpp => modm_port.cpp.in} | 21 ++ ext/aws/module.lb | 21 +- 6 files changed, 366 insertions(+), 290 deletions(-) create mode 100644 examples/nucleo_f767zi/ethernet/FreeRTOSIPConfigLocal.h create mode 100644 ext/aws/freertos_tcp.md rename ext/aws/{modm_port.cpp => modm_port.cpp.in} (79%) diff --git a/examples/nucleo_f429zi/freertos_plus_tcp/project.xml b/examples/nucleo_f429zi/freertos_plus_tcp/project.xml index 9c29693d07..395d1497f3 100644 --- a/examples/nucleo_f429zi/freertos_plus_tcp/project.xml +++ b/examples/nucleo_f429zi/freertos_plus_tcp/project.xml @@ -6,7 +6,6 @@ modm:processing:rtos modm:freertos:tcp - modm:platform:heap modm:build:scons diff --git a/examples/nucleo_f767zi/ethernet/FreeRTOSIPConfigLocal.h b/examples/nucleo_f767zi/ethernet/FreeRTOSIPConfigLocal.h new file mode 100644 index 0000000000..7e9dd59fd8 --- /dev/null +++ b/examples/nucleo_f767zi/ethernet/FreeRTOSIPConfigLocal.h @@ -0,0 +1,271 @@ +/* + * FreeRTOS+TCP V2.2.1 + * Copyright (C) 2017 Amazon.com, Inc. or its affiliates. All Rights Reserved. + * + * 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. + * + * http://www.FreeRTOS.org + * http://aws.amazon.com/freertos + * + * 1 tab == 4 spaces! + */ + +#ifndef FREERTOS_IP_CONFIG_H +# error "Don't include this file, use 'FreeRTOSIPConfig.h' instead!" +#endif + +/* Set to 1 to print out debug messages. If ipconfigHAS_DEBUG_PRINTF is set to +1 then FreeRTOS_debug_printf should be defined to the function used to print +out the debugging messages. */ +#define ipconfigHAS_DEBUG_PRINTF 0 + +/* Set to 1 to print out non debugging messages, for example the output of the +FreeRTOS_netstat() command, and ping replies. If ipconfigHAS_PRINTF is set to 1 +then FreeRTOS_printf should be set to the function used to print out the +messages. */ +#define ipconfigHAS_PRINTF 0 + +/* If the network card/driver includes checksum offloading (IP/TCP/UDP checksums) +then set ipconfigDRIVER_INCLUDED_RX_IP_CHECKSUM to 1 to prevent the software +stack repeating the checksum calculations. */ +#define ipconfigDRIVER_INCLUDED_RX_IP_CHECKSUM 1 +#define ipconfigDRIVER_INCLUDED_TX_IP_CHECKSUM 1 + +/* Several API's will block until the result is known, or the action has been +performed, for example FreeRTOS_send() and FreeRTOS_recv(). The timeouts can be +set per socket, using setsockopt(). If not set, the times below will be +used as defaults. */ +#define ipconfigSOCK_DEFAULT_RECEIVE_BLOCK_TIME ( 5000 ) +#define ipconfigSOCK_DEFAULT_SEND_BLOCK_TIME ( 5000 ) + +/* Include support for LLMNR: Link-local Multicast Name Resolution +(non-Microsoft) */ +#define ipconfigUSE_LLMNR ( 0 ) + +/* Include support for NBNS: NetBIOS Name Service (Microsoft) */ +#define ipconfigUSE_NBNS ( 0 ) + +/* Include support for DNS caching. For TCP, having a small DNS cache is very +useful. When a cache is present, ipconfigDNS_REQUEST_ATTEMPTS can be kept low +and also DNS may use small timeouts. If a DNS reply comes in after the DNS +socket has been destroyed, the result will be stored into the cache. The next +call to FreeRTOS_gethostbyname() will return immediately, without even creating +a socket. */ +#define ipconfigUSE_DNS_CACHE ( 1 ) +#define ipconfigDNS_CACHE_NAME_LENGTH ( 16 ) +#define ipconfigDNS_CACHE_ENTRIES ( 4 ) +#define ipconfigDNS_REQUEST_ATTEMPTS ( 2 ) + +/* ipconfigRAND32() is called by the IP stack to generate random numbers for +things such as a DHCP transaction number or initial sequence number. Random +number generation is performed via this macro to allow applications to use their +own random number generation method. For example, it might be possible to +generate a random number by sampling noise on an analogue input. */ +extern UBaseType_t uxRand(void); +#define ipconfigRAND32() uxRand() + +/* If ipconfigUSE_NETWORK_EVENT_HOOK is set to 1 then FreeRTOS+TCP will call the +network event hook at the appropriate times. If ipconfigUSE_NETWORK_EVENT_HOOK +is not set to 1 then the network event hook will never be called. See +http://www.FreeRTOS.org/FreeRTOS-Plus/FreeRTOS_Plus_UDP/API/vApplicationIPNetworkEventHook.shtml +*/ +#define ipconfigUSE_NETWORK_EVENT_HOOK 1 + +/* Sockets have a send block time attribute. If FreeRTOS_sendto() is called but +a network buffer cannot be obtained then the calling task is held in the Blocked +state (so other tasks can continue to executed) until either a network buffer +becomes available or the send block time expires. If the send block time expires +then the send operation is aborted. The maximum allowable send block time is +capped to the value set by ipconfigMAX_SEND_BLOCK_TIME_TICKS. Capping the +maximum allowable send block time prevents prevents a deadlock occurring when +all the network buffers are in use and the tasks that process (and subsequently +free) the network buffers are themselves blocked waiting for a network buffer. +ipconfigMAX_SEND_BLOCK_TIME_TICKS is specified in RTOS ticks. A time in +milliseconds can be converted to a time in ticks by dividing the time in +milliseconds by portTICK_PERIOD_MS. */ +#define ipconfigUDP_MAX_SEND_BLOCK_TIME_TICKS ( 5000 / portTICK_PERIOD_MS ) + +/* If ipconfigUSE_DHCP is 1 then FreeRTOS+TCP will attempt to retrieve an IP +address, netmask, DNS server address and gateway address from a DHCP server. If +ipconfigUSE_DHCP is 0 then FreeRTOS+TCP will use a static IP address. The +stack will revert to using the static IP address even when ipconfigUSE_DHCP is +set to 1 if a valid configuration cannot be obtained from a DHCP server for any +reason. The static configuration used is that passed into the stack by the +FreeRTOS_IPInit() function call. */ +#define ipconfigUSE_DHCP 0 + +/* When ipconfigUSE_DHCP is set to 1, DHCP requests will be sent out at +increasing time intervals until either a reply is received from a DHCP server +and accepted, or the interval between transmissions reaches +ipconfigMAXIMUM_DISCOVER_TX_PERIOD. The IP stack will revert to using the +static IP address passed as a parameter to FreeRTOS_IPInit() if the +re-transmission time interval reaches ipconfigMAXIMUM_DISCOVER_TX_PERIOD without +a DHCP reply being received. */ +#define ipconfigMAXIMUM_DISCOVER_TX_PERIOD ( 120000 / portTICK_PERIOD_MS ) + +/* The ARP cache is a table that maps IP addresses to MAC addresses. The IP +stack can only send a UDP message to a remove IP address if it knowns the MAC +address associated with the IP address, or the MAC address of the router used to +contact the remote IP address. When a UDP message is received from a remote IP +address the MAC address and IP address are added to the ARP cache. When a UDP +message is sent to a remote IP address that does not already appear in the ARP +cache then the UDP message is replaced by a ARP message that solicits the +required MAC address information. ipconfigARP_CACHE_ENTRIES defines the maximum +number of entries that can exist in the ARP table at any one time. */ +#define ipconfigARP_CACHE_ENTRIES 6 + +/* ARP requests that do not result in an ARP response will be re-transmitted a +maximum of ipconfigMAX_ARP_RETRANSMISSIONS times before the ARP request is +aborted. */ +#define ipconfigMAX_ARP_RETRANSMISSIONS ( 5 ) + +/* ipconfigMAX_ARP_AGE defines the maximum time between an entry in the ARP +table being created or refreshed and the entry being removed because it is stale. +New ARP requests are sent for ARP cache entries that are nearing their maximum +age. ipconfigMAX_ARP_AGE is specified in tens of seconds, so a value of 150 is +equal to 1500 seconds (or 25 minutes). */ +#define ipconfigMAX_ARP_AGE 150 + +/* Implementing FreeRTOS_inet_addr() necessitates the use of string handling +routines, which are relatively large. To save code space the full +FreeRTOS_inet_addr() implementation is made optional, and a smaller and faster +alternative called FreeRTOS_inet_addr_quick() is provided. FreeRTOS_inet_addr() +takes an IP in decimal dot format (for example, "192.168.0.1") as its parameter. +FreeRTOS_inet_addr_quick() takes an IP address as four separate numerical octets +(for example, 192, 168, 0, 1) as its parameters. If +ipconfigINCLUDE_FULL_INET_ADDR is set to 1 then both FreeRTOS_inet_addr() and +FreeRTOS_indet_addr_quick() are available. If ipconfigINCLUDE_FULL_INET_ADDR is +not set to 1 then only FreeRTOS_indet_addr_quick() is available. */ +#define ipconfigINCLUDE_FULL_INET_ADDR 1 + +/* ipconfigNUM_NETWORK_BUFFER_DESCRIPTORS defines the total number of network buffer that +are available to the IP stack. The total number of network buffers is limited +to ensure the total amount of RAM that can be consumed by the IP stack is capped +to a pre-determinable value. */ +#define ipconfigNUM_NETWORK_BUFFER_DESCRIPTORS 60 + +/* A FreeRTOS queue is used to send events from application tasks to the IP +stack. ipconfigEVENT_QUEUE_LENGTH sets the maximum number of events that can +be queued for processing at any one time. The event queue must be a minimum of +5 greater than the total number of network buffers. */ +#define ipconfigEVENT_QUEUE_LENGTH ( ipconfigNUM_NETWORK_BUFFER_DESCRIPTORS + 5 ) + +/* The address of a socket is the combination of its IP address and its port +number. FreeRTOS_bind() is used to manually allocate a port number to a socket +(to 'bind' the socket to a port), but manual binding is not normally necessary +for client sockets (those sockets that initiate outgoing connections rather than +wait for incoming connections on a known port number). If +ipconfigALLOW_SOCKET_SEND_WITHOUT_BIND is set to 1 then calling +FreeRTOS_sendto() on a socket that has not yet been bound will result in the IP +stack automatically binding the socket to a port number from the range +socketAUTO_PORT_ALLOCATION_START_NUMBER to 0xffff. If +ipconfigALLOW_SOCKET_SEND_WITHOUT_BIND is set to 0 then calling FreeRTOS_sendto() +on a socket that has not yet been bound will result in the send operation being +aborted. */ +#define ipconfigALLOW_SOCKET_SEND_WITHOUT_BIND 1 + +/* Defines the Time To Live (TTL) values used in outgoing UDP packets. */ +#define ipconfigUDP_TIME_TO_LIVE 128 +#define ipconfigTCP_TIME_TO_LIVE 128 /* also defined in FreeRTOSIPConfigDefaults.h */ + +/* USE_TCP: Use TCP and all its features */ +#define ipconfigUSE_TCP ( 1 ) + +/* USE_WIN: Let TCP use windowing mechanism. */ +#define ipconfigUSE_TCP_WIN ( 1 ) + +/* The MTU is the maximum number of bytes the payload of a network frame can +contain. For normal Ethernet V2 frames the maximum MTU is 1500. Setting a +lower value can save RAM, depending on the buffer management scheme used. If +ipconfigCAN_FRAGMENT_OUTGOING_PACKETS is 1 then (ipconfigNETWORK_MTU - 28) must +be divisible by 8. */ +#define ipconfigNETWORK_MTU 1500 + +/* Set ipconfigUSE_DNS to 1 to include a basic DNS client/resolver. DNS is used +through the FreeRTOS_gethostbyname() API function. */ +#define ipconfigUSE_DNS 0 + +/* If ipconfigREPLY_TO_INCOMING_PINGS is set to 1 then the IP stack will +generate replies to incoming ICMP echo (ping) requests. */ +#define ipconfigREPLY_TO_INCOMING_PINGS 1 + +/* If ipconfigSUPPORT_OUTGOING_PINGS is set to 1 then the +FreeRTOS_SendPingRequest() API function is available. */ +#define ipconfigSUPPORT_OUTGOING_PINGS 0 + +/* If ipconfigSUPPORT_SELECT_FUNCTION is set to 1 then the FreeRTOS_select() +(and associated) API function is available. */ +#define ipconfigSUPPORT_SELECT_FUNCTION 1 + +/* If ipconfigFILTER_OUT_NON_ETHERNET_II_FRAMES is set to 1 then Ethernet frames +that are not in Ethernet II format will be dropped. This option is included for +potential future IP stack developments. */ +#define ipconfigFILTER_OUT_NON_ETHERNET_II_FRAMES 1 + +/* If ipconfigETHERNET_DRIVER_FILTERS_FRAME_TYPES is set to 1 then it is the +responsibility of the Ethernet interface to filter out packets that are of no +interest. If the Ethernet interface does not implement this functionality, then +set ipconfigETHERNET_DRIVER_FILTERS_FRAME_TYPES to 0 to have the IP stack +perform the filtering instead (it is much less efficient for the stack to do it +because the packet will already have been passed into the stack). If the +Ethernet driver does all the necessary filtering in hardware then software +filtering can be removed by using a value other than 1 or 0. */ +#define ipconfigETHERNET_DRIVER_FILTERS_FRAME_TYPES 1 + +/* The windows simulator cannot really simulate MAC interrupts, and needs to +block occasionally to allow other tasks to run. */ +#define configWINDOWS_MAC_INTERRUPT_SIMULATOR_DELAY ( 20 / portTICK_PERIOD_MS ) + +/* Advanced only: in order to access 32-bit fields in the IP packets with +32-bit memory instructions, all packets will be stored 32-bit-aligned, plus 16-bits. +This has to do with the contents of the IP-packets: all 32-bit fields are +32-bit-aligned, plus 16-bit(!) */ +#define ipconfigPACKET_FILLER_SIZE 2 + +/* Define the size of the pool of TCP window descriptors. On the average, each +TCP socket will use up to 2 x 6 descriptors, meaning that it can have 2 x 6 +outstanding packets (for Rx and Tx). When using up to 10 TP sockets +simultaneously, one could define TCP_WIN_SEG_COUNT as 120. */ +#define ipconfigTCP_WIN_SEG_COUNT 240 + +/* Each TCP socket has a circular buffers for Rx and Tx, which have a fixed +maximum size. Define the size of Rx buffer for TCP sockets. */ +#define ipconfigTCP_RX_BUFFER_LENGTH ( 2000 ) + +/* Define the size of Tx buffer for TCP sockets. */ +#define ipconfigTCP_TX_BUFFER_LENGTH ( 2000 ) + +/* When using call-back handlers, the driver may check if the handler points to +real program memory (RAM or flash) or just has a random non-zero value. */ +#define ipconfigIS_VALID_PROG_ADDRESS(x) ( (x) != NULL ) + +/* Include support for TCP hang protection. All sockets in a connecting or +disconnecting stage will timeout after a period of non-activity. */ +#define ipconfigTCP_HANG_PROTECTION ( 1 ) +#define ipconfigTCP_HANG_PROTECTION_TIME ( 30 ) + +/* Include support for TCP keep-alive messages. */ +#define ipconfigTCP_KEEP_ALIVE ( 1 ) +#define ipconfigTCP_KEEP_ALIVE_INTERVAL ( 20 ) /* in seconds */ + +#define ipconfigETHERNET_DRIVER_FILTERS_FRAME_TYPES 1 +#define ipconfigDRIVER_INCLUDED_TX_IP_CHECKSUM 1 +#define ipconfigDRIVER_INCLUDED_RX_IP_CHECKSUM 1 +#define ipconfigZERO_COPY_RX_DRIVER 1 +#define ipconfigZERO_COPY_TX_DRIVER 1 +#define ipconfigUSE_LINKED_RX_MESSAGES 1 diff --git a/ext/aws/FreeRTOSIPConfig.h.in b/ext/aws/FreeRTOSIPConfig.h.in index 033f945017..bef1ec884a 100644 --- a/ext/aws/FreeRTOSIPConfig.h.in +++ b/ext/aws/FreeRTOSIPConfig.h.in @@ -28,286 +28,41 @@ #ifndef FREERTOS_IP_CONFIG_H #define FREERTOS_IP_CONFIG_H -/* Prototype for the function used to print out. In this case it prints to the -console before the network is connected then a UDP port after the network has -connected. */ -//extern void vLoggingPrintf( const char *pcFormatString, ... ); -extern void vPrintf(char const *format, ...); +#define ipconfigBYTE_ORDER pdFREERTOS_LITTLE_ENDIAN -/* Set to 1 to print out debug messages. If ipconfigHAS_DEBUG_PRINTF is set to -1 then FreeRTOS_debug_printf should be defined to the function used to print -out the debugging messages. */ -#define ipconfigHAS_DEBUG_PRINTF 0 -#if( ipconfigHAS_DEBUG_PRINTF == 1 ) - #define FreeRTOS_debug_printf(X) vLoggingPrintf X +/* A header file that overwrites with local project settings. */ +#if __has_include() +# include #endif -/* Set to 1 to print out non debugging messages, for example the output of the -FreeRTOS_netstat() command, and ping replies. If ipconfigHAS_PRINTF is set to 1 -then FreeRTOS_printf should be set to the function used to print out the -messages. */ -#define ipconfigHAS_PRINTF 0 -#if( ipconfigHAS_PRINTF == 1 ) - #define FreeRTOS_printf(X) vLoggingPrintf X +#ifndef ipconfigIP_TASK_STACK_SIZE_WORDS +#define ipconfigIP_TASK_STACK_SIZE_WORDS (configMINIMAL_STACK_SIZE * 4) #endif -/* Define the byte order of the target MCU (the MCU FreeRTOS+TCP is executing -on). Valid options are pdFREERTOS_BIG_ENDIAN and pdFREERTOS_LITTLE_ENDIAN. */ -#define ipconfigBYTE_ORDER pdFREERTOS_LITTLE_ENDIAN - -/* If the network card/driver includes checksum offloading (IP/TCP/UDP checksums) -then set ipconfigDRIVER_INCLUDED_RX_IP_CHECKSUM to 1 to prevent the software -stack repeating the checksum calculations. */ -#define ipconfigDRIVER_INCLUDED_RX_IP_CHECKSUM 1 -#define ipconfigDRIVER_INCLUDED_TX_IP_CHECKSUM 1 - -/* Several API's will block until the result is known, or the action has been -performed, for example FreeRTOS_send() and FreeRTOS_recv(). The timeouts can be -set per socket, using setsockopt(). If not set, the times below will be -used as defaults. */ -#define ipconfigSOCK_DEFAULT_RECEIVE_BLOCK_TIME ( 5000 ) -#define ipconfigSOCK_DEFAULT_SEND_BLOCK_TIME ( 5000 ) - -/* Include support for LLMNR: Link-local Multicast Name Resolution -(non-Microsoft) */ -#define ipconfigUSE_LLMNR ( 0 ) - -/* Include support for NBNS: NetBIOS Name Service (Microsoft) */ -#define ipconfigUSE_NBNS ( 0 ) - -/* Include support for DNS caching. For TCP, having a small DNS cache is very -useful. When a cache is present, ipconfigDNS_REQUEST_ATTEMPTS can be kept low -and also DNS may use small timeouts. If a DNS reply comes in after the DNS -socket has been destroyed, the result will be stored into the cache. The next -call to FreeRTOS_gethostbyname() will return immediately, without even creating -a socket. */ -#define ipconfigUSE_DNS_CACHE ( 1 ) -#define ipconfigDNS_CACHE_NAME_LENGTH ( 16 ) -#define ipconfigDNS_CACHE_ENTRIES ( 4 ) -#define ipconfigDNS_REQUEST_ATTEMPTS ( 2 ) - -/* The IP stack executes it its own task (although any application task can make -use of its services through the published sockets API). ipconfigUDP_TASK_PRIORITY -sets the priority of the task that executes the IP stack. The priority is a -standard FreeRTOS task priority so can take any value from 0 (the lowest -priority) to (configMAX_PRIORITIES - 1) (the highest priority). -configMAX_PRIORITIES is a standard FreeRTOS configuration parameter defined in -FreeRTOSConfig.h, not FreeRTOSIPConfig.h. Consideration needs to be given as to -the priority assigned to the task executing the IP stack relative to the -priority assigned to tasks that use the IP stack. */ -#define ipconfigIP_TASK_PRIORITY ( configMAX_PRIORITIES - 2 ) - -/* The size, in words (not bytes), of the stack allocated to the FreeRTOS+TCP -task. This setting is less important when the FreeRTOS Win32 simulator is used -as the Win32 simulator only stores a fixed amount of information on the task -stack. FreeRTOS includes optional stack overflow detection, see: -http://www.freertos.org/Stacks-and-stack-overflow-checking.html */ -#define ipconfigIP_TASK_STACK_SIZE_WORDS ( configMINIMAL_STACK_SIZE * 5 ) - -/* ipconfigRAND32() is called by the IP stack to generate random numbers for -things such as a DHCP transaction number or initial sequence number. Random -number generation is performed via this macro to allow applications to use their -own random number generation method. For example, it might be possible to -generate a random number by sampling noise on an analogue input. */ -extern UBaseType_t uxRand(void); -#define ipconfigRAND32() uxRand() - -/* If ipconfigUSE_NETWORK_EVENT_HOOK is set to 1 then FreeRTOS+TCP will call the -network event hook at the appropriate times. If ipconfigUSE_NETWORK_EVENT_HOOK -is not set to 1 then the network event hook will never be called. See -http://www.FreeRTOS.org/FreeRTOS-Plus/FreeRTOS_Plus_UDP/API/vApplicationIPNetworkEventHook.shtml -*/ -#define ipconfigUSE_NETWORK_EVENT_HOOK 1 - -/* Sockets have a send block time attribute. If FreeRTOS_sendto() is called but -a network buffer cannot be obtained then the calling task is held in the Blocked -state (so other tasks can continue to executed) until either a network buffer -becomes available or the send block time expires. If the send block time expires -then the send operation is aborted. The maximum allowable send block time is -capped to the value set by ipconfigMAX_SEND_BLOCK_TIME_TICKS. Capping the -maximum allowable send block time prevents prevents a deadlock occurring when -all the network buffers are in use and the tasks that process (and subsequently -free) the network buffers are themselves blocked waiting for a network buffer. -ipconfigMAX_SEND_BLOCK_TIME_TICKS is specified in RTOS ticks. A time in -milliseconds can be converted to a time in ticks by dividing the time in -milliseconds by portTICK_PERIOD_MS. */ -#define ipconfigUDP_MAX_SEND_BLOCK_TIME_TICKS ( 5000 / portTICK_PERIOD_MS ) - -/* If ipconfigUSE_DHCP is 1 then FreeRTOS+TCP will attempt to retrieve an IP -address, netmask, DNS server address and gateway address from a DHCP server. If -ipconfigUSE_DHCP is 0 then FreeRTOS+TCP will use a static IP address. The -stack will revert to using the static IP address even when ipconfigUSE_DHCP is -set to 1 if a valid configuration cannot be obtained from a DHCP server for any -reason. The static configuration used is that passed into the stack by the -FreeRTOS_IPInit() function call. */ -#define ipconfigUSE_DHCP 0 - -/* When ipconfigUSE_DHCP is set to 1, DHCP requests will be sent out at -increasing time intervals until either a reply is received from a DHCP server -and accepted, or the interval between transmissions reaches -ipconfigMAXIMUM_DISCOVER_TX_PERIOD. The IP stack will revert to using the -static IP address passed as a parameter to FreeRTOS_IPInit() if the -re-transmission time interval reaches ipconfigMAXIMUM_DISCOVER_TX_PERIOD without -a DHCP reply being received. */ -#define ipconfigMAXIMUM_DISCOVER_TX_PERIOD ( 120000 / portTICK_PERIOD_MS ) - -/* The ARP cache is a table that maps IP addresses to MAC addresses. The IP -stack can only send a UDP message to a remove IP address if it knowns the MAC -address associated with the IP address, or the MAC address of the router used to -contact the remote IP address. When a UDP message is received from a remote IP -address the MAC address and IP address are added to the ARP cache. When a UDP -message is sent to a remote IP address that does not already appear in the ARP -cache then the UDP message is replaced by a ARP message that solicits the -required MAC address information. ipconfigARP_CACHE_ENTRIES defines the maximum -number of entries that can exist in the ARP table at any one time. */ -#define ipconfigARP_CACHE_ENTRIES 6 - -/* ARP requests that do not result in an ARP response will be re-transmitted a -maximum of ipconfigMAX_ARP_RETRANSMISSIONS times before the ARP request is -aborted. */ -#define ipconfigMAX_ARP_RETRANSMISSIONS ( 5 ) - -/* ipconfigMAX_ARP_AGE defines the maximum time between an entry in the ARP -table being created or refreshed and the entry being removed because it is stale. -New ARP requests are sent for ARP cache entries that are nearing their maximum -age. ipconfigMAX_ARP_AGE is specified in tens of seconds, so a value of 150 is -equal to 1500 seconds (or 25 minutes). */ -#define ipconfigMAX_ARP_AGE 150 - -/* Implementing FreeRTOS_inet_addr() necessitates the use of string handling -routines, which are relatively large. To save code space the full -FreeRTOS_inet_addr() implementation is made optional, and a smaller and faster -alternative called FreeRTOS_inet_addr_quick() is provided. FreeRTOS_inet_addr() -takes an IP in decimal dot format (for example, "192.168.0.1") as its parameter. -FreeRTOS_inet_addr_quick() takes an IP address as four separate numerical octets -(for example, 192, 168, 0, 1) as its parameters. If -ipconfigINCLUDE_FULL_INET_ADDR is set to 1 then both FreeRTOS_inet_addr() and -FreeRTOS_indet_addr_quick() are available. If ipconfigINCLUDE_FULL_INET_ADDR is -not set to 1 then only FreeRTOS_indet_addr_quick() is available. */ -#define ipconfigINCLUDE_FULL_INET_ADDR 1 - -/* ipconfigNUM_NETWORK_BUFFER_DESCRIPTORS defines the total number of network buffer that -are available to the IP stack. The total number of network buffers is limited -to ensure the total amount of RAM that can be consumed by the IP stack is capped -to a pre-determinable value. */ -#define ipconfigNUM_NETWORK_BUFFER_DESCRIPTORS 60 - -/* A FreeRTOS queue is used to send events from application tasks to the IP -stack. ipconfigEVENT_QUEUE_LENGTH sets the maximum number of events that can -be queued for processing at any one time. The event queue must be a minimum of -5 greater than the total number of network buffers. */ -#define ipconfigEVENT_QUEUE_LENGTH ( ipconfigNUM_NETWORK_BUFFER_DESCRIPTORS + 5 ) - -/* The address of a socket is the combination of its IP address and its port -number. FreeRTOS_bind() is used to manually allocate a port number to a socket -(to 'bind' the socket to a port), but manual binding is not normally necessary -for client sockets (those sockets that initiate outgoing connections rather than -wait for incoming connections on a known port number). If -ipconfigALLOW_SOCKET_SEND_WITHOUT_BIND is set to 1 then calling -FreeRTOS_sendto() on a socket that has not yet been bound will result in the IP -stack automatically binding the socket to a port number from the range -socketAUTO_PORT_ALLOCATION_START_NUMBER to 0xffff. If -ipconfigALLOW_SOCKET_SEND_WITHOUT_BIND is set to 0 then calling FreeRTOS_sendto() -on a socket that has not yet been bound will result in the send operation being -aborted. */ -#define ipconfigALLOW_SOCKET_SEND_WITHOUT_BIND 1 - -/* Defines the Time To Live (TTL) values used in outgoing UDP packets. */ -#define ipconfigUDP_TIME_TO_LIVE 128 -#define ipconfigTCP_TIME_TO_LIVE 128 /* also defined in FreeRTOSIPConfigDefaults.h */ - -/* USE_TCP: Use TCP and all its features */ -#define ipconfigUSE_TCP ( 1 ) - -/* USE_WIN: Let TCP use windowing mechanism. */ -#define ipconfigUSE_TCP_WIN ( 1 ) - -/* The MTU is the maximum number of bytes the payload of a network frame can -contain. For normal Ethernet V2 frames the maximum MTU is 1500. Setting a -lower value can save RAM, depending on the buffer management scheme used. If -ipconfigCAN_FRAGMENT_OUTGOING_PACKETS is 1 then (ipconfigNETWORK_MTU - 28) must -be divisible by 8. */ -#define ipconfigNETWORK_MTU 1500 - -/* Set ipconfigUSE_DNS to 1 to include a basic DNS client/resolver. DNS is used -through the FreeRTOS_gethostbyname() API function. */ -#define ipconfigUSE_DNS 0 - -/* If ipconfigREPLY_TO_INCOMING_PINGS is set to 1 then the IP stack will -generate replies to incoming ICMP echo (ping) requests. */ -#define ipconfigREPLY_TO_INCOMING_PINGS 1 - -/* If ipconfigSUPPORT_OUTGOING_PINGS is set to 1 then the -FreeRTOS_SendPingRequest() API function is available. */ -#define ipconfigSUPPORT_OUTGOING_PINGS 0 - -/* If ipconfigSUPPORT_SELECT_FUNCTION is set to 1 then the FreeRTOS_select() -(and associated) API function is available. */ -#define ipconfigSUPPORT_SELECT_FUNCTION 1 - -/* If ipconfigFILTER_OUT_NON_ETHERNET_II_FRAMES is set to 1 then Ethernet frames -that are not in Ethernet II format will be dropped. This option is included for -potential future IP stack developments. */ -#define ipconfigFILTER_OUT_NON_ETHERNET_II_FRAMES 1 - -/* If ipconfigETHERNET_DRIVER_FILTERS_FRAME_TYPES is set to 1 then it is the -responsibility of the Ethernet interface to filter out packets that are of no -interest. If the Ethernet interface does not implement this functionality, then -set ipconfigETHERNET_DRIVER_FILTERS_FRAME_TYPES to 0 to have the IP stack -perform the filtering instead (it is much less efficient for the stack to do it -because the packet will already have been passed into the stack). If the -Ethernet driver does all the necessary filtering in hardware then software -filtering can be removed by using a value other than 1 or 0. */ -#define ipconfigETHERNET_DRIVER_FILTERS_FRAME_TYPES 1 - -/* The windows simulator cannot really simulate MAC interrupts, and needs to -block occasionally to allow other tasks to run. */ -#define configWINDOWS_MAC_INTERRUPT_SIMULATOR_DELAY ( 20 / portTICK_PERIOD_MS ) - -/* Advanced only: in order to access 32-bit fields in the IP packets with -32-bit memory instructions, all packets will be stored 32-bit-aligned, plus 16-bits. -This has to do with the contents of the IP-packets: all 32-bit fields are -32-bit-aligned, plus 16-bit(!) */ -#define ipconfigPACKET_FILLER_SIZE 2 - -/* Define the size of the pool of TCP window descriptors. On the average, each -TCP socket will use up to 2 x 6 descriptors, meaning that it can have 2 x 6 -outstanding packets (for Rx and Tx). When using up to 10 TP sockets -simultaneously, one could define TCP_WIN_SEG_COUNT as 120. */ -#define ipconfigTCP_WIN_SEG_COUNT 240 - -/* Each TCP socket has a circular buffers for Rx and Tx, which have a fixed -maximum size. Define the size of Rx buffer for TCP sockets. */ -#define ipconfigTCP_RX_BUFFER_LENGTH ( 2000 ) - -/* Define the size of Tx buffer for TCP sockets. */ -#define ipconfigTCP_TX_BUFFER_LENGTH ( 2000 ) - -/* When using call-back handlers, the driver may check if the handler points to -real program memory (RAM or flash) or just has a random non-zero value. */ -#define ipconfigIS_VALID_PROG_ADDRESS(x) ( (x) != NULL ) - -/* Include support for TCP hang protection. All sockets in a connecting or -disconnecting stage will timeout after a period of non-activity. */ -#define ipconfigTCP_HANG_PROTECTION ( 1 ) -#define ipconfigTCP_HANG_PROTECTION_TIME ( 30 ) - -/* Include support for TCP keep-alive messages. */ -#define ipconfigTCP_KEEP_ALIVE ( 1 ) -#define ipconfigTCP_KEEP_ALIVE_INTERVAL ( 20 ) /* in seconds */ - -#define portINLINE __inline +#ifndef ipconfigIP_TASK_PRIORITY +#define ipconfigIP_TASK_PRIORITY (configMAX_PRIORITIES - 2) +#endif -#define ipconfigETHERNET_DRIVER_FILTERS_FRAME_TYPES 1 -#define ipconfigDRIVER_INCLUDED_TX_IP_CHECKSUM 1 -#define ipconfigDRIVER_INCLUDED_RX_IP_CHECKSUM 1 -#define ipconfigZERO_COPY_RX_DRIVER 1 -#define ipconfigZERO_COPY_TX_DRIVER 1 -#define ipconfigUSE_LINKED_RX_MESSAGES 1 +%% if with_debug +#if defined(ipconfigHAS_PRINTF) && ipconfigHAS_PRINTF && !defined(FreeRTOS_printf) +#ifdef __cplusplus + extern "C" +#else + extern +#endif + void modm_freertos_printf(char const *fmt, ...); +# define FreeRTOS_printf(X) modm_freertos_printf(X) +#endif -/* A header file that overwrites with local project settings. */ -#if __has_include() -#include +#if defined(ipconfigHAS_DEBUG_PRINTF) && ipconfigHAS_DEBUG_PRINTF && !defined(FreeRTOS_debug_printf) +#ifdef __cplusplus + extern "C" +#else + extern +#endif + void modm_freertos_printf_debug(char const *fmt, ...); +# define FreeRTOS_debug_printf(X) modm_freertos_printf_debug(X) #endif +%% endif #endif // FREERTOS_IP_CONFIG_H diff --git a/ext/aws/freertos_tcp.md b/ext/aws/freertos_tcp.md new file mode 100644 index 0000000000..3600e69501 --- /dev/null +++ b/ext/aws/freertos_tcp.md @@ -0,0 +1,41 @@ +# FreeRTOS+TCP + +Amazon FreeRTOS+TCP is a scalable, open source and thread safe TCP/IP stack for +FreeRTOS. FreeRTOS+TCP's features and RAM footprint are fully scalable, making +it equally applicable to smaller lower throughput microcontrollers as larger +higher throughput microprocessors. + +This module provides the latest FreeRTOS+TCP LTS release integrated with modm: + +- `FreeRTOS_printf()` and `FreeRTOS_debug_printf()` forwarded to `modm:debug`. + + +## Configuration + +This module generates a `FreeRTOSIPConfig.h` config file for modm integration +with these overwritable settings: + +- `ipconfigIP_TASK_STACK_SIZE_WORDS` = `(configMINIMAL_STACK_SIZE * 4)` +- `ipconfigIP_TASK_PRIORITY` = `(configMAX_PRIORITIES - 2)` +- `FreeRTOS_printf(x)` = `MODM_LOG_INFO.printf(x)` +- `FreeRTOS_debug_printf(x)` = `MODM_LOG_DEBUG.printf(x)` + +All other config settings are unchanged by modm and are defaulted by FreeRTOS +itself, please refer to the [FreeRTOS+TCP Config documentation][config] to +understand what each of these do. + +To change a configuration setting, define a `` file, +which is included *before* the optional settings, so you can overwrite them +easily. + +An example `` file: + +```c +// Change IP task stack size +#define ipconfigIP_TASK_STACK_SIZE_WORDS 1024 +// Enable printing +#define ipconfigHAS_PRINTF 1 +#define ipconfigHAS_DEBUG_PRINTF 1 +``` + +[config]: https://www.freertos.org/FreeRTOS-Plus/FreeRTOS_Plus_TCP/TCP_IP_Configuration.html diff --git a/ext/aws/modm_port.cpp b/ext/aws/modm_port.cpp.in similarity index 79% rename from ext/aws/modm_port.cpp rename to ext/aws/modm_port.cpp.in index 8d1e8a98b2..f35f8fa8cc 100644 --- a/ext/aws/modm_port.cpp +++ b/ext/aws/modm_port.cpp.in @@ -64,3 +64,24 @@ void vPortFree(void *pv) traceFREE(pv, 0); } } + +%% if with_debug +#include + +extern "C" void modm_freertos_printf(char const *fmt, ...); +void modm_freertos_printf(char const *fmt, ...) +{ + va_list va; + va_start(va, fmt); + MODM_LOG_INFO.vprintf(fmt, va); + va_end(va); +} +extern "C" void modm_freertos_printf_debug(char const *fmt, ...); +void modm_freertos_printf_debug(char const *fmt, ...) +{ + va_list va; + va_start(va, fmt); + MODM_LOG_DEBUG.vprintf(fmt, va); + va_end(va); +} +%% endif diff --git a/ext/aws/module.lb b/ext/aws/module.lb index b9fd4a4602..5da6b250c2 100644 --- a/ext/aws/module.lb +++ b/ext/aws/module.lb @@ -36,27 +36,15 @@ This module implements TCP over Ethernet via the LAN8720A transceiver. class FreeRTOS_TCP(Module): def init(self, module): module.name = "tcp" - module.description = """ -# a:FreeRTOS-Plus-TCP - -This module defines a default FreeRTOS IP config. If you need to change a -configuration setting, then you can define a `FreeRTOSConfigIPLocal.h` file, which -is included *after* at the end of the config. You must therefore first `#undef` -the config macros, then redefine them with your options, for example: - -```c -#undef ipconfigUSE_DNS -#define ipconfigUSE_DNS 1 -``` -""" + module.description = FileReader("freertos_tcp.md") def prepare(self, module, options): module.add_submodule(FreeRTOS_TCP_LAN8720A()) - module.depends(":platform:heap") return True def build(self, env): env.outbasepath = "modm/ext" + env.substitutions = {"with_debug": env.has_module(":debug")} env.copy("freertos/FreeRTOS-Plus-TCP", "freertos_plus_tcp", ignore=env.ignore_files("portable")) env.copy("freertos/FreeRTOS-Plus-TCP/portable/BufferManagement/BufferAllocation_2.c", "freertos_plus_tcp/BufferAllocation_2.c") @@ -106,7 +94,8 @@ def build(env): core = env[":target"].get_driver("core")["type"] env.substitutions = { "core": core, - "frequency": env.get("frequency", 1000) + "frequency": env.get("frequency", 1000), + "with_debug": env.has_module(":debug") } path = core.replace("cortex-m", "ARM_CM").replace("+", "").replace("fd", "f").upper() path = path.replace("CM7F", "CM7/r0p1") # use subfolder for M7 @@ -114,7 +103,7 @@ def build(env): env.outbasepath = "modm/ext" # Copy our own modm-specific port - env.copy("modm_port.cpp", "freertos/modm_port.cpp") + env.template("modm_port.cpp.in", "freertos/modm_port.cpp") # Copy the entire source folder, minus portable folder and some files. env.copy("freertos/FreeRTOS/Source", "freertos", ignore=env.ignore_files("*.txt", "*.readme", "portable", "include"))