|
@@ -0,0 +1,429 @@
|
|
|
|
+/*
|
|
|
|
+ * 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;
|
|
|
|
+}
|