MCUDev Black STM32F407VET6 + STM32F407ZET6 dev boards

Discussion and questions about boards that can run MicroPython but don't have a dedicated forum.
Target audience: Everyone interested in running MicroPython on other hardware.
User avatar
JohnLittle
Posts: 11
Joined: Mon Oct 08, 2018 7:10 pm

Re: MCUDev Black STM32F407VET6 + STM32F407ZET6 dev boards

Post by JohnLittle » Sun Jul 21, 2019 7:37 am

Hey @OutoftheBOTS_

a native solution based on your C code would of course be the best solution, but would a micropython implementation be fast enough to get started?

I've been playing with jupyter notebook + micropython remote ( + vim-binding ) and have started converting your code.

This is way more advanced than the usual stuff I do with micropython but a good opportunity to learn.

I suppose I need to use machine.mem16() and machine.mem8() here, I could be wrong though! Also, I would love to use some kind of loop in TFT_Init() but the addresses being poked alternate randomely between LCD_RAM and LCD_REG, so I couldn't think of one. I'll check some existing code for inspiration!

Cheers,
John

Code: Select all

import stm
import time
import machine

LCD_REG = const(0x60000000)
LCD_RAM = const(0x60020000)

def TFT_Init():
    BIT12 = const(1 << 12)
    _BIT12 = const(0xFFFF ^ BIT12)

    #hardware reset
    machine.mem16[stm.GPIO_ODR] &= _BIT12
    time.sleep_ms(250)
    machine.mem16[stm.GPIO_ODR] |= BIT12
    time.sleep_ms(120)

    #SOFTWARE RESET
    machine.mem8[LCD_REG] = 0x01
    time.sleep_ms(1000)

    #POWER CONTROL A
    machine.mem8[LCD_REG] = 0xCB
    machine.mem8[LCD_RAM] = 0x39
    machine.mem8[LCD_RAM] = 0x2C
    machine.mem8[LCD_RAM] = 0x00
    machine.mem8[LCD_RAM] = 0x34
    machine.mem8[LCD_RAM] = 0x02
    ...

DJShadow1966
Posts: 60
Joined: Sun Jun 23, 2019 4:55 am
Location: Gateshead, Tyne and Wear

Re: MCUDev Black STM32F407VET6 + STM32F407ZET6 dev boards

Post by DJShadow1966 » Sun Jul 21, 2019 2:35 pm

Hello John

Been working on this too and have a lot of code already written stuck on some :-

Code: Select all

void FSMC_Init(void){
	//enable RCC for FSMC and both GPIO ports
	RCC->AHB3ENR |= RCC_AHB3ENR_FSMCEN;
	RCC->AHB1ENR |= RCC_AHB1ENR_GPIODEN | RCC_AHB1ENR_GPIOEEN;
and

Code: Select all

	//setup FSMC on Bank1 NORSRAM1
	//setup timings of FSCM
	FSMC_Bank1->BTCR[1] = FSMC_BTR1_ADDSET_1 | FSMC_BTR1_DATAST_1;
	// Bank1 NOR/SRAM control register configuration
	FSMC_Bank1->BTCR[0] = FSMC_BCR1_MWID_0 | FSMC_BCR1_WREN | FSMC_BCR1_MBKEN;
Currently my code is :-

Code: Select all

import stm
import time
import machine

stm.RCC_AHB3ENR |=
stm.RCC_AHB3ENR |=
stm.RCC_AHB1ENR |= [stm.RCC_AHB1ENR 

machine.mem16[stm.GPIOD + stm.GPIO_MODER] = 0b1100111110110011
machine.mem16[stm.GPIOE + stm.GPIO_MODER] = 0b1111111110000000

machine.mem16[stm.GPIOD + stm.GPIO_OTYPER] &= 0b0011000001001100
machine.mem16[stm.GPIOE + stm.GPIO_OTYPER] &= 0b0000000001111111

machine.mem16[stm.GPIOD + stm.GPIO_OSPEEDR] |= (0b11<<(2*0)) | (0b11<<(2*1)) | (0b11<<(2*4)) | (0b11<<(2*5)) | (0b11<<(2*7)) | (0b11<<(2*8)) | (0b11<<(2*9)) | (0b11<<(2*10)) | (0b11<<(2*11)) | (0b11<<(2*14)) | (0b11<<(2*15))
machine.mem16[stm.GPIOE + stm.GPIO_OSPEEDR] |= (0b11<<(2*7)) | (0b11<<(2*8)) | (0b11<<(2*9)) | (0b11<<(2*10)) | (0b11<<(2*11)) | (0b11<<(2*12)) | (0b11<<(2*13)) | (0b11<<(2*14)) | (0b11<<(2*15))

machine.mem16[stm.GPIOD + stm.GPIO_PUPDR] &= ((0b11<<(2*2)) | (0b11<<(2*3)) | (0b11<<(2*6)) | (0b11<<(2*12)) | (0b11<<(2*13)))
machine.mem16[stm.GPIOE + stm.GPIO_PUPDR] &= ((0b11<<(2*0)) | (0b11<<(2*1)) | (0b11<<(2*2)) | (0b11<<(2*3)) | (0b11<<(2*4)) | (0b11<<(2*5)) | (0b11<<(2*6)))

machine.mem16[stm.GPIOD + stm.GPIO_AFR0] = (machine.mem16[stm.GPIOD + stm.GPIO_AFR0] & (0b1111<<(4*2) | 0b1111<<(4*3) | 0b1111<<(4*6))) | 0b1100<<(4*0) | 0b1100<<(4*1) | 0b1100<<(4*4) | 0b1100<<(4*5) | 0b1100<<(4*7)
machine.mem16[stm.GPIOD + stm.GPIO_AFR1] = (machine.mem16[stm.GPIOD + stm.GPIO_AFR1] & (0b1111<<(4*(13-8)) | 0b1111<<(4*(12-8)))) | 0b1100<<(4*(8-8)) | 0b1100<<(4*(9-8)) | 0b1100<<(4*(10-8)) | 0b1100<<(4*(11-8)) | 0b1100<<(4*(14-8)) | 0b1100<<(4*(15-8))

machine.mem16[stm.GPIOE + stm.GPIO_AFR0] = (machine.mem16[stm.GPIOE + stm.GPIO_AFR0] & ~(0b1111<<7)) | 0b1100<<(4*7)
machine.mem16[stm.GPIOE + stm.GPIO_AFR1] = 0xCCCCCCCC

LCD_REG = const(0x60000000)
LCD_RAM = const(0x60040000)

def TFT_Init():
    BIT12 = const(1 << 12)
    _BIT12 = const(0xFFFF ^ BIT12)

    #hardware reset
    machine.mem16[stm.GPIO_ODR] &= _BIT12
    time.sleep_ms(250)
    machine.mem16[stm.GPIO_ODR] |= BIT12
    time.sleep_ms(120)

    #SOFTWARE RESET
    machine.mem8[LCD_REG] = 0x01
    time.sleep_ms(1000)

    #POWER CONTROL A
    machine.mem8[LCD_REG] = 0xCB
    machine.mem8[LCD_RAM] = 0x39
    machine.mem8[LCD_RAM] = 0x2C
    machine.mem8[LCD_RAM] = 0x00
    machine.mem8[LCD_RAM] = 0x34
    machine.mem8[LCD_RAM] = 0x02
    
    #DRIVER TIMING CONTROL A
    machine.mem8[LCD_REG] = 0xE8
    machine.mem8[LCD_RAM] = 0x85
    machine.mem8[LCD_RAM] = 0x00
    machine.mem8[LCD_RAM] = 0x78
    
    #DRIVER TIMING CONTROL B
    machine.mem8[LCD_REG] = 0xEA
    machine.mem8[LCD_RAM] = 0x00
    machine.mem8[LCD_RAM] = 0x00
    
    #POWER ON SEQUENCE CONTROL
    machine.mem8[LCD_REG] = 0xED
    machine.mem8[LCD_RAM] = 0x64
    machine.mem8[LCD_RAM] = 0x03
    machine.mem8[LCD_RAM] = 0x12
    machine.mem8[LCD_RAM] = 0x81

    #PUMP RATIO CONTROL
    machine.mem8[LCD_REG] = 0xF7
    machine.mem8[LCD_RAM] = 0x20

    #POWER CONTROL,VRH[5:0]
    machine.mem8[LCD_REG] = 0xC0
    machine.mem8[LCD_RAM] = 0x23

    #POWER CONTROL,SAP[2:0]BT[3:0]
    machine.mem8[LCD_REG] = 0xC1
    machine.mem8[LCD_RAM] = 0x10

    #VCM CONTROL
    machine.mem8[LCD_REG] = 0xC5
    machine.mem8[LCD_RAM] = 0x3E
    machine.mem8[LCD_RAM] = 0x28

    #VCM CONTROL 2
    machine.mem8[LCD_REG] = 0xC7
    machine.mem8[LCD_RAM] = 0x86

    #MEMORY ACCESS CONTROL
    machine.mem8[LCD_REG] = 0x36
    machine.mem8[LCD_RAM] = 0x48

    #PIXEL FORMAT
    machine.mem8[LCD_REG] = 0x3A
    machine.mem8[LCD_RAM] = 0x55

    #FRAME RATIO CONTROL, STANDARD RGB COLOR
    machine.mem8[LCD_REG] = 0xB1
    machine.mem8[LCD_RAM] = 0x00
    machine.mem8[LCD_RAM] = 0x18

    #DISPLAY FUNCTION CONTROL
    machine.mem8[LCD_REG] = 0xB6
    machine.mem8[LCD_RAM] = 0x08
    machine.mem8[LCD_RAM] = 0x82
    machine.mem8[LCD_RAM] = 0x27

    #3GAMMA FUNCTION DISABLE
    machine.mem8[LCD_REG] = 0xF2
    machine.mem8[LCD_RAM] = 0x00

    #GAMMA CURVE SELECTED
    machine.mem8[LCD_REG] = 0x26
    machine.mem8[LCD_RAM] = 0x01

    #POSITIVE GAMMA CORRECTION
    machine.mem8[LCD_REG] = 0xE0
    machine.mem8[LCD_RAM] = 0x0F
    machine.mem8[LCD_RAM] = 0x31
    machine.mem8[LCD_RAM] = 0x2B
    machine.mem8[LCD_RAM] = 0x0C
    machine.mem8[LCD_RAM] = 0x0E
    machine.mem8[LCD_RAM] = 0x08
    machine.mem8[LCD_RAM] = 0x4E
    machine.mem8[LCD_RAM] = 0xF1
    machine.mem8[LCD_RAM] = 0x37
    machine.mem8[LCD_RAM] = 0x07
    machine.mem8[LCD_RAM] = 0x10
    machine.mem8[LCD_RAM] = 0x03
    machine.mem8[LCD_RAM] = 0x0E
    machine.mem8[LCD_RAM] = 0x09
    machine.mem8[LCD_RAM] = 0x00

    #NEGATIVE GAMMA CORRECTION
    machine.mem8[LCD_REG] = 0xE1
    machine.mem8[LCD_RAM] = 0x00
    machine.mem8[LCD_RAM] = 0x0E
    machine.mem8[LCD_RAM] = 0x14
    machine.mem8[LCD_RAM] = 0x03
    machine.mem8[LCD_RAM] = 0x11
    machine.mem8[LCD_RAM] = 0x07
    machine.mem8[LCD_RAM] = 0x31
    machine.mem8[LCD_RAM] = 0xC1
    machine.mem8[LCD_RAM] = 0x48
    machine.mem8[LCD_RAM] = 0x08
    machine.mem8[LCD_RAM] = 0x0F
    machine.mem8[LCD_RAM] = 0x0C
    machine.mem8[LCD_RAM] = 0x31
    machine.mem8[LCD_RAM] = 0x36
    machine.mem8[LCD_RAM] = 0x0F

    #EXIT SLEEP
    machine.mem8[LCD_REG] = 0x11
    time.sleep_ms(120)

    #TURN ON DISPLAY
    machine.mem8[LCD_REG] = 0x29

    #dispaly inversion
    #machine.mem8[LCD_REG] = 0x21

    #setup Memory Access Control
    machine.mem8[LCD_REG] = 0x36
    machine.mem8[LCD_RAM] = 0b00111111

def ILI9341_Set_Address(X1, Y1, X2, Y2):
    #set X min and max
    machine.mem8[LCD_REG] = 0x2A
    machine.mem16[LCD_RAM] = X1>>8
    machine.mem16[LCD_RAM] = X1
    machine.mem16[LCD_RAM] = X2>>8
    machine.mem16[LCD_RAM] = X2

    #set y min and max
    machine.mem8[LCD_REG] = 0x2B
    machine.mem16[LCD_RAM] = Y1>>8
    machine.mem16[LCD_RAM] = Y1
    machine.mem16[LCD_RAM] = Y2>>8
    machine.mem16[LCD_RAM] = Y2

    #write data command
    machine.mem8[LCD_REG] = 0x2C
     
def draw_pixel(X, Y, colour):
    ILI9341_Set_Address(X, Y, X, Y)
    machine.mem16[LCD_RAM] = colour       
The rest I too have seem to got right following on from the snippet you included.

User avatar
JohnLittle
Posts: 11
Joined: Mon Oct 08, 2018 7:10 pm

Re: MCUDev Black STM32F407VET6 + STM32F407ZET6 dev boards

Post by JohnLittle » Sun Jul 21, 2019 4:53 pm

Wow, that's amazing, thanks for doing this!

I wonder if jupyter + micropython can be shared somehow to avoid duplicating work, I seem to have typed exactly the same thing.

For reference, help(stm) outputs the following (see below), so the register address is stm.RCC_AHB3ENR and FSMEN (according to the reference page 166) is bit 0.

For RCC_AHB1ENR, GPIODEN is bit 3 and GPIOEEN bit 4 (page 165).

Code: Select all

object <module 'stm'> is of type module
  __name__ -- stm
  mem8 -- <8-bit memory>
  mem16 -- <16-bit memory>
  mem32 -- <32-bit memory>
  TIM2 -- 1073741824
  TIM3 -- 1073742848
  TIM4 -- 1073743872
  TIM5 -- 1073744896
  TIM6 -- 1073745920
  TIM7 -- 1073746944
  TIM12 -- 1073747968
  TIM13 -- 1073748992
  TIM14 -- 1073750016
  RTC -- 1073752064
  WWDG -- 1073753088
  IWDG -- 1073754112
  I2S2EXT -- 1073755136
  SPI2 -- 1073756160
  SPI3 -- 1073757184
  I2S3EXT -- 1073758208
  USART2 -- 1073759232
  USART3 -- 1073760256
  UART4 -- 1073761280
  UART5 -- 1073762304
  I2C1 -- 1073763328
  I2C2 -- 1073764352
  I2C3 -- 1073765376
  CAN1 -- 1073767424
  CAN2 -- 1073768448
  PWR -- 1073770496
  DAC1 -- 1073771520
  DAC -- 1073771520
  TIM1 -- 1073807360
  TIM8 -- 1073808384
  USART1 -- 1073811456
  USART6 -- 1073812480
  ADC1 -- 1073815552
  ADC2 -- 1073815808
  ADC3 -- 1073816064
  ADC123_COMMON -- 1073816320
  SDIO -- 1073818624
  SPI1 -- 1073819648
  SYSCFG -- 1073821696
  EXTI -- 1073822720
  TIM9 -- 1073823744
  TIM10 -- 1073824768
  TIM11 -- 1073825792
  GPIOA -- 1073872896
  GPIOB -- 1073873920
  GPIOC -- 1073874944
  GPIOD -- 1073875968
  GPIOE -- 1073876992
  GPIOF -- 1073878016
  GPIOG -- 1073879040
  GPIOH -- 1073880064
  GPIOI -- 1073881088
  CRC -- 1073885184
  RCC -- 1073887232
  FLASH -- 1073888256
  DMA1 -- 1073897472
  DMA2 -- 1073898496
  ETH -- 1073905664
  DCMI -- 1342504960
  RNG -- 1342572544
  DBGMCU -- 3758366720
  ADC_SR -- 0
  ADC_CR1 -- 4
  ADC_CR2 -- 8
  ADC_SMPR1 -- 12
  ADC_SMPR2 -- 16
  ADC_JOFR1 -- 20
  ADC_JOFR2 -- 24
  ADC_JOFR3 -- 28
  ADC_JOFR4 -- 32
  ADC_HTR -- 36
  ADC_LTR -- 40
  ADC_SQR1 -- 44
  ADC_SQR2 -- 48
  ADC_SQR3 -- 52
  ADC_JSQR -- 56
  ADC_JDR1 -- 60
  ADC_JDR2 -- 64
  ADC_JDR3 -- 68
  ADC_JDR4 -- 72
  ADC_DR -- 76
  CRC_DR -- 0
  CRC_IDR -- 4
  CRC_CR -- 8
  DAC_CR -- 0
  DAC_SWTRIGR -- 4
  DAC_DHR12R1 -- 8
  DAC_DHR12L1 -- 12
  DAC_DHR8R1 -- 16
  DAC_DHR12R2 -- 20
  DAC_DHR12L2 -- 24
  DAC_DHR8R2 -- 28
  DAC_DHR12RD -- 32
  DAC_DHR12LD -- 36
  DAC_DHR8RD -- 40
  DAC_DOR1 -- 44
  DAC_DOR2 -- 48
  DAC_SR -- 52
  DBGMCU_IDCODE -- 0
  DBGMCU_CR -- 4
  DBGMCU_APB1FZ -- 8
  DBGMCU_APB2FZ -- 12
  DMA_LISR -- 0
  DMA_HISR -- 4
  DMA_LIFCR -- 8
  DMA_HIFCR -- 12
  EXTI_IMR -- 0
  EXTI_EMR -- 4
  EXTI_RTSR -- 8
  EXTI_FTSR -- 12
  EXTI_SWIER -- 16
  EXTI_PR -- 20
  FLASH_ACR -- 0
  FLASH_KEYR -- 4
  FLASH_OPTKEYR -- 8
  FLASH_SR -- 12
  FLASH_CR -- 16
  FLASH_OPTCR -- 20
  FLASH_OPTCR1 -- 24
  GPIO_MODER -- 0
  GPIO_OTYPER -- 4
  GPIO_OSPEEDR -- 8
  GPIO_PUPDR -- 12
  GPIO_IDR -- 16
  GPIO_ODR -- 20
  GPIO_BSRR -- 24
  GPIO_LCKR -- 28
  GPIO_AFR0 -- 32
  GPIO_AFR1 -- 36
  GPIO_BSRRL -- 24
  GPIO_BSRRH -- 26
  SYSCFG_MEMRMP -- 0
  SYSCFG_PMC -- 4
  SYSCFG_EXTICR0 -- 8
  SYSCFG_EXTICR1 -- 12
  SYSCFG_EXTICR2 -- 16
  SYSCFG_EXTICR3 -- 20
  SYSCFG_CMPCR -- 32
  I2C_CR1 -- 0
  I2C_CR2 -- 4
  I2C_OAR1 -- 8
  I2C_OAR2 -- 12
  I2C_DR -- 16
  I2C_SR1 -- 20
  I2C_SR2 -- 24
  I2C_CCR -- 28
  I2C_TRISE -- 32
  IWDG_KR -- 0
  IWDG_PR -- 4
  IWDG_RLR -- 8
  IWDG_SR -- 12
  PWR_CR -- 0
  PWR_CSR -- 4
  RCC_CR -- 0
  RCC_PLLCFGR -- 4
  RCC_CFGR -- 8
  RCC_CIR -- 12
  RCC_AHB1RSTR -- 16
  RCC_AHB2RSTR -- 20
  RCC_AHB3RSTR -- 24
  RCC_APB1RSTR -- 32
  RCC_APB2RSTR -- 36
  RCC_AHB1ENR -- 48
  RCC_AHB2ENR -- 52
  RCC_AHB3ENR -- 56
  RCC_APB1ENR -- 64
  RCC_APB2ENR -- 68
  RCC_AHB1LPENR -- 80
  RCC_AHB2LPENR -- 84
  RCC_AHB3LPENR -- 88
  RCC_APB1LPENR -- 96
  RCC_APB2LPENR -- 100
  RCC_BDCR -- 112
  RCC_CSR -- 116
  RCC_SSCGR -- 128
  RCC_PLLI2SCFGR -- 132
  RTC_TR -- 0
  RTC_DR -- 4
  RTC_CR -- 8
  RTC_ISR -- 12
  RTC_PRER -- 16
  RTC_WUTR -- 20
  RTC_CALIBR -- 24
  RTC_ALRMAR -- 28
  RTC_ALRMBR -- 32
  RTC_WPR -- 36
  RTC_SSR -- 40
  RTC_SHIFTR -- 44
  RTC_TSTR -- 48
  RTC_TSDR -- 52
  RTC_TSSSR -- 56
  RTC_CALR -- 60
  RTC_TAFCR -- 64
  RTC_ALRMASSR -- 68
  RTC_ALRMBSSR -- 72
  RTC_BKP0R -- 80
  RTC_BKP1R -- 84
  RTC_BKP2R -- 88
  RTC_BKP3R -- 92
  RTC_BKP4R -- 96
  RTC_BKP5R -- 100
  RTC_BKP6R -- 104
  RTC_BKP7R -- 108
  RTC_BKP8R -- 112
  RTC_BKP9R -- 116
  RTC_BKP10R -- 120
  RTC_BKP11R -- 124
  RTC_BKP12R -- 128
  RTC_BKP13R -- 132
  RTC_BKP14R -- 136
  RTC_BKP15R -- 140
  RTC_BKP16R -- 144
  RTC_BKP17R -- 148
  RTC_BKP18R -- 152
  RTC_BKP19R -- 156
  SPI_CR1 -- 0
  SPI_CR2 -- 4
  SPI_SR -- 8
  SPI_DR -- 12
  SPI_CRCPR -- 16
  SPI_RXCRCR -- 20
  SPI_TXCRCR -- 24
  SPI_I2SCFGR -- 28
  SPI_I2SPR -- 32
  TIM_CR1 -- 0
  TIM_CR2 -- 4
  TIM_SMCR -- 8
  TIM_DIER -- 12
  TIM_SR -- 16
  TIM_EGR -- 20
  TIM_CCMR1 -- 24
  TIM_CCMR2 -- 28
  TIM_CCER -- 32
  TIM_CNT -- 36
  TIM_PSC -- 40
  TIM_ARR -- 44
  TIM_RCR -- 48
  TIM_CCR1 -- 52
  TIM_CCR2 -- 56
  TIM_CCR3 -- 60
  TIM_CCR4 -- 64
  TIM_BDTR -- 68
  TIM_DCR -- 72
  TIM_DMAR -- 76
  TIM_OR -- 80
  USART_SR -- 0
  USART_DR -- 4
  USART_BRR -- 8
  USART_CR1 -- 12
  USART_CR2 -- 16
  USART_CR3 -- 20
  USART_GTPR -- 24
  WWDG_CR -- 0
  WWDG_CFR -- 4
  WWDG_SR -- 8
  RNG_CR -- 0
  RNG_SR -- 4
  RNG_DR -- 8

DJShadow1966
Posts: 60
Joined: Sun Jun 23, 2019 4:55 am
Location: Gateshead, Tyne and Wear

Re: MCUDev Black STM32F407VET6 + STM32F407ZET6 dev boards

Post by DJShadow1966 » Sun Jul 21, 2019 6:23 pm

Hello John

Many thanks I am pretty much have a similar background to yourself, started programming in Machine code on Z80 CPU some years ago when I was 14 pretty much self taught until mid 20's, still do some machine code, but getting on an memory doesn't work so good.

Getting further on in the code should have something pretty workable by the end of week.

Regards Mike

OutoftheBOTS_
Posts: 847
Joined: Mon Nov 20, 2017 10:18 am

Re: MCUDev Black STM32F407VET6 + STM32F407ZET6 dev boards

Post by OutoftheBOTS_ » Sun Jul 21, 2019 8:44 pm

JohnLittle wrote:
Sun Jul 21, 2019 4:53 pm
Wow, that's amazing, thanks for doing this!

I wonder if jupyter + micropython can be shared somehow to avoid duplicating work, I seem to have typed exactly the same thing.

For reference, help(stm) outputs the following (see below), so the register address is stm.RCC_AHB3ENR and FSMEN (according to the reference page 166) is bit 0.

For RCC_AHB1ENR, GPIODEN is bit 3 and GPIOEEN bit 4 (page 165).

Code: Select all

object <module 'stm'> is of type module
  __name__ -- stm
  mem8 -- <8-bit memory>
  mem16 -- <16-bit memory>
  mem32 -- <32-bit memory>
  TIM2 -- 1073741824
  TIM3 -- 1073742848
  TIM4 -- 1073743872
  TIM5 -- 1073744896
  TIM6 -- 1073745920
  TIM7 -- 1073746944
  TIM12 -- 1073747968
  TIM13 -- 1073748992
  TIM14 -- 1073750016
  RTC -- 1073752064
  WWDG -- 1073753088
  IWDG -- 1073754112
  I2S2EXT -- 1073755136
  SPI2 -- 1073756160
  SPI3 -- 1073757184
  I2S3EXT -- 1073758208
  USART2 -- 1073759232
  USART3 -- 1073760256
  UART4 -- 1073761280
  UART5 -- 1073762304
  I2C1 -- 1073763328
  I2C2 -- 1073764352
  I2C3 -- 1073765376
  CAN1 -- 1073767424
  CAN2 -- 1073768448
  PWR -- 1073770496
  DAC1 -- 1073771520
  DAC -- 1073771520
  TIM1 -- 1073807360
  TIM8 -- 1073808384
  USART1 -- 1073811456
  USART6 -- 1073812480
  ADC1 -- 1073815552
  ADC2 -- 1073815808
  ADC3 -- 1073816064
  ADC123_COMMON -- 1073816320
  SDIO -- 1073818624
  SPI1 -- 1073819648
  SYSCFG -- 1073821696
  EXTI -- 1073822720
  TIM9 -- 1073823744
  TIM10 -- 1073824768
  TIM11 -- 1073825792
  GPIOA -- 1073872896
  GPIOB -- 1073873920
  GPIOC -- 1073874944
  GPIOD -- 1073875968
  GPIOE -- 1073876992
  GPIOF -- 1073878016
  GPIOG -- 1073879040
  GPIOH -- 1073880064
  GPIOI -- 1073881088
  CRC -- 1073885184
  RCC -- 1073887232
  FLASH -- 1073888256
  DMA1 -- 1073897472
  DMA2 -- 1073898496
  ETH -- 1073905664
  DCMI -- 1342504960
  RNG -- 1342572544
  DBGMCU -- 3758366720
  ADC_SR -- 0
  ADC_CR1 -- 4
  ADC_CR2 -- 8
  ADC_SMPR1 -- 12
  ADC_SMPR2 -- 16
  ADC_JOFR1 -- 20
  ADC_JOFR2 -- 24
  ADC_JOFR3 -- 28
  ADC_JOFR4 -- 32
  ADC_HTR -- 36
  ADC_LTR -- 40
  ADC_SQR1 -- 44
  ADC_SQR2 -- 48
  ADC_SQR3 -- 52
  ADC_JSQR -- 56
  ADC_JDR1 -- 60
  ADC_JDR2 -- 64
  ADC_JDR3 -- 68
  ADC_JDR4 -- 72
  ADC_DR -- 76
  CRC_DR -- 0
  CRC_IDR -- 4
  CRC_CR -- 8
  DAC_CR -- 0
  DAC_SWTRIGR -- 4
  DAC_DHR12R1 -- 8
  DAC_DHR12L1 -- 12
  DAC_DHR8R1 -- 16
  DAC_DHR12R2 -- 20
  DAC_DHR12L2 -- 24
  DAC_DHR8R2 -- 28
  DAC_DHR12RD -- 32
  DAC_DHR12LD -- 36
  DAC_DHR8RD -- 40
  DAC_DOR1 -- 44
  DAC_DOR2 -- 48
  DAC_SR -- 52
  DBGMCU_IDCODE -- 0
  DBGMCU_CR -- 4
  DBGMCU_APB1FZ -- 8
  DBGMCU_APB2FZ -- 12
  DMA_LISR -- 0
  DMA_HISR -- 4
  DMA_LIFCR -- 8
  DMA_HIFCR -- 12
  EXTI_IMR -- 0
  EXTI_EMR -- 4
  EXTI_RTSR -- 8
  EXTI_FTSR -- 12
  EXTI_SWIER -- 16
  EXTI_PR -- 20
  FLASH_ACR -- 0
  FLASH_KEYR -- 4
  FLASH_OPTKEYR -- 8
  FLASH_SR -- 12
  FLASH_CR -- 16
  FLASH_OPTCR -- 20
  FLASH_OPTCR1 -- 24
  GPIO_MODER -- 0
  GPIO_OTYPER -- 4
  GPIO_OSPEEDR -- 8
  GPIO_PUPDR -- 12
  GPIO_IDR -- 16
  GPIO_ODR -- 20
  GPIO_BSRR -- 24
  GPIO_LCKR -- 28
  GPIO_AFR0 -- 32
  GPIO_AFR1 -- 36
  GPIO_BSRRL -- 24
  GPIO_BSRRH -- 26
  SYSCFG_MEMRMP -- 0
  SYSCFG_PMC -- 4
  SYSCFG_EXTICR0 -- 8
  SYSCFG_EXTICR1 -- 12
  SYSCFG_EXTICR2 -- 16
  SYSCFG_EXTICR3 -- 20
  SYSCFG_CMPCR -- 32
  I2C_CR1 -- 0
  I2C_CR2 -- 4
  I2C_OAR1 -- 8
  I2C_OAR2 -- 12
  I2C_DR -- 16
  I2C_SR1 -- 20
  I2C_SR2 -- 24
  I2C_CCR -- 28
  I2C_TRISE -- 32
  IWDG_KR -- 0
  IWDG_PR -- 4
  IWDG_RLR -- 8
  IWDG_SR -- 12
  PWR_CR -- 0
  PWR_CSR -- 4
  RCC_CR -- 0
  RCC_PLLCFGR -- 4
  RCC_CFGR -- 8
  RCC_CIR -- 12
  RCC_AHB1RSTR -- 16
  RCC_AHB2RSTR -- 20
  RCC_AHB3RSTR -- 24
  RCC_APB1RSTR -- 32
  RCC_APB2RSTR -- 36
  RCC_AHB1ENR -- 48
  RCC_AHB2ENR -- 52
  RCC_AHB3ENR -- 56
  RCC_APB1ENR -- 64
  RCC_APB2ENR -- 68
  RCC_AHB1LPENR -- 80
  RCC_AHB2LPENR -- 84
  RCC_AHB3LPENR -- 88
  RCC_APB1LPENR -- 96
  RCC_APB2LPENR -- 100
  RCC_BDCR -- 112
  RCC_CSR -- 116
  RCC_SSCGR -- 128
  RCC_PLLI2SCFGR -- 132
  RTC_TR -- 0
  RTC_DR -- 4
  RTC_CR -- 8
  RTC_ISR -- 12
  RTC_PRER -- 16
  RTC_WUTR -- 20
  RTC_CALIBR -- 24
  RTC_ALRMAR -- 28
  RTC_ALRMBR -- 32
  RTC_WPR -- 36
  RTC_SSR -- 40
  RTC_SHIFTR -- 44
  RTC_TSTR -- 48
  RTC_TSDR -- 52
  RTC_TSSSR -- 56
  RTC_CALR -- 60
  RTC_TAFCR -- 64
  RTC_ALRMASSR -- 68
  RTC_ALRMBSSR -- 72
  RTC_BKP0R -- 80
  RTC_BKP1R -- 84
  RTC_BKP2R -- 88
  RTC_BKP3R -- 92
  RTC_BKP4R -- 96
  RTC_BKP5R -- 100
  RTC_BKP6R -- 104
  RTC_BKP7R -- 108
  RTC_BKP8R -- 112
  RTC_BKP9R -- 116
  RTC_BKP10R -- 120
  RTC_BKP11R -- 124
  RTC_BKP12R -- 128
  RTC_BKP13R -- 132
  RTC_BKP14R -- 136
  RTC_BKP15R -- 140
  RTC_BKP16R -- 144
  RTC_BKP17R -- 148
  RTC_BKP18R -- 152
  RTC_BKP19R -- 156
  SPI_CR1 -- 0
  SPI_CR2 -- 4
  SPI_SR -- 8
  SPI_DR -- 12
  SPI_CRCPR -- 16
  SPI_RXCRCR -- 20
  SPI_TXCRCR -- 24
  SPI_I2SCFGR -- 28
  SPI_I2SPR -- 32
  TIM_CR1 -- 0
  TIM_CR2 -- 4
  TIM_SMCR -- 8
  TIM_DIER -- 12
  TIM_SR -- 16
  TIM_EGR -- 20
  TIM_CCMR1 -- 24
  TIM_CCMR2 -- 28
  TIM_CCER -- 32
  TIM_CNT -- 36
  TIM_PSC -- 40
  TIM_ARR -- 44
  TIM_RCR -- 48
  TIM_CCR1 -- 52
  TIM_CCR2 -- 56
  TIM_CCR3 -- 60
  TIM_CCR4 -- 64
  TIM_BDTR -- 68
  TIM_DCR -- 72
  TIM_DMAR -- 76
  TIM_OR -- 80
  USART_SR -- 0
  USART_DR -- 4
  USART_BRR -- 8
  USART_CR1 -- 12
  USART_CR2 -- 16
  USART_CR3 -- 20
  USART_GTPR -- 24
  WWDG_CR -- 0
  WWDG_CFR -- 4
  WWDG_SR -- 8
  RNG_CR -- 0
  RNG_SR -- 4
  RNG_DR -- 8
Ok you guys are making great progress and are likely to it working using just a pure python implementation.

I do notice that the reference manual quoted above is for the STM32F7 not the STMF407 do be aware the registers are different between the 2 MCUs and I believe this is why the authors of MP use the HAL libraries so to make code more portable between the MCUs.

Use this refernce manual for the STMF4 https://www.st.com/content/ccc/resource ... 031020.pdf

Also if you want to see the exact memory addresses that I have used you can always look at the maco definitions in STM32F4xx.h

OutoftheBOTS_
Posts: 847
Joined: Mon Nov 20, 2017 10:18 am

Re: MCUDev Black STM32F407VET6 + STM32F407ZET6 dev boards

Post by OutoftheBOTS_ » Sun Jul 21, 2019 9:09 pm

DJShadow1966 wrote:
Sun Jul 21, 2019 2:35 pm
Hello John

Been working on this too and have a lot of code already written stuck on some :-

Code: Select all

void FSMC_Init(void){
	//enable RCC for FSMC and both GPIO ports
	RCC->AHB3ENR |= RCC_AHB3ENR_FSMCEN;
	RCC->AHB1ENR |= RCC_AHB1ENR_GPIODEN | RCC_AHB1ENR_GPIOEEN;
and

Code: Select all

	//setup FSMC on Bank1 NORSRAM1
	//setup timings of FSCM
	FSMC_Bank1->BTCR[1] = FSMC_BTR1_ADDSET_1 | FSMC_BTR1_DATAST_1;
	// Bank1 NOR/SRAM control register configuration
	FSMC_Bank1->BTCR[0] = FSMC_BCR1_MWID_0 | FSMC_BCR1_WREN | FSMC_BCR1_MBKEN;
Currently my code is :-

Code: Select all

import stm
import time
import machine

stm.RCC_AHB3ENR |=
stm.RCC_AHB3ENR |=
stm.RCC_AHB1ENR |= [stm.RCC_AHB1ENR 

machine.mem16[stm.GPIOD + stm.GPIO_MODER] = 0b1100111110110011
machine.mem16[stm.GPIOE + stm.GPIO_MODER] = 0b1111111110000000

machine.mem16[stm.GPIOD + stm.GPIO_OTYPER] &= 0b0011000001001100
machine.mem16[stm.GPIOE + stm.GPIO_OTYPER] &= 0b0000000001111111

machine.mem16[stm.GPIOD + stm.GPIO_OSPEEDR] |= (0b11<<(2*0)) | (0b11<<(2*1)) | (0b11<<(2*4)) | (0b11<<(2*5)) | (0b11<<(2*7)) | (0b11<<(2*8)) | (0b11<<(2*9)) | (0b11<<(2*10)) | (0b11<<(2*11)) | (0b11<<(2*14)) | (0b11<<(2*15))
machine.mem16[stm.GPIOE + stm.GPIO_OSPEEDR] |= (0b11<<(2*7)) | (0b11<<(2*8)) | (0b11<<(2*9)) | (0b11<<(2*10)) | (0b11<<(2*11)) | (0b11<<(2*12)) | (0b11<<(2*13)) | (0b11<<(2*14)) | (0b11<<(2*15))

machine.mem16[stm.GPIOD + stm.GPIO_PUPDR] &= ((0b11<<(2*2)) | (0b11<<(2*3)) | (0b11<<(2*6)) | (0b11<<(2*12)) | (0b11<<(2*13)))
machine.mem16[stm.GPIOE + stm.GPIO_PUPDR] &= ((0b11<<(2*0)) | (0b11<<(2*1)) | (0b11<<(2*2)) | (0b11<<(2*3)) | (0b11<<(2*4)) | (0b11<<(2*5)) | (0b11<<(2*6)))

machine.mem16[stm.GPIOD + stm.GPIO_AFR0] = (machine.mem16[stm.GPIOD + stm.GPIO_AFR0] & (0b1111<<(4*2) | 0b1111<<(4*3) | 0b1111<<(4*6))) | 0b1100<<(4*0) | 0b1100<<(4*1) | 0b1100<<(4*4) | 0b1100<<(4*5) | 0b1100<<(4*7)
machine.mem16[stm.GPIOD + stm.GPIO_AFR1] = (machine.mem16[stm.GPIOD + stm.GPIO_AFR1] & (0b1111<<(4*(13-8)) | 0b1111<<(4*(12-8)))) | 0b1100<<(4*(8-8)) | 0b1100<<(4*(9-8)) | 0b1100<<(4*(10-8)) | 0b1100<<(4*(11-8)) | 0b1100<<(4*(14-8)) | 0b1100<<(4*(15-8))

machine.mem16[stm.GPIOE + stm.GPIO_AFR0] = (machine.mem16[stm.GPIOE + stm.GPIO_AFR0] & ~(0b1111<<7)) | 0b1100<<(4*7)
machine.mem16[stm.GPIOE + stm.GPIO_AFR1] = 0xCCCCCCCC

LCD_REG = const(0x60000000)
LCD_RAM = const(0x60040000)

def TFT_Init():
    BIT12 = const(1 << 12)
    _BIT12 = const(0xFFFF ^ BIT12)

    #hardware reset
    machine.mem16[stm.GPIO_ODR] &= _BIT12
    time.sleep_ms(250)
    machine.mem16[stm.GPIO_ODR] |= BIT12
    time.sleep_ms(120)

    #SOFTWARE RESET
    machine.mem8[LCD_REG] = 0x01
    time.sleep_ms(1000)

    #POWER CONTROL A
    machine.mem8[LCD_REG] = 0xCB
    machine.mem8[LCD_RAM] = 0x39
    machine.mem8[LCD_RAM] = 0x2C
    machine.mem8[LCD_RAM] = 0x00
    machine.mem8[LCD_RAM] = 0x34
    machine.mem8[LCD_RAM] = 0x02
    
    #DRIVER TIMING CONTROL A
    machine.mem8[LCD_REG] = 0xE8
    machine.mem8[LCD_RAM] = 0x85
    machine.mem8[LCD_RAM] = 0x00
    machine.mem8[LCD_RAM] = 0x78
    
    #DRIVER TIMING CONTROL B
    machine.mem8[LCD_REG] = 0xEA
    machine.mem8[LCD_RAM] = 0x00
    machine.mem8[LCD_RAM] = 0x00
    
    #POWER ON SEQUENCE CONTROL
    machine.mem8[LCD_REG] = 0xED
    machine.mem8[LCD_RAM] = 0x64
    machine.mem8[LCD_RAM] = 0x03
    machine.mem8[LCD_RAM] = 0x12
    machine.mem8[LCD_RAM] = 0x81

    #PUMP RATIO CONTROL
    machine.mem8[LCD_REG] = 0xF7
    machine.mem8[LCD_RAM] = 0x20

    #POWER CONTROL,VRH[5:0]
    machine.mem8[LCD_REG] = 0xC0
    machine.mem8[LCD_RAM] = 0x23

    #POWER CONTROL,SAP[2:0]BT[3:0]
    machine.mem8[LCD_REG] = 0xC1
    machine.mem8[LCD_RAM] = 0x10

    #VCM CONTROL
    machine.mem8[LCD_REG] = 0xC5
    machine.mem8[LCD_RAM] = 0x3E
    machine.mem8[LCD_RAM] = 0x28

    #VCM CONTROL 2
    machine.mem8[LCD_REG] = 0xC7
    machine.mem8[LCD_RAM] = 0x86

    #MEMORY ACCESS CONTROL
    machine.mem8[LCD_REG] = 0x36
    machine.mem8[LCD_RAM] = 0x48

    #PIXEL FORMAT
    machine.mem8[LCD_REG] = 0x3A
    machine.mem8[LCD_RAM] = 0x55

    #FRAME RATIO CONTROL, STANDARD RGB COLOR
    machine.mem8[LCD_REG] = 0xB1
    machine.mem8[LCD_RAM] = 0x00
    machine.mem8[LCD_RAM] = 0x18

    #DISPLAY FUNCTION CONTROL
    machine.mem8[LCD_REG] = 0xB6
    machine.mem8[LCD_RAM] = 0x08
    machine.mem8[LCD_RAM] = 0x82
    machine.mem8[LCD_RAM] = 0x27

    #3GAMMA FUNCTION DISABLE
    machine.mem8[LCD_REG] = 0xF2
    machine.mem8[LCD_RAM] = 0x00

    #GAMMA CURVE SELECTED
    machine.mem8[LCD_REG] = 0x26
    machine.mem8[LCD_RAM] = 0x01

    #POSITIVE GAMMA CORRECTION
    machine.mem8[LCD_REG] = 0xE0
    machine.mem8[LCD_RAM] = 0x0F
    machine.mem8[LCD_RAM] = 0x31
    machine.mem8[LCD_RAM] = 0x2B
    machine.mem8[LCD_RAM] = 0x0C
    machine.mem8[LCD_RAM] = 0x0E
    machine.mem8[LCD_RAM] = 0x08
    machine.mem8[LCD_RAM] = 0x4E
    machine.mem8[LCD_RAM] = 0xF1
    machine.mem8[LCD_RAM] = 0x37
    machine.mem8[LCD_RAM] = 0x07
    machine.mem8[LCD_RAM] = 0x10
    machine.mem8[LCD_RAM] = 0x03
    machine.mem8[LCD_RAM] = 0x0E
    machine.mem8[LCD_RAM] = 0x09
    machine.mem8[LCD_RAM] = 0x00

    #NEGATIVE GAMMA CORRECTION
    machine.mem8[LCD_REG] = 0xE1
    machine.mem8[LCD_RAM] = 0x00
    machine.mem8[LCD_RAM] = 0x0E
    machine.mem8[LCD_RAM] = 0x14
    machine.mem8[LCD_RAM] = 0x03
    machine.mem8[LCD_RAM] = 0x11
    machine.mem8[LCD_RAM] = 0x07
    machine.mem8[LCD_RAM] = 0x31
    machine.mem8[LCD_RAM] = 0xC1
    machine.mem8[LCD_RAM] = 0x48
    machine.mem8[LCD_RAM] = 0x08
    machine.mem8[LCD_RAM] = 0x0F
    machine.mem8[LCD_RAM] = 0x0C
    machine.mem8[LCD_RAM] = 0x31
    machine.mem8[LCD_RAM] = 0x36
    machine.mem8[LCD_RAM] = 0x0F

    #EXIT SLEEP
    machine.mem8[LCD_REG] = 0x11
    time.sleep_ms(120)

    #TURN ON DISPLAY
    machine.mem8[LCD_REG] = 0x29

    #dispaly inversion
    #machine.mem8[LCD_REG] = 0x21

    #setup Memory Access Control
    machine.mem8[LCD_REG] = 0x36
    machine.mem8[LCD_RAM] = 0b00111111

def ILI9341_Set_Address(X1, Y1, X2, Y2):
    #set X min and max
    machine.mem8[LCD_REG] = 0x2A
    machine.mem16[LCD_RAM] = X1>>8
    machine.mem16[LCD_RAM] = X1
    machine.mem16[LCD_RAM] = X2>>8
    machine.mem16[LCD_RAM] = X2

    #set y min and max
    machine.mem8[LCD_REG] = 0x2B
    machine.mem16[LCD_RAM] = Y1>>8
    machine.mem16[LCD_RAM] = Y1
    machine.mem16[LCD_RAM] = Y2>>8
    machine.mem16[LCD_RAM] = Y2

    #write data command
    machine.mem8[LCD_REG] = 0x2C
     
def draw_pixel(X, Y, colour):
    ILI9341_Set_Address(X, Y, X, Y)
    machine.mem16[LCD_RAM] = colour       
The rest I too have seem to got right following on from the snippet you included.
The STM32 has 32 bit registers so you will need to use machine.mem32[] to write to the STM32 registers then when writing to the TFT GRAM you will need to use machine.mem16[] as it write 16 bits of data at a time but when you write to the TFT control register you will need to use machine.mem8[] as the TFT only has 8 bit regiters

OutoftheBOTS_
Posts: 847
Joined: Mon Nov 20, 2017 10:18 am

Re: MCUDev Black STM32F407VET6 + STM32F407ZET6 dev boards

Post by OutoftheBOTS_ » Sun Jul 21, 2019 10:41 pm

Also when I wired up my TFT I mainly used the TFT header on the STM32F407VRT6 black except I used different pin for the RS/DC pin and reset pin.

On the header it connects the reset pin to the reset button on the board but I connected it to PD12 so that I could do a hardware reset in software so if your just using the pins on the TFT header then you won't need to setup PD12 and you won't need the first few lines in the init.

Also I used A16 (PD11) as the RS/DC pin because I wanted to wire the same as others had that were programming in MBed so I didn't connect my RS/DC pin on the TFT to the header but rather connected it to PD11 on the main break out header. The TFT header uses A18(PD13) as the RS/DC pin so this means in the code were it is setting up the pins to AF_FSMC you will need to change it so that it sets up PD13 instead of PD11.

Also you will of course need to then change the address of LCD_RAM. I used 0x60020000 because 0x60000000 (base address) + 0x20000 (A16) if you going to use the TFT header pins and A18 as your RS/DC then the LCD_RAM address will be 0x60080000. You will notice that those addresses seem to be 1 bit out and this confused me for ages before I got it to work but it seems in 16bit mode the STM maps (moves) the address bits to the side by 1 bit see following answer from the net
Turns out that address bits differ between 8-bit and 16-bit addressing mode. In 8-bit addressing it's mapped to bits [0-23] and in 16-bit to [1-24], so if you want to use A16 pin as CMD / DATA selection, the address of DATA transfer is 0x60010000 in 8-bit mode and 0x60020000 in 16-bit.

OutoftheBOTS_
Posts: 847
Joined: Mon Nov 20, 2017 10:18 am

Re: MCUDev Black STM32F407VET6 + STM32F407ZET6 dev boards

Post by OutoftheBOTS_ » Mon Jul 22, 2019 6:18 am

DJShadow1966 wrote:
Sun Jul 21, 2019 2:35 pm
Hello John

Been working on this too and have a lot of code already written stuck on some :-

Code: Select all

void FSMC_Init(void){
	//enable RCC for FSMC and both GPIO ports
	RCC->AHB3ENR |= RCC_AHB3ENR_FSMCEN;
	RCC->AHB1ENR |= RCC_AHB1ENR_GPIODEN | RCC_AHB1ENR_GPIOEEN;
and

Code: Select all

	//setup FSMC on Bank1 NORSRAM1
	//setup timings of FSCM
	FSMC_Bank1->BTCR[1] = FSMC_BTR1_ADDSET_1 | FSMC_BTR1_DATAST_1;
	// Bank1 NOR/SRAM control register configuration
	FSMC_Bank1->BTCR[0] = FSMC_BCR1_MWID_0 | FSMC_BCR1_WREN | FSMC_BCR1_MBKEN;
Currently my code is :-

Code: Select all

import stm
import time
import machine

stm.RCC_AHB3ENR |=
stm.RCC_AHB3ENR |=
stm.RCC_AHB1ENR |= [stm.RCC_AHB1ENR 

machine.mem16[stm.GPIOD + stm.GPIO_MODER] = 0b1100111110110011
machine.mem16[stm.GPIOE + stm.GPIO_MODER] = 0b1111111110000000

machine.mem16[stm.GPIOD + stm.GPIO_OTYPER] &= 0b0011000001001100
machine.mem16[stm.GPIOE + stm.GPIO_OTYPER] &= 0b0000000001111111

machine.mem16[stm.GPIOD + stm.GPIO_OSPEEDR] |= (0b11<<(2*0)) | (0b11<<(2*1)) | (0b11<<(2*4)) | (0b11<<(2*5)) | (0b11<<(2*7)) | (0b11<<(2*8)) | (0b11<<(2*9)) | (0b11<<(2*10)) | (0b11<<(2*11)) | (0b11<<(2*14)) | (0b11<<(2*15))
machine.mem16[stm.GPIOE + stm.GPIO_OSPEEDR] |= (0b11<<(2*7)) | (0b11<<(2*8)) | (0b11<<(2*9)) | (0b11<<(2*10)) | (0b11<<(2*11)) | (0b11<<(2*12)) | (0b11<<(2*13)) | (0b11<<(2*14)) | (0b11<<(2*15))

machine.mem16[stm.GPIOD + stm.GPIO_PUPDR] &= ((0b11<<(2*2)) | (0b11<<(2*3)) | (0b11<<(2*6)) | (0b11<<(2*12)) | (0b11<<(2*13)))
machine.mem16[stm.GPIOE + stm.GPIO_PUPDR] &= ((0b11<<(2*0)) | (0b11<<(2*1)) | (0b11<<(2*2)) | (0b11<<(2*3)) | (0b11<<(2*4)) | (0b11<<(2*5)) | (0b11<<(2*6)))

machine.mem16[stm.GPIOD + stm.GPIO_AFR0] = (machine.mem16[stm.GPIOD + stm.GPIO_AFR0] & (0b1111<<(4*2) | 0b1111<<(4*3) | 0b1111<<(4*6))) | 0b1100<<(4*0) | 0b1100<<(4*1) | 0b1100<<(4*4) | 0b1100<<(4*5) | 0b1100<<(4*7)
machine.mem16[stm.GPIOD + stm.GPIO_AFR1] = (machine.mem16[stm.GPIOD + stm.GPIO_AFR1] & (0b1111<<(4*(13-8)) | 0b1111<<(4*(12-8)))) | 0b1100<<(4*(8-8)) | 0b1100<<(4*(9-8)) | 0b1100<<(4*(10-8)) | 0b1100<<(4*(11-8)) | 0b1100<<(4*(14-8)) | 0b1100<<(4*(15-8))

machine.mem16[stm.GPIOE + stm.GPIO_AFR0] = (machine.mem16[stm.GPIOE + stm.GPIO_AFR0] & ~(0b1111<<7)) | 0b1100<<(4*7)
machine.mem16[stm.GPIOE + stm.GPIO_AFR1] = 0xCCCCCCCC

LCD_REG = const(0x60000000)
LCD_RAM = const(0x60040000)

def TFT_Init():
    BIT12 = const(1 << 12)
    _BIT12 = const(0xFFFF ^ BIT12)

    #hardware reset
    machine.mem16[stm.GPIO_ODR] &= _BIT12
    time.sleep_ms(250)
    machine.mem16[stm.GPIO_ODR] |= BIT12
    time.sleep_ms(120)

    #SOFTWARE RESET
    machine.mem8[LCD_REG] = 0x01
    time.sleep_ms(1000)

    #POWER CONTROL A
    machine.mem8[LCD_REG] = 0xCB
    machine.mem8[LCD_RAM] = 0x39
    machine.mem8[LCD_RAM] = 0x2C
    machine.mem8[LCD_RAM] = 0x00
    machine.mem8[LCD_RAM] = 0x34
    machine.mem8[LCD_RAM] = 0x02
    
    #DRIVER TIMING CONTROL A
    machine.mem8[LCD_REG] = 0xE8
    machine.mem8[LCD_RAM] = 0x85
    machine.mem8[LCD_RAM] = 0x00
    machine.mem8[LCD_RAM] = 0x78
    
    #DRIVER TIMING CONTROL B
    machine.mem8[LCD_REG] = 0xEA
    machine.mem8[LCD_RAM] = 0x00
    machine.mem8[LCD_RAM] = 0x00
    
    #POWER ON SEQUENCE CONTROL
    machine.mem8[LCD_REG] = 0xED
    machine.mem8[LCD_RAM] = 0x64
    machine.mem8[LCD_RAM] = 0x03
    machine.mem8[LCD_RAM] = 0x12
    machine.mem8[LCD_RAM] = 0x81

    #PUMP RATIO CONTROL
    machine.mem8[LCD_REG] = 0xF7
    machine.mem8[LCD_RAM] = 0x20

    #POWER CONTROL,VRH[5:0]
    machine.mem8[LCD_REG] = 0xC0
    machine.mem8[LCD_RAM] = 0x23

    #POWER CONTROL,SAP[2:0]BT[3:0]
    machine.mem8[LCD_REG] = 0xC1
    machine.mem8[LCD_RAM] = 0x10

    #VCM CONTROL
    machine.mem8[LCD_REG] = 0xC5
    machine.mem8[LCD_RAM] = 0x3E
    machine.mem8[LCD_RAM] = 0x28

    #VCM CONTROL 2
    machine.mem8[LCD_REG] = 0xC7
    machine.mem8[LCD_RAM] = 0x86

    #MEMORY ACCESS CONTROL
    machine.mem8[LCD_REG] = 0x36
    machine.mem8[LCD_RAM] = 0x48

    #PIXEL FORMAT
    machine.mem8[LCD_REG] = 0x3A
    machine.mem8[LCD_RAM] = 0x55

    #FRAME RATIO CONTROL, STANDARD RGB COLOR
    machine.mem8[LCD_REG] = 0xB1
    machine.mem8[LCD_RAM] = 0x00
    machine.mem8[LCD_RAM] = 0x18

    #DISPLAY FUNCTION CONTROL
    machine.mem8[LCD_REG] = 0xB6
    machine.mem8[LCD_RAM] = 0x08
    machine.mem8[LCD_RAM] = 0x82
    machine.mem8[LCD_RAM] = 0x27

    #3GAMMA FUNCTION DISABLE
    machine.mem8[LCD_REG] = 0xF2
    machine.mem8[LCD_RAM] = 0x00

    #GAMMA CURVE SELECTED
    machine.mem8[LCD_REG] = 0x26
    machine.mem8[LCD_RAM] = 0x01

    #POSITIVE GAMMA CORRECTION
    machine.mem8[LCD_REG] = 0xE0
    machine.mem8[LCD_RAM] = 0x0F
    machine.mem8[LCD_RAM] = 0x31
    machine.mem8[LCD_RAM] = 0x2B
    machine.mem8[LCD_RAM] = 0x0C
    machine.mem8[LCD_RAM] = 0x0E
    machine.mem8[LCD_RAM] = 0x08
    machine.mem8[LCD_RAM] = 0x4E
    machine.mem8[LCD_RAM] = 0xF1
    machine.mem8[LCD_RAM] = 0x37
    machine.mem8[LCD_RAM] = 0x07
    machine.mem8[LCD_RAM] = 0x10
    machine.mem8[LCD_RAM] = 0x03
    machine.mem8[LCD_RAM] = 0x0E
    machine.mem8[LCD_RAM] = 0x09
    machine.mem8[LCD_RAM] = 0x00

    #NEGATIVE GAMMA CORRECTION
    machine.mem8[LCD_REG] = 0xE1
    machine.mem8[LCD_RAM] = 0x00
    machine.mem8[LCD_RAM] = 0x0E
    machine.mem8[LCD_RAM] = 0x14
    machine.mem8[LCD_RAM] = 0x03
    machine.mem8[LCD_RAM] = 0x11
    machine.mem8[LCD_RAM] = 0x07
    machine.mem8[LCD_RAM] = 0x31
    machine.mem8[LCD_RAM] = 0xC1
    machine.mem8[LCD_RAM] = 0x48
    machine.mem8[LCD_RAM] = 0x08
    machine.mem8[LCD_RAM] = 0x0F
    machine.mem8[LCD_RAM] = 0x0C
    machine.mem8[LCD_RAM] = 0x31
    machine.mem8[LCD_RAM] = 0x36
    machine.mem8[LCD_RAM] = 0x0F

    #EXIT SLEEP
    machine.mem8[LCD_REG] = 0x11
    time.sleep_ms(120)

    #TURN ON DISPLAY
    machine.mem8[LCD_REG] = 0x29

    #dispaly inversion
    #machine.mem8[LCD_REG] = 0x21

    #setup Memory Access Control
    machine.mem8[LCD_REG] = 0x36
    machine.mem8[LCD_RAM] = 0b00111111

def ILI9341_Set_Address(X1, Y1, X2, Y2):
    #set X min and max
    machine.mem8[LCD_REG] = 0x2A
    machine.mem16[LCD_RAM] = X1>>8
    machine.mem16[LCD_RAM] = X1
    machine.mem16[LCD_RAM] = X2>>8
    machine.mem16[LCD_RAM] = X2

    #set y min and max
    machine.mem8[LCD_REG] = 0x2B
    machine.mem16[LCD_RAM] = Y1>>8
    machine.mem16[LCD_RAM] = Y1
    machine.mem16[LCD_RAM] = Y2>>8
    machine.mem16[LCD_RAM] = Y2

    #write data command
    machine.mem8[LCD_REG] = 0x2C
     
def draw_pixel(X, Y, colour):
    ILI9341_Set_Address(X, Y, X, Y)
    machine.mem16[LCD_RAM] = colour       
The rest I too have seem to got right following on from the snippet you included.
There might not be definitions already in MP for the FSMC register so we can define some. The couple we need start on page 1577 of the reference manual https://www.st.com/content/ccc/resource ... 031020.pdf

The ones your stuck on should look something like this

Code: Select all

#constants of register
RCC_AHB3ENR_FSMCEN = 0x1 #bit to enable FSMC clock
RCC_AHB1ENR_GPIODEN = (0x1 << 3) #bit to enable D port clock
RCC_AHB1ENR_GPIOEEN = (0x1U << 4U) #bit to enable E port clock
FSMC_Bank1_base = 0xA0000000U # FSMC registers base address
FSMC_BCR_bank1_offset = 0x0
FSMC_BTR_bank1_offset = 0x04
FSMC_BTR1_ADDSET_1 = 0x2 
FSMC_BTR1_DATAST_1 = (0x02 << 8)
FSMC_BCR1_MWID_0 = (0x1 << 4)
FSMC_BCR1_WREN = (0x1 << 12)
FSMC_BCR1_MBKEN = 0x1

#RCC->AHB3ENR |= RCC_AHB3ENR_FSMCEN;
machine.mem32[stm.RCC_AHB3ENR] |= RCC_AHB3ENR_FSMCEN


#this shouldn't be needed in MP as MP should have already enabled all the clocks for all the GPIO ports
#RCC->AHB1ENR |= RCC_AHB1ENR_GPIODEN | RCC_AHB1ENR_GPIOEEN;
machine.mem32[stm.RCC_AHB1ENR] |= RCC_AHB1ENR_GPIODEN | RCC_AHB1ENR_GPIOEEN

#FSMC_Bank1->BTCR[1] = FSMC_BTR1_ADDSET_1 | FSMC_BTR1_DATAST_1;
machine.mem32[FSMC_Bank1_base + FSMC_BCR_bank1_offset] = FSMC_BTR1_ADDSET_1 | FSMC_BTR1_DATAST_1

#FSMC_Bank1->BTCR[0] = FSMC_BCR1_MWID_0 | FSMC_BCR1_WREN | FSMC_BCR1_MBKEN;
machine.mem32[FSMC_Bank1_base + FSMC_BTR_bank1_offset] = FSMC_BCR1_MWID_0 | FSMC_BCR1_WREN | FSMC_BCR1_MBKEN

DJShadow1966
Posts: 60
Joined: Sun Jun 23, 2019 4:55 am
Location: Gateshead, Tyne and Wear

Re: MCUDev Black STM32F407VET6 + STM32F407ZET6 dev boards

Post by DJShadow1966 » Mon Jul 22, 2019 7:28 am

Hello OutOfBots

Wish I had refreshed the post as I pretty much have typed up what you put. Again many thanks for all your help. So pretty much I now have :-

Code: Select all

import stm
import time
import machine

def FSMC_Init():
    #constants of register
    RCC_AHB3ENR_FSMCEN = 0x1 #bit to enable FSMC clock
    RCC_AHB1ENR_GPIODEN = (0x1 << 3) #bit to enable D port clock
    RCC_AHB1ENR_GPIOEEN = (0x1 << 4) #bit to enable E port clock
    FSMC_Bank1_base = 0xA0000000 # FSMC registers base address
    FSMC_BCR_bank1_offset = 0x0
    FSMC_BTR_bank1_offset = 0x04
    FSMC_BTR1_ADDSET_1 = 0x2 
    FSMC_BTR1_DATAST_1 = (0x02 << 8)
    FSMC_BCR1_MWID_0 = (0x1 << 4)
    FSMC_BCR1_WREN = (0x1 << 12)
    FSMC_BCR1_MBKEN = 0x1
    
    machine.mem32[stm.RCC_AHB3ENR] |= RCC_AHB3ENR_FSMCEN
    machine.mem32[stm.RCC_AHB1ENR] |= RCC_AHB1ENR_GPIODEN | RCC_AHB1ENR_GPIOEEN
    
    machine.mem32[stm.GPIOD + stm.GPIO_MODER] |= 0b1100111110110011
    machine.mem32[stm.GPIOE + stm.GPIO_MODER] |= 0b1111111110000000

    machine.mem32[stm.GPIOD + stm.GPIO_OTYPER] &= 0b0011000001001100
    machine.mem32[stm.GPIOE + stm.GPIO_OTYPER] &= 0b0000000001111111

    machine.mem32[stm.GPIOD + stm.GPIO_OSPEEDR] |= (0b11<<(2*0)) | (0b11<<(2*1)) | (0b11<<(2*4)) | (0b11<<(2*5)) | (0b11<<(2*7)) | (0b11<<(2*8)) | (0b11<<(2*9)) | (0b11<<(2*10)) | (0b11<<(2*11)) | (0b11<<(2*14)) | (0b11<<(2*15))
    machine.mem32[stm.GPIOE + stm.GPIO_OSPEEDR] |= (0b11<<(2*7)) | (0b11<<(2*8)) | (0b11<<(2*9)) | (0b11<<(2*10)) | (0b11<<(2*11)) | (0b11<<(2*12)) | (0b11<<(2*13)) | (0b11<<(2*14)) | (0b11<<(2*15))

    machine.mem32[stm.GPIOD + stm.GPIO_PUPDR] &= ((0b11<<(2*2)) | (0b11<<(2*3)) | (0b11<<(2*6)) | (0b11<<(2*12)) | (0b11<<(2*13)))
    machine.mem32[stm.GPIOE + stm.GPIO_PUPDR] &= ((0b11<<(2*0)) | (0b11<<(2*1)) | (0b11<<(2*2)) | (0b11<<(2*3)) | (0b11<<(2*4)) | (0b11<<(2*5)) | (0b11<<(2*6)))

    machine.mem32[stm.GPIOD + stm.GPIO_AFR0] = (machine.mem32[stm.GPIOD + stm.GPIO_AFR0] & (0b1111<<(4*2) | 0b1111<<(4*3) | 0b1111<<(4*6))) | 0b1100<<(4*0) | 0b1100<<(4*1) | 0b1100<<(4*4) | 0b1100<<(4*5) | 0b1100<<(4*7)
    machine.mem32[stm.GPIOD + stm.GPIO_AFR1] = (machine.mem32[stm.GPIOD + stm.GPIO_AFR1] & (0b1111<<(4*(13-8)) | 0b1111<<(4*(12-8)))) | 0b1100<<(4*(8-8)) | 0b1100<<(4*(9-8)) | 0b1100<<(4*(10-8)) | 0b1100<<(4*(11-8)) | 0b1100<<(4*(14-8)) | 0b1100<<(4*(15-8))

    machine.mem32[stm.GPIOE + stm.GPIO_AFR0] = (machine.mem32[stm.GPIOE + stm.GPIO_AFR0] & ~(0b1111<<7)) | 0b1100<<(4*7)
    machine.mem32[stm.GPIOE + stm.GPIO_AFR1] = 0xCCCCCCCC
    
    machine.mem32[FSMC_Bank1_base + FSMC_BCR_bank1_offset] = FSMC_BTR1_ADDSET_1 | FSMC_BTR1_DATAST_1
    machine.mem32[FSMC_Bank1_base + FSMC_BTR_bank1_offset] = FSMC_BCR1_MWID_0 | FSMC_BCR1_WREN | FSMC_BCR1_MBKEN

def TFT_Init():
    BIT12 = const(1 << 12)
    _BIT12 = const(0xFFFF ^ BIT12)

    #hardware reset
    machine.mem16[stm.GPIO_ODR] &= _BIT12
    time.sleep_ms(250)
    machine.mem16[stm.GPIO_ODR] |= BIT12
    time.sleep_ms(120)

    #SOFTWARE RESET
    machine.mem8[LCD_REG] = 0x01
    time.sleep_ms(1000)

    #POWER CONTROL A
    machine.mem8[LCD_REG] = 0xCB
    machine.mem16[LCD_RAM] = 0x39
    machine.mem16[LCD_RAM] = 0x2C
    machine.mem16[LCD_RAM] = 0x00
    machine.mem16[LCD_RAM] = 0x34
    machine.mem16[LCD_RAM] = 0x02
    
    #DRIVER TIMING CONTROL A
    machine.mem8[LCD_REG] = 0xE8
    machine.mem16[LCD_RAM] = 0x85
    machine.mem16[LCD_RAM] = 0x00
    machine.mem16[LCD_RAM] = 0x78
    
    #DRIVER TIMING CONTROL B
    machine.mem8[LCD_REG] = 0xEA
    machine.mem16[LCD_RAM] = 0x00
    machine.mem16[LCD_RAM] = 0x00
    
    #POWER ON SEQUENCE CONTROL
    machine.mem8[LCD_REG] = 0xED
    machine.mem16[LCD_RAM] = 0x64
    machine.mem16[LCD_RAM] = 0x03
    machine.mem16[LCD_RAM] = 0x12
    machine.mem16[LCD_RAM] = 0x81

    #PUMP RATIO CONTROL
    machine.mem8[LCD_REG] = 0xF7
    machine.mem16[LCD_RAM] = 0x20

    #POWER CONTROL,VRH[5:0]
    machine.mem8[LCD_REG] = 0xC0
    machine.mem16[LCD_RAM] = 0x23

    #POWER CONTROL,SAP[2:0]BT[3:0]
    machine.mem8[LCD_REG] = 0xC1
    machine.mem16[LCD_RAM] = 0x10

    #VCM CONTROL
    machine.mem8[LCD_REG] = 0xC5
    machine.mem16[LCD_RAM] = 0x3E
    machine.mem16[LCD_RAM] = 0x28

    #VCM CONTROL 2
    machine.mem8[LCD_REG] = 0xC7
    machine.mem16[LCD_RAM] = 0x86

    #MEMORY ACCESS CONTROL
    machine.mem8[LCD_REG] = 0x36
    machine.mem16[LCD_RAM] = 0x48

    #PIXEL FORMAT
    machine.mem8[LCD_REG] = 0x3A
    machine.mem16[LCD_RAM] = 0x55

    #FRAME RATIO CONTROL, STANDARD RGB COLOR
    machine.mem8[LCD_REG] = 0xB1
    machine.mem16[LCD_RAM] = 0x00
    machine.mem16[LCD_RAM] = 0x18

    #DISPLAY FUNCTION CONTROL
    machine.mem8[LCD_REG] = 0xB6
    machine.mem16[LCD_RAM] = 0x08
    machine.mem16[LCD_RAM] = 0x82
    machine.mem16[LCD_RAM] = 0x27

    #3GAMMA FUNCTION DISABLE
    machine.mem8[LCD_REG] = 0xF2
    machine.mem16[LCD_RAM] = 0x00

    #GAMMA CURVE SELECTED
    machine.mem8[LCD_REG] = 0x26
    machine.mem16[LCD_RAM] = 0x01

    #POSITIVE GAMMA CORRECTION
    machine.mem8[LCD_REG] = 0xE0
    machine.mem16[LCD_RAM] = 0x0F
    machine.mem16[LCD_RAM] = 0x31
    machine.mem16[LCD_RAM] = 0x2B
    machine.mem16[LCD_RAM] = 0x0C
    machine.mem16[LCD_RAM] = 0x0E
    machine.mem16[LCD_RAM] = 0x08
    machine.mem16[LCD_RAM] = 0x4E
    machine.mem16[LCD_RAM] = 0xF1
    machine.mem16[LCD_RAM] = 0x37
    machine.mem16[LCD_RAM] = 0x07
    machine.mem16[LCD_RAM] = 0x10
    machine.mem16[LCD_RAM] = 0x03
    machine.mem16[LCD_RAM] = 0x0E
    machine.mem16[LCD_RAM] = 0x09
    machine.mem16[LCD_RAM] = 0x00

    #NEGATIVE GAMMA CORRECTION
    machine.mem8[LCD_REG] = 0xE1
    machine.mem16[LCD_RAM] = 0x00
    machine.mem16[LCD_RAM] = 0x0E
    machine.mem16[LCD_RAM] = 0x14
    machine.mem16[LCD_RAM] = 0x03
    machine.mem16[LCD_RAM] = 0x11
    machine.mem16[LCD_RAM] = 0x07
    machine.mem16[LCD_RAM] = 0x31
    machine.mem16[LCD_RAM] = 0xC1
    machine.mem16[LCD_RAM] = 0x48
    machine.mem16[LCD_RAM] = 0x08
    machine.mem16[LCD_RAM] = 0x0F
    machine.mem16[LCD_RAM] = 0x0C
    machine.mem16[LCD_RAM] = 0x31
    machine.mem16[LCD_RAM] = 0x36
    machine.mem16[LCD_RAM] = 0x0F

    #EXIT SLEEP
    machine.mem8[LCD_REG] = 0x11
    time.sleep_ms(120)

    #TURN ON DISPLAY
    machine.mem8[LCD_REG] = 0x29

    #display inversion
    #machine.mem8[LCD_REG] = 0x21

    #setup Memory Access Control
    machine.mem8[LCD_REG] = 0x36
    machine.mem16[LCD_RAM] = 0b00111111
    
def ILI9341_Set_Address(X1, Y1, X2, Y2):
    #set X min and max
    machine.mem8[LCD_REG] = 0x2A
    machine.mem16[LCD_RAM] = X1>>8
    machine.mem16[LCD_RAM] = X1
    machine.mem16[LCD_RAM] = X2>>8
    machine.mem16[LCD_RAM] = X2

    #set y min and max
    machine.mem8[LCD_REG] = 0x2B
    machine.mem16[LCD_RAM] = Y1>>8
    machine.mem16[LCD_RAM] = Y1
    machine.mem16[LCD_RAM] = Y2>>8
    machine.mem16[LCD_RAM] = Y2

    #write data command
    machine.mem8[LCD_REG] = 0x2C
     
def draw_pixel(X, Y, colour):
    ILI9341_Set_Address(X, Y, X, Y)
    machine.mem16[LCD_RAM] = colour  

LCD_REG = const(0x60000000)
LCD_RAM = const(0x60080000)    

Regards Mike

User avatar
Roberthh
Posts: 3667
Joined: Sat May 09, 2015 4:13 pm
Location: Rhineland, Europe

Re: MCUDev Black STM32F407VET6 + STM32F407ZET6 dev boards

Post by Roberthh » Mon Jul 22, 2019 8:17 am

Using the mem_xx() functions is very slow. For initialization, that's fine. But for other operations like setting coordinates or data transfer using native code and direct pointers is way faster. I used that for my SSD1963 driver (https://github.com/robert-hh/SSD1963-TF ... or-PyBoard), which uses 8 bit parallel data transfers. The file TFT_io.py contains the functions for accessing the memory, both native and assembly code. Native code only takes twice the time of assembly code, but is much easier to write and maintain, since the control structures of Python are available.

Post Reply