[feat] add pio_rmii_tx instance

This commit is contained in:
zhji 2025-03-15 16:19:50 +08:00
parent 60ce3bbf6d
commit d0eeb2b47e
6 changed files with 134 additions and 0 deletions

View File

@ -28,6 +28,9 @@ target_sources(${PROJ_NAME}.elf PUBLIC start.S)
add_subdirectory(${BASE_DIR}/driver driver)
target_link_libraries(${PROJ_NAME}.elf driver)
add_subdirectory(${BASE_DIR}/component component)
target_link_libraries(${PROJ_NAME}.elf component)
add_subdirectory(${BASE_DIR}/CMSIS)
target_link_libraries(${PROJ_NAME}.elf cmsis)

9
component/CMakeLists.txt Normal file
View File

@ -0,0 +1,9 @@
file(GLOB FILELIST
component.c
)
set(TARGET component)
add_library(${TARGET} STATIC ${FILELIST})
add_subdirectory(${CMAKE_CURRENT_LIST_DIR}/pio_instance pio_instance)
target_link_libraries(${TARGET} pio_instance)

1
component/component.c Normal file
View File

@ -0,0 +1 @@

View File

@ -0,0 +1,10 @@
file(GLOB FILELIST
src/pio_rmii_tx.c
)
set(TARGET pio_instance)
add_library(${TARGET} STATIC ${FILELIST})
target_include_directories(${TARGET} PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}/inc)
target_include_directories(${TARGET} PUBLIC ${BASE_DIR}/driver/inc)
target_include_directories(${TARGET} PUBLIC ${BASE_DIR}/driver/inc/reg)

View File

@ -0,0 +1,25 @@
#ifndef __HARDWARE_PIO_RMII_TX_H__
#define __HARDWARE_PIO_RMII_TX_H__
#include "pio.h"
struct pio_rmii_tx_s {
uint16_t clkdiv;
uint8_t sm;
uint8_t addr;
uint8_t flag;
uint8_t pin; /* increase order of pin CLK-EN-D0-D1 */
};
#ifdef __cplusplus
extern "C" {
#endif
void pio_rmii_tx_init(struct pio_rmii_tx_s *cfg);
void pio_rmii_write(struct pio_rmii_tx_s *rmii, uint32_t *data, uint32_t length);
#ifdef __cplusplus
}
#endif
#endif /* __HARDWARE_PIO_RMII_TX_H__ */

View File

@ -0,0 +1,86 @@
#include "pio_rmii_tx.h"
void pio_rmii_tx_init(struct pio_rmii_tx_s *rmii)
{
struct pio_cfg_s cfg;
uint32_t pio = PIO0_BASE + (PIO1_BASE - PIO0_BASE) * (rmii->sm / PIO_SM_COUNT);
uint8_t sm = rmii->sm % PIO_SM_COUNT;
uint8_t addr = rmii->addr;
cfg.pio_base = pio; /* pio register address base */
cfg.clkdiv_int = rmii->clkdiv; /* clock divisor of integer part, 1~65535 is available, 0 present 65536 divisor */
cfg.clkdiv_frac = 0; /* clock divisor of fractional part, (div_frac/256) is actual value */
cfg.sm = sm; /* state machine identification, 0~3 is available */
cfg.fifo_join = PIO_FIFO_RX_JOIN_TX; /* tx/ tx fifo join type */
cfg.wrap_bottom = 0; /* ater reaching wrap_top, execution is wrapped to this address */
cfg.wrap_top = 14; /* after reaching this address, execution is wrapped to wrap_bottom */
cfg.mov_status_sel_rx = 0; /* comparison used for the 'MOV x, STATUS' instruction */
cfg.mov_status_level = 0; /* comparison level for the 'MOV x, STATUS' instruction */
cfg.thresh_bits_pull = 32; /* number of bits shifted out of TXSR before autopull or conditional pull, 1~31, 0 present 32 */
cfg.thresh_bits_push = 0; /* number of bits shifted into RXSR before autopush or conditional push, 1~31, 0 present 32 */
cfg.out_dir_to_right = 1; /* shift OSR direction */
cfg.in_dir_to_right = 0; /* shift ISR direction */
cfg.auto_pull = 1; /* pull automatically when the output shift register is emptied */
cfg.auto_push = 0; /* push automatically when the input shift register is filled */
cfg.out_sticky = 0; /* continuously assert the most recent OUT/SET to the pins */
cfg.inline_outen = 0; /* whether use a bit of OUT data as an auxiliary write enable */
cfg.outen_sel = 0; /* which data bit to use for inline OUT enable */
cfg.side_optional = 0; /* allow instructions to perform sideset optionally, rather than on every instruction */
cfg.side_dest_pindir = 0; /* side data is asserted to pin OEs or pin values */
cfg.pin_side_count = 2; /* the number of delay bits co-opted for side-set, inclusive of the enable bit, if present */
cfg.pin_side_base = rmii->pin + 0; /* the virtual pin corresponding to SIDESET bit 0, not PIO_PIN_XXX, is absolute pin index */
cfg.pin_set_count = 4; /* the number of pins asserted by a SET, max of 5 */
cfg.pin_set_base = rmii->pin + 0; /* the virtual pin corresponding to SET bit 0, not PIO_PIN_XXX, is absolute pin index */
cfg.pin_out_count = 2; /* the number of pins asserted by an OUT, value of 1 to 31 pins, 0 present 32 */
cfg.pin_out_base = rmii->pin + 2; /* the virtual pin corresponding to OUT bit 0 , not PIO_PIN_XXX, is absolute pin index*/
cfg.pin_in_base = 0; /* the virtual pin corresponding to IN bit 0, not PIO_PIN_XXX, is absolute pin index */
cfg.pin_jmp = 0; /* the pin index to use as condition for 'JMP PIN' instruction */
pio_init(&cfg);
/* wait data from user */
pio_instr_place(pio, addr + 0, pio_instr_JMP(PIO_INSTR_JMP_COND_OSR_NEMPTY, addr + 2, pio_instr_side(0, 0, 2)));
pio_instr_place(pio, addr + 1, pio_instr_JMP(PIO_INSTR_JMP_COND_ALWAYS, addr + 0, pio_instr_side(1, 0, 2)));
/* only 6 byte preamble need auto send, 6 * 8 / 2 - 1 = 23 */
pio_instr_place(pio, addr + 2, pio_instr_SET(PIO_INSTR_SET_DEST_X, 23, pio_instr_side(1, 0, 2)));
/* preamble */
pio_instr_place(pio, addr + 3, pio_instr_SET(PIO_INSTR_SET_DEST_PINS, 0b0110, pio_instr_side(2, 0, 2)));
pio_instr_place(pio, addr + 4, pio_instr_JMP(PIO_INSTR_JMP_COND_X_WITH_DEC, addr + 3, pio_instr_side(3, 0, 2)));
/* output 2 bits data every clock */
pio_instr_place(pio, addr + 5, pio_instr_OUT(PIO_INSTR_OUT_DEST_PINS, 2, pio_instr_side(2, 0, 2)));
pio_instr_place(pio, addr + 6, pio_instr_JMP(PIO_INSTR_JMP_COND_OSR_NEMPTY, addr + 5, pio_instr_side(3, 0, 2)));
/* force data pin to low level when idle */
pio_instr_place(pio, addr + 7, pio_instr_SET(PIO_INSTR_SET_DEST_PINS, 0, pio_instr_side(0, 0, 2)));
/* inter packet gap, 0.96us */
pio_instr_place(pio, addr + 8, pio_instr_SET(PIO_INSTR_SET_DEST_X, 2, pio_instr_side(1, 0, 2)));
pio_instr_place(pio, addr + 9, pio_instr_SET(PIO_INSTR_SET_DEST_Y, 22, pio_instr_side(0, 0, 2)));
pio_instr_place(pio, addr + 10, pio_instr_MOV(PIO_INSTR_MOV_DEST_Y, PIO_INSTR_MOV_SRC_Y, PIO_INSTR_MOV_OP_NONE, pio_instr_side(1, 0, 2))); /* nop */
pio_instr_place(pio, addr + 11, pio_instr_JMP(PIO_INSTR_JMP_COND_Y_WITH_DEC, addr + 10, pio_instr_side(0, 0, 2)));
pio_instr_place(pio, addr + 12, pio_instr_JMP(PIO_INSTR_JMP_COND_X_WITH_DEC, addr + 9, pio_instr_side(1, 0, 2)));
/* packet complete because of empty TX_FIFO, set a flag to inform user */
pio_instr_place(pio, addr + 13, pio_instr_IRQ(PIO_INSTR_IRQ_OP_RAISE, PIO_INSTR_IRQ_WAIT_DISABLE, rmii->flag, pio_instr_side(0, 0, 2)));
pio_instr_place(pio, addr + 14, pio_instr_JMP(PIO_INSTR_JMP_COND_ALWAYS, addr + 0, pio_instr_side(1, 0, 2)));
pio_instr_insert(pio, sm, pio_instr_SET(PIO_INSTR_SET_DEST_PINDIRS, 0xF, pio_instr_side(0, 0, 2)));
while (!pio_instr_is_complete(pio, sm));
pio_instr_insert(pio, sm, pio_instr_JMP(PIO_INSTR_JMP_COND_ALWAYS, addr + 0, pio_instr_side(0, 0, 2)));
while (!pio_instr_is_complete(pio, sm));
pio_enable(pio, sm);
}
void pio_rmii_write(struct pio_rmii_tx_s *rmii, uint32_t *data, uint32_t length)
{
uint32_t pio, idx, status;
uint8_t sm;
pio = PIO0_BASE + (PIO1_BASE - PIO0_BASE) * (rmii->sm / PIO_SM_COUNT);
sm = rmii->sm % PIO_SM_COUNT;
idx = 0;
while (idx < length) {
status = pio_fifo_get_status(pio, sm);
status &= (PIO_FIFO_STATUS_SM0_TX_FULL << sm);
if (!status) {
pio_fifo_write(pio, sm, data[idx++]);
}
}
}