Very cool and keep at it The more community porting TinyCLR the better it gets over time. We need others to dig into it and let us know what they find.
I’m facing more problems than I was thinking with the porting. The migration reference manual from ST is mostly funny than helpful.
I’ve ported to F7 Arduino STM32 package in 1h… with no problem.
I’ve implemented startup code (it works at 216Mhz), UART, PWM/timer, Interrupt, power (CAN/ADC/DAC implemented but not tested). I2C and SPI need more upgrades.
USB OTG FS doesn’t work at all and I’m getting crazy to figure out the problem (doesn’t reset and doesn’t fire interrupt at first glance, it seems completely dead).
Deploying the Tinyclr blink app via UART it works, but I get:
Create TS.
Loading Deployment Assemblies.
Resolving.
The debugging target runtime is loading the application assemblies and starting execution.
Ready.
Cannot find any entrypoint!
Sure that the CortexM7 LIB is correctly compiled and working?
try to see what one of the .netmf developers (CW2 from his code i learn a lot)was tried to port earlier for .netmf 4.4 and you can find here source for STM32F746NUCLEO and i belive you here you can find a lot things that can help you for porting of your discovery to TinyCLR (also .netmf 4.4 too)
Fixed USB also, I had some defines not correctly set, but checking again (mostly 200 times) I got it e voilà USB working!
Thanks @valon_hoti_gmail_com for a hint in your startup code
I’m spending time these days to the board becouse I have some spare time unitl next week.
The board is running fine but few problems still exist, of course. The I2C bus need a major revision due to a bad joke from ST guys not preserving F4 compatibility. SPI is done but DISCO-746 has no free port. I’m looking into Display driver (mostly done, but not enough memory for the video cache, sigh!) so I’m studying to enable and use the on board QuadSPI 16MB as video layers cache.
These weekend I will deploy on github the F7 device code so it will be public.
Now working to port on 0.9.0 src code … but finally it works again also under 0.9.0.
I’m writing SDRAM enable code and mapping it in memory space. After that I (probably) can enable LDTC features on TinyCLR.
I have now enabled the SDRAM and mapped to LTDC VIDEO RAM in the code, the display correctly setup and clear.
I’m facing a problem with the Graphics managed library, becouse it gives me a OutOfMemoryException when try to allocate fromHdc. This is obvious if the Graphics call try to allocate 480x272x2=256K heap memory for the context.
Any suggestion ?
(PS: What is supposed to do the DisplayController.WriteString() method ?)
static void DisplayTest()
{
DisplayController displayController = DisplayController.GetDefault();
//var r = md.Init();
displayController.ApplySettings(new ParallelDisplayControllerSettings
{
Width = 480,
Height = 272,
PixelClockRate = 9600000, // not used in native code
PixelPolarity = false,
OutputEnablePolarity = true,
OutputEnableIsFixed = true,
HorizontalFrontPorch = 32,
HorizontalBackPorch = 13,
HorizontalSyncPulseWidth = 41,
HorizontalSyncPolarity = false,
VerticalFrontPorch = 2,
VerticalBackPorch = 2,
VerticalSyncPulseWidth = 10,
VerticalSyncPolarity = false,
DataFormat = DisplayDataFormat.Rgb565 // not really correct: it is Rgb888 for Disco-746 display...
});
displayController.WriteString("Test");
var screen = Graphics.FromHdc(displayController.Hdc);
screen.Clear(Color.Black);
var GreenPen = new Pen(Color.Blue);
screen.DrawRectangle(GreenPen, 10, 10, 2, 10);
screen.Flush();
}
Looking for a device on transport ‘USB’.
Found device port ‘USB’ with ID ‘dca38750-5539-4f4c-bb7d-8a50b9ba1088’ for transport ‘Usb’.
Starting device deployment.
Attempting to connect to device ‘USB:DISCO-F746NG’: iteration 0.
Opening port ‘\?\usb#vid_1b9f&pid_5000#6&1e013c1f&0&2#{c13bcfe9-5e84-4187-9baa-45597ffcbb6f}’.
Attaching debugger engine.
Debugger engine attached.
Querying device assemblies.
Found assemblies:
TinyCLR_M4 v1.0.0.0.
mscorlib v0.9.0.0.
GHIElectronics.TinyCLR.Devices v0.9.0.0.
GHIElectronics.TinyCLR.Drawing v0.9.0.0.
GHIElectronics.TinyCLR.Storage v0.9.0.0.
Generating device specific assemblies.
Deploying assemblies:
TinyCLR_M4 v1.0.0.0 with size 2.188 bytes at ‘H:\Embedded\PROJECTS\TinyCLR\TinyCLR_M4\TinyCLR_M4\bin\Debug\pe\TinyCLR_M4.pe’.
mscorlib v0.9.0.0 with size 77.204 bytes at ‘H:\Embedded\PROJECTS\TinyCLR\TinyCLR_M4\TinyCLR_M4\bin\Debug\pe\mscorlib.pe’.
GHIElectronics.TinyCLR.Devices v0.9.0.0 with size 50.324 bytes at ‘H:\Embedded\PROJECTS\TinyCLR\TinyCLR_M4\TinyCLR_M4\bin\Debug\pe\GHIElectronics.TinyCLR.Devices.pe’.
GHIElectronics.TinyCLR.Storage v0.9.0.0 with size 7.796 bytes at ‘H:\Embedded\PROJECTS\TinyCLR\TinyCLR_M4\TinyCLR_M4\bin\Debug\pe\GHIElectronics.TinyCLR.Storage.pe’.
Total deployment size is 137.512 bytes.
Incrementally deploying assemblies to the device:
Erasing sector 1 (262.144 bytes).
Writing sector 1 (2.192 bytes).
Erasing sector 3 (262.144 bytes).
Writing sector 3 (58.120 bytes).
Assemblies deployed. There are 648.920 bytes left in the deployment area.
Restarting interpreter.
Attaching to device.
Waiting for device to initialize.
Eccezione generata: ‘System.OutOfMemoryException’ in GHIElectronics.TinyCLR.Drawing.dll
Eccezione non gestita di tipo ‘System.OutOfMemoryException’ in GHIElectronics.TinyCLR.Drawing.dll
Hi Dat, yes I moved heap to SDRAM, but I made SDRAM_Init() call to my SDRAM init code in wrong place. It need to be sitted in the SystemInit() otherwise It doesn’t work.
extern "C" {
void __section("SectionForBootstrapOperations") SystemInit() {
SCB_EnableICache();
// enable FPU coprocessors (CP10, CP11)
SCB->CPACR |= 0x3 << 2 * 10 | 0x3 << 2 * 11; // full access
#if DEBUG || _DEBUG
// configure jtag debug support
DBGMCU->CR = DBGMCU_CR_DBG_SLEEP;
#endif
// allow unaligned memory access and do not enforce 8 byte stack alignment
SCB->CCR &= ~(SCB_CCR_UNALIGN_TRP_Msk);
// added by db
PWR->CR1 = (PWR->CR1 & ~PWR_CR1_VOS_Msk)
| PWR_CR1_VOS_1 | PWR_CR1_VOS_0;
// for clock configuration the cpu has to run on the internal 16MHz oscillator
RCC->CR |= RCC_CR_HSION;
while (!(RCC->CR & RCC_CR_HSIRDY));
RCC->CFGR = RCC_CFGR_SW_HSI; // sysclk = AHB = APB1 = APB2 = HSI (16MHz)
RCC->CR &= ~(RCC_CR_PLLON | RCC_CR_PLLI2SON); // pll off
#if RCC_PLLCFGR_PLLS_BITS == RCC_PLLCFGR_PLLSRC_HSE
// turn HSE on
RCC->CR |= RCC_CR_HSEON;
while (!(RCC->CR & RCC_CR_HSERDY));
#endif
FLASH->ACR = FLASH_ACR_PRFTEN | FLASH_ACR_LATENCY_BITS | FLASH_ACR_ARTEN;
}
// setup PLL
RCC->PLLCFGR = RCC_PLLCFGR_PLL_BITS; // pll multipliers
RCC->CR |= RCC_CR_PLLON; // pll on
while (!(RCC->CR & RCC_CR_PLLRDY));
//while ((PWR->CSR1 & PWR_CSR1_VOSRDY) == 0);
// final clock setup
RCC->CFGR = (RCC->CFGR & ~(RCC_CFGR_HPRE_Msk | RCC_CFGR_PPRE1_Msk | RCC_CFGR_PPRE2_Msk));
RCC->CFGR |= RCC_CFGR_SW_PLL // sysclk = pll out (STM32F7_SYSTEM_CLOCK_HZ)
| RCC_CFGR_HPRE_DIV_BITS // AHB clock
| RCC_CFGR_PPRE1_DIV_BITS // APB1 clock
| RCC_CFGR_PPRE2_DIV_BITS; // APB2 clock
while ((RCC->CFGR & RCC_CFGR_SWS) != RCC_CFGR_SWS_PLL);
// minimal peripheral clocks
#ifdef RCC_AHB1ENR_DTCMRAMEN
RCC->AHB1ENR = RCC_AHB1ENR_DTCMRAMEN; // 64k RAM (DTCM)
#endif
RCC->AHB2ENR = 0;
RCC->AHB3ENR = 0;
RCC->APB1ENR = RCC_APB1ENR_PWREN; // PWR clock used for sleep;
RCC->APB2ENR = RCC_APB2ENR_SYSCFGEN; // SYSCFG clock used for IO;
// stop HSI clock
#if RCC_PLLCFGR_PLLS_BITS == RCC_PLLCFGR_PLLSRC_HSE
RCC->CR &= ~RCC_CR_HSION;
#endif
//SYSCFG->MEMRMP = 1; // map System memory to Boot area
#ifdef STM32F7_Enable_RTC
STM32F7_RTC_Initialize(); // enable RTC
#endif
// GPIO port A to D is always present
RCC->AHB1ENR |= RCC_AHB1ENR_GPIOAEN | RCC_AHB1ENR_GPIOBEN | RCC_AHB1ENR_GPIOCEN | RCC_AHB1ENR_GPIODEN;
#ifdef RCC_AHB1ENR_GPIOEEN
RCC->AHB1ENR |= RCC_AHB1ENR_GPIOEEN;
#endif
#ifdef RCC_AHB1ENR_GPIOFEN
RCC->AHB1ENR |= RCC_AHB1ENR_GPIOFEN;
#endif
#ifdef RCC_AHB1ENR_GPIOGEN
RCC->AHB1ENR |= RCC_AHB1ENR_GPIOGEN;
#endif
#ifdef RCC_AHB1ENR_GPIOHEN
RCC->AHB1ENR |= RCC_AHB1ENR_GPIOHEN;
#endif
#ifdef RCC_AHB1ENR_GPIOIEN
RCC->AHB1ENR |= RCC_AHB1ENR_GPIOIEN;
#endif
#ifdef RCC_AHB1ENR_GPIOJEN
RCC->AHB1ENR |= RCC_AHB1ENR_GPIOJEN;
#endif
#ifdef RCC_AHB1ENR_GPIOKEN
RCC->AHB1ENR |= RCC_AHB1ENR_GPIOKEN;
#endif
//STM32F7_DebugLed(true);
#ifdef USE_SDRAM_HEAP
SDRAM_Init(); // Init MT48LC4M32 SDRAM for heap
#endif
}
}
@Dat_Tran thank you for your suggestion. I’m aware that regs are mostly the same for F4 and F7.
The sdram seems to work fine and I tested it with big allocation of 2Mb arrays in managed code and native code with no problems at all. But when I apply settings in the DisplayController, mcu after one or two minutes or less goes lockup. This are typical memory issue, but I can’t find the couse…
I got a very tricky problem with framebuffer. It seems that SDRAM need a pullup and 100Mhz initialization on GPIO port for FMC due to some misterious reason, that is opposite to what ST shows (pullup none and 50Mhz with SDRAM CL=2 that is working for TinyCLR heap allocations). I suppose that when the mcu run at 216Mhz the ram is running at 108Mhz so 50Mhz delay on the GPIO pins is not enough for the LDTC direct memory reading …
Now I found some problem sending data from managed code to native driver. For some reason when I set up:
_display = DisplayController.GetDefault();
ParallelDisplayControllerSettings _settings = new ParallelDisplayControllerSettings()
{
Width = 480,
Height = 272,
PixelClockRate = 9600000, // not used in native code
PixelPolarity = false,
OutputEnablePolarity = true, // this must be true
OutputEnableIsFixed = true,
HorizontalFrontPorch = 8,
HorizontalBackPorch = 43,
HorizontalSyncPulseWidth = 2,
HorizontalSyncPolarity = false,
VerticalFrontPorch = 2,
VerticalBackPorch = 2,
VerticalSyncPulseWidth = 10,
VerticalSyncPolarity = false,
DataFormat = DisplayDataFormat.Rgb565 // Must be RGB565
};
_display.ApplySettings(_settings);
_display.WriteString("\f* Discovery STM32F746 board *\n\n");
_display.WriteString ("* TinyCLR 0.9.0 for STM32F7 *");
Apparently the config data are not correctly passed to native code. I got crazy to figure out what going wrong and I see that in the native code the if/else ALWAYS evaluate to true, setting wrong screen params.
//HorizontalSyncPolarity
if (m_STM32F7_DisplayHorizontalSyncPolarity == false)
hltdc_F.Init.HSPolarity = LTDC_HSPOLARITY_AL; <--- I expect this
else
hltdc_F.Init.HSPolarity = LTDC_HSPOLARITY_AH; <--- but it set this one
//VerticalSyncPolarity
if (m_STM32F7_DisplayVerticalSyncPolarity == false)
hltdc_F.Init.VSPolarity = LTDC_VSPOLARITY_AL; <-- as previous
else
hltdc_F.Init.VSPolarity = LTDC_VSPOLARITY_AH;
//OutputEnablePolarity
if (m_STM32F7_DisplayOutputEnablePolarity == false)
hltdc_F.Init.DEPolarity = LTDC_DEPOLARITY_AL; <-- as previous
else
hltdc_F.Init.DEPolarity = LTDC_DEPOLARITY_AH;
//OutputEnablePolarity
if (m_STM32F7_DisplayPixelPolarity == false)
hltdc_F.Init.PCPolarity = LTDC_PCPOLARITY_IPC; <-- as previous
else
hltdc_F.Init.PCPolarity = LTDC_GCR_PCPOL;
Probably in STM32F7_Display_SetConfiguration() native call some params are screwed up.