diff --git a/.github/workflows/c-arduino-tests.yml b/.github/workflows/c-arduino-tests.yml index a4a3a63f5f..aab59621a5 100644 --- a/.github/workflows/c-arduino-tests.yml +++ b/.github/workflows/c-arduino-tests.yml @@ -57,5 +57,6 @@ jobs: arduino-cli core install arduino:megaavr arduino-cli core install arduino:samd arduino-cli core install arduino:sam + arduino-cli core install arduino:mbed - name: Perform Arduino tests for C target with default scheduler run: ./gradlew test --tests org.lflang.tests.runtime.CArduinoTest.runArduinoTests \ No newline at end of file diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index f565fc9082..b11e6cba91 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -70,7 +70,7 @@ jobs: # Run the C Arduino integration tests. c-arduino-tests: - uses: lf-lang/lingua-franca/.github/workflows/c-arduino-tests.yml@master + uses: lf-lang/lingua-franca/.github/workflows/c-arduino-tests.yml@arduino-mbed-support needs: cancel # Run the C Zephyr integration tests. diff --git a/org.lflang/src/lib/c/reactor-c b/org.lflang/src/lib/c/reactor-c index 2ec5deff12..7b8b74a515 160000 --- a/org.lflang/src/lib/c/reactor-c +++ b/org.lflang/src/lib/c/reactor-c @@ -1 +1 @@ -Subproject commit 2ec5deff12daf66ce106892083443fc85385d035 +Subproject commit 7b8b74a5151984dd2d11610c081a1cbf5e7d1536 diff --git a/org.lflang/src/org/lflang/federated/extensions/CExtension.java b/org.lflang/src/org/lflang/federated/extensions/CExtension.java index 1d6d2dea0e..579aff2ca1 100644 --- a/org.lflang/src/org/lflang/federated/extensions/CExtension.java +++ b/org.lflang/src/org/lflang/federated/extensions/CExtension.java @@ -611,7 +611,7 @@ private String generateCodeToInitializeFederate(FederateInstance federate, Linke code.pr(String.join("\n", "// Initialize the socket mutex", "lf_mutex_init(&outbound_socket_mutex);", - "lf_cond_init(&port_status_changed);" + "lf_cond_init(&port_status_changed, &mutex);" )); // Find the STA (A.K.A. the global STP offset) for this federate. diff --git a/org.lflang/src/org/lflang/generator/c/CGenerator.java b/org.lflang/src/org/lflang/generator/c/CGenerator.java index a344a8c5a4..64e42062af 100644 --- a/org.lflang/src/org/lflang/generator/c/CGenerator.java +++ b/org.lflang/src/org/lflang/generator/c/CGenerator.java @@ -537,7 +537,7 @@ public void doGenerate(Resource resource, LFGeneratorContext context) { } } else { try { - FileUtil.arduinoDeleteHelper(fileConfig.getSrcGenPath().resolve("src/")); + FileUtil.arduinoDeleteHelper(fileConfig.getSrcGenPath().resolve("src/"), targetConfig.threading); FileUtil.relativeIncludeHelper(fileConfig.getSrcGenPath().resolve("src/")); } catch (IOException e) { //noinspection ThrowableNotThrown,ResultOfMethodCallIgnored @@ -1913,11 +1913,10 @@ protected void setUpGeneralParameters() { // So that each separate compile knows about modal reactors, do this: targetConfig.compileDefinitions.put("MODAL_REACTORS", "TRUE"); } - if (targetConfig.threading && targetConfig.platformOptions.platform == Platform.ARDUINO) { - //Add error message when user attempts to set threading=true for Arduino - if (targetConfig.setByUser.contains(TargetProperty.THREADING)) { - System.out.println("Threading is incompatible on Arduino. Setting threading to false."); - } + if (targetConfig.threading && targetConfig.platformOptions.platform == Platform.ARDUINO + && (targetConfig.platformOptions.board == null || !targetConfig.platformOptions.board.contains("mbed"))) { + //non-MBED boards should not use threading + System.out.println("Threading is incompatible on your current Arduino flavor. Setting threading to false."); targetConfig.threading = false; } diff --git a/org.lflang/src/org/lflang/generator/c/CPreambleGenerator.java b/org.lflang/src/org/lflang/generator/c/CPreambleGenerator.java index 45e48f7d9c..891cf36d0c 100644 --- a/org.lflang/src/org/lflang/generator/c/CPreambleGenerator.java +++ b/org.lflang/src/org/lflang/generator/c/CPreambleGenerator.java @@ -80,12 +80,6 @@ public static String generateDefineDirectives( code.pr("#define LOG_LEVEL " + logLevel); code.pr("#define TARGET_FILES_DIRECTORY " + addDoubleQuotes(srcGenPath.toString())); - - if (targetConfig.platformOptions.platform == Platform.ARDUINO) { - code.pr("#define MICROSECOND_TIME"); - code.pr("#define BIT_32"); - } - if (tracing != null) { targetConfig.compileDefinitions.put("LF_TRACE", tracing.traceFileName); } diff --git a/org.lflang/src/org/lflang/util/ArduinoUtil.java b/org.lflang/src/org/lflang/util/ArduinoUtil.java index 5ead7e196d..85eac8ae8f 100644 --- a/org.lflang/src/org/lflang/util/ArduinoUtil.java +++ b/org.lflang/src/org/lflang/util/ArduinoUtil.java @@ -66,9 +66,10 @@ private LFCommand arduinoCompileCommand(FileConfig fileConfig, TargetConfig targ var fileWriter = new FileWriter(testScript.getAbsoluteFile(), true); BufferedWriter bufferedWriter = new BufferedWriter(fileWriter); String board = targetConfig.platformOptions.board != null ? targetConfig.platformOptions.board : "arduino:avr:leonardo"; + String isThreaded = targetConfig.platformOptions.board.contains("mbed") ? "-DLF_THREADED" : "-DLF_UNTHREADED"; bufferedWriter.write("arduino-cli compile -b " + board + " --build-property " + - "compiler.c.extra_flags=\"-DLF_UNTHREADED -DPLATFORM_ARDUINO -DINITIAL_EVENT_QUEUE_SIZE=10 -DINITIAL_REACT_QUEUE_SIZE=10\" " + - "--build-property compiler.cpp.extra_flags=\"-DLF_UNTHREADED -DPLATFORM_ARDUINO -DINITIAL_EVENT_QUEUE_SIZE=10 -DINITIAL_REACT_QUEUE_SIZE=10\" " + "compiler.c.extra_flags=\"" + isThreaded + " -DPLATFORM_ARDUINO -DINITIAL_EVENT_QUEUE_SIZE=10 -DINITIAL_REACT_QUEUE_SIZE=10\" " + + "--build-property compiler.cpp.extra_flags=\"" + isThreaded + " -DPLATFORM_ARDUINO -DINITIAL_EVENT_QUEUE_SIZE=10 -DINITIAL_REACT_QUEUE_SIZE=10\" " + srcGenPath.toString()); bufferedWriter.close(); return commandFactory.createCommand( diff --git a/org.lflang/src/org/lflang/util/FileUtil.java b/org.lflang/src/org/lflang/util/FileUtil.java index 84b3eab429..61fa3d8816 100644 --- a/org.lflang/src/org/lflang/util/FileUtil.java +++ b/org.lflang/src/org/lflang/util/FileUtil.java @@ -394,20 +394,22 @@ private static boolean copyDirectoryFromJar(JarURLConnection connection, final P * @param dir The folder to search for folders and files to delete. * @throws IOException If the given folder and unneeded files cannot be deleted. */ - public static void arduinoDeleteHelper(Path dir) throws IOException { + public static void arduinoDeleteHelper(Path dir, boolean threadingOn) throws IOException { deleteDirectory(dir.resolve("core/federated")); // TODO: Add Federated Support to Arduino deleteDirectory(dir.resolve("include/core/federated")); // TODO: Add Federated Support to Arduino - deleteDirectory(dir.resolve("core/threaded")); // No Threaded Support for Arduino - deleteDirectory(dir.resolve("include/core/threaded")); // No Threaded Support for Arduino + if (!threadingOn) { + deleteDirectory(dir.resolve("core/threaded")); // No Threaded Support for Arduino + deleteDirectory(dir.resolve("include/core/threaded")); // No Threaded Support for Arduino + deleteDirectory(dir.resolve("core/platform/arduino_mbed")); // No Threaded Support for Arduino + } List allPaths = Files.walk(dir) .sorted(Comparator.reverseOrder()) .collect(Collectors.toList()); for (Path path : allPaths) { String toCheck = path.toString().toLowerCase(); - if (toCheck.contains("cmake") || toCheck.contains("semaphore") - || (toCheck.contains("core/platform/") && !toCheck.contains("lf_arduino"))) { + if (toCheck.contains("cmake")) { Files.delete(path); } } @@ -444,7 +446,7 @@ private static String fileNameMatchConverter(String fileName, Path currPath, Map */ public static boolean isCFile(Path path) { String fileName = path.getFileName().toString(); - return fileName.endsWith(".c") || fileName.endsWith(".h"); + return fileName.endsWith(".c") || fileName.endsWith(".cpp") || fileName.endsWith(".h"); } /** diff --git a/test/C/src/arduino/BlinkMBED.lf b/test/C/src/arduino/BlinkMBED.lf new file mode 100644 index 0000000000..f9702d27cc --- /dev/null +++ b/test/C/src/arduino/BlinkMBED.lf @@ -0,0 +1,22 @@ +/** + * This example demonstrates a very simple blink program that will turn on and + * off an LED on the Arduino Board with a 50% duty cycle switching every + * half-second. + */ +target C { + platform: { + name: "arduino", + board: "arduino:mbed:nano33ble" + } +} + +main reactor BlinkMBED { + timer t1(0, 1 sec) + timer t2(500 msec, 1 sec) + + reaction(startup) {= pinMode(LED_BUILTIN, OUTPUT); =} + + reaction(t1) {= digitalWrite(LED_BUILTIN, HIGH); =} + + reaction(t2) {= digitalWrite(LED_BUILTIN, LOW); =} +}