10#include "system_rp2040.h"
12using namespace _PIO0_;
13using namespace _PIO1_;
19function<void()> pio_rp2040::_handler_pio0[12] = {
nullptr };
20function<void()> pio_rp2040::_handler_pio1[12] = {
nullptr };
27 SM_EXECCTRL.WRAP_TOP = 0x1f;
29 SM_SHIFTCTRL.OUT_SHIFTDIR = 1;
30 SM_SHIFTCTRL.IN_SHIFTDIR = 1;
32 SM_PINCTRL.SET_COUNT = 5;
35void SM::setRegister(out_dest_t reg, uint32_t val,
36 uint8_t offset, uint8_t size) {
38 bool en = isEnabled();
40 uint8_t out_base = regs.SM_PINCTRL.OUT_BASE;
41 uint8_t out_count = regs.SM_PINCTRL.OUT_COUNT;
43 regs.SM_PINCTRL.OUT_BASE = offset;
44 regs.SM_PINCTRL.OUT_COUNT = size;
46 while(pio.FLEVEL & (0xf << (sm_index << 3))) {
47 execute( op_PULL(0, 0) );
52 execute( op_PULL(0, 0) );
53 execute( op_OUT (0, reg, 0) );
55 regs.SM_PINCTRL.OUT_BASE = out_base;
56 regs.SM_PINCTRL.OUT_COUNT = out_count;
60void SM::setClock(uint32_t hz) {
61 regs.SM_CLKDIV.INT = CLK_SYS / hz;
62 uint64_t frac = ((CLK_SYS % hz) << 8);
64 regs.SM_CLKDIV.FRAC = frac;
67void SM::attachIrq(function<
void()> handler) {
69 pio_rp2040::_handler_pio1[sm_index + 8] = handler;
71 pio_rp2040::_handler_pio0[sm_index + 8] = handler;
75 pio_set.IRQ0_INTE = 1 << (sm_index + 8);
78void SM::disableIrq() {
79 pio_clr.IRQ0_INTE = 1 << (sm_index + 8);
82void SM::attachTXNFULLIrq(function<
void()> handler) {
84 pio_rp2040::_handler_pio1[sm_index + 4] = handler;
86 pio_rp2040::_handler_pio0[sm_index + 4] = handler;
89void SM::enableTXNFULLIrq() {
90 pio_set.IRQ0_INTE = 1 << (sm_index + 4);
93void SM::disableTXNFULLIrq() {
94 pio_clr.IRQ0_INTE = 1 << (sm_index + 4);
97void SM::attachRXNEMPTYIrq(function<
void()> handler) {
99 pio_rp2040::_handler_pio1[sm_index + 0] = handler;
101 pio_rp2040::_handler_pio0[sm_index + 0] = handler;
104void SM::enableRXNEMPTYIrq() {
105 pio_set.IRQ0_INTE = 1 << (sm_index);
108void SM::disableRXNEMPTYIrq() {
109 pio_clr.IRQ0_INTE = 1 << (sm_index);
112pio_rp2040::pio_rp2040(
PIO0_t & pio, uint8_t pio_index)
114 _pio_xor(*(
PIO0_t *)((uint8_t *)&pio + 0x1000)),
115 _pio_set(*(
PIO0_t *)((uint8_t *)&pio + 0x2000)),
116 _pio_clr(*(
PIO0_t *)((uint8_t *)&pio + 0x3000)),
117 _pio_index(pio_index),
120 _sm_regbanks = (
SM_regs *)&pio.SM0_CLKDIV;
122 _pio.CTRL.SM_ENABLE = 0x0;
123 _pio.CTRL.SM_RESTART = 0xf;
125 for(
int i=0; i < 32; ++i) {
126 _pio.INSTR_MEM[i] = 0;
129 for(
int i=0; i < 4; ++i) {
133 NVIC_EnableIRQ(PIO0_IRQ_0_IRQn);
134 NVIC_EnableIRQ(PIO1_IRQ_0_IRQn);
137pio_rp2040::~pio_rp2040() {
139 _pio.CTRL.SM_ENABLE = 0x0;
145 for(sm_index=0; sm_index < 4; ++sm_index) {
146 if (!_in_use[sm_index])
break;
148 assert(sm_index < 4);
150 _in_use[sm_index] =
true;
152 uint8_t load_at_addr = 0;
153 if (prgm.origin == -1) {
155 load_at_addr = _next_free_addr;
158 assert(prgm.origin >= _next_free_addr);
159 load_at_addr = prgm.origin;
162 assert((load_at_addr + prgm.length) <= 32);
164 for(
int i=0; i < prgm.length; i++) {
165 uint16_t inst = prgm.instructions[i];
167 if (is_JMP(inst) && (prgm.origin == -1)) {
168 inst += load_at_addr;
170 _pio.INSTR_MEM[i + load_at_addr] = inst;
173 SM* sm =
new SM(_pio, _pio_set, _pio_clr, _pio_index, sm_index,
174 load_at_addr, _sm_regbanks[sm_index]);
176 sm->setRegister(out_dest_t::PC, load_at_addr);
178 _next_free_addr += load_at_addr + prgm.length;
184 void PIO0_IRQ_0_Handler(
void) {
185 uint32_t status = PIO0.IRQ0_INTS;
186 while (uint8_t pos = __builtin_ffs(status)) {
187 status ^= 1 << --pos;
189 PIO0.IRQ = 1 << (pos - 8);
191 if (pio_rp2040::_handler_pio0[pos])
192 pio_rp2040::_handler_pio0[pos]();
196 void PIO1_IRQ_0_Handler(
void) {
197 uint32_t status = PIO1.IRQ0_INTS;
198 while (uint8_t pos = __builtin_ffs(status)) {
199 status ^= 1 << --pos;
201 PIO1.IRQ = 1 << (pos - 8);
203 if (pio_rp2040::_handler_pio1[pos])
204 pio_rp2040::_handler_pio1[pos]();