-
Notifications
You must be signed in to change notification settings - Fork 1
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Tinker Board as SPI slave #1
Comments
Thanks for that request, |
I can do that but can You give some adivce? From datasheet http://www.t-firefly.com/download/firefly-rk3288/docs/TRM/rk3288-chapter-42-serial-peripheral-interface-(spi).pdf I read that i need to change |
Well. After hours of reading datasheet I make conclustion. I have to make something like this void tinkerboard_spi_slave_init(enum SPIController controller, struct spi_mode_config_t mode_config) {
int32_t pin = _spi_configs[controller].clk;
_set_config(_rk3288_gpio_block_base + ALIGN(_gpio_header_pins[pin].grf_bank_offset),
_gpio_header_pins[pin].grf_pin_offset, 1, _gpio_header_pins[pin].grf_config_size);
_gpio_header_pins[pin].mode = SPI;
printf("Pin %d", &pin);
pin = _spi_configs[controller].txd;
_set_config(_rk3288_gpio_block_base + ALIGN(_gpio_header_pins[pin].grf_bank_offset),
_gpio_header_pins[pin].grf_pin_offset, 1, _gpio_header_pins[pin].grf_config_size);
_gpio_header_pins[pin].mode = SPI;
printf("Pin %d", &pin);
pin = _spi_configs[controller].rxd;
_set_config(_rk3288_gpio_block_base + ALIGN(_gpio_header_pins[pin].grf_bank_offset),
_gpio_header_pins[pin].grf_pin_offset, 1, _gpio_header_pins[pin].grf_config_size);
_gpio_header_pins[pin].mode = SPI;
printf("Pin %d", &pin);
_spi_internals[controller].cs_pin = mode_config.slave_select;
tinkerboard_set_gpio_mode(_spi_internals[controller].cs_pin, INPUT);
tinkerboard_set_gpio_pud(_spi_internals[controller].cs_pin, PULLUP);
uint32_t config = 0;
config |= 1 << 20;
config |= mode_config.data_frame_size << CR0_DFS_OFFSET;
config |= mode_config.clk_mode << CR0_SCPH_OFFSET;
config |= mode_config.byte_order << CR0_FBM_OFFSET;
config |= 1 << CR0_BHT_OFFSET;
config |= mode_config.transfer_mode << CR0_XFM_OFFSET;
_spi_set_ctrlr0(controller, config);
_spi_set_fifo_size(controller , 31);
_spi_enable_controller(controller, 1);
_spi_internals[controller].fifo_len = 31;
_spi_configs[controller].initialized = 1;
} This is my init function. I use build in transfer function. I dont know if my clock function is set for slave. Can You plase help me a bit? |
Great that you already had a look into it.
The naive approach should be totally possible by just unmasking the interrupts and checking for them. About the DMA, I saw the register for activating it but did no further research on how to use and configure them. About your question about the clock speed. I assume that as long as the internal clockspeed for the controller is high enough it will adjust to the clk signal of the master. I set the divider in a way that 66.7MHz are possible so even if there is an additional division by 2 it is still way fast enough to read the data from a Raspberry Pi on max speed. |
I hope my explanation helped you a bit finding your way into this topic. It might be difficult but should be totally possible. And it would be really cool if this feature can be added. |
Thanks for tips. I would like to know what uint32_t pin = _spi_configs[controller].clk;
_set_config(_rk3288_gpio_block_base + ALIGN(_gpio_header_pins[pin].grf_bank_offset),
_gpio_header_pins[pin].grf_pin_offset, 1, _gpio_header_pins[pin].grf_config_size);
_gpio_header_pins[pin].mode = SPI; From your tips it looks like i have to:
As a CPU resources it wont be a problem and it have to be SPI. Any request from you will be helpful. |
And how I can recive Data from FIFO? |
Now i have problem. My code dont work's on line before load |
The _set_config function sets the pin function by configuring the IOMUX. Because almost every pin can have several functions you need to set which component is finally using the pin. And here is the first thing what could be wrong. You need to set one (and I would start with CS0) of the chip select pins using this function. The register for that is GPIO8A[7] which you can find in the documentation of the GRF. But the value to set it to the SPI function is 1 just as it is for the .clk, .rxd and .txd. So this code should do it: uint32_t pin = _spi_configs[controller].cs0;
_set_config(_rk3288_gpio_block_base + ALIGN(_gpio_header_pins[pin].grf_bank_offset),
_gpio_header_pins[pin].grf_pin_offset, 1, _gpio_header_pins[pin].grf_config_size); Reading and writing data from and to the FIFOs is done via the RXDR and TXDR registers. About the interrupt handling. This is maybe the most tricky part. First I would try if after unmasking the interrupts in SPI_ISR gets set after writing data to the slave. After that I would try to figure out how to use the DMA and then how Interrupt handling can be realized. |
i finally set all to spi slave but now i get errors when i try to send and recive files. My buffers are stuck and use this function. void tinkerboard_spi_transfer(enum SPIController controller, uint8_t* tx_buff, uint8_t* rx_buff, uint32_t length, struct spi_mode_config_t mode_config) {
_spi_enable_controller(controller, 1);
unsigned long remain = 0;
_spi_internals[controller].tx = tx_buff;
_spi_internals[controller].tx_end = tx_buff + length;
_spi_internals[controller].rx = rx_buff;
_spi_internals[controller].rx_end = rx_buff + length;
// Check if slave select is used
if(_spi_internals[controller].cs_pin != NO_SS) {
tinkerboard_set_gpio_state(_spi_internals[controller].cs_pin, LOW);
}
do {
if(_spi_internals[controller].tx) {
remain = _spi_internals[controller].tx_end - _spi_internals[controller].tx;
_spi_send(controller, mode_config);
}
if(_spi_internals[controller].rx) {
remain = _spi_internals[controller].rx_end - _spi_internals[controller].rx;
_spi_receive(controller, mode_config);
}
} while (remain);
// If spi controller is still busy keep waiting and eventually timing out
if(_spi_internals[controller].tx) {
_spi_wait_for_idle(controller);
}
// Check if slave select is used
if(_spi_internals[controller].cs_pin != NO_SS) {
tinkerboard_set_gpio_state(_spi_internals[controller].cs_pin, HIGH);
}
_spi_enable_controller(controller, 0);
} Can you help me with this matter? |
So i get to the point where i need to set interrupt on chip CS(or on whatever chip) and read data baiscly. But the biggest problem is how to set PIN interrupt. |
and from my logic it should work like this
The main problem is how to set interrrupt and how to get data as slave. This buffer |
Normally the CS when in slave mode should be handled by the hardware. The driver then works with the status registers to know when new data is available. The interrupt I was talking about should be raised when the buffers are empty. Like this you will have the most amount of free CPU cycles by utilizing the available hardware. |
@MackoLysy how is it going, could you make some progress on the SPI slave topic? |
Hello, after I configured SPI slave mode, the BUSY bit of the SR register remains BUSY, even if I fail to SPI. |
@MackoLysy could you make some progress on the SPI slave topic? |
Is a possible to set Tinker Board as slave via your library?
The text was updated successfully, but these errors were encountered: