17#include "pio_rp2350.h"
18#include "system_rp2350.h"
20using namespace _PIO0_;
21using namespace _PIO1_;
22using namespace _PIO2_;
23using namespace _RESETS_;
30function<void()> pio_rp2350::_handler_pio0[16] = {
nullptr };
31function<void()> pio_rp2350::_handler_pio1[16] = {
nullptr };
32function<void()> pio_rp2350::_handler_pio2[16] = {
nullptr };
39 SM_EXECCTRL.WRAP_TOP = 0x1f;
41 SM_SHIFTCTRL.OUT_SHIFTDIR = 1;
42 SM_SHIFTCTRL.IN_SHIFTDIR = 1;
44 SM_PINCTRL.SET_COUNT = 5;
47void SM::setRegister(out_dest_t reg, uint32_t val,
48 uint8_t offset, uint8_t size) {
50 bool en = isEnabled();
52 uint8_t out_base = regs.SM_PINCTRL.OUT_BASE;
53 uint8_t out_count = regs.SM_PINCTRL.OUT_COUNT;
55 regs.SM_PINCTRL.OUT_BASE = offset;
56 regs.SM_PINCTRL.OUT_COUNT = size;
58 while(pio.FLEVEL & (0xf << (sm_index << 3))) {
59 execute( op_PULL(0, 0) );
63 pio.TXF[sm_index] = val;
64 execute( op_PULL(0, 0) );
65 execute( op_OUT (0, reg, 0) );
67 regs.SM_PINCTRL.OUT_BASE = out_base;
68 regs.SM_PINCTRL.OUT_COUNT = out_count;
72void SM::setClock(uint32_t hz) {
73 regs.SM_CLKDIV.INT = CLK_SYS / hz;
74 uint64_t frac = ((CLK_SYS % hz) << 8);
77 regs.SM_CLKDIV.FRAC = frac;
80void SM::attachIrq(
const function<
void()>& handler)
const {
83 pio_rp2350::_handler_pio0[sm_index + 8] = handler;
86 pio_rp2350::_handler_pio1[sm_index + 8] = handler;
89 pio_rp2350::_handler_pio2[sm_index + 8] = handler;
95 pio_set.IRQ0_INTE = 1 << (sm_index + 8);
98void SM::disableIrq() {
99 pio_clr.IRQ0_INTE = 1 << (sm_index + 8);
102void SM::attachTXNFULLIrq(
const function<
void()>& handler)
const {
104 pio_rp2350::_handler_pio1[sm_index + 4] = handler;
106 pio_rp2350::_handler_pio0[sm_index + 4] = handler;
109void SM::enableTXNFULLIrq() {
110 pio_set.IRQ0_INTE = 1 << (sm_index + 4);
113void SM::disableTXNFULLIrq() {
114 pio_clr.IRQ0_INTE = 1 << (sm_index + 4);
117void SM::attachRXNEMPTYIrq(
const function<
void()>& handler)
const {
119 pio_rp2350::_handler_pio1[sm_index + 0] = handler;
121 pio_rp2350::_handler_pio0[sm_index + 0] = handler;
124void SM::enableRXNEMPTYIrq() {
125 pio_set.IRQ0_INTE = 1 << (sm_index);
128void SM::disableRXNEMPTYIrq() {
129 pio_clr.IRQ0_INTE = 1 << (sm_index);
132pio_rp2350::pio_rp2350(
PIO0_t & pio, uint8_t pio_index)
134 _pio_xor(*(
PIO0_t *)((uint8_t *)&pio + 0x1000)),
135 _pio_set(*(
PIO0_t *)((uint8_t *)&pio + 0x2000)),
136 _pio_clr(*(
PIO0_t *)((uint8_t *)&pio + 0x3000)),
137 _pio_index(pio_index),
142 RESETS_CLR.RESET.PIO0 <<= 1;
143 }
else if (&pio == &PIO1) {
144 RESETS_CLR.RESET.PIO1 <<= 1;
145 }
else if (&pio == &PIO2) {
146 RESETS_CLR.RESET.PIO2 <<= 1;
152 _sm_regbanks = (
SM_regs *)&pio.SM0_CLKDIV;
154 _pio.CTRL.SM_ENABLE = 0x0;
155 _pio.CTRL.SM_RESTART = 0xf;
157 for(
auto & mem : _pio.INSTR_MEM) {
161 NVIC_EnableIRQ(PIO0_IRQ_0_IRQn);
162 NVIC_EnableIRQ(PIO1_IRQ_0_IRQn);
163 NVIC_EnableIRQ(PIO2_IRQ_0_IRQn);
166pio_rp2350::~pio_rp2350() {
168 _pio.CTRL.SM_ENABLE = 0x0;
174 for(sm_index=0; sm_index < 4; ++sm_index) {
175 if (!_in_use[sm_index])
break;
177 assert(sm_index < 4);
179 _in_use[sm_index] =
true;
181 uint8_t load_at_addr;
182 if (prgm.origin == -1) {
184 load_at_addr = _next_free_addr;
187 assert(prgm.origin >= _next_free_addr);
188 load_at_addr = prgm.origin;
191 assert((load_at_addr + prgm.length) <= 32);
193 for(
int i=0; i < prgm.length; i++) {
194 uint16_t inst = prgm.instructions[i];
196 if (is_JMP(inst) && (prgm.origin == -1)) {
197 inst += load_at_addr;
199 _pio.INSTR_MEM[i + load_at_addr] = inst;
202 SM* sm =
new SM(_pio, _pio_set, _pio_clr, _pio_index, sm_index,
203 load_at_addr, _sm_regbanks[sm_index]);
205 sm->setRegister(out_dest_t::PC, load_at_addr);
207 _next_free_addr += load_at_addr + prgm.length;
213 void PIO0_IRQ_0_Handler(
void) {
214 uint32_t status = PIO0.IRQ0_INTS;
215 while (uint8_t pos = __builtin_ffs((
int)status)) {
216 status ^= 1 << --pos;
218 PIO0.IRQ = 1 << (pos - 8);
220 if (pio_rp2350::_handler_pio0[pos])
221 pio_rp2350::_handler_pio0[pos]();
225 void PIO1_IRQ_0_Handler(
void) {
226 uint32_t status = PIO1.IRQ0_INTS;
227 while (uint8_t pos = __builtin_ffs((
int)status)) {
228 status ^= 1 << --pos;
230 PIO1.IRQ = 1 << (pos - 8);
232 if (pio_rp2350::_handler_pio1[pos])
233 pio_rp2350::_handler_pio1[pos]();
237 void PIO2_IRQ_0_Handler(
void) {
238 uint32_t status = PIO2.IRQ0_INTS;
239 while (uint8_t pos = __builtin_ffs((
int)status)) {
240 status ^= 1 << --pos;
242 PIO2.IRQ = 1 << (pos - 8);
244 if (pio_rp2350::_handler_pio2[pos])
245 pio_rp2350::_handler_pio2[pos]();