1
0
mirror of https://github.com/raspberrypi/pico-sdk.git synced 2025-08-07 17:02:52 +03:00

SDK 2.0.0 release

This commit is contained in:
graham sanderson
2024-08-08 06:02:04 -05:00
parent 45984e276f
commit efe2103f9b
933 changed files with 349909 additions and 66256 deletions

View File

@@ -48,10 +48,35 @@ void program::add_instruction(std::shared_ptr<instruction> inst) {
msg << "instruction requires 'side' to specify side set value for the instruction because non optional sideset was specified for the program at " << sideset.location;
throw syntax_error(inst->location, msg.str());
}
inst->pre_validate(*this);
instructions.push_back(inst);
}
using syntax_error = yy::parser::syntax_error;
using syntax_error = syntax_error;
void program::set_pio_version(const yy::location &l, int version) {
if (version < 0 || version > 1) {
throw syntax_error(l, "only PIO versions 0 (rp2040) and 1 (rp2350) are supported");
}
pio_version = version;
}
void program::set_clock_div(const yy::location &l, float clock_div) {
if (clock_div < 1.0f || clock_div >= 65536.0f) {
throw syntax_error(l, "clock divider must be between 1 and 65546");
}
clock_div_int = (uint16_t)clock_div;
if (clock_div_int == 0) {
clock_div_frac = 0;
} else {
clock_div_frac = (uint8_t)((clock_div - (float)clock_div_frac) * (1u << 8u));
}
}
void program::set_fifo_config(const yy::location &l, fifo_config config) {
fifo_loc = l;
fifo = config;
}
void program::add_symbol(std::shared_ptr<symbol> symbol) {
const auto &existing = pioasm->get_symbol(symbol->name, this);
@@ -115,6 +140,10 @@ int binary_operation::resolve(pio_assembler *pioasm, const program *program, con
return lvalue | rvalue;
case xor_:
return lvalue ^ rvalue;
case shl_:
return lvalue << rvalue;
case shr_:
return lvalue >> rvalue;
default:
throw syntax_error(location, "internal error");
}
@@ -150,6 +179,33 @@ void program::add_lang_opt(std::string lang, std::string name, std::string value
}
void program::finalize() {
if (mov_status.type != mov_status_type::unspecified) {
uint n = mov_status.n->resolve(*this);
if (mov_status.type == mov_status_type::irq_set) {
if (n > 7) throw syntax_error(mov_status.n->location, "irq number should be >= 0 and <= 7");
mov_status.final_n = mov_status.param * 8 + n;
} else {
if (n > 31) throw syntax_error(mov_status.n->location, "fido depth should be >= 0 and <= 31");
mov_status.final_n = n;
}
}
if (in.pin_count) {
in.final_pin_count = in.pin_count->resolve(*this);
if (!pio_version && in.final_pin_count != 32) throw syntax_error(in.pin_count->location, "in pin count must be 32 for PIO version 0");
if (in.final_pin_count < 1 || in.final_pin_count > 32) throw syntax_error(in.pin_count->location, "in pin count should be >= 1 and <= 32");
in.final_threshold = in.threshold->resolve(*this);
if (in.final_threshold < 1 || in.final_threshold > 32) throw syntax_error(in.threshold->location, "threshold should be >= 1 and <= 32");
}
if (out.pin_count) {
out.final_pin_count = out.pin_count->resolve(*this);
if (out.final_pin_count < 0 || out.final_pin_count > 32) throw syntax_error(out.pin_count->location, "out pin count should be >= 0 and <= 32");
out.final_threshold = out.threshold->resolve(*this);
if (out.final_threshold < 1 || out.final_threshold > 32) throw syntax_error(out.threshold->location, "threshold should be >= 1 and <= 32");
}
if (set_count.value) {
final_set_count = set_count.value->resolve(*this);
if (final_set_count < 0 || final_set_count > 5) throw syntax_error(set_count.location, "set pin count should be >= 0 and <= 5");
}
if (sideset.value) {
int bits = sideset.value->resolve(*this);
if (bits < 0) {
@@ -169,6 +225,13 @@ void program::finalize() {
sideset_max = 0;
delay_max = 31;
}
if (fifo != fifo_config::rx && fifo != fifo_config::tx && fifo != fifo_config::txrx) {
std::stringstream msg;
if (in.pin_count && in.autop) {
msg << "autopush is incompatible with your selected FIFO configuration specified at " << fifo_loc;
throw syntax_error(in.location, msg.str());
}
}
}
int name_ref::resolve(pio_assembler *pioasm, const program *program, const resolvable &scope) {
@@ -195,7 +258,7 @@ int name_ref::resolve(pio_assembler *pioasm, const program *program, const resol
}
}
uint instruction::encode(const program &program) {
uint instruction::encode(program &program) {
raw_encoding raw = raw_encode(program);
int _delay = delay->resolve(program);
if (_delay < 0) {
@@ -228,14 +291,15 @@ uint instruction::encode(const program &program) {
_sideset |= 0x10u;
}
}
return (((uint) raw.type) << 13u) | (((uint) _delay | (uint) _sideset) << 8u) | (raw.arg1 << 5u) | raw.arg2;
// note we store the 6th bit of arg2 above the 16 bits of instruction
return (((uint) raw.type) << 13u) | (((uint) _delay | (uint) _sideset) << 8u) | (raw.arg1 << 5u) | raw.arg2 | ((raw.arg2 >> 5) << 16);
}
raw_encoding instruction::raw_encode(const program &program) {
raw_encoding instruction::raw_encode(program& program) {
throw syntax_error(location, "internal error");
}
uint instr_word::encode(const program &program) {
uint instr_word::encode(program &program) {
uint value = encoding->resolve(program);
if (value > 0xffffu) {
throw syntax_error(location, ".word value must be a positive 16 bit value");
@@ -243,7 +307,55 @@ uint instr_word::encode(const program &program) {
return value;
}
raw_encoding instr_jmp::raw_encode(const program &program) {
uint instr_mov::get_push_get_index(const program &program, extended_mov index) {
if (index.loc == mov::fifo_y) {
return 0;
} else {
uint v = index.fifo_index->resolve(program);
if (v > 7) {
throw syntax_error(index.fifo_index->location, "FIFO index myst be between 0 and 7");
}
return v | 8;
}
}
void instr_push::pre_validate(program& program) {
if (program.fifo != fifo_config::rx && program.fifo != fifo_config::txrx) {
throw syntax_error(location, "FIFO must be configured for 'txrx' or 'rx' to use this instruction");
}
}
void instr_mov::pre_validate(program &program) {
if (dest.uses_fifo()) {
if (src.loc != mov::isr) {
throw syntax_error(location, "mov rxfifo[] source must be isr");
}
if (program.fifo != fifo_config::txput && program.fifo != fifo_config::putget) {
throw syntax_error(location, "FIFO must be configured for 'txput' or 'putget' to use this instruction");
}
} else if (src.uses_fifo()) {
if (dest.loc != mov::osr) {
throw syntax_error(location, "mov ,txfifo[] target must be osr");
}
if (program.fifo != fifo_config::txget && program.fifo != fifo_config::putget) {
throw syntax_error(location, "FIFO must be configured for 'txget' or 'putget' to use this instruction");
}
}
}
raw_encoding instr_mov::raw_encode(program& program) {
if (!dest.uses_fifo() && !src.uses_fifo()) {
// regular mov
return {inst_type::mov, (uint) dest.loc, (uint) src.loc | ((uint) op << 3u)};
}
if (dest.uses_fifo()) {
return {inst_type::push_pull, 0, 0x10 | get_push_get_index(program, dest) };
} else {
return {inst_type::push_pull, 0x4, 0x10 | get_push_get_index(program, src) };
}
}
raw_encoding instr_jmp::raw_encode(program& program) {
int dest = target->resolve(program);
if (dest < 0) {
throw syntax_error(target->location, "jmp target address must be positive");
@@ -255,7 +367,7 @@ raw_encoding instr_jmp::raw_encode(const program &program) {
return {inst_type::jmp, (uint) cond, (uint) dest};
}
raw_encoding instr_in::raw_encode(const program &program) {
raw_encoding instr_in::raw_encode(program& program) {
int v = value->resolve(program);
if (v < 1 || v > 32) {
throw syntax_error(value->location, "'in' bit count must be >= 1 and <= 32");
@@ -263,7 +375,7 @@ raw_encoding instr_in::raw_encode(const program &program) {
return {inst_type::in, (uint) src, (uint) v & 0x1fu};
}
raw_encoding instr_out::raw_encode(const program &program) {
raw_encoding instr_out::raw_encode(program& program) {
int v = value->resolve(program);
if (v < 1 || v > 32) {
throw syntax_error(value->location, "'out' bit count must be >= 1 and <= 32");
@@ -271,7 +383,7 @@ raw_encoding instr_out::raw_encode(const program &program) {
return {inst_type::out, (uint) dest, (uint) v & 0x1fu};
}
raw_encoding instr_set::raw_encode(const program &program) {
raw_encoding instr_set::raw_encode(program& program) {
int v = value->resolve(program);
if (v < 0 || v > 31) {
throw syntax_error(value->location, "'set' bit count must be >= 0 and <= 31");
@@ -279,7 +391,7 @@ raw_encoding instr_set::raw_encode(const program &program) {
return {inst_type::set, (uint) dest, (uint) v};
}
raw_encoding instr_wait::raw_encode(const program &program) {
raw_encoding instr_wait::raw_encode(program& program) {
uint pol = polarity->resolve(program);
if (pol > 1) {
throw syntax_error(polarity->location, "'wait' polarity must be 0 or 1");
@@ -289,21 +401,38 @@ raw_encoding instr_wait::raw_encode(const program &program) {
case wait_source::irq:
if (arg2 > 7) throw syntax_error(source->param->location, "irq number must be must be >= 0 and <= 7");
break;
case wait_source::gpio:
if (arg2 > 31)
throw syntax_error(source->param->location, "absolute GPIO number must be must be >= 0 and <= 31");
case wait_source::gpio: {
if (!program.pio_version) {
if (arg2 > 31)
throw syntax_error(source->param->location, "absolute GPIO number must be must be >= 0 and <= 31");
} else {
if (arg2 > 47)
throw syntax_error(source->param->location, "absolute GPIO number must be must be >= 0 and <= 47");
}
int bitmap = 1u << (arg2 >> 4);
if (bitmap == 4 && program.used_gpio_ranges & 1) {
throw syntax_error(source->param->location, "absolute GPIO number must be must be >= 0 and <= 31 as a GPIO number <16 has already been used");
}
if (bitmap == 1 && program.used_gpio_ranges & 4) {
throw syntax_error(source->param->location, "absolute GPIO number must be must be >= 16 and <= 47 as a GPIO number >32 has already been used");
}
program.used_gpio_ranges |= bitmap;
break;
}
case wait_source::pin:
if (arg2 > 31) throw syntax_error(polarity->location, "pin number must be must be >= 0 and <= 31");
if (arg2 > 31) throw syntax_error(source->param->location, "pin number must be must be >= 0 and <= 31");
break;
case wait_source::jmppin:
if (arg2 > 3) throw syntax_error(source->param->location, "jmppin offset must be must be >= 0 and <= 3");
break;
}
return {inst_type::wait, (pol << 2u) | (uint) source->target, arg2 | (source->flag ? 0x10u : 0u)};
return {inst_type::wait, (pol << 2u) | (uint) source->target, arg2 | (source->irq_type << 3)};
}
raw_encoding instr_irq::raw_encode(const program &program) {
raw_encoding instr_irq::raw_encode(program& program) {
uint arg2 = num->resolve(program);
if (arg2 > 7) throw syntax_error(num->location, "irq number must be must be >= 0 and <= 7");
if (relative) arg2 |= 0x10u;
arg2 |= irq_type << 3;
return {inst_type::irq, (uint)modifiers, arg2};
}
@@ -333,9 +462,9 @@ int pio_assembler::write_output() {
source.global_symbols = public_symbols(get_dummy_global_program());
for (auto &program : programs) {
program.finalize();
source.programs.emplace_back(compiled_source::program(program.name));
source.programs.emplace_back(program.name);
auto &cprogram = source.programs[source.programs.size() - 1];
cprogram = compiled_source::program(program.name);
cprogram.pio_version = program.pio_version;
// encode the instructions
std::transform(program.instructions.begin(), program.instructions.end(),
@@ -358,8 +487,32 @@ int pio_assembler::write_output() {
}
if (program.wrap) cprogram.wrap = program.wrap->resolve(program); else cprogram.wrap = std::max((int)program.instructions.size() - 1, 0);
if (program.wrap_target) cprogram.wrap_target = program.wrap_target->resolve(program); else cprogram.wrap_target = 0;
cprogram.clock_div_int = program.clock_div_int;
cprogram.clock_div_frac = program.clock_div_frac;
if (program.wrap_target) {
cprogram.wrap_target = program.wrap_target->resolve(program);
if (cprogram.wrap_target >= program.instructions.size()) {
throw syntax_error(program.wrap_target->location, ".wrap_target cannot be placed after the last program instruction");
}
} else {
cprogram.wrap_target = 0;
}
if (program.origin.value) cprogram.origin = program.origin.value->resolve(program);
cprogram.mov_status_type = program.mov_status.type == mov_status_type::unspecified ? -1 : (int)program.mov_status.type;
cprogram.mov_status_n = program.mov_status.final_n;
cprogram.fifo = program.fifo;
cprogram.used_gpio_ranges = program.used_gpio_ranges;
auto in_out_convert = [](const in_out &io) {
return compiled_source::in_out{
.pin_count = io.final_pin_count,
.right = io.right,
.autop = io.autop,
.threshold = io.final_threshold,
};
};
cprogram.in = in_out_convert(program.in);
cprogram.out = in_out_convert(program.out);
cprogram.set_count = program.final_set_count;
if (program.sideset.value) {
cprogram.sideset_bits_including_opt = program.sideset_bits_including_opt;
cprogram.sideset_opt = program.sideset_opt;