Forum Discussion
Altera_Forum
Honored Contributor
11 years agoSPI from HPS through FPGA not working
Hello,
Since 6 month i am working with SOC Cyclone V Evalboard from Altera. I use Yocto to build linux and EDS V 14.0 for development. For Knowledge and HowTo my first place is Rocketboards, but i also use Searchengines to find answers ;) With the Evalboard i use I2C, SPI and GPIOs(all from HPS) as interface to other devices like display, port expander, leds, gpios,... without problems. Now i want to route the spi pins from the hps to the fpga.- 'exported' the pins in qsys.
- routed the exported pins to the leds in quartus
- Create all needed files. preloader, u-boot, dtb
6 Replies
- Altera_Forum
Honored Contributor
Hi all
I found my problem. Remember to initialize this pin to '1' in the FPGA, if using Motorola SPI frame format ('0' for TI SSP):
Now it works! Best regards Brianhps_0_spim0_ss_in_n => '1'- JJohn
New Contributor
Thank you so much for letting us know to tie this signal off. Had been struggling to get SPI Master working.
- Altera_Forum
Honored Contributor
I have the same problem = (SPI can not transfer data (TFE in SR is cleared and no more changes) I think that it is related with clocking, but I doubt, because the controller makes changes in registers, and hence clocked all okay.
I2С through FPGA working fine. - Altera_Forum
Honored Contributor
All works.
root@socfpga:~# ./mem 0xfff00008 data = 0x00000001 root@socfpga:~# ./mem 0xfff00008 0 ;disable root@socfpga:~# ./mem 0xfff00010 1 ;cs 0 root@socfpga:~# ./mem 0xfff00014 100 ; clock &per_base_clk / 100 root@socfpga:~# ./mem 0xfff00000 0xcf ; cpol cpha 16-bit root@socfpga:~# ./mem 0xfff00008 1 ; enable root@socfpga:~# ./mem 0xfff00060 ;read data = 0x00000000 root@socfpga:~# ./mem 0xfff00060 256 ;write root@socfpga:~# ./mem 0xfff00028 ;status data = 0x0000000e ; RX not empty... root@socfpga:~# ./mem 0xfff00024 ;rx data count data = 0x00000001 root@socfpga:~# ./mem 0xfff00060 ;read data = 0x0000040a In QSYS SPI clock 100MHz ... .hps_0_spim0_txd (temp_mosi), //mosi hps_0_spim0.txd .hps_0_spim0_rxd (temp_miso), //miso .rxd .hps_0_spim0_ss_in_n (), // .ss_in_n .hps_0_spim0_ssi_oe_n (), // .ssi_oe_n .hps_0_spim0_ss_0_n (temp_cs_n), // .ss_0_n .hps_0_spim0_ss_1_n (), // .ss_1_n .hps_0_spim0_ss_2_n (), // .ss_2_n .hps_0_spim0_ss_3_n (), //sck .ss_3_n .hps_0_spim0_sclk_out_clk (spi_sck) /**/ ); /**/ wire spi_sck; assign temp_sclk=spi_sck & hps_fpga_reset_n; hps_0_spim0: spi@0xfff00000 { compatible = "snps,dw-spi-mmio-14.1", "snps,dw-spi-mmio"; reg = < 0xFFF00000 0x00000100 >; interrupt-parent = < &hps_0_arm_gic_0 >; interrupts = < 0 154 4 >; # address-cells = < 1 >; /* embeddedsw.dts.params.#address-cells type NUMBER */ # size-cells = < 0 >; /* embeddedsw.dts.params.#size-cells type NUMBER */ bus-num = < 0 >; /* embeddedsw.dts.params.bus-num type NUMBER */ num-chipselect = < 1 >; /* embeddedsw.dts.params.num-chipselect type NUMBER */ status = "okay"; /* embeddedsw.dts.params.status type STRING */ clocks = < &per_base_clk >; /* appended from boardinfo */ spidev0: spidev@0 { compatible = "spidev"; /* appended from boardinfo */ reg = < 4293918720 >; /* appended from boardinfo */ spi-max-frequency = < 100000000 >; /* appended from boardinfo */ enable-dma = < 1 >; /* appended from boardinfo */ }; //end spidev@0 (spidev0) }; //end spi@0xfff00000 (hps_0_spim0) - Altera_Forum
Honored Contributor
akaspar, how you send data to spi?
- Altera_Forum
Honored Contributor
Hi ask
I have the same issue as you described in this thread. How did you manage to get it to work? I'm not using Linux but uCos, but I still can't make the SPI controller start transmitting data. It just puts the data into the FIFO buffer. I have verified that my pin mapping is correct: - CS pin can be toggled (Can be set low by SPI controller or by PIO CS pin, both works) - SS pin can be toggled (selecting SPI mode 0 or 3). I can break in my code and using the debugger I can select another SPI frameformat (TI instead of Motorola). After this "trick" I can write data into the DR register and data gets transmitted (until SPI driver is disabled/enabled again). Here is my init function:
Here is my write function:ALT_STATUS_CODE FramDriver_Init(ALT_SPI_CTLR_t eAltSPIModNum){ static uint8_t u8RunOnce = 1; ALT_STATUS_CODE eAltStatusCode = ALT_E_SUCCESS; ALT_SPI_CONFIG_t cfg = { .frame_size = ALT_SPI_DFS_8BIT, .frame_format = ALT_SPI_FRF_SPI, .clk_phase = ALT_SPI_SCPH_TOGGLE_START, .clk_polarity = ALT_SPI_SCPOL_INACTIVE_HIGH, .transfer_mode = ALT_SPI_TMOD_TXRX, .loopback_mode = false, .slave_output_enable = true }; // Make sure CS pin is high before initializing SPI peripheral. Is also pulled up externally... SET_CS_PIN_HIGH; if (1 == u8RunOnce) { u8RunOnce = 0; eAltStatusCode = alt_spi_init(eAltSPIModNum, &stAltSPIdevice); } eAltStatusCode = alt_spi_disable(&stAltSPIdevice); if (eAltStatusCode == ALT_E_SUCCESS) { eAltStatusCode = alt_spi_config_set(&stAltSPIdevice, &cfg); } if (eAltStatusCode == ALT_E_SUCCESS) { eAltStatusCode = alt_spi_speed_set(&stAltSPIdevice, SPI_SPEED); } if (eAltStatusCode == ALT_E_SUCCESS) { eAltStatusCode = alt_spi_slave_select_enable(&stAltSPIdevice, SPI_SLAVE_DEVICE); } if (eAltStatusCode == ALT_E_SUCCESS) { eAltStatusCode = alt_spi_enable(&stAltSPIdevice); } return eAltStatusCode; }
I have read all manuals for HPS and Cyclone V regarding SPI and TX should start if the following conditions are met: --- Quote Start --- The SPI master starts data transfers when all the following conditions are met: • The SPI master is enabled • There is at least one valid entry in the transmit FIFO buffer • A slave device is selected --- Quote End --- I can see all three conditions in my SPI status registers, but still no output. Any help would be appreciated! Best regards Brian P.S. I tried the command sequence above from u-boot, but I can't make it write out data...ALT_STATUS_CODE FramDriverReadStatusRegister(uint8_t *uip8Status){ ALT_STATUS_CODE eAltStatusCode = ALT_E_SUCCESS; const uint16_t au16TxOpCodeBuffer = {(uint16_t)OP_CODE_RDSR, 0x0000}; uint16_t au16RxBuffer = {0x0000, 0x0000}; // Check if SPI is initialized! if (0 == stAltSPIdevice.location) { // SPI is not initialized -> Return BAD_OPERATION return ALT_E_BAD_OPERATION; } // Handle CS pin manually!!! SET_CS_PIN_LOW; // Debug alt_spi_int_clear(&stAltSPIdevice, ALT_SPI_STATUS_TXEI); alt_spi_int_clear(&stAltSPIdevice, ALT_SPI_STATUS_RXUI); alt_spi_int_clear(&stAltSPIdevice, ALT_SPI_STATUS_ALL); // Write Op Code for Read Status register (OP_CODE_RDSR) eAltStatusCode = alt_spi_tx_fifo_enq(&stAltSPIdevice, au16TxOpCodeBuffer); // Wait for FIFO to be empty while(ALT_E_TRUE != alt_spi_tx_fifo_is_empty(&stAltSPIdevice)); // Wait for transfer to complete! -> Poll busy flag! while (ALT_E_TRUE == alt_spi_is_busy(&stAltSPIdevice)); // Read back Status Register from device (Size is specified to 1 byte) eAltStatusCode = alt_spi_rx_fifo_deq(&stAltSPIdevice, au16RxBuffer); // Return status register in uip8Status *uip8Status = (uint8_t) (au16RxBuffer & 0x00FF); // Handle CS pin manually!!! SET_CS_PIN_HIGH; return eAltStatusCode; }