Coordination for all stm32h7 porting efforts
Hi,
It seems that several people are interested in getting stm32h7 to work better, specifically spi, and i2c.
Several issues and pull requests have been opened for this purpose: https://github.com/libopencm3/libopencm3/issues/1455 Arduino Portenta h7 additions https://github.com/libopencm3/libopencm3/issues/1392 Working stm32H7 spi ? https://github.com/libopencm3/libopencm3/pull/1452 Enable required files to ensure successful build of a "stm32h7" only lib https://github.com/libopencm3/libopencm3/pull/1456 stm32: When setting baudrate of a USART, first get the clock frequency for that USART.
The important point is the code architecture: libopencm3 has files that offer functions common to all or a subrange of the stm32 chips, and files that are specific to a family. I dont have enough expertise to determine how the split should be really done.
My questions are -is the stm32h7 using a specific v3 spi block different from other platforms? or can we reuse spiv2 -what functions can be kept in the common files and what functions have to be put in a separate file?
The same questions are valid for i2c, which is an equally important communication block.
Since we are several people interested in this I assume some collaboration is possible.
calling @bm16ton @roman65536 and @ventZI, who seem to be the most advanced on this question.
Oh wow thank you for responding to my previous issue/post its appreciated! The spi v3 is a beast, fifo based, which is fine but the errata makes it difficult. Having to disable spi after every transaction, set the t-size etc re-enable etc is where i think im going wrong. Setting the tsize to unlimited should work around that but i havent gotten that to work either. Its very possible i hhave sum stupidlysimple thing set wrong and im beating the wrong horses on it. Unfortunatly i dont think spi v3 shares much with the previous v2. I hhavent done much testing but i2c v2 seems to be working but alas ive always had issues with i2c v2 so well see once i gget more miles on it. Also on my list to tackle is dma. With 2 dma muxes sum work will be required but i do think (based of a very quick look) that the current code for dmamux (or at least parts) will be reusable so thats nice. When i started i thought usbhs was gonna be my biggest hurdle but that took 15min, but spi is my problem child facepalm. I did find sum potential issues and even tho its not working ill throw a logic analyzer on it hopefuly later today and see if its actually transmitting anything now. The qspi flash isnt working for either but i hhavent throw much effort at it yet. So yeah even tho im way underqualified to do so im gonna focus on spi and dma for now. Fingers crossed. Be nice if those of us working on the h7 had a central place to communicate and share, combine code without spamming the issues area lol. Again thank you for the response!
Issues are fine for discussing code :) Communication is more efficient when it is not dispatched in several places. (note: I wont go to any discord)
funny you say that i finally broke down and decided to try it, went to install it in playstore and all the artwork/design reminded me if a 5th grade class room and i said no and stopped. I like gist but it seems all libopencm3 conversations have stopped. Being a guy who combined a couple arduino sketches then jumped to libopen has been tuff. Resources have been slim. My current method for anything new/unsupported has been go bare metal get it working.Then replace everything i can with whats already in libopen, then add functions for whats left over. Big hurdles for on old redneck learning new tricks, but very rewarding
On Thu, 12 Jan 2023, 10:12 am slorquet, @.***> wrote:
Issues are fine for discussing code :) Communication is more efficient when it is not dispatched in several places. (note: I wont go to any discord)
— Reply to this email directly, view it on GitHub https://github.com/libopencm3/libopencm3/issues/1457#issuecomment-1380537359, or unsubscribe https://github.com/notifications/unsubscribe-auth/ADAWMPYR3Z56S7O5YVFCO2LWSANM7ANCNFSM6AAAAAATZKZBFA . You are receiving this because you were mentioned.Message ID: @.***>
@bm16ton Have a working qspi if you are interested. But is outside libopencm3 structure/tree (since I was interested trying out mapping and later on read/write/erase using ext2 fs) and once it worked, I didn't bother to put it to libopencm3. However qspi very depends on the qspi device, resp. qspi device capabilities (instruction in 1bit/4bit mode, address length 16,24,32 bit, address mode 1,4 bit etc).
I would be interested in working USB MSC on H7 :)
rgds Roman
Omg! yes please i would very much like to see/use that code. Ive been working on spi mostly. I had tested my spi device on tge pins im using and it worked before my attempts in libopen 2days later i test it again....dead. God only knows when it died or how many of my attempts may have worked lol. I digress yes please that would be great. Glad were all coming together on this
On Thu, 12 Jan 2023, 3:50 pm Roman Pollak, @.***> wrote:
@bm16ton https://github.com/bm16ton Have a working qspi if you are interested. But is outside libopencm3 structure/tree (since I was interested trying out mapping and later on read/write/erase using ext2 fs) and once it worked, I didn't bother to put it to libopencm3. However qspi very depends on the qspi device, resp. qspi device capabilities (instruction in 1bit/4bit mode, address length 16,24,32 bit, address mode 1,4 bit etc).
rgds Roman
— Reply to this email directly, view it on GitHub https://github.com/libopencm3/libopencm3/issues/1457#issuecomment-1380979128, or unsubscribe https://github.com/notifications/unsubscribe-auth/ADAWMP3OORKJ6K3JAT7OM3TWSBU77ANCNFSM6AAAAAATZKZBFA . You are receiving this because you were mentioned.Message ID: @.***>
needed to write to the rtc's backup registers for bootloader. All the registers i needed etc matched up. If i find time tonight ill check the rest its possible that it would be a very quick ez port. Sidenote my H7 is ulpi usbhs only, I need to check how many usb endpoints the usbfs the various h7s have. Ive found what looks like a static 4 in places representing the amount of endpoints. But my f413zh has 6. If the h7's have more as well itll make any fix i come up with go a diff way.
@bm16ton here we go : I use "W25Q64" device, so to see what is going on, you need the datasheet. I used this :https://www.pjrc.com/store/w25q64fv.pdf
In quad_map() is inline more explanation how and why to setup h7's qspi registers.
@slorquet feel free to integrate it (somehow) to libopencm3 if you like. I know, I did it the quick and dirty way, this could be implemented much better and universaly where you could somehow define the flash instructions for enable qspi, read qspi, write qspi, erase etc.
And sorry for just copy pasting it here.
rgds Roman
void quad_setup(void) { /* the usual enable and setup pins for qspi */ rcc_periph_clock_enable(RCC_QSPI); rcc_periph_reset_pulse(RST_QSPI); gpio_mode_setup(GPIOD, GPIO_MODE_AF, GPIO_PUPD_NONE, GPIO11| GPIO12| GPIO13 ); gpio_set_output_options(GPIOD, GPIO_OTYPE_PP, GPIO_OSPEED_100MHZ, GPIO11| GPIO12| GPIO13); gpio_set_af(GPIOD, GPIO_AF9, GPIO11| GPIO12| GPIO13); gpio_mode_setup(GPIOB, GPIO_MODE_AF, GPIO_PUPD_NONE, GPIO2|GPIO6 ); gpio_set_output_options(GPIOB, GPIO_OTYPE_PP, GPIO_OSPEED_100MHZ, GPIO2|GPIO6); gpio_set_af(GPIOB, GPIO_AF9, GPIO2); gpio_set_af(GPIOB, GPIO_AF10, GPIO6); gpio_mode_setup(GPIOE, GPIO_MODE_AF, GPIO_PUPD_NONE, GPIO2 ); gpio_set_output_options(GPIOE, GPIO_OTYPE_PP, GPIO_OSPEED_100MHZ, GPIO2); gpio_set_af(GPIOE, GPIO_AF9, GPIO2);
/* Not sure anymore why, but it works :) I guess clock prescale for spi mode (generaly flash starts in spi mode and we have to turn on the qspi mode on) address len needs to be set, so the mcu knows about the size of flash for mapping */
QUADSPI_CR= 80<<QUADSPI_CR_PRESCALE_SHIFT
| 3 << QUADSPI_CR_FTHRES_SHIFT
| QUADSPI_CR_EN ;
QUADSPI_DCR = 22<<QUADSPI_DCR_FSIZE_SHIFT
| 7 << QUADSPI_DCR_CSHT_SHIFT ;
QUADSPI_ABR =0;
QUADSPI_DLR =16;
QUADSPI_AR =0;
QUADSPI_CCR=0x00000166; // enable reset 66 Page 70 in the datasheet
while( (QUADSPI_SR & 32) == 32 );
QUADSPI_CCR=0x00000199; // soft reset Page 70
while( (QUADSPI_SR & 32) == 32 );
while(!(QUADSPI_SR & 0x04));
while(!(QUADSPI_SR & 0x02)); /* Wait for TCF flag to be set */
QUADSPI_CCR=0x00000138; // enable quadspi Page 68
while( (QUADSPI_SR & 32) == 32 );
while(!(QUADSPI_SR & 0x02)); /* Wait for TCF flag to be set */
/* W25Q64 is now in the qspi mode */ }
quad_map() { /* Page 31 in the data sheet following keep in mind : we are sending command in 4 bit mode, we are sending address in 4 bit mode, we have 2 dummy cycle in 4 bit mode and we receive data in 4 bit mode. the Address len acording datasheet 24bit aka 3 bytes and we'd like to map the flash to memory.
datasheet of h7:
FMODE : 3 Memory map
DCYC: 2 dummy cycles
ABSIZE: 32Bit
ABMODE: No alternative bytes
ADSIZE: 24 Bit according Flashdevice
ADMODE: Using 4 Lines for sending address
IMODE: Send command via 4 Lines
DMODE: Receive data via 4 lines
Command is Fast Read (0Bh) in QPI Mode Page 31
*/
QUADSPI_CCR = 3 << QUADSPI_CCR_FMODE_SHIFT
| 2 << QUADSPI_CCR_DCYC_SHIFT
| 0 << QUADSPI_CCR_ABMODE_SHIFT
| 3 << QUADSPI_CCR_ABSIZE_SHIFT
| 3 << QUADSPI_CCR_ADMODE_SHIFT
| 2 << QUADSPI_CCR_ADSIZE_SHIFT
| 3 << QUADSPI_CCR_IMODE_SHIFT
| 3 << QUADSPI_CCR_DMODE_SHIFT
// | QUADSPI_CCR_SIOO
// | QUADSPI_CCR_DDRM
| 0x0B ; // quad fast read in qspi
while( (QUADSPI_SR & 32) == 32 );
}
quad_read(uint32_t addr, size_t len, uint8_t *dest) {
/* Same as Above on MAP, difference is FMODE is READ DLR is set to len-1 AR to flash Adress */
QUADSPI_CR &= ~ QUADSPI_CR_EN;
QUADSPI_DLR = len -1 ;
//QUADSPI_DLR = len ;
QUADSPI_CCR = 1 << QUADSPI_CCR_FMODE_SHIFT
| 2 << QUADSPI_CCR_DCYC_SHIFT
| 0 << QUADSPI_CCR_ABMODE_SHIFT
| 3 << QUADSPI_CCR_ABSIZE_SHIFT
| 3 << QUADSPI_CCR_ADMODE_SHIFT
| 2 << QUADSPI_CCR_ADSIZE_SHIFT
| 3 << QUADSPI_CCR_IMODE_SHIFT
| 3 << QUADSPI_CCR_DMODE_SHIFT
// | QUADSPI_CCR_SIOO
// | QUADSPI_CCR_DDRM
| 0x0B ; // quad fast read in qspi
QUADSPI_CR |= QUADSPI_CR_EN;
QUADSPI_ABR =0;
QUADSPI_AR = addr;
while(len)
{
// while(!(QUADSPI_SR & 0x02));
while((QUADSPI_SR & 32) != 32);
*(uint32_t *)dest = QUADSPI_DR;
dest+=4;
len-=4;
}
QUADSPI_FCR=0x1b; //CLEAR CTFC Flag
QUADSPI_CR &= ~ QUADSPI_CR_EN;
}
quad_write(uint32_t addr, size_t len, uint8_t *dest) {
QUADSPI_FCR=2; //CLEAR CTFC Flag
QUADSPI_CR |= QUADSPI_CR_EN;
QUADSPI_CCR = 0 << QUADSPI_CCR_FMODE_SHIFT
| 0 << QUADSPI_CCR_DCYC_SHIFT
| 0 << QUADSPI_CCR_ABMODE_SHIFT
| 0 << QUADSPI_CCR_ABSIZE_SHIFT
| 0 << QUADSPI_CCR_ADMODE_SHIFT
| 2 << QUADSPI_CCR_ADSIZE_SHIFT
| 3 << QUADSPI_CCR_IMODE_SHIFT
| 0 << QUADSPI_CCR_DMODE_SHIFT
// | QUADSPI_CCR_SIOO
// | QUADSPI_CCR_DDRM
| 0x06 ; // quad write enable in qspi
while( (QUADSPI_SR & 32) == 32 );
QUADSPI_FCR=2; //CLEAR CTFC Flag
QUADSPI_CR &= ~ QUADSPI_CR_EN;
QUADSPI_DLR = len -1 ; QUADSPI_CCR = 0 << QUADSPI_CCR_FMODE_SHIFT | 0 << QUADSPI_CCR_DCYC_SHIFT | 0 << QUADSPI_CCR_ABMODE_SHIFT | 3 << QUADSPI_CCR_ABSIZE_SHIFT | 3 << QUADSPI_CCR_ADMODE_SHIFT | 2 << QUADSPI_CCR_ADSIZE_SHIFT | 3 << QUADSPI_CCR_IMODE_SHIFT | 3 << QUADSPI_CCR_DMODE_SHIFT // | QUADSPI_CCR_SIOO // | QUADSPI_CCR_DDRM | 0x02 ; // quad write page in qspi QUADSPI_CR |= QUADSPI_CR_EN; QUADSPI_ABR =0; QUADSPI_AR = addr;
while(len)
{
while(!(QUADSPI_SR & 0x04));
QUADSPI_DR = *(uint32_t *)dest;
dest+=4;
len-=4;
}
QUADSPI_FCR=2; //CLEAR CTFC Flag
QUADSPI_CR &= ~ QUADSPI_CR_EN;
}
quad_erase(uint32_t addr) {
QUADSPI_FCR=2; //CLEAR CTFC Flag
QUADSPI_CR |= QUADSPI_CR_EN;
QUADSPI_CCR = 0 << QUADSPI_CCR_FMODE_SHIFT
| 0 << QUADSPI_CCR_DCYC_SHIFT
| 0 << QUADSPI_CCR_ABMODE_SHIFT
| 0 << QUADSPI_CCR_ABSIZE_SHIFT
| 0 << QUADSPI_CCR_ADMODE_SHIFT
| 2 << QUADSPI_CCR_ADSIZE_SHIFT
| 3 << QUADSPI_CCR_IMODE_SHIFT
| 0 << QUADSPI_CCR_DMODE_SHIFT
// | QUADSPI_CCR_SIOO
// | QUADSPI_CCR_DDRM
| 0x06 ; // quad write enable in qspi
while( (QUADSPI_SR & 32) == 32 );
QUADSPI_FCR=2; //CLEAR CTFC Flag
QUADSPI_CR &= ~ QUADSPI_CR_EN;
QUADSPI_CR |= QUADSPI_CR_EN;
QUADSPI_CCR = 0 << QUADSPI_CCR_FMODE_SHIFT
| 0 << QUADSPI_CCR_DCYC_SHIFT
| 0 << QUADSPI_CCR_ABMODE_SHIFT
| 0 << QUADSPI_CCR_ABSIZE_SHIFT
| 3 << QUADSPI_CCR_ADMODE_SHIFT
| 2 << QUADSPI_CCR_ADSIZE_SHIFT
| 3 << QUADSPI_CCR_IMODE_SHIFT
| 0 << QUADSPI_CCR_DMODE_SHIFT
// | QUADSPI_CCR_SIOO
// | QUADSPI_CCR_DDRM
| 0x20 ; // quad erase in qspi
// QUADSPI_ABR =0;
QUADSPI_AR = addr;
while( (QUADSPI_SR & 32) == 32 );
QUADSPI_CR &= ~ QUADSPI_CR_EN;
QUADSPI_FCR=2; //CLEAR CTFC Flag
QUADSPI_CR |= QUADSPI_CR_EN;
QUADSPI_CCR = 0 << QUADSPI_CCR_FMODE_SHIFT
| 0 << QUADSPI_CCR_DCYC_SHIFT
| 0 << QUADSPI_CCR_ABMODE_SHIFT
| 0 << QUADSPI_CCR_ABSIZE_SHIFT
| 0 << QUADSPI_CCR_ADMODE_SHIFT
| 2 << QUADSPI_CCR_ADSIZE_SHIFT
| 3 << QUADSPI_CCR_IMODE_SHIFT
| 0 << QUADSPI_CCR_DMODE_SHIFT
// | QUADSPI_CCR_SIOO
// | QUADSPI_CCR_DDRM
| 0x04 ; // quad write disable in qspi
while( (QUADSPI_SR & 32) == 32 );
QUADSPI_FCR=2; //CLEAR CTFC Flag
QUADSPI_CR &= ~ QUADSPI_CR_EN;
}
Damn this is awesome thank you. Its vague but if memory serves 128mb can mapped to system (read only) then the rest is all indirect access after that. If thats correct thats more then fine by me. The portenta has a MX25L12833FZ2I. I already have the ez clock functions for qspi working.I know sum level of chip specific settings can be read/determined or maybe culled from a list at compile time with model passed. Im fairly certain the wear leveling stuff is complicated af.So im probly a long ways off from tackling that. But im not sure the most common use cases so not sure how much a priority it should have.My gut says probly pretty high. I kinda feel were making sum progress, but this is the most collaboration ive ever been involved in so...
Hi,
Tomorrow I will need to work on stm32h7 spi, so can you tell me @ventZl if you intent to push your working SPI (not QSPI) code today, or if I just reimplement it tomorrow? Unfinished is fine.
Either solution is fine, no pressure, but I would just like to know so I can plan my day,
Thanks, Sebastien
@slorquet be sure you have a logic analyzer or dso right next to you :) to double check. Code from #1392 should work, may be there is one little issue. Since my example is fullduplex, I check after every write whether there are data from receiver. This is probably not necessary when spi is set to tx only.
Also not sure how do you like to handle spi packetwise communication, which would be great for lcd displays ? But maybe you already have some sort of concept how to put it all together.
rgds Roman
I'll have a look, also I have a working driver for NuttX. I do not want to copy code, but I can still observe the proper sequencing of register accesses.
What I'm primarily concerned about is write a properly integrated spiv3 driver within libopencm3, so raw code gives a hand but is not what I need. I must separate which functions will go inside the common files and which ones are specific to the stm32h7.
I'll have a fx2lafw analyzer with sigrok pulseview.
Working now on the code structure for stm32h7 spi
Here is my plan
spi_common_all.c cannot be used for spiv3 since so many things are different, register names, bit definitions, transfer algorithms.
so I've made a new file spi_common_v12.c with most routines from spi_common_all, except reset which is the actually only common routine.
I have then started spi_common_v3 for the stm32h7, rewriting most of the contents in spi_common_v12 (aka _all)
The pull request sent by @ventZl , even if surprising, makes a lot of sense but has errors and is missing important bits to allow spi transfer.
The routines are not working yet but there is progress, both in code structure and actual spi behaviour.
For your information here are the main changes I've done today, I'm not sending a pull request yet because it's not ready https://github.com/libopencm3/libopencm3/compare/master...slorquet:libopencm3:stm32h7-spi
@karlp I know you are very busy, and I would like to be allowed to push trivial changes like the breaking uart thing. Because obviously you dont have enough time for this project, which cannot be blamed and is very understandable, but is also blocking the progress of the project.
@slorquet went quickly over your code, is cool. I know is not the final and not working yet.. Cant wait until you push your changes.
One little note. On h7 the SPI_TXDR/SPI_RXDR are 32 bit register. In SPI_CFG1 can be set the length (4-32bit) of the frame. For some application it would be cool, we could set and use up to the 32bit frame (currently the functions handle 8/16 bit frames) Not sure whether libopencm3 is universal enough to do something like this.
Thanks for the review, that is very useful. Also motivating to know I'm not just shouting in the dark.
I will make the functions that currently get uint16 to get uint32, and add new functions for uint16. Also functions that take byte buffers could be useful.
I have read in the ref manual that this spiv3 has stuff to pack bytes in fifo entries, I'm not sure about that. I hope defaults dont trigger a strange fifo packing behaviour.
For the moment a simple test with a SPI flash (software driven CS) stalls waiting for TXP to clear at that line:
while (!(SPI_SR(spi) & SPI_SR_TXP));
I may be missing something related to emptying/clearing fifo during init.
Can confirm https://github.com/libopencm3/libopencm3/issues/1392 spi code works and finally gets my ili9341 working. Not much different from my earlier attempts except the flush function. Im software controlling cs without any issues as well. Converting to simple functions should be easy (ill get on it). ADC is next for me; bringing in adc patch set from https://github.com/allocortech/libopencm3/tree/stm32h7_adc_defs to try next. sum clock set/gets added, external ram (needs generic functions), simple cp of i2c v2 (seems working);, spi (needs basic functions), qspi flash (needs functions, currently untested), USBHS (works), UART (works). And all inside a single example, uhg i know, ill pretty things up once further along. I did a basic adc setup wo knowing the correct order or requirements. No errors and sum slim variances from floating but doesnt seem to be associated with PC2. Simple linux kernel driver included for easy testing. Can switch between human readable and binary output via sysfs switch. https://github.com/bm16ton/libopencm3-portentaH7
Ok spi_send8 updated and spi_flush added, should any settings be added to spi_init as common use? Also adc was a stupid mistake on my part and example is working now with kernel driver. I should probly give dma a driveby. Maybe look at booting the m4 core as well.
flush should not be needed independently. It should be integrated in the transmit/exchange code. Why are so many bits required to check for tx completion?
there is progress on my side: I could exchange two bytes. and now I am stuck waiting RXP to set again after trying to exchange the third byte.
My code is much simpler than yours at this point. Also based on #1392 but no need to flush yet. Maybe thats my problem now lol
Edit: WHY do we need to flush anything after a byte is received? Is the SPI not stopping the clock after the byte we send?
Edit: spi_init_master is a problem, it enables the SPI so configs done later are not taken into account. here is my current init that just exchanges two bytes for now:
/* Setup SPI parameters. */
spi_reset(SPI5);
spi_disable_crc(SPI5);
spi_enable_software_slave_management(SPI5);
spi_set_full_duplex_mode(SPI5);
spi_send_msb_first(SPI5);
spi_set_baudrate_prescaler(SPI5,2);
spi_set_data_size(SPI5,8);
spi_set_master_mode(SPI5);
//spi_init_master(SPI5, 3, 0, 0, false, false);
spi_fifo_reception_threshold_8bit(SPI5);
spi_set_transfer_size(SPI5,0);
/* Finally enable the SPI. */
spi_enable(SPI5);
fifo threshold 8 bits and transfer size ARE required or the first two bytes dont even make it.
and here is my current xfer:
uint8_t spi_xfer8(uint32_t spi, uint8_t data)
{
uint8_t ret;
/* Start a transaction */
SPI_IFCR(spi) &= ~SPI_IFCR_SUSPC;
SPI_CR1(spi) |= SPI_CR1_CSTART;
/* Wait for room to write in fifo. */
while (!(SPI_SR(spi) & SPI_SR_TXP));
SPI_TXDR8(spi) = data;
/* Wait for rx data in fifo. */
while (!(SPI_SR(spi) & SPI_SR_RXP));
/* Read the data. */
ret = SPI_RXDR8(spi);
/* Suspend SPI */
SPI_CR1(spi) |= SPI_CR1_CSUSP;
while(!(SPI_SR(spi) & SPI_SR_SUSP));
return ret;
}
like nuttx does I start the transfer before and suspend it just after receiving.
Got it working without flush. The KEY was the need to set CSTART before EACH CALL to xmit8. and define transaction len to zero AND fifo threshold to 1-data
Then you must not suspend. This init and xfer are ok:
/* Setup SPI parameters. */
spi_reset(SPI5);
spi_disable_crc(SPI5);
spi_enable_software_slave_management(SPI5);
spi_set_full_duplex_mode(SPI5);
spi_send_msb_first(SPI5);
spi_set_baudrate_prescaler(SPI5,2);
spi_set_data_size(SPI5,8);
spi_set_master_mode(SPI5);
//spi_init_master(SPI5, 3, 0, 0, false, false);
spi_fifo_packet_size_1data(SPI5);
spi_set_transfer_size(SPI5,0);
/* Finally enable the SPI. */
spi_enable(SPI5);
xfer:
uint8_t spi_xfer8(uint32_t spi, uint8_t data)
{
uint8_t ret;
/* make sure data will be transmitted at next fifo write */
SPI_CR1(spi) |= SPI_CR1_CSTART;
/* Wait for room to write in fifo. */
while (!(SPI_SR(spi) & SPI_SR_TXP));
SPI_TXDR8(spi) = data;
/* Wait for rx data in fifo. */
while (!(SPI_SR(spi) & SPI_SR_RXP));
/* Read the data. */
ret = SPI_RXDR8(spi);
return ret;
}
This version of the file (dont forget the header) contains working spi for h7, but DO NOT USE init_master yet. Only individual f functions. https://github.com/libopencm3/libopencm3/compare/master...slorquet:libopencm3:stm32h7-spi
Sorry just noticed your posts, yeah that tsize is a real problem, 0 seems to be the only logical way, dont feel like turning spi on/off after every byte. Tho I have seen that done in libopencm3 books and examples as a way to control CS pin. Without tsize you loose one of the registers for knowing when transfer is complete, but txp and rxp seem to work just fine. The flush confuses me as well. I was having a byte left over in my receive fifo when doing a spi_xfer to an ili9341 that has no touchscreen so nothing to read. The xfer function seems to sending 8 then reading 8 but I was doing an additional read after just to clear that from nowhere byte. Luckily someone pointed out that PR cuz that seemed to fix it for me, for now.
Can boot m4 core now, added the following functions for that; setcm4bootadd0 setcm4bootadd1 bootboth (needs new name) forcem4boot getcm4bootadd0
Are you using full duplex mode? In that mode the RM says in this mode the two fifo stay synchronized. Are you sure you are not writing too many data to your tx fifo?
tsize only makes sense for transfers with known size that end with a CRC, otherwise tsize=0 is enough, the module will send as soon as there is something in the fifo.
simplex rx only mode is the strangest of all, it will send clocks and acquire bytes as soon as START is asserted. in libopencm3 I recommend sticking with usual full duplex for the moment.
HA yeah Im using full duplex, Its just the xfer function on the previous stm32's would send8 read8 and all was good, But before I got it working (So I was def screwing something up) the xfer function was supposed to be sending 8 reading 8 but I still needed to do another read to empty the fifo. Probly something very foolishly silly on my part. Yeah I agree with keeping tsize 0, the errata seems to crazy otherwise. On my other older stm32's I slowdown the spi by increasing the prescaler on the fly to say take a touchscreen reading then decrease prescale on the fly before writing to screen. But I see in comments above people having issues changing settings after init. Ill hafta test that at some point could be problematic for my touchscreen en-devours.. I doubt anything I could write would be committed so no harm in setting the spi init function for h7 to tsize=0, with cs allowed to be controlled via software, and probly a few others im not thinking of, but if changes cannot be made after the fact, I may need to be more picky on that list. I guess next goal is either dma or adding m4 variant so I dont need to use arduino sketches for testing the m4. Things kinda seem like they are moving along.
To change settings, the spi has to be disabled. If spi is enabled, the config registers are read only.
I got abused by spi_init_master for a long time, because this function enables spi at the end, so any config change later is not applied.
I feel this has to be changed. it should not enable spi. Or else, every function that changes settings must disable spi temporarily. this does not feel right.
This applies to prescaller? Did this start with spi v3 on h7's? I dont like the idea of an orgy of spi enable/disable just to talk to a touchscreen etc on same bus. I was gonna agree with yeah but then thought shit spi_init kinda says it in the name. Im guessing its for common/easy use cases sorta thing. But having a simple maybe unused switch to keep it from starting the spi would be nice. We can add to the h7s if u think it maybe helpful? Speaking of names functions like get_spi_clock, get_i2c_clock actually returning the parent clock speeds seems wrong. If i saw you working on a i2c project and asked what your i2c clock was and u responded 200mhz...id be confused. Maybe we should call it get_spi_parent_clock or spi_clock_if_we_gave_up_on_math_partway_thru edit: Crap i also switch between 8bit and 16bit spi on the fly in projects i was hoping to up port to h7. Hrm
According to RM0433 chapter 50.11.3
SPI configuration register 1 (SPI_CFG1) Address offset: 0x08 Reset value: 0x0007 0007 Content of this register is write protected when SPI is enabled
So, yes
This is confirmed by the NuttX driver, which temporarily disables the spi peripheral to change the current data rate.
the disable/enable operation is just a quick register write, it's ugly but it's easy to do.
However I believe libopencm3 functions could just WARN the user that the spi must be disabled for the settings to have any effect.
the spi_init_master can be update to take enough settings so a default master will work, and continue enabling spi on return. no problem.
I just deeply miss the lack of guidance from project leaders.
For SPI the actual value of the clock is not that critical, no need to know the actual speed of the bus that is connected. The functions do not set an actual baud rate, but just a prescaler selection.
i2c on the other hand need to know the actual speed of the clock powering it so it can use normal I2C clock rates.
Wow, been up for a couple days now, but seems like the opposite of a step forward. I see a lot of tft inits drop speed just for the init to avoid race conditions. Well ok guess I better buckup and make do. Still sucks tho. I love my f407 a little more everyday.. Oh dont get me wrong I dont mind what the functioons for getting clocks do...Just the names of them. Im a terrible coder but I sometimes know how regular words work, and those names dont seem to line up. Adding the word parent or similiar would be fine.
@bm16ton I tried out your libopencm3 with your examples, but looks like there are some issues with usb. It doesn't work on my hardware (DevEBox stm32h7xx). Looks like you are using the ULPI Interface right ??
Do you know by any chance how to change it to integrated OTG HS Phy with just two wires (DP/DM) ?
I get stucked in : .. halted: PC: 0x08001df2 halted: PC: 0x08001dee halted: PC: 0x08001df0 halted: PC: 0x08001df2 halted: PC: 0x08001dee halted: PC: 0x08001df0 halted: PC: 0x08001df2 halted: PC: 0x08001dee ^Chalted: PC: 0x08001df0 halted: PC: 0x08001df2
Program received signal SIGINT, Interrupt.
0x08001df2 in stm32f207_usbd_init () at ../../usb/usb_f207.c:91
91 while (OTG_HS_GRSTCTL & OTG_GRSTCTL_CSRST);
(gdb) bt
#0 0x08001df2 in stm32f207_usbd_init () at ../../usb/usb_f207.c:91
#1 0x08001458 in usbd_init (driver=0x8004660 <stm32f207_usb_driver>, dev=dev@entry=0x80042c3
rgds Roman
Hello Roman! So your chip has the ulpi integrated? For reasons someone smarter then me would need to explain the integrated ulpi is different then external, requires registers and a clock with "phyc" in the name (if memory serves anyway). id look at Stoyan Shopov github stoyan-shopov usbhs for stm32f723. Its just sum minor changes to the init to get it going i believe. My code works on my f4s, f7s, and h7 with external ulpi, the only board i have with internal is f723 and it wont init. To switch back to using the hs port in fullspeed mode dp/dm you can copy the original init from stock libopencm3 file usb_f207.c into mine. The og driver is for that exact use case. Unfortunately im away from home/pc today (typing on broken screened phone hooefully not many typos) but when i return tonight id love to edit that init for integrated ulpi and see if we can get yeah going? If i find a min i maybe able to whio something up using my cell and post it here, fingers crossed. Wish i could see what i just ttyped i hope its legible.
Hallo Ben, Thank you for the hint. Actually after fiddling around (needed to change few things) even the usb_f107.c works. (macros need to be change to OTP_FS.. ) Slowly I'm making progress with the internal FS usb. There is still something wrong with the initialization of the chip (it only work when the chip had a working usb driver from stmcube and flashed with libopencm3 after it), but at least it started to communicate with me :) The initialization of H7 in stmcube is little bit more complex then in the libopencm3, so it needs some changes as well. Once it starts to work with libopencm3 from ground up, i'll let you guys know.
Thats great! If i understand correctly with cubemx usb code on the board if you place it in bootloader mode and upload a libopencm3 firmware when the bootliader jumps it works? Makes sense, kinda like when something only works after a redet cuz of a misorder. Im surprised the 207 driver didnt work out of the box for yeah. I do believe i had to make 2 small if h7 changes to get usb highspeed going and one or both may be required for usbfs over usbhs pins. Or are you using pins A11/A12 (fs pins) then def go with 103 driver. After your last message i realized my example wont boot on anyboard that doesnt have the same i2c device attached so i did a quick dirty port of i2c-star (usb to i2c with linux driver support in mainline kernel) and removed all the other stuff to make it easier/cleaner. ill do a lil cleanup and post hopefully soonish. Remind me again your board does have a builtin ulpi? Thats badass hope you use that! ill help anyway i can just ask
On Wed, 25 Jan 2023, 2:20 pm Roman Pollak, @.***> wrote:
Hallo Ben, Thank you for the hint. Actually after fiddling around (needed to change few things) even the usb_f107.c works. (macros need to be change to OTP_FS.. ) Slowly I'm making progress with the internal FS usb. There is still something wrong with the initialization of the chip (it only work when the chip had a working usb driver from stmcube and flashed with libopencm3 after it), but at least it started to communicate with me :) The initialization of H7 in stmcube is little bit more complex then in the libopencm3, so it needs some changes as well. Once it starts to work with libopencm3 from ground up, i'll let you guys know.
— Reply to this email directly, view it on GitHub https://github.com/libopencm3/libopencm3/issues/1457#issuecomment-1404115594, or unsubscribe https://github.com/notifications/unsubscribe-auth/ADAWMP6KO23YUHJVMD4WA2TWUF4ILANCNFSM6AAAAAATZKZBFA . You are receiving this because you were mentioned.Message ID: @.***>
Basically I am using A11/A12 (fs pins, since those are connected to usb). My board is a cheap H743 DevEBox board.
Just clarify :
- load usb msc example build with cube.
- connect usb -> linux recognize as it suppose to.
- disconnect usb
- load usb msc example build with libopencm3
- connect usb -> linux recognize as msc device
- can access to device via mount/od/hexdump
- back to step 3, works fine after reconnect few times
I will go over the order how the stuff initialize (if it match with the cube order), but on this site of pond is getting late...