[feat] add pio_rmii_tx instance
This commit is contained in:
parent
60ce3bbf6d
commit
d0eeb2b47e
@ -28,6 +28,9 @@ target_sources(${PROJ_NAME}.elf PUBLIC start.S)
|
|||||||
add_subdirectory(${BASE_DIR}/driver driver)
|
add_subdirectory(${BASE_DIR}/driver driver)
|
||||||
target_link_libraries(${PROJ_NAME}.elf 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)
|
add_subdirectory(${BASE_DIR}/CMSIS)
|
||||||
target_link_libraries(${PROJ_NAME}.elf cmsis)
|
target_link_libraries(${PROJ_NAME}.elf cmsis)
|
||||||
|
|
||||||
|
|||||||
9
component/CMakeLists.txt
Normal file
9
component/CMakeLists.txt
Normal 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
1
component/component.c
Normal file
@ -0,0 +1 @@
|
|||||||
|
|
||||||
10
component/pio_instance/CMakeLists.txt
Normal file
10
component/pio_instance/CMakeLists.txt
Normal 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)
|
||||||
25
component/pio_instance/inc/pio_rmii_tx.h
Normal file
25
component/pio_instance/inc/pio_rmii_tx.h
Normal 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__ */
|
||||||
86
component/pio_instance/src/pio_rmii_tx.c
Normal file
86
component/pio_instance/src/pio_rmii_tx.c
Normal 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++]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
Loading…
Reference in New Issue
Block a user