AdaCore / Ada_Drivers_Library

Ada source code and complete sample GNAT projects for selected bare-board platforms supported by GNAT.
BSD 3-Clause "New" or "Revised" License
247 stars 144 forks source link

Conflict with GPIO with SDRAM & serial port #32

Closed fridgemagnet2 closed 8 years ago

fridgemagnet2 commented 8 years ago

I've just started playing with the stm32f29-disco board so the architecture is a bit new to me, I was planning to use one of the serial ports to transfer some bitmaps which could then be rendered on the display. I have the serial port demo working fine along with the "draw" example which I'm using as a starting point. However I've spotted that after initialising the display device, the serial port no longer works. I think this is down to a conflict with the PB6 GPIO - this is used as the Tx pin in the serial demo but also appears to be used in setting up the SDRAM.

Given that the serial demo code has the comment "arbitrary values" about the GPIO settings assigned to the UART, I'm guessing I can configure this to use a different pair however it's not clear to me which GPIOs are free for assignment or how to figure this out despite having downloaded an assortment of documents for this board.

lambourg commented 8 years ago

The pins of the STM32 are configured to route a specific peripheral via calls to "Configure_Alternate_Function". I suggest you download the STM32F429 datasheet document, that describes in detail the various functions that each pin can be assigned to.

You can also try using STM32CubeMX that allows some automated configuration of the pins.

In your specific case, PA9 and PA10 can for example be configured to route the TX/RX of the USART1, using the Alternate Function number 7. This pin configuration has to be performed before the initialization of the USART peripheral.

fridgemagnet2 commented 8 years ago

Thanks for the pointer, I've tracked down the table and made more sense of this now. However having tried various configurations and UARTS which I don't think should have any conflicts with the I/O needed to drive the display, every single one I've got working fails once the display has been initialised.

Delving a bit further with a working configuration (UART5 mapped to PC12 & PD2), the problem appears to be around the _InitializeLayer call in framebuffer_ltdc.adb, specifically the call to Fill:

if To_DMA2D_CM (Buffer.Color_Mode) in DMA2D_Dst_Color_Mode then
       DMA2D_Fill (To_DMA2D_Buffer (Buffer), Color, True);
else
         HAL.Bitmap.Bitmap_Buffer (Buffer).Fill (Color);
end if;

I'm guessing that _DMA2DFill is an optimised fill routine using the DMA engine and it's this that is causing the problem. If I comment this call out and just use the plain HAL version everything works. This is sufficient for what I'm doing in that it's got me something that works however there does appear to be something wrong in this area.

Rgs,

Jon

lambourg commented 8 years ago

DMA2D is a purely internal peripheral: all it does is performing graphical-oriented memory transfers or memory fills (e.g. does not imply directly exercising external pins whatsoever). Having such call preventing you from using a USART is a bit surprising, except if having the DMA2D_Fill call the pins of the FSMC (the framebuffer is always located in the external SDRAM) and thus modifies your USART expected behavior, because they share those pins. However, using the regular Bitmap_Buffer's Put_Pixel should basically do the same (except that it's the CPU that's in charge of filling the framebuffer): e.g. exercising the FSMC. So your test is a bit puzzling.

BTW, I suppose you're using the STM32F429I-Disco, right? I don't think there's such thing as stm32f29-disco board...

fridgemagnet2 commented 8 years ago

Yes, it's the F429I-Disco board I've been using. UART5 shares with DCMI, SDI and SPI I believe, neither of which I believe are used for this scenario. It's interesting because I had identical results with some of the other UARTs that I got working aside from 5 in that the behaviour seems to be that it's the receive side which fails. Unfortunately I can't get the debugger working on my board (GPS just hangs) - the simple test I did was to loopback the port then send a byte & call the (blocking) read to fetch it back. If I put this code before the call to initialise and clear the screen then the screen only gets cleared if the loopback cable is connected (as you'd expect - remove it and the character is never received). However if I put the serial code after the display initialise but before I clear down the screen, the screen is always cleared regardless of whether the loopback cable is connected or not. This suggests that it is simply falling through the test for receive data ready.

Rgs,

Jon.

lambourg commented 8 years ago

Just to make sure I understand properly the situation:

Are the steps correct?

What about initializing the display first, and then setup the pins? Also have you tried to lock your pins after configuring them?

fridgemagnet2 commented 8 years ago

Here is the relevant bit of code:

   Display.Initialize;
   Display.Initialize_Layer (1, RGB_565);
   Display.Set_Orientation (HAL.Framebuffer.Landscape);

   Initialize (COM);
   Configure (COM, Baud_Rate => 115_200);
   Outgoing.Set (HAL.Byte (65));
   Put (COM, Outgoing'Unchecked_Access);
   Get (COM,Incoming'Unchecked_Access,1) ;

   Clear;

so in this configuration, the UART configuration doesn't work. Moving the Initialize(COM) call to before the display initialisation code doesn't make any difference. Moving all the comms code to before the display initialisation sequence gives the expected result ie. the Get call only completes if the TX/Rx pins are looped back on each other. I haven't looked at locking the pins.

Fabien-Chouteau commented 8 years ago

At this point you have to inspect the state of the drivers with the debugger. Reproduce the erroneous state and try to search why the UART is not working. What is the failure exactly? Is the code waiting in a busy loop? If yes, what is it waiting for? Are the UART registers in a good shape? Is there any error flags in the status register? Etc.

fridgemagnet2 commented 8 years ago

As I mentioned in an earlier post, so far I've been unable to get the debugger working with GPS2016 - I've installed it on 2 different machines and both of them just hang GPS when I launch it.

I've achieved what I intended with this board for now so this isn't really an issue for me any more, I was more pointing out what I'd discovered along the way. Happy to try things to assist with improving the software but I haven't got the time to devote significant amounts of effort pursuing it.

lambourg commented 8 years ago

A quick question: are you on linux or windows? In the first case, what version of stlink tools are you using? (c.f. https://github.com/texane/stlink). Also have you tried upgrading the stlink firmware on your board?

fridgemagnet2 commented 8 years ago

it's on Windows and that;s a good point - I upgraded the firmware the other day for a different reason but haven't tried using the debugger since. I will give it a go when I get five minutes and report back.

fridgemagnet2 commented 8 years ago

Sorry for the delay in getting back onto this, been a bit busy with other things. I'm using ST-LINK 3.9.0 and just tried a debug session with this version of firmware and unfortunately it's made no difference - GPS just hangs indefinitely when the session starts.