1 /* 2 * Copyright (c) 2020 Raspberry Pi (Trading) Ltd. 3 * 4 * SPDX-License-Identifier: BSD-3-Clause 5 */ 6 7 #include <algorithm> 8 #include <iostream> 9 #include "output_format.h" 10 #include "pio_disassembler.h" 11 12 struct c_sdk_output : public output_format { 13 struct factory { factoryc_sdk_output::factory14 factory() { 15 output_format::add(new c_sdk_output()); 16 } 17 }; 18 c_sdk_outputc_sdk_output19 c_sdk_output() : output_format("c-sdk") {} 20 get_descriptionc_sdk_output21 std::string get_description() override { 22 return "C header suitable for use with the Raspberry Pi Pico SDK"; 23 } 24 output_symbolsc_sdk_output25 void output_symbols(FILE *out, std::string prefix, const std::vector<compiled_source::symbol> &symbols) { 26 int count = 0; 27 for (const auto &s : symbols) { 28 if (!s.is_label) { 29 fprintf(out, "#define %s%s %d\n", prefix.c_str(), s.name.c_str(), s.value); 30 count++; 31 } 32 } 33 if (count) { 34 fprintf(out, "\n"); 35 count = 0; 36 } 37 for (const auto &s : symbols) { 38 if (s.is_label) { 39 fprintf(out, "#define %soffset_%s %du\n", prefix.c_str(), s.name.c_str(), s.value); 40 count++; 41 } 42 } 43 if (count) { 44 fprintf(out, "\n"); 45 } 46 } 47 headerc_sdk_output48 void header(FILE *out, std::string msg) { 49 std::string dashes = std::string(msg.length(), '-'); 50 fprintf(out, "// %s //\n", dashes.c_str()); 51 fprintf(out, "// %s //\n", msg.c_str()); 52 fprintf(out, "// %s //\n", dashes.c_str()); 53 fprintf(out, "\n"); 54 } 55 outputc_sdk_output56 int output(std::string destination, std::vector<std::string> output_options, 57 const compiled_source &source) override { 58 59 for (const auto &program : source.programs) { 60 for(const auto &p : program.lang_opts) { 61 if (p.first.size() >= name.size() && p.first.compare(0, name.size(), name) == 0) { 62 std::cerr << "warning: " << name << " does not support output options; " << p.first << " lang_opt ignored.\n"; 63 } 64 } 65 } 66 FILE *out = open_single_output(destination); 67 if (!out) return 1; 68 69 header(out, "This file is autogenerated by pioasm; do not edit!"); 70 71 fprintf(out, "#pragma once\n"); 72 fprintf(out, "\n"); 73 fprintf(out, "#if !PICO_NO_HARDWARE\n"); 74 fprintf(out, "#include \"hardware/pio.h\"\n"); 75 fprintf(out, "#endif\n"); 76 fprintf(out, "\n"); 77 78 output_symbols(out, "", source.global_symbols); 79 80 for (const auto &program : source.programs) { 81 header(out, program.name); 82 83 std::string prefix = program.name + "_"; 84 85 fprintf(out, "#define %swrap_target %d\n", prefix.c_str(), program.wrap_target); 86 fprintf(out, "#define %swrap %d\n", prefix.c_str(), program.wrap); 87 fprintf(out, "\n"); 88 89 output_symbols(out, prefix, program.symbols); 90 91 fprintf(out, "static const uint16_t %sprogram_instructions[] = {\n", prefix.c_str()); 92 for (int i = 0; i < (int)program.instructions.size(); i++) { 93 const auto &inst = program.instructions[i]; 94 if (i == program.wrap_target) { 95 fprintf(out, " // .wrap_target\n"); 96 } 97 fprintf(out, " 0x%04x, // %2d: %s\n", inst, i, 98 disassemble(inst, program.sideset_bits_including_opt.get(), program.sideset_opt).c_str()); 99 if (i == program.wrap) { 100 fprintf(out, " // .wrap\n"); 101 } 102 } 103 fprintf(out, "};\n"); 104 fprintf(out, "\n"); 105 106 fprintf(out, "#if !PICO_NO_HARDWARE\n"); 107 fprintf(out, "static const struct pio_program %sprogram = {\n", prefix.c_str()); 108 fprintf(out, " .instructions = %sprogram_instructions,\n", prefix.c_str()); 109 fprintf(out, " .length = %d,\n", (int) program.instructions.size()); 110 fprintf(out, " .origin = %d,\n", program.origin.get()); 111 fprintf(out, "};\n"); 112 fprintf(out, "\n"); 113 fprintf(out, "static inline pio_sm_config %sprogram_get_default_config(uint offset) {\n", prefix.c_str()); 114 fprintf(out, " pio_sm_config c = pio_get_default_sm_config();\n"); 115 fprintf(out, " sm_config_set_wrap(&c, offset + %swrap_target, offset + %swrap);\n", prefix.c_str(), 116 prefix.c_str()); 117 if (program.sideset_bits_including_opt.is_specified()) { 118 fprintf(out, " sm_config_set_sideset(&c, %d, %s, %s);\n", program.sideset_bits_including_opt.get(), 119 program.sideset_opt ? "true" : "false", 120 program.sideset_pindirs ? "true" : "false"); 121 } 122 fprintf(out, " return c;\n"); 123 fprintf(out, "}\n"); 124 125 // todo maybe have some code blocks inside or outside here? 126 for(const auto& o : program.code_blocks) { 127 fprintf(out, "\n"); 128 if (o.first == name) { 129 for(const auto &contents : o.second) { 130 fprintf(out, "%s", contents.c_str()); 131 fprintf(out, "\n"); 132 } 133 } 134 } 135 136 fprintf(out, "#endif\n"); 137 fprintf(out, "\n"); 138 } 139 if (out != stdout) { fclose(out); } 140 return 0; 141 } 142 }; 143 144 static c_sdk_output::factory creator; 145