From 4c1eff0373b7a4a0072fc7515352139cd9d6d02f Mon Sep 17 00:00:00 2001 From: Fredrik Thulin Date: Mon, 16 May 2016 15:45:02 +0200 Subject: Add code to talk with the external RTC chip. --- .gitignore | 1 + Makefile | 3 +- .../TARGET_CRYPTECH_ALPHA/stm32f4xx_hal_conf.h | 2 +- .../TARGET_CRYPTECH_ALPHA/stm32f4xx_hal_msp.c | 35 ++++- projects/board-test/Makefile | 2 +- projects/board-test/rtc-test.c | 161 +++++++++++++++++++++ stm-init.c | 29 ++++ stm-rtc.c | 89 ++++++++++++ stm-rtc.h | 62 ++++++++ stm-uart.c | 23 +++ stm-uart.h | 3 + 11 files changed, 406 insertions(+), 4 deletions(-) create mode 100644 projects/board-test/rtc-test.c create mode 100644 stm-rtc.c create mode 100644 stm-rtc.h diff --git a/.gitignore b/.gitignore index ad98d14..b8b0ae3 100644 --- a/.gitignore +++ b/.gitignore @@ -6,3 +6,4 @@ *.hex *.lst *.map +*~ diff --git a/Makefile b/Makefile index 42bd054..43cc10b 100644 --- a/Makefile +++ b/Makefile @@ -52,6 +52,7 @@ export BOARD_OBJS = \ $(TOPLEVEL)/stm-init.o \ $(TOPLEVEL)/stm-fmc.o \ $(TOPLEVEL)/stm-uart.o \ + $(TOPLEVEL)/stm-rtc.o \ $(TOPLEVEL)/syscalls.o \ $(BOARD_DIR)/TOOLCHAIN_GCC_ARM/startup_stm32f429xx.o \ $(BOARD_DIR)/system_stm32f4xx.o \ @@ -127,7 +128,7 @@ hsm: $(BOARD_OBJS) $(LIBS) $(LIBHAL_DIR)/libhal.a # don't automatically delete objects, to avoid a lot of unnecessary rebuilding .SECONDARY: $(BOARD_OBJS) -.PHONY: board-test rtos-test libhal-test +.PHONY: board-test rtos-test libhal-test cli-test clean: rm -f $(BOARD_OBJS) diff --git a/libraries/mbed/targets/cmsis/TARGET_STM/TARGET_STM32F4/TARGET_CRYPTECH_ALPHA/stm32f4xx_hal_conf.h b/libraries/mbed/targets/cmsis/TARGET_STM/TARGET_STM32F4/TARGET_CRYPTECH_ALPHA/stm32f4xx_hal_conf.h index 437ba0d..31c0e31 100644 --- a/libraries/mbed/targets/cmsis/TARGET_STM/TARGET_STM32F4/TARGET_CRYPTECH_ALPHA/stm32f4xx_hal_conf.h +++ b/libraries/mbed/targets/cmsis/TARGET_STM/TARGET_STM32F4/TARGET_CRYPTECH_ALPHA/stm32f4xx_hal_conf.h @@ -68,7 +68,7 @@ //#define HAL_SDRAM_MODULE_ENABLED //#define HAL_HASH_MODULE_ENABLED #define HAL_GPIO_MODULE_ENABLED -//#define HAL_I2C_MODULE_ENABLED +#define HAL_I2C_MODULE_ENABLED //#define HAL_I2S_MODULE_ENABLED //#define HAL_IWDG_MODULE_ENABLED //#define HAL_LTDC_MODULE_ENABLED diff --git a/libraries/mbed/targets/cmsis/TARGET_STM/TARGET_STM32F4/TARGET_CRYPTECH_ALPHA/stm32f4xx_hal_msp.c b/libraries/mbed/targets/cmsis/TARGET_STM/TARGET_STM32F4/TARGET_CRYPTECH_ALPHA/stm32f4xx_hal_msp.c index 81f2367..a430c5e 100644 --- a/libraries/mbed/targets/cmsis/TARGET_STM/TARGET_STM32F4/TARGET_CRYPTECH_ALPHA/stm32f4xx_hal_msp.c +++ b/libraries/mbed/targets/cmsis/TARGET_STM/TARGET_STM32F4/TARGET_CRYPTECH_ALPHA/stm32f4xx_hal_msp.c @@ -47,7 +47,7 @@ void HAL_MspInit(void) /* USER CODE END MspInit 0 */ - /* XXX + /* XXX * Fredrik's HAL_MspInit sets this to NVIC_PRIORITYGROUP_4 (as just * happened in HAL_Init), but then he resets it to NVIC_PRIORITYGROUP_0 * in stm_init. */ @@ -177,4 +177,37 @@ void HAL_UART_MspDeInit(UART_HandleTypeDef* huart) } } +void HAL_I2C_MspInit(I2C_HandleTypeDef* hi2c) +{ + GPIO_InitTypeDef GPIO_InitStruct; + if (hi2c->Instance == I2C2) { + /* + * I2C2 GPIO Configuration + * PH5 ------> I2C2_SDA + * PH4 ------> I2C2_SCL + */ + __GPIOH_CLK_ENABLE(); + + GPIO_InitStruct.Pin = GPIO_PIN_4 | GPIO_PIN_5; + GPIO_InitStruct.Mode = GPIO_MODE_AF_OD; + GPIO_InitStruct.Pull = GPIO_PULLUP; + GPIO_InitStruct.Speed = GPIO_SPEED_HIGH; + GPIO_InitStruct.Alternate = GPIO_AF4_I2C2; + HAL_GPIO_Init(GPIOH, &GPIO_InitStruct); + + /* Peripheral clock enable */ + __I2C2_CLK_ENABLE(); + } + +} + +void HAL_I2C_MspDeInit(I2C_HandleTypeDef* hi2c) +{ + if(hi2c->Instance == I2C2) { + __I2C2_CLK_DISABLE(); + HAL_GPIO_DeInit(GPIOH, GPIO_PIN_4 | GPIO_PIN_5); + } +} + + /************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/ diff --git a/projects/board-test/Makefile b/projects/board-test/Makefile index a4a0a70..9b1812f 100644 --- a/projects/board-test/Makefile +++ b/projects/board-test/Makefile @@ -1,4 +1,4 @@ -TEST = led-test short-test uart-test fmc-test fmc-perf fmc-probe +TEST = led-test short-test uart-test fmc-test fmc-perf fmc-probe rtc-test all: $(TEST:=.elf) diff --git a/projects/board-test/rtc-test.c b/projects/board-test/rtc-test.c new file mode 100644 index 0000000..b8a7511 --- /dev/null +++ b/projects/board-test/rtc-test.c @@ -0,0 +1,161 @@ +/* + * Test code for the RTC. + * + * Dumps the SRAM and EEPROM on startup, then enables the oscillator. + * After that, the clock registers are read once a second - the first byte + * is seconds (and some control bits, so dont expect 0..59). + * + */ +#include + +#include "stm32f4xx_hal.h" +#include "stm-init.h" +#include "stm-led.h" +#include "stm-uart.h" +#include "stm-rtc.h" + +#define DELAY() HAL_Delay(1000) + + +uint8_t buf[1024]; +uint32_t i; + + +uint32_t device_ready(uint16_t i2c_addr) +{ + uart_send_string2(STM_UART_MGMT, "Checking readiness of 0x"); + uart_send_number2(STM_UART_MGMT, i2c_addr, 4, 16); + uart_send_string2(STM_UART_MGMT, "..."); + + if (rtc_device_ready(i2c_addr) == HAL_OK) { + uart_send_string2(STM_UART_MGMT, "OK\r\n"); + return 1; + } + + uart_send_string2(STM_UART_MGMT, "Not ready (0x"); + uart_send_number2(STM_UART_MGMT, i, 4, 16); + uart_send_string2(STM_UART_MGMT, ")\r\n"); + + return 0; +} + + +void send_byte(const uint16_t i2c_addr, const uint8_t value) +{ + uint8_t ch = value; + + uart_send_string2(STM_UART_MGMT, "Sending "); + uart_send_number2(STM_UART_MGMT, ch, 2, 16); + uart_send_string2(STM_UART_MGMT, " to 0x"); + uart_send_number2(STM_UART_MGMT, i2c_addr, 4, 16); + uart_send_string2(STM_UART_MGMT, "..."); + + if (rtc_send_byte(i2c_addr, ch, 1000) != HAL_OK) { + uart_send_string2(STM_UART_MGMT, "Timeout\r\n"); + Error_Handler(); + } + + uart_send_string2(STM_UART_MGMT, "OK\r\n"); +} + +void read_bytes (uint8_t *buf, const uint16_t i2c_addr, const uint8_t len) +{ + uart_send_string2(STM_UART_MGMT, "Reading "); + uart_send_number2(STM_UART_MGMT, len, 3, 10); + uart_send_string2(STM_UART_MGMT, " bytes from 0x"); + uart_send_number2(STM_UART_MGMT, i2c_addr, 4, 16); + uart_send_string2(STM_UART_MGMT, "..."); + + if (rtc_read_bytes(i2c_addr, buf, len, 1000) != HAL_OK) { + uart_send_string2(STM_UART_MGMT, "Timeout\r\n"); + Error_Handler(); + } + + uart_send_string2(STM_UART_MGMT, "OK\r\n"); +} + +void request_data(uint8_t *buf, const uint16_t i2c_addr, const uint8_t offset, const uint8_t bytes) +{ + send_byte(i2c_addr, offset); + read_bytes(buf, i2c_addr, bytes); +} + +void print_time() +{ + request_data(buf, RTC_RTC_ADDR, RTC_TIME_OFFSET, RTC_TIME_BYTES); + + for (i = 0; i < RTC_TIME_BYTES; i++) { + uart_send_number2(STM_UART_MGMT, buf[i], 2, 16); + uart_send_string2(STM_UART_MGMT, " "); + } +} + +void dump_sram() +{ + request_data(buf, RTC_RTC_ADDR, 0x0, RTC_SRAM_TOTAL_BYTES); + + uart_send_string2(STM_UART_MGMT, "SRAM contents:\r\n"); + uart_send_hexdump(STM_UART_MGMT, buf, 0, RTC_SRAM_TOTAL_BYTES); + + uart_send_string2(STM_UART_MGMT, "\r\n"); +} + +void dump_eeprom() +{ + request_data(buf, RTC_EEPROM_ADDR, 0x0, RTC_EEPROM_TOTAL_BYTES); + + uart_send_string2(STM_UART_MGMT, "EEPROM contents:\r\n"); + uart_send_hexdump(STM_UART_MGMT, buf, 0, RTC_EEPROM_TOTAL_BYTES); + uart_send_string2(STM_UART_MGMT, "\r\n"); + + request_data(buf, RTC_EEPROM_ADDR, RTC_EEPROM_EUI48_OFFSET, RTC_EEPROM_EUI48_BYTES); + uart_send_string2(STM_UART_MGMT, "EEPROM EUI-48:\r\n"); + uart_send_hexdump(STM_UART_MGMT, buf, RTC_EEPROM_EUI48_OFFSET, RTC_EEPROM_EUI48_BYTES); + + uart_send_string2(STM_UART_MGMT, "\r\n"); +} + +void enable_oscillator() +{ + uart_send_string2(STM_UART_MGMT, "Enabling oscillator...\r\n"); + + if (rtc_enable_oscillator() != HAL_OK) { + uart_send_string2(STM_UART_MGMT, "Timeout\r\n"); + Error_Handler(); + } + + uart_send_string2(STM_UART_MGMT, "OK\r\n"); +} + + +int +main() +{ + stm_init(); + uart_send_string2(STM_UART_MGMT, "\r\n\r\n*** Init done\r\n"); + + dump_sram(); + dump_eeprom(); + + enable_oscillator(); + + while (1) { + memset(buf, 0, sizeof(buf)); + + if (! device_ready(RTC_RTC_ADDR)) { + goto fail; + } + + print_time(buf); + + uart_send_string2(STM_UART_MGMT, "\r\n\r\n"); + + HAL_GPIO_TogglePin(LED_PORT, LED_GREEN); + DELAY(); + continue; + + fail: + HAL_GPIO_TogglePin(LED_PORT, LED_RED); + DELAY(); + } +} diff --git a/stm-init.c b/stm-init.c index 2219d43..af3d47b 100644 --- a/stm-init.c +++ b/stm-init.c @@ -44,6 +44,9 @@ #ifdef HAL_UART_MODULE_ENABLED #include "stm-uart.h" #endif +#ifdef HAL_I2C_MODULE_ENABLED +#include "stm-rtc.h" +#endif /* Private variables ---------------------------------------------------------*/ @@ -55,6 +58,9 @@ static void MX_GPIO_Init(void); static void MX_USART1_UART_Init(void); static void MX_USART2_UART_Init(void); #endif +#ifdef HAL_I2C_MODULE_ENABLED +static void MX_I2C2_Init(void); +#endif void stm_init(void) { @@ -74,6 +80,9 @@ void stm_init(void) MX_USART1_UART_Init(); MX_USART2_UART_Init(); #endif +#ifdef HAL_I2C_MODULE_ENABLED + MX_I2C2_Init(); +#endif } @@ -138,6 +147,26 @@ static void MX_GPIO_Init(void) } #endif +#ifdef HAL_I2C_MODULE_ENABLED +/* I2C2 init function (external RTC chip) */ +void MX_I2C2_Init(void) +{ + hi2c_rtc.Instance = I2C2; + hi2c_rtc.Init.ClockSpeed = 10000; + hi2c_rtc.Init.DutyCycle = I2C_DUTYCYCLE_2; + hi2c_rtc.Init.OwnAddress1 = 0; /* Will operate as Master */ + hi2c_rtc.Init.AddressingMode = I2C_ADDRESSINGMODE_7BIT; + hi2c_rtc.Init.DualAddressMode = I2C_DUALADDRESS_DISABLED; + hi2c_rtc.Init.OwnAddress2 = 0; + hi2c_rtc.Init.GeneralCallMode = I2C_GENERALCALL_DISABLED; + hi2c_rtc.Init.NoStretchMode = I2C_NOSTRETCH_DISABLED; + + if (HAL_I2C_Init(&hi2c_rtc) != HAL_OK) { + Error_Handler(); + } +} +#endif + /** * @brief This function is executed in case of error occurrence. * @param None diff --git a/stm-rtc.c b/stm-rtc.c new file mode 100644 index 0000000..85afdf4 --- /dev/null +++ b/stm-rtc.c @@ -0,0 +1,89 @@ +/* + * stm-rtc.c + * ---------- + * Functions for using the externally connected RTC chip. + * + * Copyright (c) 2015-2016, NORDUnet A/S All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * - Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * - Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * - Neither the name of the NORDUnet nor the names of its contributors may + * be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS + * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A + * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED + * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "stm32f4xx_hal.h" +#include "stm-rtc.h" + +I2C_HandleTypeDef hi2c_rtc; + +HAL_StatusTypeDef rtc_device_ready(uint16_t i2c_addr) +{ + return HAL_I2C_IsDeviceReady (&hi2c_rtc, i2c_addr, 10, 1000); +} + +HAL_StatusTypeDef rtc_enable_oscillator() +{ + uint8_t buf[2]; + HAL_StatusTypeDef res; + + buf[0] = 0; /* Offset of RTCSEC */ + buf[1] = 1 << 7; /* datasheet REGISTERS 5-1, bit 7 = ST (start oscillator) */ + + while (HAL_I2C_Master_Transmit (&hi2c_rtc, RTC_RTC_ADDR_W, buf, 2, 1000) != HAL_OK) { + res = HAL_I2C_GetError (&hi2c_rtc); + if (res != HAL_I2C_ERROR_AF) { + return res; + } + } + + return HAL_OK; +} + +HAL_StatusTypeDef rtc_send_byte(const uint16_t i2c_addr, const uint8_t value, const uint16_t timeout) +{ + HAL_StatusTypeDef res; + + while (HAL_I2C_Master_Transmit (&hi2c_rtc, i2c_addr, &value, 1, timeout) != HAL_OK) { + res = HAL_I2C_GetError (&hi2c_rtc); + if (res != HAL_I2C_ERROR_AF) { + return res; + } + } + + return HAL_OK; +} + +HAL_StatusTypeDef rtc_read_bytes (const uint16_t i2c_addr, uint8_t *buf, const uint8_t len, const uint16_t timeout) +{ + HAL_StatusTypeDef res; + + while (HAL_I2C_Master_Receive (&hi2c_rtc, i2c_addr, buf, len, 1000) != HAL_OK) { + res = HAL_I2C_GetError (&hi2c_rtc); + if (res != HAL_I2C_ERROR_AF) { + return res; + } + } + + return HAL_OK; +} diff --git a/stm-rtc.h b/stm-rtc.h new file mode 100644 index 0000000..edbed9d --- /dev/null +++ b/stm-rtc.h @@ -0,0 +1,62 @@ +/* + * stm-rtc.h + * --------- + * Functions and defines to use the externally connected RTC chip. + * + * Copyright (c) 2015-2016, NORDUnet A/S All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * - Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * - Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * - Neither the name of the NORDUnet nor the names of its contributors may + * be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS + * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A + * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED + * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef __STM32_RTC_H +#define __STM32_RTC_H + +#include "stm32f4xx_hal.h" + +extern I2C_HandleTypeDef hi2c_rtc; + +extern HAL_StatusTypeDef rtc_device_ready(uint16_t i2c_addr); +extern HAL_StatusTypeDef rtc_enable_oscillator(); +extern HAL_StatusTypeDef rtc_send_byte(const uint16_t i2c_addr, const uint8_t value, const uint16_t timeout); +extern HAL_StatusTypeDef rtc_read_bytes (const uint16_t i2c_addr, uint8_t *buf, const uint8_t len, const uint16_t timeout); + +#define RTC_RTC_ADDR 0xdf +#define RTC_EEPROM_ADDR 0xaf + +#define RTC_RTC_ADDR_W RTC_RTC_ADDR ^ 1 /* turn off LSB to write */ +#define RTC_EEPROM_ADDR_W RTC_EEPROM_ADDR ^ 1 /* turn off LSB to write */ + +#define RTC_SRAM_TOTAL_BYTES 0x5f +#define RTC_EEPROM_TOTAL_BYTES 0x7f + +#define RTC_EEPROM_EUI48_OFFSET 0xf0 +#define RTC_EEPROM_EUI48_BYTES 8 + +#define RTC_TIME_OFFSET 0x0 /* Time is at offest 0 in SRAM */ +#define RTC_TIME_BYTES 8 + +#endif /* __STM32_RTC_H */ diff --git a/stm-uart.c b/stm-uart.c index 2605f99..6f49ce3 100644 --- a/stm-uart.c +++ b/stm-uart.c @@ -165,3 +165,26 @@ HAL_StatusTypeDef uart_send_number2(enum stm_uart_port port, uint32_t num, uint8 return HAL_UART_Transmit(uart, (uint8_t *) where, digits, 0x1); } + +HAL_StatusTypeDef uart_send_hexdump(enum stm_uart_port port, const uint8_t *buf, + const uint8_t start_offset, const uint8_t end_offset) +{ + uint32_t i; + + uart_send_string2(port, "00 -- "); + + for (i = 0; i <= end_offset; i++) { + if (i && (! (i % 16))) { + uart_send_string2(port, "\r\n"); + + if (i != end_offset) { + /* Output new offset unless the last byte is reached */ + uart_send_number2(port, i, 2, 16); + uart_send_string2(port, " -- "); + } + } + + uart_send_number2(port, *(buf + i), 2, 16); + uart_send_string2(port, " "); + } +} diff --git a/stm-uart.h b/stm-uart.h index 21f3701..e4ee1c3 100644 --- a/stm-uart.h +++ b/stm-uart.h @@ -63,6 +63,9 @@ extern HAL_StatusTypeDef uart_send_number2(enum stm_uart_port port, uint32_t num extern HAL_StatusTypeDef uart_send_bytes(enum stm_uart_port port, uint8_t *buf, size_t len); extern HAL_StatusTypeDef uart_receive_bytes(enum stm_uart_port port, uint8_t *buf, size_t len, uint32_t timeout); +extern HAL_StatusTypeDef uart_send_hexdump(enum stm_uart_port port, const uint8_t *buf, + const uint8_t start_offset, const uint8_t end_offset); + #define uart_send_binary(num, bits) uart_send_number(num, bits, 2) #define uart_send_integer(num, digits) uart_send_number(num, digits, 10) #define uart_send_hex(num, digits) uart_send_number(num, digits, 16) -- cgit v1.2.3