static void spi2_ios(void) { u32 val; reg_set(RCC_APB2ENR, 0x08); /* Activate PortB */ /* Configure NSS pin (PB12) */ val = reg_rd(GPIOB + 0x04); val &= 0xFFF0FFFF; val |= 0x00030000; /* output, 50MHz, push-pull */ reg_wr(GPIOB+0x04, val); reg_wr(GPIO_BSRR(GPIOB), (0x01 << 12)); /* Disable SS (nss=1) */ /* Configure SCK pin (PB13) */ val = reg_rd(GPIOB + 0x04); val &= 0xFF0FFFFF; val |= 0x00B00000; /* output, 50MHz, AF, push-pull */ reg_wr(GPIOB+0x04, val); /* Configure MOSI pin (PB15) */ val = reg_rd(GPIOB + 0x04); val &= 0x0FFFFFFF; val |= 0xB0000000; /* output, 50MHz, AF, push-pull */ reg_wr(GPIOB+0x04, val); /* Configure MISO pin (PB14) */ val = reg_rd(GPIOB + 0x04); val &= 0xF0FFFFFF; val |= 0x04000000; /* input, floating */ reg_wr(GPIOB + 0x04, val); }
int main(void) { hw_init(); while(1) { /* Set LED on */ reg_wr((u32)GPIOI_BSRR, (0x1 << 1) ); /* Start Timer2 */ reg_set(TIM2_CR1, 1); /* Wait Timer2 ends */ while(reg_rd(TIM2_CR1) & 1) ; /* Set LED off */ reg_wr((u32)GPIOI_BSRR, (0x1 << 17) ); /* Start Timer2 */ reg_set(TIM2_CR1, 1); /* Wait Timer2 ends */ while(reg_rd(TIM2_CR1) & 1) ; } }
static void spi1_ios(void) { u32 val; reg_set(RCC_APB2ENR, 0x04); /* Activate GPIOA */ /* Configure NSS pin (PA4) */ val = reg_rd(GPIOA); val &= 0xFFF0FFFF; val |= 0x00030000; /* output, 50MHz, push-pull */ reg_wr(GPIOA, val); reg_wr(GPIO_BSRR(GPIOA), (0x01 << 4)); /* Disable SS (nss=1) */ /* Configure SCK pin (PA5) */ val = reg_rd(GPIOA); val &= 0xFF0FFFFF; val |= 0x00B00000; /* output, 50MHz, AF, push-pull */ reg_wr(GPIOA, val); /* Configure MOSI pin (PA7) */ val = reg_rd(GPIOA); val &= 0x0FFFFFFF; val |= 0xB0000000; /* output, 50MHz, AF, push-pull */ reg_wr(GPIOA, val); /* Configure MISO pin (PA6) */ val = reg_rd(GPIOA); val &= 0xF0FFFFFF; val |= 0x04000000; /* input, floating */ reg_wr(GPIOA, val); }
static void hw_init_clock(void) { u32 val; /* 1) Activate HSE, that will be used as PLL source */ /* Clear HSEON bit */ reg_clr(RCC_CR, 0x00010000); /* Clear HSEBYP bit */ reg_clr(RCC_CR, 0x00040000); /* Activate HSE (set HSEON) */ reg_set(RCC_CR, 0x00010000); /* Wait until HSERDY bit set */ while( (reg_rd(RCC_CR) & 0x00020000) == 0) ; /* 2) Configure and activate PLL */ /* Configure PLL */ val = (432 << 6); // set N (VCO multiplier) val |= 25; // set M (VCO divisor) val |= ( 0 << 16); // set P (output divisor val |= ( 9 << 24); // set Q (peripheral divisor) reg_wr(RCC_PLLCFGR, val); /* Activate PLL */ reg_set(RCC_CR, 0x01000000); while( (reg_rd(RCC_CR) & 0x02000000) == 0) ; /* 3) Update flash latency, and peripheral bus prescaler */ /* Set Flash latency to 7 */ reg_set(FLASH_ACR, 0x07); /* PCLK1 - Set APB1 clock divider to 4 (value 5) */ reg_set(RCC_CFGR, (5 << 10) ); /* PCLK2 - Set APB2 clock divider to 2 (value 4) */ reg_set(RCC_CFGR, (4 << 13) ); /* 4) Switch the current clock to PLL */ /* Change the clock source */ val = reg_rd(RCC_CFGR); val &= ~0x03; val |= 0x02; reg_wr(RCC_CFGR, val); /* Wait until, clock source is modified */ while( (reg_rd(RCC_CFGR) & 0x0C) != (0x02 << 2)) ; }
static void hw_init_gpio(void) { u32 val; /* Activate GPIO-I controller */ val = reg_rd((u32)RCC_AHB1ENR); val |= 0x0100; reg_wr((u32)RCC_AHB1ENR, val); /* Configure GPIOI-1 as output */ val = reg_rd((u32)GPIOI_MODER); val |= (0x01 << 2); reg_wr((u32)GPIOI_MODER, val); }
unsigned int jtag3ctrl_get_speed(void) { unsigned int div; uint32_t clk; int sel; /* clock source */ sel = GET_CLK_SEL(reg_rd(REG_CFG)); clk = jtag_clk_tab[sel]; /* brg divisor */ div = reg_rd(REG_BRG_DIV) + 2; DCC_LOG3(LOG_TRACE, "sel: %d (%d MHz) div: %d", sel, clk / 1000000, div); return (clk / div) / 2; }
char rd_byte(int dev, unsigned int addr) { unsigned int val; val = reg_rd(dev, XFL_BASE_ADDR + (addr << 2)); return (char)(val & 0x000000FF); }
void jtag3ctrl_loopback(bool enable) { unsigned int cfg; cfg = reg_rd(REG_CFG); cfg = (enable) ? cfg | CFG_LOOP : cfg & ~CFG_LOOP; reg_wr(REG_CFG, cfg); }
static int but_value(void) { int v; v = reg_rd(GPIO_IDR(GPIOA)); v &= 0x0A; v ^= 0x0A; return v; }
void jtag3ctrl_aux_uart(bool enable) { unsigned int cfg; cfg = reg_rd(REG_CFG); cfg = (enable) ? cfg | CFG_UART_EN : cfg & ~CFG_UART_EN; reg_wr(REG_CFG, cfg); }
void jtag3ctrl_rtck(bool enable) { int cfg = reg_rd(REG_CFG); if (enable) cfg |= CFG_RTCK_EN; else cfg &= ~CFG_RTCK_EN; reg_wr(REG_CFG, cfg); }
void jtag3ctrl_nrst(bool assert) { int cfg = reg_rd(REG_CFG); if (assert) cfg |= CFG_TAP_NRST; else cfg &= ~CFG_TAP_NRST; reg_wr(REG_CFG, cfg); }
static void hw_init_timer(void) { reg_set(RCC_APB1ENR, 0x01); /* Activate Timer2 */ while( (reg_rd(RCC_APB1ENR) & 1) == 0) ; /* Configure Timer2 */ reg_wr (TIM2_CR1, 0x0200); /* Input clock divided by 4 */ reg_wr (TIM2_ARR, 0x8000); /* Value used when reloaded */ reg_wr (TIM2_PSC, 0x80); /* Prescaler */ reg_set(TIM2_CR1, 0x08); /* Set OPM (one-pulse-mode) */ }
static void hw_init_clock(void) { u32 val; /* Clear HSEON bit */ reg_clr(RCC_CR, 0x00010000); /* Clear HSEBYP bit */ reg_clr(RCC_CR, 0x00040000); /* Activate HSE (set HSEON) */ reg_set(RCC_CR, 0x00010000); /* Wait until HSERDY bit set */ while( (reg_rd(RCC_CR) & 0x00020000) == 0) ; /* Select HSE as new clock source */ val = reg_rd(RCC_CFGR); val &= ~0x03; val |= 0x01; reg_wr(RCC_CFGR, val); /* Wait until, clock source is modified */ while( (reg_rd(RCC_CFGR) & 0x0C) != (0x01 << 2)) ; }
void uart_init(void) { u32 baud; u32 v; v = hw_getfreq(); baud = (u32)(v / 115200); /* Set the divider value for baud clock generator */ reg_wr(UART2_BASE + 0x10, baud); /* Activate UART2 */ v = reg_rd(UART2_BASE + 0x08); /* Read CTRL reg */ v |= 0x03; /* Set RX enable and TX enable bits */ reg_wr(UART2_BASE + 0x08, v); /* Write back CTRL reg */ }
static void hw_init_ltdc (void) { u32 val; /* Activate GPIO controller */ val = reg_rd((u32)RCC_AHB1ENR); val |= 0x0010; /* GPIO-E */ val |= 0x0040; /* GPIO-G */ val |= 0x0100; /* GPIO-I */ val |= 0x0200; /* GPIO-J */ val |= 0x0400; /* GPIO-K */ reg_wr((u32)RCC_AHB1ENR, val); /* Configure GPIO-E pins mode */ val = reg_rd((u32)GPIOE_MODER); val &= 0xFFFFFCFF; /* PE-4 : LCD_B0 */ val |= 0x00000200; /* PE-4 : use alternate function */ reg_wr((u32)GPIOE_MODER, val); /* Configure GPIO-E alternate functions */ val = reg_rd((u32)GPIOE_AFRL); val |= (0x0E << 16); /* PE-4 = AF14 : LTDC */ reg_wr((u32)GPIOE_AFRL, val); /* Configure GPIO-G pins mode */ val = reg_rd((u32)GPIOG_MODER); val |= (0x02 << 24); /* PG-12 : LCD_B4 */ reg_wr((u32)GPIOG_MODER, val); /* Configure GPIO-G alternate functions */ val = reg_rd((u32)GPIOG_AFRH); val |= (0x0E << 16); /* PG-12 = AF14 : LTDC */ reg_wr((u32)GPIOG_AFRH, val); /* Configure GPIO-I pins mode */ val = reg_rd((u32)GPIOI_MODER); val |= (0x02 << 18); /* PI-9 : LCD_VSYNC */ val |= (0x02 << 20); /* PI-10 : LCD_HSYNC */ val |= (0x02 << 28); /* PI-14 : LCD_CLK */ val |= (0x02 << 30); /* PI-15 : LCD_R0 */ val |= (0x01 << 24); /* PI-12 : LCD_DISP - manual output */ reg_wr((u32)GPIOI_MODER, val); /* Configure GPIO-I alternate functions */ val = reg_rd((u32)GPIOI_AFRH); val |= (0x0E << 4); /* PI-9 = AF14 : LTDC */ val |= (0x0E << 8); /* PI-10 = AF14 : LTDC */ val |= (0x0E << 24); /* PI-14 = AF14 : LTDC */ val |= (0x0E << 28); /* PI-15 = AF14 : LTDC */ reg_wr((u32)GPIOI_AFRH, val); /* Configure GPIO-J pins mode */ val = reg_rd((u32)GPIOJ_MODER); val &= 0x03000000; /* Reset all except PJ12 (used by USB) */ val |= 0xA8AAAAAA; /* Use alternate function for all lcd ios */ reg_wr((u32)GPIOJ_MODER, val); /* Configure GPIO-J alternate functions */ val = 0xEEEEEEEE; reg_wr((u32)GPIOJ_AFRL, val); val = reg_rd((u32)GPIOJ_AFRH); val &= 0x000F0000; val |= 0xEEE0EEEE; reg_wr((u32)GPIOJ_AFRH, val); /* Configure GPIOK pins as alternate-function */ val = reg_rd((u32)GPIOK_MODER); val |= (0x02 << 0); /* PK-0 : LCD_G5 */ val |= (0x02 << 2); /* PK-1 : LCD_G6 */ val |= (0x02 << 4); /* PK-2 : LCD_G7 */ val |= (0x01 << 6); /* PK-3 : LCD_BackLight - manual output */ val |= (0x02 << 8); /* PK-4 : LCD_B5 */ val |= (0x02 << 10); /* PK-5 : LCD_B6 */ val |= (0x02 << 12); /* PK-6 : LCD_B7 */ val |= (0x02 << 14); /* PK-7 : LCD_DE */ reg_wr((u32)GPIOK_MODER, val); /* Configure GPIO-I alternate functions */ val = reg_rd((u32)GPIOK_AFRL); val |= (0x0E << 0); /* PK-0 = AF14 : LTDC */ val |= (0x0E << 4); /* PK-1 = AF14 : LTDC */ val |= (0x0E << 8); /* PK-2 = AF14 : LTDC */ val |= (0x0E << 16); /* PK-4 = AF14 : LTDC */ val |= (0x0E << 20); /* PK-5 = AF14 : LTDC */ val |= (0x0E << 24); /* PK-6 = AF14 : LTDC */ val |= (0x0E << 28); /* PK-7 = AF14 : LTDC */ reg_wr((u32)GPIOK_AFRL, val); /* 2) Configure Clocks */ val = reg_rd(RCC_PLLSAI); /* Set VCO division factor (SAI "N") */ val &= ~(0x1FF << 6); val |= (192 << 6); /* Set LCD division factor (SAI "R") */ val &= ~(0x07 << 28); val |= ( 5 << 28); /* Update RCC PLLSAI */ reg_wr(RCC_PLLSAI, val); /* Activate PLL-SAI */ reg_set(RCC_CR, 0x10000000); while( (reg_rd(RCC_CR) & 0x20000000) == 0) ; /* Update LCD dedicated clock prescaller */ val = reg_rd(RCC_DKCFGR1); val &= ~(0x03 << 16); val |= (0x01 << 16); /* div by 4 */ reg_wr(RCC_DKCFGR1, val); }
/** * Send one byte to the display * * @param c value to send */ void disp_putc(u8 c) { while ( (reg_rd(UART2_SR) & 0x80) != 0x80) ; reg_wr(UART2_DR, c); }
u8 spi_rd(void) { while( (reg_rd(SPI0_STATUS) & 0x04) == 0) ; return( reg_rd(SPI0_DATA) ); }
void spi_wr(u32 c) { while ( (reg_rd(SPI0_STATUS) & 0x02) == 0) ; reg_wr(SPI0_DATA, c); }
void uart_putc(u8 c) { while( reg_rd(UART2_STATE) & 0x01) ; reg_wr(UART2_DATA, c); }
void spi_flush(void) { while (reg_rd(SPI0_STATUS) & 0x04) reg_rd(SPI0_DATA); }
unsigned int jtag3ctrl_set_speed(unsigned int freq) { uint32_t brg_freq; uint32_t brg_fmax; uint32_t brg_fmin; uint32_t tap_freq; uint32_t cfg; uint32_t clk; int32_t div; int sel; int err; int min = INT_MAX; int best_sel; brg_fmax = jtag_clk_tab[15] / 2; brg_freq = freq * 2; if (brg_freq > brg_fmax) { brg_freq = brg_fmax; } brg_fmin = jtag_clk_tab[0] / 0x10000; if (brg_freq < brg_fmin) { brg_freq = brg_fmin; } DCC_LOG1(LOG_INFO, "brg freq=%d", brg_freq); /* find the best matching frequency, but never bigger than the desired frequency */ best_sel = -1; for (sel = 0; sel <= 15; sel++) { clk = jtag_clk_tab[sel]; div = ((clk + (brg_freq / 2)) / brg_freq) - 2; /* range checking */ if (div < 0) div = 0; if (div >= 0xffff) div = 0xfffe; err = brg_freq - (clk / (div + 2)); DCC_LOG3(LOG_INFO, "clk=%d div=%d err=%d", clk, (div + 2), brg_freq - (clk / (div + 2))); if ((err >= 0) && (err < min)) { min = err; best_sel = sel; if (err == 0) break; } } if (best_sel < 0) best_sel = 0; clk = jtag_clk_tab[best_sel]; div = ((clk + (brg_freq / 2)) / brg_freq) - 2; /* range checking */ if (div < 0) div = 0; if (div >= 0xffff) div = 0xfffe; /* select the clock source */ cfg = reg_rd(REG_CFG) & ~CFG_CLK_SEL(0xf); reg_wr(REG_CFG, cfg | CFG_CLK_SEL(best_sel)); /* configure the brg divisor */ reg_wr(REG_BRG_DIV, div); brg_freq = clk / (div + 2); tap_freq = brg_freq / 2; DCC_LOG2(LOG_INFO, "sel: %d div: %d", best_sel, div + 2); DCC_LOG4(LOG_TRACE, "clk=%d.%06d MHz, TAP freq: %d.%06d MHz", clk / 1000000, clk % 1000000, tap_freq / 1000000, tap_freq % 1000000); return tap_freq; }
void spi_wait(void) { while( reg_rd(SPI0_STATUS) & 0x10 ) ; }