123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429 |
- /*
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Lesser General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this library. If not, see <http://www.gnu.org/licenses/>.
- */
- #include <unicore-mx/stm32/rcc.h>
- #include <unicore-mx/stm32/gpio.h>
- #include <string.h>
- #include <stdio.h>
- #define DMB() __asm__ volatile ("dmb")
- #define FLASH_BASE (0x40022000)
- #define FLASH_ACR (*(volatile uint32_t *)(FLASH_BASE + 0x00))
- #define LED_GREEN_PIN GPIO5
- #define LED_GREEN_PORT GPIOA
- #define LED_RED_PIN GPIO4
- #define LED_RED_PORT GPIOA
- #define I2C3_SDA_PIN GPIO1
- #define I2C3_SDA_PORT GPIOC
- #define I2C3_SCL_PIN GPIO0
- #define I2C3_SCL_PORT GPIOC
- #define I2C3_AF (7)
- #define I2C3_BASE 0x40007800
- #define I2C3 I2C3_BASE
- #define I2C I2C3
- #define I2C3_CR1 (*(volatile uint32_t *)(I2C3))
- #define I2C3_CR2 (*(volatile uint32_t *)(I2C3 + 0x04))
- #define I2C3_OAR1 (*(volatile uint32_t *)(I2C3 + 0x08))
- #define I2C3_OAR2 (*(volatile uint32_t *)(I2C3 + 0x0c))
- #define I2C3_TIMINGR (*(volatile uint32_t *)(I2C3 + 0x10))
- #define I2C3_SR1 (*(volatile uint32_t *)(I2C3 + 0x14))
- #define I2C3_ISR (*(volatile uint32_t *)(I2C3 + 0x18))
- #define I2C3_ICR (*(volatile uint32_t *)(I2C3 + 0x1C))
- #define I2C3_TXDR (*(volatile uint32_t *)(I2C3 + 0x28))
- #define I2C3_RXDR (*(volatile uint32_t *)(I2C3 + 0x24))
- #define I2C_CR1_ENABLE (1 << 0)
- #define I2C_CR1_DNF (1 << 8)
- #define I2C_CR1_ANFOFF (1 << 12)
- #define I2C_CR1_NOSTRETCH (1 << 17)
- #define I2C_CR2_START (1 << 13)
- #define I2C_CR2_STOP (1 << 14)
- #define I2C_CR2_RD_WRN (1 << 10)
- #define I2C_CR2_NBYTES_SHIFT (16)
- #define I2C_CR2_RELOAD (1 << 24)
- #define I2C_CR2_AUTOEND (1 << 25)
- #define I2C_CR1_ACK (1 << 10)
- #define I2C_CR2_FREQ_MASK (0x3ff)
- #define I2C_CCR_MASK (0xfff)
- #define I2C_ISR_TXIS (1 << 1)
- #define I2C_ISR_TXE (1 << 0)
- #define I2C_ISR_RXNE (1 << 2)
- #define I2C_ISR_NACKF (1 << 4)
- #define I2C_ISR_TCR (1 << 7)
- #define I2C_ICR_ARLOCF (1 << 9)
- #define I2C_ICR_BERRCF (1 << 8)
- #define I2C_ICR_ADDRCF (1 << 3)
- #define I2C_ICR_NACKF (1 << 4)
- #define I2C_ICR_STOPF (1 << 5)
- #define I2C_ICR_ALLCF (I2C_ICR_NACKF | I2C_ICR_ARLOCF | I2C_ICR_BERRCF | I2C_ICR_ADDRCF )
- #define RCC_CFGR_PLLDIV2 (0x01 << 22)
- #define RCC_CFGR_PLLMUL4 (0x01 << 18)
- #define RCC_PRESCALER_DIV_NONE 0
- #define ROM_SRC 0x50
- #define ROM_DST 0x51
- #define ROM_TEST_NACK 0x52
- #define ROM_PAGE_SIZE (32)
- #define ROM_SIZE (8192)
- #define ROM_PAGES (ROM_SIZE / ROM_PAGE_SIZE)
- static void wait_a_bit(void)
- {
- volatile int i;
- for (i = 0; i < 30000; i++) { /* Wait a bit. */
- __asm__("nop");
- }
- }
- static void i2c_acquire(void)
- {
- rcc_periph_clock_enable(RCC_I2C3);
- I2C3_CR1 |= I2C_CR1_ENABLE;
- }
- static void i2c_release(void)
- {
- I2C3_CR1 &= ~(I2C_CR1_ENABLE);
- rcc_periph_clock_disable(RCC_I2C3);
- }
- static void i2c_setup(void)
- {
- /* 400KHz */
- uint32_t presc = 0, scll = 0x2E, sclh = 0x11, sdadel = 0x01, scldel = 0x0b;
- /* 100KHz */
- //uint32_t presc = 1, scll = 0x56, sclh = 0x3e, sdadel = 0x01, scldel = 0x0a;
- rcc_periph_clock_enable(RCC_GPIOC);
- gpio_set_output_options(GPIOC, GPIO_OTYPE_OD, GPIO_OSPEED_HIGH, I2C3_SDA_PIN);
- gpio_mode_setup(GPIOC, GPIO_MODE_AF, GPIO_PUPD_PULLUP,
- I2C3_SDA_PIN | I2C3_SCL_PIN);
- gpio_set_af(GPIOC, I2C3_AF, I2C3_SDA_PIN | I2C3_SCL_PIN);
- i2c_acquire();
- /* Disable */
- I2C3_CR1 &= ~(I2C_CR1_ENABLE);
- /* configure analog noise filter */
- I2C3_CR1 |= I2C_CR1_ANFOFF;
- /* configure digital noise filter */
- I2C3_CR1 |= I2C_CR1_DNF;
- /* set timing registers */
- I2C3_TIMINGR = (presc << 28) | (scldel << 20) | (sdadel << 16) | (sclh << 8) | scll;
- /* configure clock stretching */
- I2C3_CR1 &= ~(I2C_CR1_NOSTRETCH);
- /* Clear interrupt */
- I2C3_ICR |= I2C_ICR_ALLCF;
- i2c_release();
- }
- static void gpio_setup(void)
- {
- /* Enable GPIO clock. */
- rcc_periph_clock_enable(RCC_GPIOA);
- /* set pins to output mode, push pull */
- gpio_mode_setup(LED_GREEN_PORT, GPIO_MODE_OUTPUT, GPIO_PUPD_NONE, LED_GREEN_PIN);
- gpio_mode_setup(LED_RED_PORT, GPIO_MODE_OUTPUT, GPIO_PUPD_NONE, LED_RED_PIN);
- }
- static void wait_sent(void)
- {
- volatile uint32_t sr1;
- do {
- sr1 = I2C3_ISR;
- } while ((sr1 & (I2C_ISR_TXE)) == 0);
- }
- static void wait_reload(void)
- {
- volatile uint32_t sr1;
- do {
- sr1 = I2C3_ISR;
- } while ((sr1 & (I2C_ISR_TCR)) == 0);
- }
- static void wait_start(void)
- {
- volatile uint32_t cr2;
- do {
- cr2 = I2C3_CR2;
- } while ((cr2 & (I2C_CR2_START)) != 0);
- }
- static void wait_stop(void)
- {
- volatile uint32_t cr2;
- do {
- cr2 = I2C3_CR2;
- } while ((cr2 & (I2C_CR2_STOP)) != 0);
- }
- static void wait_rxd(void)
- {
- volatile uint32_t sr1;
- do {
- sr1 = I2C3_ISR;
- } while ((sr1 & (I2C_ISR_RXNE)) == 0);
- }
- static void clear_err(void)
- {
- I2C3_ICR |= I2C_ICR_ALLCF;
- }
- static void clear_stop(void)
- {
- I2C3_ICR |= I2C_ICR_STOPF;
- }
- static int eeprom_write_page(uint8_t rom, uint16_t address, const uint8_t *buf)
- {
- volatile uint32_t sr1, sr2, cr2;
- int i;
- if (rom != ROM_DST)
- return 0;
- clear_err();
- I2C3_CR2 = ((ROM_PAGE_SIZE + 2) << I2C_CR2_NBYTES_SHIFT) | I2C_CR2_AUTOEND;
- I2C3_CR2 |= (rom << 1);
- I2C3_CR2 |= I2C_CR2_START;
- wait_start();
- I2C3_TXDR = ((uint8_t)((address >> 8) & (0xFF)));
- wait_sent();
- I2C3_TXDR = ((uint8_t)((address & 0xFF)));
- for (i = 0; i < ROM_PAGE_SIZE; i++) {
- wait_sent();
- I2C3_TXDR = buf[i];
- }
- wait_a_bit();
- clear_stop();
- return i;
- }
- static int eeprom_read_page(uint8_t rom, uint16_t address, uint8_t *buf)
- {
- volatile uint32_t sr1, sr2;
- int i;
- clear_err();
- I2C3_CR2 = (2 << I2C_CR2_NBYTES_SHIFT) | I2C_CR2_RELOAD;
- I2C3_CR2 |= (rom << 1);
- I2C3_CR2 |= I2C_CR2_START;
- wait_start();
- I2C3_TXDR = ((uint8_t)((address & 0xFF00) >> 8));
- wait_sent();
- clear_err();
- I2C3_CR2 = (rom << 1);
- I2C3_CR2 |= I2C_CR2_RD_WRN;
- I2C3_CR2 |= (ROM_PAGE_SIZE << I2C_CR2_NBYTES_SHIFT);
- I2C3_CR2 |= I2C_CR2_START;
- I2C3_TXDR = ((uint8_t)((address & 0xFF)));
- //wait_sent();
- wait_start();
- clear_err();
- for (i = 0; i < ROM_PAGE_SIZE; i++) {
- //I2C3_TXDR = 0xFF;
- //wait_sent();
- wait_rxd();
- buf[i] = I2C3_RXDR;
- }
- I2C3_CR2 |= I2C_CR2_STOP;
- clear_stop();
- return i;
- }
- static int eeprom_read_cur(uint8_t rom, uint8_t *buf)
- {
- int i;
- retry:
- clear_err();
- I2C3_CR2 = (ROM_PAGE_SIZE << I2C_CR2_NBYTES_SHIFT);
- I2C3_CR2 |= (rom << 1) | I2C_CR2_RD_WRN;
- I2C3_CR2 |= I2C_CR2_START;
- wait_start();
- if (I2C3_ISR & I2C_ISR_NACKF) {
- wait_a_bit();
- clear_stop();
- goto retry;
- }
- for (i = 0; i < ROM_PAGE_SIZE; i++) {
- wait_rxd();
- buf[i] = I2C3_RXDR;
- }
- return i;
- }
- static void flash_set_waitstates(unsigned int waitstates)
- {
- if (waitstates && ((FLASH_ACR & 1) == 0))
- FLASH_ACR |= 1;
- if (!waitstates && ((FLASH_ACR & 1) == 1))
- FLASH_ACR &= 1;
- while ((FLASH_ACR & 1) != waitstates)
- ;
- }
- static void clock_pll_on(void)
- {
- uint32_t reg32;
- uint32_t cpu_freq, hsi_freq, hpre, ppre1, ppre2, flash_waitstates;
- /* Enable Power controller */
- rcc_periph_clock_enable(RCC_PWR);
- /* Select clock parameters (CPU Speed = 32MHz) */
- cpu_freq = 32000000;
- hsi_freq = 16000000;
- hpre = RCC_PRESCALER_DIV_NONE;
- ppre1 = RCC_PRESCALER_DIV_NONE;
- ppre2 = RCC_PRESCALER_DIV_NONE;
- flash_waitstates = 1;
- flash_set_waitstates(flash_waitstates);
- /* Enable internal high-speed oscillator. */
- RCC_CR |= RCC_CR_HSI16ON;
- DMB();
- while ((RCC_CR & RCC_CR_HSI16RDY) == 0) {};
- /* Select HSI as SYSCLK source. */
- reg32 = RCC_CFGR;
- reg32 &= ~((1 << 1) | (1 << 0));
- RCC_CFGR = (reg32 | RCC_CFGR_SW_HSI16);
- DMB();
- /*
- * Set prescalers for AHB, ADC, ABP1, ABP2.
- */
- reg32 = RCC_CFGR;
- reg32 &= ~(0xF << 4);
- RCC_CFGR = (reg32 | (hpre << 4));
- DMB();
- reg32 = RCC_CFGR;
- reg32 &= ~(0x07 << 8);
- RCC_CFGR = (reg32 | (ppre1 << 8));
- DMB();
- reg32 &= ~(0x07 << 11);
- RCC_CFGR = (reg32 | (ppre2 << 11));
- DMB();
- reg32 &= ~(0x0F << 18);
- RCC_CFGR = (reg32 | RCC_CFGR_PLLMUL4);
- DMB();
- reg32 &= ~(0x03 << 22);
- RCC_CFGR = (reg32 | RCC_CFGR_PLLDIV2);
- DMB();
- /* Enable PLL oscillator and wait for it to stabilize. */
- RCC_CR |= RCC_CR_PLLON;
- DMB();
- while ((RCC_CR & RCC_CR_PLLRDY) == 0) {};
- /* Select PLL as SYSCLK source. */
- reg32 = RCC_CFGR;
- reg32 &= ~((1 << 1) | (1 << 0));
- RCC_CFGR = (reg32 | RCC_CFGR_SW_PLL);
- DMB();
- /* Wait for PLL clock to be selected. */
- while (((RCC_CFGR >> 2) & 0x03) != RCC_CFGR_SW_PLL)
- ;
- }
- static uint8_t cache[ROM_PAGE_SIZE];
- static uint8_t vcache[ROM_PAGE_SIZE];
- int main(void)
- {
- int i;
- clock_pll_on();
- gpio_setup();
- gpio_set(LED_RED_PORT, LED_RED_PIN);
- i2c_setup();
- wait_a_bit();
- wait_a_bit();
- wait_a_bit();
- i2c_acquire();
- #if 0
- /* TEST - fill the DST */
- for (i = 0; i < ROM_PAGES; i++) {
- memset(cache, (uint8_t)i, 32);
- eeprom_write_page(ROM_DST,i * ROM_PAGE_SIZE,cache);
- }
- #endif
- memset(cache, 0, 32);
- for (i = 0; i < ROM_PAGES; i++) {
- /* Green: Read */
- gpio_set(LED_RED_PORT, LED_GREEN_PIN);
- gpio_clear(LED_GREEN_PORT, LED_GREEN_PIN);
- eeprom_read_page(ROM_SRC, i * ROM_PAGE_SIZE, cache);
- eeprom_read_page(ROM_DST, i * ROM_PAGE_SIZE, vcache);
- if(memcmp(vcache, cache, ROM_PAGE_SIZE) == 0) {
- /* Skip sector, already matching. */
- continue;
- }
- /* Red: Write */
- gpio_set(LED_GREEN_PORT, LED_GREEN_PIN);
- gpio_clear(LED_RED_PORT, LED_RED_PIN);
- eeprom_write_page(ROM_DST, i * ROM_PAGE_SIZE, cache);
- /* Both: verify */
- gpio_clear(LED_GREEN_PORT, LED_GREEN_PIN);
- eeprom_read_page(ROM_DST, i * ROM_PAGE_SIZE, vcache);
- if(memcmp(vcache, cache, ROM_PAGE_SIZE) != 0) {
- while(1) {
- /* blink red: panic */
- gpio_toggle(LED_RED_PORT, LED_RED_PIN);
- for (i = 0; i < 10; i++)
- wait_a_bit();
- }
- }
- gpio_set(LED_GREEN_PORT, LED_GREEN_PIN);
- gpio_set(LED_RED_PORT, LED_RED_PIN);
- }
- i2c_release();
- while (1) {
- /* blink green: success */
- gpio_set(LED_RED_PORT, LED_RED_PIN);
- gpio_toggle(LED_GREEN_PORT, LED_GREEN_PIN);
- for (i = 0; i < 10; i++)
- wait_a_bit();
- }
- return 0;
- }
|