view hw.c @ 27:5c9d2e3d6591

Add flashread/writeblock commands which read/write a block of data to flash with a CRC.
author Daniel O'Connor <darius@dons.net.au>
date Tue, 20 Nov 2012 21:54:06 +1030
parents 1e2fa7396f98
children 435c6330896c
line wrap: on
line source

#include <stdint.h>
#include <stdio.h>
#include "stm32f10x.h"

#include "1wire.h"
#include "lcd.h"

#define I2C_TIMEOUT 10000

static void	hw_port_cfg(void);

/* Wait for cnt microseconds */
void
_usleep16(uint16_t cnt) {
    TIM6->ARR = cnt > 3 ? cnt - 3 : cnt;
    TIM_SetCounter(TIM6, 0);
    TIM_Cmd(TIM6, ENABLE);
    while ((TIM6->CR1 & TIM_CR1_CEN) != 0)
	;
}

void
hw_init(void) {
    hw_port_cfg();
    lcd_init();
    lcd_setpwm(1000);
}

static void
hw_port_cfg(void) {
    FSMC_NORSRAMInitTypeDef		FSMC_NORSRAMInitStructure;
    FSMC_NORSRAMTimingInitTypeDef	p;
    GPIO_InitTypeDef			GPIO_InitStructure;
    I2C_InitTypeDef			I2C_InitStructure;
    SPI_InitTypeDef			SPI_InitStructure;
    TIM_TimeBaseInitTypeDef		TIM_TimeBaseStructure;
    USART_InitTypeDef 			USART_InitStructure;

    /* Enable clocks */
    RCC_APB1PeriphClockCmd(RCC_APB1Periph_PWR | RCC_APB1Periph_BKP | RCC_APB1Periph_TIM4 | RCC_APB1Periph_I2C1,
			   ENABLE);

    RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1 | RCC_APB2Periph_GPIOA | RCC_APB2Periph_GPIOB | RCC_APB2Periph_GPIOB | 
			   RCC_APB2Periph_GPIOE | RCC_APB2Periph_SPI1, ENABLE);

    RCC_AHBPeriphClockCmd(RCC_AHBPeriph_FSMC | RCC_AHBPeriph_CRC, ENABLE);

    /* Allow access to BKP Domain */
    PWR_BackupAccessCmd(ENABLE);

    /* Reset Backup Domain
     *
     * This resets the RTC etc back to 0 so probably only useful under user command
     BKP_DeInit();
    */

    /* Enable Low Speed External clock */
    RCC_LSEConfig(RCC_LSE_ON);

    /* Wait till LSE is ready */
    while (RCC_GetFlagStatus(RCC_FLAG_LSERDY) == RESET)
	;

    /* Select LSE as RTC Clock Source */
    RCC_RTCCLKConfig(RCC_RTCCLKSource_LSE);

    /* Enable RTC Clock */
    RCC_RTCCLKCmd(ENABLE);

    /* Wait for RTC registers synchronization */
    RTC_WaitForSynchro();

    /* Wait until last write operation on RTC registers has finished */
    RTC_WaitForLastTask();

    /* Wait until last write operation on RTC registers has finished */
    RTC_WaitForLastTask();

    /* Set RTC prescaler: set RTC period to 1sec */
    RTC_SetPrescaler(32767); /* RTC period = RTCCLK/RTC_PR = (32.768 KHz)/(32767+1) */

    /* Wait until last write operation on RTC registers has finished */
    RTC_WaitForLastTask();

    /* Port configuration */
    /* Configure USART1 TX (PA.09) as alternate function push-pull */
    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9;
    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
    GPIO_Init(GPIOA, &GPIO_InitStructure);

    /* Configure USART1 RX (PA.10) as input floating */
    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10;
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;
    GPIO_Init(GPIOA, &GPIO_InitStructure);

    /* Configure PB5 as output push-pull for LED */
    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_5;
    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
    GPIO_Init(GPIOB, &GPIO_InitStructure);

    /* Configure PB15 as input pull-up push-pull for push button */
    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_15;
    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU;
    GPIO_Init(GPIOB, &GPIO_InitStructure);

    /* USART configuration */
    /* USART1 - 115200 8n1, no flow control TX & RX enabled */
    USART_InitStructure.USART_BaudRate = 115200;
    USART_InitStructure.USART_WordLength = USART_WordLength_8b;
    USART_InitStructure.USART_StopBits = USART_StopBits_1;
    USART_InitStructure.USART_Parity = USART_Parity_No;
    USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None;
    USART_InitStructure.USART_Mode = USART_Mode_Rx | USART_Mode_Tx;
    USART_Init(USART1, &USART_InitStructure);

    /* Enable interrupts on receive data */
    USART_ITConfig(USART1, USART_IT_RXNE, ENABLE);

    /* Enable USART */
    USART_Cmd(USART1, ENABLE);

    /* Enable FSMC clock */

    /* Configures LCD Control lines (FSMC Pins) in alternate function Push-Pull mode.
     *
     * PD0(D2), PD1(D3), PD4(NOE), PD5(NWE), PD7(NE1/CS), PD8(D13), PD9(D14),
     * PD10(D15), PD11(A16/RS) PD14(D0), PD15(D1)
     */
    GPIO_InitStructure.GPIO_Pin = (GPIO_Pin_0 | GPIO_Pin_1 | GPIO_Pin_4 | GPIO_Pin_5 | GPIO_Pin_7 |
				   GPIO_Pin_8 | GPIO_Pin_9 | GPIO_Pin_10 | GPIO_Pin_11 | 
				   GPIO_Pin_14 | GPIO_Pin_15);
    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
    GPIO_Init(GPIOD, &GPIO_InitStructure);

    /* PE7(D4), PE8(D5), PE9(D6), PE10(D7), PE11(D8), PE12(D9), PE13(D10),
     * PE14(D11), PE15(D12)
     */
    GPIO_InitStructure.GPIO_Pin = (GPIO_Pin_7 | GPIO_Pin_8 | GPIO_Pin_9 | GPIO_Pin_10 | 
				   GPIO_Pin_11 | GPIO_Pin_12 | GPIO_Pin_13 | GPIO_Pin_14 |
				   GPIO_Pin_15);
    GPIO_Init(GPIOE, &GPIO_InitStructure);

    /* Configure backlight control (PD13/FSMC_A18 remapped to TIM4_CH2) */

    /* Enable timer function
     * Note source clock is SYSCLK / 2 = 36MHz
     */
    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_13;
    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
    GPIO_Init(GPIOD, &GPIO_InitStructure);

    /* Remap TIM4_CH2 to PD13 */
    GPIO_PinRemapConfig(GPIO_Remap_TIM4, ENABLE);
    
    /* Reset TIM4 */
    TIM_DeInit(TIM4);

    /* Time Base configuration */
    TIM_TimeBaseStructure.TIM_Period = 999;
    TIM_TimeBaseStructure.TIM_Prescaler = 0;
    TIM_TimeBaseStructure.TIM_ClockDivision = 0;
    TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Down;

    TIM_TimeBaseInit(TIM4, &TIM_TimeBaseStructure);

    /* Enable timer */
    TIM_OC2PreloadConfig(TIM4, TIM_OCPreload_Enable);
    TIM_ARRPreloadConfig(TIM4, ENABLE);
    TIM_Cmd(TIM4, ENABLE);

    /* Configure reset pin (PE1) as GPIO out PP */
    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_1;
    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
    GPIO_Init(GPIOE, &GPIO_InitStructure);

    /* Configures the Parallel interface (FSMC) for LCD (Parallel mode) */
    /* Timing configuration */
    p.FSMC_AddressSetupTime = 5;
    p.FSMC_AddressHoldTime = 5;
    p.FSMC_DataSetupTime = 5;
    p.FSMC_BusTurnAroundDuration = 0;
    p.FSMC_CLKDivision = 0;
    p.FSMC_DataLatency = 0;
    p.FSMC_AccessMode = FSMC_AccessMode_A;

    /* FSMC_Bank1_NORSRAM1 configured as follows:
       - Data/Address MUX = Disable
       - Memory Type = SRAM
       - Data Width = 16bit
       - Write Operation = Enable
       - Extended Mode = Disable
       - Asynchronous Wait = Disable */
    FSMC_NORSRAMInitStructure.FSMC_Bank = FSMC_Bank1_NORSRAM1;
    FSMC_NORSRAMInitStructure.FSMC_DataAddressMux = FSMC_DataAddressMux_Disable;
    FSMC_NORSRAMInitStructure.FSMC_MemoryType = FSMC_MemoryType_SRAM;
    FSMC_NORSRAMInitStructure.FSMC_MemoryDataWidth = FSMC_MemoryDataWidth_16b;
    FSMC_NORSRAMInitStructure.FSMC_BurstAccessMode = FSMC_BurstAccessMode_Disable;
    FSMC_NORSRAMInitStructure.FSMC_AsynchronousWait = FSMC_AsynchronousWait_Disable;
    FSMC_NORSRAMInitStructure.FSMC_WaitSignalPolarity = FSMC_WaitSignalPolarity_Low;
    FSMC_NORSRAMInitStructure.FSMC_WrapMode = FSMC_WrapMode_Disable;
    FSMC_NORSRAMInitStructure.FSMC_WaitSignalActive = FSMC_WaitSignalActive_BeforeWaitState;
    FSMC_NORSRAMInitStructure.FSMC_WriteOperation = FSMC_WriteOperation_Enable;
    FSMC_NORSRAMInitStructure.FSMC_WaitSignal = FSMC_WaitSignal_Disable;
    FSMC_NORSRAMInitStructure.FSMC_ExtendedMode = FSMC_ExtendedMode_Disable;
    FSMC_NORSRAMInitStructure.FSMC_WriteBurst = FSMC_WriteBurst_Disable;
    FSMC_NORSRAMInitStructure.FSMC_ReadWriteTimingStruct = &p;
    FSMC_NORSRAMInitStructure.FSMC_WriteTimingStruct = &p;
    FSMC_NORSRAMInit(&FSMC_NORSRAMInitStructure);  

    /* Enable FSMC_Bank1_NORSRAM1 */
    FSMC_NORSRAMCmd(FSMC_Bank1_NORSRAM1, ENABLE);

    /* Configure touch screen controller
     *
     * Connected to SPI1 which is shared with the AT45DB161D.
     *
     * The touch screen is selected with PB7.
     * The flash chip is selected with PA4.
     */

    /* Configure MOSI, MISO and SCLK as alternate function PP */
    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_5 | GPIO_Pin_6 | GPIO_Pin_7;
    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
    GPIO_Init(GPIOA, &GPIO_InitStructure);

    /* Configure flash chip select pin (PA4) as GPIO out PP */
    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_4;
    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
    GPIO_Init(GPIOA, &GPIO_InitStructure);

    /* Configure touch chip select pin (PB7) as GPIO out PP */
    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_7;
    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
    GPIO_Init(GPIOB, &GPIO_InitStructure);

    /* De-select touch & flash */
    GPIO_SetBits(GPIOA, GPIO_Pin_4);
    GPIO_SetBits(GPIOB, GPIO_Pin_7);
    
    /* SPI1 Config */
    SPI_InitStructure.SPI_Direction = SPI_Direction_2Lines_FullDuplex;
    SPI_InitStructure.SPI_Mode = SPI_Mode_Master;
    SPI_InitStructure.SPI_DataSize = SPI_DataSize_8b;
    SPI_InitStructure.SPI_CPOL = SPI_CPOL_Low;
    SPI_InitStructure.SPI_CPHA = SPI_CPHA_1Edge;
    SPI_InitStructure.SPI_NSS = SPI_NSS_Soft;
    SPI_InitStructure.SPI_BaudRatePrescaler = SPI_BaudRatePrescaler_2;
    SPI_InitStructure.SPI_FirstBit = SPI_FirstBit_MSB;
    SPI_InitStructure.SPI_CRCPolynomial = 7;
    SPI_Init(SPI1, &SPI_InitStructure);

    /* SPI1 enable */
    SPI_Cmd(SPI1, ENABLE);

    /* Configure TIM6 for interval timing */
    /* Reset TIM6 */
    TIM_DeInit(TIM6);

    /* Time Base configuration */
    TIM_TimeBaseStructure.TIM_Period = 0;
    TIM_TimeBaseStructure.TIM_Prescaler = (SystemCoreClock / 2 / 1000000) - 1; /* 1 MHz clock */
    TIM_TimeBaseInit(TIM6, &TIM_TimeBaseStructure);

    TIM_Cmd(TIM6, DISABLE);

    /* Setup for single pulse mode clear UDIS */
    TIM_SelectOnePulseMode(TIM6, TIM_OPMode_Single);
    TIM_UpdateDisableConfig(TIM6, DISABLE);

    /* Setup GPIO for delay test & 1-wire
     * PE2 -> pin 3 on header
     * PE3 -> pin 4 on header */
    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_2 | GPIO_Pin_3;
    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
    GPIO_Init(GPIOE, &GPIO_InitStructure);

    OWInit();

#if 0
    while (1) {
	GPIO_SetBits(GPIOE, GPIO_Pin_2);
	_usleep16(10);
	GPIO_ResetBits(GPIOE, GPIO_Pin_2);
	_usleep16(20);
	GPIO_SetBits(GPIOE, GPIO_Pin_2);
	_usleep16(30);
	GPIO_ResetBits(GPIOE, GPIO_Pin_2);
	_usleep16(100);
    }
#endif

    /* Setup I2C bus */
      
    /* Configure SCL/SDA pins */
    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_8 | GPIO_Pin_9;
    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_OD;
    GPIO_Init(GPIOB, &GPIO_InitStructure);
      
    /* Reset I2C1 */
    I2C_DeInit(I2C1);

    /* Setup I2C1 */
    I2C_InitStructure.I2C_Mode = I2C_Mode_I2C;
    I2C_InitStructure.I2C_DutyCycle = I2C_DutyCycle_2;
    I2C_InitStructure.I2C_OwnAddress1 = 0x00;
    I2C_InitStructure.I2C_Ack = I2C_Ack_Enable;
    I2C_InitStructure.I2C_AcknowledgedAddress = I2C_AcknowledgedAddress_7bit;
    I2C_InitStructure.I2C_ClockSpeed = 100000;
    I2C_Init(I2C1, &I2C_InitStructure);

    /* Start I2C controller */
    I2C_Cmd(I2C1, ENABLE);

#if 0
    uint32_t I2C_TimeOut = I2C_TIMEOUT;

    /* Clear the I2C1 AF flag */
    I2C_ClearFlag(I2C1, I2C_FLAG_AF);

    /* Enable I2C1 acknowledgement if it is already disabled by other function */
    I2C_AcknowledgeConfig(I2C1, ENABLE);

    /*---------------------------- Transmission Phase ---------------------------*/

    /* Send I2C1 START condition */
    I2C_GenerateSTART(I2C1, ENABLE);

    /*!< Test on I2C1 EV5 and clear it */
    while ((!I2C_GetFlagStatus(I2C1, I2C_FLAG_SB)) && I2C_TimeOut) {
	I2C_TimeOut--;
    }

    if (I2C_TimeOut == 0) {
	return ERROR;
    }
  
    I2C_TimeOut = I2C_TIMEOUT;
    /* Send STLM75 slave address for write */
    I2C_Send7bitAddress(I2C1, LM75_ADDR, I2C_Direction_Transmitter);

    while ((!I2C_CheckEvent(LM75_I2C, I2C_EVENT_MASTER_TRANSMITTER_MODE_SELECTED)) && I2C_TimeOut) {
	I2C_TimeOut--;
    }

    if ((I2C_GetFlagStatus(LM75_I2C, I2C_FLAG_AF) != 0x00) || (I2C_TimeOut == 0)) {
	return ERROR;
    } else {
	return SUCCESS;
    }

#endif
}