Commit d7b26872 authored by Henrique Silva's avatar Henrique Silva

Merge branch 'devel' into master

parents 890b3a7a 8c4fcf39
This diff is collapsed.
......@@ -33,17 +33,26 @@
Debug/
*.launch
*.xml
#.cproject
#.project
.cproject
.project
#Temporary files
*.swp
*.map
*~
*#*
*.#*
#Dependency files
*.d
#Binaries
*.axf
*.bin
\ No newline at end of file
*.bin
#Cmake file
CMakeFiles/
*.dir/*
Makefile
*cmake_install.cmake
CMakeCache.txt
\ No newline at end of file
<?xml version="1.0" encoding="UTF-8"?>
<projectDescription>
<name>afcipm</name>
<comment></comment>
<projects>
<project>lpc_chip_175x_6x</project>
</projects>
<buildSpec>
<buildCommand>
<name>org.eclipse.cdt.managedbuilder.core.genmakebuilder</name>
<triggers>clean,full,incremental,</triggers>
<arguments>
</arguments>
</buildCommand>
<buildCommand>
<name>org.eclipse.cdt.managedbuilder.core.ScannerConfigBuilder</name>
<triggers>full,incremental,</triggers>
<arguments>
</arguments>
</buildCommand>
</buildSpec>
<natures>
<nature>org.eclipse.cdt.core.cnature</nature>
<nature>org.eclipse.cdt.managedbuilder.core.managedBuildNature</nature>
<nature>org.eclipse.cdt.managedbuilder.core.ScannerConfigNature</nature>
</natures>
</projectDescription>
# Define minimal required version of CMake.
cmake_minimum_required(VERSION 2.8.7)
# Project definition
project(openMMC C CXX ASM)
# Color definitions
if(NOT WIN32)
string(ASCII 27 Esc)
set(ColourReset "${Esc}[m")
set(ColourBold "${Esc}[1m")
set(Red "${Esc}[31m")
set(Green "${Esc}[32m")
set(Yellow "${Esc}[33m")
set(Blue "${Esc}[34m")
set(Magenta "${Esc}[35m")
set(Cyan "${Esc}[36m")
set(White "${Esc}[37m")
set(BoldRed "${Esc}[1;31m")
set(BoldGreen "${Esc}[1;32m")
set(BoldYellow "${Esc}[1;33m")
set(BoldBlue "${Esc}[1;34m")
set(BoldMagenta "${Esc}[1;35m")
set(BoldCyan "${Esc}[1;36m")
set(BoldWhite "${Esc}[1;37m")
endif()
##
# CMake environment settings
#
#Find a toolchain file
if(NOT CMAKE_TOOLCHAIN_FILE)
message(WARNING "${Yellow}No toolchain configuration file specified. Using default option!${ColourReset}")
include(toolchain/toolchain-arm-none-eabi.cmake)
endif()
set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} "${CMAKE_SOURCE_DIR}/build_cfg")
set(CMAKE_COLOR_MAKEFILE ON)
set(CMAKE_VERBOSE_MAKEFILE ON)
set(CMAKE_ALLOW_LOOSE_LOOP_CONSTRUCTS TRUE)
set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${PROJECT_BINARY_DIR}/out)
set(CMAKE_LIBRARY_OUTPUT_DIRECTORY ${PROJECT_BINARY_DIR}/lib)
set(CMAKE_ARCHIVE_OUTPUT_DIRECTORY ${PROJECT_BINARY_DIR}/lib)
if(NOT CMAKE_BUILD_TYPE)
set(CMAKE_BUILD_TYPE Debug CACHE STRING
"Choose the type of build, options are: none Debug Release Trace."
FORCE)
endif()
# Include board specific code
set(CMAKE_ERROR_FLAGS "-Wall -Wextra -Wpointer-arith -Wno-packed-bitfield-compat -Wno-unused-parameter -Wno-missing-field-initializers")
# Build specific flags
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${CMAKE_ERROR_FLAGS}")
set(CMAKE_C_FLAGS_DEBUG "${CMAKE_C_FLAGS} -O0 -g3 -DDEBUG")
set(CMAKE_C_FLAGS_RELEASE "${CMAKE_C_FLAGS} -O3")
# When we break up long strings in CMake we get semicolon
# separated lists, undo this here...
string(REGEX REPLACE ";" " " CMAKE_C_FLAGS "${CMAKE_C_FLAGS}")
string(REGEX REPLACE ";" " " CMAKE_C_FLAGS_DEBUG "${CMAKE_C_FLAGS_DEBUG}")
string(REGEX REPLACE ";" " " CMAKE_C_FLAGS_RELEASE "${CMAKE_C_FLAGS_RELEASE}")
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS}" CACHE STRING "")
set(CMAKE_C_FLAGS_DEBUG "${CMAKE_C_FLAGS_DEBUG}" CACHE STRING "")
set(CMAKE_C_FLAGS_RELEASE "${CMAKE_C_FLAGS_RELEASE}" CACHE STRING "")
set(PROJ_SRCS ${CMAKE_CURRENT_SOURCE_DIR}/main_mmc.c)
add_subdirectory(port/board)
add_subdirectory(port/chip)
add_subdirectory(FreeRTOS)
add_subdirectory(boot)
add_subdirectory(modules)
if(CMAKE_BUILD_TYPE STREQUAL "Trace")
add_subdirectory(trace)
endif()
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -DTARGET_CONTROLLER=${TARGET_CONTROLLER} -DTARGET_BOARD_NAME=${TARGET_BOARD_NAME} -DTARGET_BOARD_MAJOR=${TARGET_BOARD_MAJOR} -DTARGET_BOARD_MINOR=${TARGET_BOARD_MINOR} ")
# Libraries path
link_directories(${CMAKE_LIBRARY_OUTPUT_DIRECTORY})
## Create executable
add_executable(${CMAKE_PROJECT_NAME} ${LPC17_SRCS} ${PROJ_SRCS})
set_target_properties(${CMAKE_PROJECT_NAME} PROPERTIES COMPILE_FLAGS ${MODULES_FLAGS})
add_executable(bootloader ${BOOT_SRCS} ${LPC17_SRCS})
# Linker flags
set(CMAKE_SHARED_LIBRARY_LINK_C_FLAGS "")
set_target_properties(${CMAKE_PROJECT_NAME} PROPERTIES
SUFFIX ".axf"
LINK_FLAGS "-T ${CMAKE_SOURCE_DIR}/linker/lpc1764_app.ld -Wl,-Map=${CMAKE_SOURCE_DIR}/linker/lpc1764_app.map" )
set_target_properties(bootloader PROPERTIES
SUFFIX ".axf"
LINK_FLAGS "-T ${CMAKE_SOURCE_DIR}/linker/lpc1764_boot.ld -Wl,-Map=${CMAKE_SOURCE_DIR}/linker/lpc1764_boot.map")
# Headers path
target_include_directories(${CMAKE_PROJECT_NAME} PUBLIC ${PROJ_HDRS})
target_include_directories(bootloader PUBLIC ${PROJ_HDRS})
# Link libraries
target_link_libraries(${CMAKE_PROJECT_NAME} gcc c m FreeRTOS lpcopen)
target_link_libraries(bootloader gcc c m lpcopen)
##Generate .hex file
add_custom_command(TARGET ${CMAKE_PROJECT_NAME} POST_BUILD
COMMAND ${CMAKE_OBJCOPY} -O binary ${CMAKE_PROJECT_NAME}.axf ${CMAKE_PROJECT_NAME}.bin
WORKING_DIRECTORY ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}
COMMENT "Converting the AXF output to a binary file"
)
add_custom_command(TARGET bootloader POST_BUILD
COMMAND ${CMAKE_OBJCOPY} -O binary bootloader.axf bootloader.bin
WORKING_DIRECTORY ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}
COMMENT "Converting the AXF output to a binary file"
)
##Program command
set(LPCXPRESSO_PATH /usr/local/lpcxpresso_7.8.0_426/lpcxpresso/)
find_program(DFU_UTIL dfu-util)
find_program(NXP_PROG crt_emu_cm3_nxp PATHS ${LPCXPRESSO_PATH}/bin NO_DEFAULT_PATH)
if(NOT DFU_UTIL)
message(WARNING "${ColourBold}${Red}Dfu-util not found! Can't boot the LPCLink board!${ColourReset}")
elseif(NOT NXP_PROG)
message(WARNING "${ColourBold}${Red}crt_emu_cm3_nxp not found! Can't program the LPC chip!${ColourReset}")
else()
# Boot the programmer
execute_process(
COMMAND ${DFU_UTIL} -d 0x471:0xdf55 -c 0 -t 2048 -R -D ${LPCXPRESSO_PATH}/bin/LPCXpressoWIN.enc
ERROR_QUIET
)
# Program the chip (available only for LPC1764 so far)
add_custom_target(program_boot
WORKING_DIRECTORY ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/
DEPENDS bootloader
COMMAND ${NXP_PROG} -wire=winusb -p${TARGET_CONTROLLER} -g -flash-load=bootloader.bin -load-base=0x0000
)
add_custom_target(program_app
WORKING_DIRECTORY ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/
DEPENDS ${CMAKE_PROJECT_NAME}
COMMAND ${NXP_PROG} -wire=winusb -p${TARGET_CONTROLLER} -g -flash-load-exec=${CMAKE_PROJECT_NAME}.bin -load-base=0x2000
)
add_custom_target(program_all
WORKING_DIRECTORY ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/
DEPENDS ${CMAKE_PROJECT_NAME} bootloader
COMMAND ${NXP_PROG} -wire=winusb -p${TARGET_CONTROLLER} -flash-mass-erase
COMMAND make -C ${CMAKE_SOURCE_DIR} program_boot
COMMAND make -C ${CMAKE_SOURCE_DIR} program_app
)
endif()
# Build FreeRTOS library
set(FREERTOS_INC ${CMAKE_CURRENT_SOURCE_DIR}/include)
include_directories(${PROJ_HDRS})
include_directories(${FREERTOS_INC})
set(PROJ_HDRS ${PROJ_HDRS} ${FREERTOS_INC} PARENT_SCOPE)
set(LIBFREERTOS_SRCS
list.c
queue.c
timers.c
port.c
tasks.c
heap_4.c
heap_2.c
event_groups.c
)
add_library(FreeRTOS STATIC ${LIBFREERTOS_SRCS})
......@@ -349,6 +349,47 @@ BlockLink_t *pxLink;
}
/*-----------------------------------------------------------*/
#include "string.h"
void *pvPortCalloc(size_t count, size_t size)
{
void *p;
/* allocate 'count' objects of size 'size' */
p = pvPortMalloc(count * size);
if (p) {
/* zero the memory */
memset(p, 0, count * size);
}
return p;
}
void *calloc(size_t count, size_t nbytes) __attribute__((alias("pvPortCalloc")));
/*-----------------------------------------------------------*/
void *pvPortRealloc(void *mem, size_t newsize)
{
void *p;
p = pvPortMalloc(newsize);
if (p) {
/* Copy the contents of the old region */
if (mem != NULL) {
memcpy(p, mem, newsize);
vPortFree(mem);
}
}
return p;
}
void *realloc(void *ptr, size_t nbytes) __attribute__((alias("pvPortRealloc")));
/*-----------------------------------------------------------*/
/*-----------------------------------------------------------*/
size_t xPortGetFreeHeapSize( void )
{
return xFreeBytesRemaining;
......
......@@ -57,7 +57,7 @@ licensing and training services.
#define configMINIMAL_STACK_SIZE ( ( unsigned short ) 150 )
#define configTOTAL_HEAP_SIZE ( ( size_t ) ( 0x4000 ) )
#define configMAX_TASK_NAME_LEN ( 12 )
#define configUSE_TRACE_FACILITY 0
#define configUSE_TRACE_FACILITY 1
#define configUSE_16_BIT_TICKS 0
#define configIDLE_SHOULD_YIELD 0
#define configUSE_CO_ROUTINES 0
......@@ -68,7 +68,7 @@ licensing and training services.
#define configCHECK_FOR_STACK_OVERFLOW 1
#define configUSE_RECURSIVE_MUTEXES 0
#define configQUEUE_REGISTRY_SIZE 3
#define configGENERATE_RUN_TIME_STATS 0
#define configGENERATE_RUN_TIME_STATS 1
#define configUSE_MALLOC_FAILED_HOOK 0
#define configENABLE_BACKWARD_COMPATIBILITY 1
#define configUSE_APPLICATION_TASK_TAG 0
......@@ -77,6 +77,7 @@ licensing and training services.
#define configAPPLICATION_ALLOCATED_HEAP 1
#define USE_HEAP_4
void vAssertCalled( char* file, uint32_t line);
#define configASSERT( x ) if( ( x ) == 0 ) { vAssertCalled( __FILE__, __LINE__ );}
#if (configGENERATE_RUN_TIME_STATS == 1)
......@@ -92,7 +93,7 @@ extern void vConfigureTimerForRunTimeStats( void );
#define INCLUDE_vTaskPrioritySet 1
#define INCLUDE_uxTaskPriorityGet 0
#define INCLUDE_vTaskDelete 1
#define INCLUDE_vTaskCleanUpResources 0
#define INCLUDE_vTaskCleanUpResources 1
#define INCLUDE_vTaskSuspend 1
#define INCLUDE_vTaskDelayUntil 1
#define INCLUDE_vTaskDelay 1
......
......@@ -162,6 +162,8 @@ void vPortDefineHeapRegions( const HeapRegion_t * const pxHeapRegions );
*/
void *pvPortMalloc( size_t xSize ) PRIVILEGED_FUNCTION;
void vPortFree( void *pv ) PRIVILEGED_FUNCTION;
void *pvPortCalloc(size_t count, size_t size) PRIVILEGED_FUNCTION;
void *pvPortRealloc(void *mem, size_t newsize) PRIVILEGED_FUNCTION;
void vPortInitialiseBlocks( void ) PRIVILEGED_FUNCTION;
size_t xPortGetFreeHeapSize( void ) PRIVILEGED_FUNCTION;
size_t xPortGetMinimumEverFreeHeapSize( void ) PRIVILEGED_FUNCTION;
......
TOOLCHAIN = arm-none-eabi-
CC = $(TOOLCHAIN)gcc
AR = $(TOOLCHAIN)ar
OBJCOPY = $(TOOLCHAIN)objcopy
PROJ = afcipm
MAKEFILE = Makefile
MAKE = make
MCPU = cortex-m3
LIBDIR = lib
BUILDDIR = out
#Used for program operation (LPCLink specific software)
LPCXPRESSO_PATH=/usr/local/lpcxpresso*/lpcxpresso
#Flags to be passed on to gcc
DEFS = -DDEBUG -DCORE_M3 -D__CODE_RED -D__USE_LPCOPEN -DNO_BOARD_LIB -D__LPC17XX__ -D__NEWLIB__
LD_SCRIPT = linker/lpc1764.ld
MAP = linker/afcipm.map
LD_FLAGS = -T $(LD_SCRIPT) -Xlinker -Map=$(MAP)
LD_FLAGS += -Xlinker --gc-sections
LD_FLAGS += -mcpu=$(MCPU) -mthumb
LD_FLAGS += --specs=nosys.specs
LPCOPEN_LIBNAME = lpcopen
LPCOPEN_LIBFILE = $(LIBDIR)/lib$(LPCOPEN_LIBNAME).a
LPCOPEN_PATH = ./port/nxp/lpc17xx/lpcopen
LPCOPEN_SRCPATH = $(LPCOPEN_PATH)/src
LPCOPEN_SRC = $(shell find $(LPCOPEN_SRCPATH) -name '*.c')
LPCOPEN_INCPATH = $(LPCOPEN_PATH)/inc
LPCOPEN_OBJS = $(LPCOPEN_SRC:%.c=%.o)
FREERTOS_LIBNAME = freertos
FREERTOS_LIBFILE = $(LIBDIR)/lib$(FREERTOS_LIBNAME).a
FREERTOS_PATH = ./FreeRTOS
FREERTOS_SRCPATH = $(FREERTOS_PATH)
FREERTOS_SRC = $(shell find $(FREERTOS_SRCPATH) -name '*.c')
FREERTOS_INCPATH = $(FREERTOS_PATH)/include
FREERTOS_OBJS = $(FREERTOS_SRC:%.c=%.o)
INCLUDES = -I./
INCLUDES += -I./board/afcv3
INCLUDES += -I./port/nxp/lpc17xx
INCLUDES += -I./modules
INCLUDES += -I./trace/Include
INCLUDES += -I./modules/sensors
INCLUDES += -I$(LPCOPEN_INCPATH)
INCLUDES += -I$(FREERTOS_INCPATH)
EXTRA_CFLAGS = -Wall -O0 -g3 -std=gnu99
CFLAGS = $(DEFS) $(INCLUDES)
CFLAGS += -mcpu=$(MCPU) -mthumb
CFLAGS += -Wno-packed-bitfield-compat
CFLAGS += -fno-builtin -ffunction-sections -fdata-sections -fno-strict-aliasing -fmessage-length=0 -nostdlib
CFLAGS += $(EXTRA_CFLAGS)
LIBS += -lgcc -lc -lm -l$(FREERTOS_LIBNAME) -l$(LPCOPEN_LIBNAME)
DEPS = -MMD -MP -MF"$(@:%.o=%.d)" -MT"$(@:%.o=%.o)" -MT"$(@:%.o=%.d)"
PROJ_SRCDIR = ./
PROJ_SRC = $(shell find $(PROJ_SRCDIR) -type d \( -path $(FREERTOS_PATH) -o -path $(LPCOPEN_PATH) \) -prune -o -name '*.c' -print)
PROJ_OBJS = $(PROJ_SRC:%.c=%.o)
.PRECIOUS: %.axf %.bin
all: $(PROJ).bin
folders:
@mkdir -p $(LIBDIR)
@mkdir -p $(BUILDDIR)
%.bin: $(BUILDDIR)/%.axf
@echo 'Creating Binary file from .axf'
$(OBJCOPY) -O binary $< $(BUILDDIR)/$@
@echo 'Binary file created succesfully!'
@echo ' '
#Linker
%.axf: folders $(FREERTOS_LIBFILE) $(LPCOPEN_LIBFILE) $(PROJ_OBJS)
@echo 'Invoking MCU Linker'
$(CC) $(LD_FLAGS) -o $(BUILDDIR)/$(notdir $@) $(PROJ_OBJS) -L$(LIBDIR) $(LIBS)
@echo '$@ linked successfully!'
@echo ' '
#Sources Compile
%.o: %.c
@echo 'Building $< '
$(CC) $(CFLAGS) $(DEPS) -o $@ -c $<
-include $(@:%.o=%.d)
@echo ' $< built successfully!'
@echo ' '
#Archiver for FreeRTOS objects
$(FREERTOS_LIBFILE): $(FREERTOS_OBJS)
@echo 'Archiving $@ objs'
$(AR) -r $@ $(FREERTOS_OBJS)
@echo 'Library $@ successfully created'
@echo ' '
#Archiver for LPCOpen objects
$(LPCOPEN_LIBFILE): $(LPCOPEN_OBJS)
@echo 'Archiving $@ objs'
$(AR) -r $@ $(LPCOPEN_OBJS)
@echo 'Library $@ successfully created'
@echo ' '
#Other targets
clean:
@rm -rf $(PROJ_OBJS) $(PROJ_OBJS:%.o=%.d) *.map
@rm -rf $(BUILDDIR)
mrproper: clean
@rm -rf $(LPCOPEN_OBJS) $(LPCOPEN_OBJS:%.o=%.d)
@rm -rf $(FREERTOS_OBJS) $(FREERTOS_OBJS:%.o=%.d)
@rm -rf $(LIBDIR)
boot:
@echo 'Booting LPCLink...'
$(LPCXPRESSO_PATH)/bin/dfu-util -d 0x471:0xdf55 -c 0 -t 2048 -R -D $(LPCXPRESSO_PATH)/bin/LPCXpressoWIN.enc
@echo 'LPCLink booted!'
@echo ' '
program:
@if [ ! -f $(BUILDDIR)/$(PROJ).axf ]; then \
$(MAKE) $(PROJ).axf; \
fi
@$(MAKE) -i boot
@echo 'Programing Flash...'
#Program flash and reset chip
$(LPCXPRESSO_PATH)/bin/crt_emu_cm3_nxp -wire=winusb -pLPC1764 -flash-load-exec=$(BUILDDIR)/$(PROJ).axf
@echo 'Programed Successfully!'
@echo ' '
#Debug print
print-%: ; @echo $*=$($*)
.PHONY: all clean mrproper boot program folders
# AFCIPM
MMC firmware for AFC boards
# openMMC
Open Source modular IPM Controller firmware
## Installation:
To compile this firmware, it is necessary to install **`GCC ARM Embedded`**, a specific toolchain to Cortex-M and Cortex-R processors.
You can download it's binary and install yourself:
* https://launchpad.net/gcc-arm-embedded/+download
The following packages are needed in your system in order to compile the firmware:
- **gcc-arm-none-eabi**
- **cmake**
- **cmake-gui** (Optional)
or run the following command:
**gcc-arm-none-eabi** can be installed from the pre-compiled files found at: https://launchpad.net/gcc-arm-embedded/+download
or you can run the following command under Ubuntu:
sudo apt-get install gcc-arm-none-eabi
Next step is to clone this repository into your workspace.
git clone https://github.com/lnls-dig/openMMC
## Compilation
Go to the repository folder
cd afcipm
cd /path/to/repo/
If this is the first time compiling this firmware, run CMake configuration scripts
Compile the firmware
cmake .
make all
You can set your board options in the file `build_cfg/config.cmake`. You can change the Controller, Board name, version and select which modules you want to be included in your compilation.
It will create a `.axf` file and a `.bin` file, which you can use to program your processor.
After changing the desired options, run the CMake configuration command again (the CMakeCache file will not be edited by this command) and compile the firmware:
If you want to create only a `.bin` file, or specify a different output name, run
make -s
make <output_name>.bin
*NOTE: The compiler will return several warnings, most of them are regarding the LPCOpen libraries and do not affect the library functionality.*
Both a `.axf` file and a `.bin` file will be generated in the `out` folder. You can use any one you prefer to program your processor.
To clean the compilation files (binaries, objects and dependence files), just run
......@@ -33,7 +43,17 @@ To clean the compilation files (binaries, objects and dependence files), just ru
## Programming LPC1764
If you own a *LPCLink* board, you can use it to program the LPC1764 processor via its JTAG interface
make program
To transfer only the application firmware, run
make program_app
To transfer only the bootloader firmware, run
make program_boot
If you want to erase the whole Flash and copy both firmwares:
make program_all
**NOTE**: In this case you must have the LPCXpresso installed in your machine, since we need to use some initialization scripts that they provide.
**NOTE 2**: We only have linker scripts to LPC1764, so if you wish to compile to a different target, you'll have to change the `afcipm_mem.ld` file, which defines the memory regions, otherwise you'll run into some HardFault errors.
**NOTE 2**: We only have linker scripts to LPC1764, so if you wish to compile to a different target, you'll have to change the `linker\lpc1764_boot.ld` and `linker\lpc1764_app.ld` files, which defines the memory regions, otherwise you'll run into some HardFault errors.
#include "port.h"
#include "pin_mapping.h"
#include "ad84xx.h"
void dac_vadj_init( void )
{
gpio_set_pin_dir( GPIO_DAC_VADJ_RST_PORT, GPIO_DAC_VADJ_RST_PIN, OUTPUT);
gpio_set_pin_dir( GPIO_DAC_VADJ_CSN_PORT, GPIO_DAC_VADJ_CSN_PIN, OUTPUT);
gpio_set_pin_state( GPIO_DAC_VADJ_RST_PORT, GPIO_DAC_VADJ_RST_PIN, LOW);
spi_config( DAC_VADJ_SPI_SPEED, DAC_VADJ_FRAME_SIZE, SPI_MASTER, SPI_POLLING );
gpio_set_pin_state( GPIO_DAC_VADJ_RST_PORT, GPIO_DAC_VADJ_RST_PIN, HIGH);
}
void dac_vadj_config( uint8_t addr, uint8_t val )
{
uint8_t data[2] = { (val), (addr & 0x3) };
spi_assertSSEL();
spi_write( &data, sizeof(data) );
spi_deassertSSEL();
}
#ifndef AD84XX_H_
#define AD84XX_H_
#define DAC_VADJ_SPI_SPEED 10000000
#define DAC_VADJ_FRAME_SIZE 10
void dac_vadj_init( void );
void dac_vadj_config( uint8_t addr, uint8_t val );
#endif
#ifndef FPGA_SPI_H_
#define FPGA_SPI_H_
#define FPGA_SPI 0
#define FPGA_BITRATE 10000000
#define FPGA_UPDATE_RATE 5000 // in ms
#define FPGA_MEM_ADDR_MAX 0xFF
#define WR_COMMAND 0x80
#define RD_COMMAND 0x00
#define NO_DIAG 0x00
#define FPGA_TEMP_DEVID 0x01
#define FMC1_TEMP_DEVID 0x02
#define FMC2_TEMP_DEVID 0x03
#define DCDC_TEMP_DEVID 0x04
#define SDRAM_TEMP_DEVID 0x05
#define FMC1_12V_CURR_DEVID 0x06
#define FMC1_P3V3_CURR_DEVID 0x07
#define FMC1_VADJ_CURR_DEVID 0x08
#define FMC2_12V_CURR_DEVID 0x09
#define FMC2_P3V3_CURR_DEVID 0x0A
#define FMC2_VADJ_CURR_DEVID 0x0B
#define FMC1_12V_DEVID 0x0C
#define FMC1_P3V3_DEVID 0x0D
#define FMC1_VADJ_DEVID 0x0E
#define FMC2_12V_DEVID 0x0F
#define FMC2_P3V3_DEVID 0x10
#define FMC2_VADJ_DEVID 0x11
typedef struct {
#ifdef BF_MS_FIRST
uint8_t dev_id;
uint32_t measure:24;
#else
uint32_t measure:24;
uint8_t dev_id;
#endif
} t_sensor_diag;
typedef struct __attribute__ ((__packed__)) {
#ifdef BF_MS_FIRST
uint32_t reserved:26,
fmc2_pg_c2m:1,
fmc1_pg_c2m:1,
fmc2_pg_m2c:1,
fmc1_pg_m2c:1,
fmc2_prsnt_m2c_n:1,
fmc1_prsnt_m2c_n:1;
#else
uint32_t fmc1_prsnt_m2c_n:1,
fmc2_prsnt_m2c_n:1,
fmc1_pg_m2c:1,
fmc2_pg_m2c:1,
fmc1_pg_c2m:1,
fmc2_pg_c2m:1,
reserved:26;
#endif
} t_fmc_diag;
#include "sdr.h"
/* AFC diagnostic struct sent to FPGA via SPI */
typedef struct __attribute__ ((__packed__)) {
uint32_t cardID[4];
uint32_t slot_id:16,
ipmi_addr:16;
uint32_t data_valid;
t_sensor_diag sensor[NUM_SENSOR];
t_fmc_diag fmc_slot;
} board_diagnostic;
typedef union {
board_diagnostic info;
uint32_t buffer[sizeof(board_diagnostic)/sizeof(uint32_t)];
} t_board_diagnostic;
uint8_t cmpBuffs(uint32_t *buf_a, uint32_t len_a, uint32_t *bufb, uint32_t len_b);
void vTaskFPGA_COMM( void * Parameters );
void init_fpga_spi( void );
void init_diag_struct( board_diagnostic * diag );
#endif
set(BOOT_PATH ${CMAKE_CURRENT_SOURCE_DIR})
set(BOOT_SRCS ${BOOT_SRCS} ${BOOT_PATH}/boot.c )
set(BOOT_SRCS ${BOOT_SRCS} PARENT_SCOPE)
set(PROJ_HDRS ${PROJ_HDRS} ${BOOT_PATH} PARENT_SCOPE)
#include "chip.h"
#include "boot.h"
#include "iap.h"
int main (void)
{
SystemCoreClockUpdate();
Bool upgrade = FALSE;
uint32_t upgr_fw_id, user_fw_id;
Chip_GPIO_Init(LPC_GPIO);
Chip_GPIO_SetPinDIROutput(LPC_GPIO, 1, 9);
user_fw_id = *(uint32_t*)USER_FLASH_ID_ADDR;
upgr_fw_id = *(uint32_t*)UPGRADE_FLASH_ID_ADDR;
//if(user_fw_id == 0xFFFFFFFF || ((upgr_fw_id != 0xFFFFFFFF) && (user_fw_id < upgr_fw_id))) {
if(upgr_fw_id != 0xFFFFFFFF) {
upgrade = TRUE;
Chip_GPIO_SetPinState(LPC_GPIO, 1, 9, 0 );
}
if (upgrade) {
update_firmware();
}
execute_user_code();
while (1);
}
void program_page( uint32_t address, uint32_t * data, uint32_t size )
{
uint32_t sector_start = (address & 0xFF000) >> 12;
uint32_t sector_end = ((address+size) & 0xFF000) >> 12;
if (size % 256) {
/* Data should be a 256 byte boundary */
return;
}
if (Chip_IAP_PreSectorForReadWrite( sector_start, sector_end ) != IAP_CMD_SUCCESS) {
return;
}
Chip_IAP_CopyRamToFlash( address, data, size );
}
void erase_sector( uint32_t sector_start, uint32_t sector_end )
{
if (Chip_IAP_PreSectorForReadWrite( sector_start, sector_end ) != IAP_CMD_SUCCESS) {
return;
}
Chip_IAP_EraseSector( sector_start, sector_end );
}
void execute_user_code( void )
{
USER_ENTRY_PFN user_entry;
user_entry = (USER_ENTRY_PFN)*((uint32_t*)(USER_FLASH_START_ADDR +4));
if (user_entry) {
(user_entry)();
}
}
void update_firmware( void )
{
uint32_t dst = USER_FLASH_START_ADDR;
uint32_t *src = (uint32_t *)UPGRADE_FLASH_START_ADDR;
uint32_t page[64];
for(uint8_t j=0; j<(sizeof(page)/sizeof(uint32_t)); j++) {
page[j] = 0xFFFFFFFF;
}
uint32_t fw_size = USER_FLASH_END_ADDR - USER_FLASH_START_ADDR;
uint32_t offset;
erase_sector( USER_FLASH_START_SECTOR , USER_FLASH_END_SECTOR );
for ( offset = 0; offset < fw_size; dst += sizeof(page)) {
/* Populate a page from source address */
for (uint8_t i = 0; i<sizeof(page)/4; i++, src++, offset+=4 ) {
page[i] = *src;
}
/* Program it into dst */
program_page( dst, page, sizeof(page) );
/* Reset the data in local storage */
for(uint8_t j=0; j<(sizeof(page)/sizeof(uint32_t)); j++) {
page[j] = 0xFFFFFFFF;
}
}
//erase_sector( UPGRADE_FLASH_START_SECTOR , UPGRADE_FLASH_END_SECTOR );
}
#define USER_FLASH_START_ADDR (0x2000)
#define USER_FLASH_START_SECTOR (0x2)
#define USER_FLASH_END_ADDR (0x10000)
#define USER_FLASH_END_SECTOR (0xF)
/* Last 4 bytes are reserved for Firmware Version ID */
#define USER_FLASH_ID_ADDR (0xFFFC)
#define UPGRADE_FLASH_START_ADDR (0x10000)
#define UPGRADE_FLASH_START_SECTOR (0x10)
#define UPGRADE_FLASH_END_ADDR (0x1E000)
#define UPGRADE_FLASH_END_SECTOR (0x11)
/* Last 4 bytes are reserved for Firmware Version ID */
#define UPGRADE_FLASH_ID_ADDR (0x1DFFC)
typedef void (*USER_ENTRY_PFN)();
void erase_sector( uint32_t sector_start, uint32_t sector_end );
void execute_user_code( void );
void update_firmware( void );
MEMORY
{
/* Define each memory region */
/* First 8kB are reserved for bootloader */
/* Last 2 sectors (32kB each) are reserved for firmware upgrade */
MFlash128 (rx) : ORIGIN = 0x2000, LENGTH = 0xE000 /* 56K bytes */
RamLoc16 (rwx) : ORIGIN = 0x10000000, LENGTH = 0x4000 /* 16K bytes */
RamAHB16 (rwx) : ORIGIN = 0x2007c000, LENGTH = 0x4000 /* 16K bytes */
}
/* Define a symbol for the top of each memory region */
__top_MFlash128 = 0x2000 + 0xE000;
__top_RamLoc16 = 0x10000000 + 0x4000;
__top_RamAHB16 = 0x2007c000 + 0x4000;
ENTRY(ResetISR)
SECTIONS
{
/* MAIN TEXT SECTION */
.text : ALIGN(4)
{
FILL(0xff)
__vectors_start__ = ABSOLUTE(.) ;
KEEP(*(.isr_vector))
/* Global Section Table */
. = ALIGN(4) ;
__section_table_start = .;
__data_section_table = .;
LONG(LOADADDR(.data));
LONG( ADDR(.data));
LONG( SIZEOF(.data));
LONG(LOADADDR(.data_RAM2));
LONG( ADDR(.data_RAM2));
LONG( SIZEOF(.data_RAM2));
__data_section_table_end = .;
__bss_section_table = .;
LONG( ADDR(.bss));
LONG( SIZEOF(.bss));
LONG( ADDR(.bss_RAM2));
LONG( SIZEOF(.bss_RAM2));
__bss_section_table_end = .;
__section_table_end = . ;
/* End of Global Section Table */
*(.after_vectors*)
} >MFlash128
.text : ALIGN(4)
{
*(.text*)
*(.rodata .rodata.* .constdata .constdata.*)
/* . = ALIGN(4); */
} > MFlash128
.ipmi_handlers : ALIGN(32)
{
_ipmi_handlers = .;
KEEP(*(.ipmi_handlers))
_eipmi_handlers = .;
} > MFlash128
/*
* for exception handling/unwind - some Newlib functions (in common
* with C++ and STDC++) use this.
*/
.ARM.extab : ALIGN(4)
{
*(.ARM.extab* .gnu.linkonce.armextab.*)
} > MFlash128
__exidx_start = .;
.ARM.exidx : ALIGN(4)
{
*(.ARM.exidx* .gnu.linkonce.armexidx.*)
} > MFlash128
__exidx_end = .;
_etext = .;
/* DATA section for RamAHB16 */
.data_RAM2 : ALIGN(4)
{
FILL(0xff)
PROVIDE(__start_data_RAM2 = .) ;
*(.ramfunc.$RAM2)
*(.ramfunc.$RamAHB16)
*(.data.$RAM2*)
*(.data.$RamAHB16*)
. = ALIGN(4) ;
PROVIDE(__end_data_RAM2 = .) ;
} > RamAHB16 AT>MFlash128
/* MAIN DATA SECTION */
.uninit_RESERVED : ALIGN(4)
{
KEEP(*(.bss.$RESERVED*))
. = ALIGN(4) ;
_end_uninit_RESERVED = .;
} > RamLoc16
/* Main DATA section (RamLoc16) */
.data : ALIGN(4)
{
FILL(0xff)
_data = . ;
*(vtable)
*(.ramfunc*)
*(.data*)
. = ALIGN(4) ;
_edata = . ;
} > RamLoc16 AT>MFlash128
/* BSS section for RamAHB16 */
.bss_RAM2 : ALIGN(4)
{
PROVIDE(__start_bss_RAM2 = .) ;
*(.bss.$RAM2*)
*(.bss.$RamAHB16*)
. = ALIGN(4) ;
PROVIDE(__end_bss_RAM2 = .) ;
} > RamAHB16
/* MAIN BSS SECTION */
.bss : ALIGN(4)
{
_bss = .;
*(.bss*)
*(COMMON)
. = ALIGN(4) ;
_ebss = .;
PROVIDE(end = .);
} > RamLoc16
/* NOINIT section for RamAHB16 */
.noinit_RAM2 (NOLOAD) : ALIGN(4)
{
*(.noinit_RAM2*)
*(.noinit_RamAHB16*)
. = ALIGN(4) ;
} > RamAHB16
/* DEFAULT NOINIT SECTION */
.noinit (NOLOAD): ALIGN(4)
{
_noinit = .;
*(.noinit*)
. = ALIGN(4) ;
_end_noinit = .;
} > RamLoc16
PROVIDE(_pvHeapStart = DEFINED(__user_heap_base) ? __user_heap_base : .);
PROVIDE(_vStackTop = DEFINED(__user_stack_top) ? __user_stack_top : __top_RamLoc16 - 0);
}
/*
* GENERATED FILE - DO NOT EDIT
* (c) Code Red Technologies Ltd, 2008-13
* (c) NXP Semiconductors 2013-2015
* Generated linker script file for LPC1764
* Created from generic_c.ld (7.8.0 ())
* By LPCXpresso v7.8.0 [Build 426] [2015-05-28] on Thu Jul 30 09:03:05 BRT 2015
*/
/* Memory spaces definitions */
INCLUDE "linker/lpc1764_mem.ld"
MEMORY
{
/* Define each memory region */
/* First 8kB are reserved for bootloader */
MFlash128 (rx) : ORIGIN = 0x0000, LENGTH = 0x2000 /* 8K bytes */
RamLoc16 (rwx) : ORIGIN = 0x10000000, LENGTH = 0x4000 /* 16K bytes */
RamAHB16 (rwx) : ORIGIN = 0x2007c000, LENGTH = 0x4000 /* 16K bytes */
}
/* Define a symbol for the top of each memory region */
__top_MFlash128 = 0x0000 + 0x2000;
__top_RamLoc16 = 0x10000000 + 0x4000;
__top_RamAHB16 = 0x2007c000 + 0x4000;
ENTRY(ResetISR)
SECTIONS
{
/* MAIN TEXT SECTION */
/* MAIN TEXT SECTION */
.text : ALIGN(4)
{
FILL(0xff)
__vectors_start__ = ABSOLUTE(.) ;
KEEP(*(.isr_vector))
/* Global Section Table */
. = ALIGN(4) ;
__section_table_start = .;
......@@ -41,12 +42,11 @@ SECTIONS
__bss_section_table_end = .;
__section_table_end = . ;
/* End of Global Section Table */
*(.after_vectors*)
} >MFlash128
.text : ALIGN(4)
{
*(.text*)
......@@ -61,13 +61,13 @@ SECTIONS
*/
.ARM.extab : ALIGN(4)
{
*(.ARM.extab* .gnu.linkonce.armextab.*)
*(.ARM.extab* .gnu.linkonce.armextab.*)
} > MFlash128
__exidx_start = .;
.ARM.exidx : ALIGN(4)
{
*(.ARM.exidx* .gnu.linkonce.armexidx.*)
*(.ARM.exidx* .gnu.linkonce.armexidx.*)
} > MFlash128
__exidx_end = .;
......@@ -76,18 +76,17 @@ SECTIONS
/* DATA section for RamAHB16 */
.data_RAM2 : ALIGN(4)
{
FILL(0xff)
PROVIDE(__start_data_RAM2 = .) ;
*(.ramfunc.$RAM2)
*(.ramfunc.$RamAHB16)
*(.data.$RAM2*)
*(.data.$RamAHB16*)
. = ALIGN(4) ;
PROVIDE(__end_data_RAM2 = .) ;
FILL(0xff)
PROVIDE(__start_data_RAM2 = .) ;
*(.ramfunc.$RAM2)
*(.ramfunc.$RamAHB16)
*(.data.$RAM2*)
*(.data.$RamAHB16*)
. = ALIGN(4) ;
PROVIDE(__end_data_RAM2 = .) ;
} > RamAHB16 AT>MFlash128
/* MAIN DATA SECTION */
.uninit_RESERVED : ALIGN(4)
{
......@@ -96,27 +95,26 @@ SECTIONS
_end_uninit_RESERVED = .;
} > RamLoc16
/* Main DATA section (RamLoc16) */
.data : ALIGN(4)
{
FILL(0xff)
_data = . ;
*(vtable)
*(.ramfunc*)
*(.data*)
. = ALIGN(4) ;
_edata = . ;
} > RamLoc16 AT>MFlash128
/* Main DATA section (RamLoc16) */
.data : ALIGN(4)
{
FILL(0xff)
_data = . ;
*(vtable)
*(.ramfunc*)
*(.data*)
. = ALIGN(4) ;
_edata = . ;
} > RamLoc16 AT>MFlash128
/* BSS section for RamAHB16 */
.bss_RAM2 : ALIGN(4)
{
PROVIDE(__start_bss_RAM2 = .) ;
*(.bss.$RAM2*)
*(.bss.$RamAHB16*)
. = ALIGN(4) ;
PROVIDE(__end_bss_RAM2 = .) ;
PROVIDE(__start_bss_RAM2 = .) ;
*(.bss.$RAM2*)
*(.bss.$RamAHB16*)
. = ALIGN(4) ;
PROVIDE(__end_bss_RAM2 = .) ;
} > RamAHB16
/* MAIN BSS SECTION */
......@@ -129,24 +127,24 @@ SECTIONS
_ebss = .;
PROVIDE(end = .);
} > RamLoc16
/* NOINIT section for RamAHB16 */
.noinit_RAM2 (NOLOAD) : ALIGN(4)
{
*(.noinit_RAM2*)
*(.noinit_RamAHB16*)
. = ALIGN(4) ;
} > RamAHB16
*(.noinit_RAM2*)
*(.noinit_RamAHB16*)
. = ALIGN(4) ;
} > RamAHB16
/* DEFAULT NOINIT SECTION */
.noinit (NOLOAD): ALIGN(4)
{
_noinit = .;
*(.noinit*)
*(.noinit*)
. = ALIGN(4) ;
_end_noinit = .;
} > RamLoc16
PROVIDE(_pvHeapStart = DEFINED(__user_heap_base) ? __user_heap_base : .);
PROVIDE(_vStackTop = DEFINED(__user_stack_top) ? __user_stack_top : __top_RamLoc16 - 0);
}
/*
* GENERATED FILE - DO NOT EDIT
* (c) Code Red Technologies Ltd, 2008-2015
* (c) NXP Semiconductors 2013-2015
* Linker script memory definitions
* Created from LinkMemoryTemplate
* By LPCXpresso v7.8.0 [Build 426] [2015-05-28] on Thu Jul 30 09:03:05 BRT 2015)
*/
MEMORY
{
/* Define each memory region */
MFlash128 (rx) : ORIGIN = 0x0, LENGTH = 0x20000 /* 128K bytes */
RamLoc16 (rwx) : ORIGIN = 0x10000000, LENGTH = 0x4000 /* 16K bytes */
RamAHB16 (rwx) : ORIGIN = 0x2007c000, LENGTH = 0x4000 /* 16K bytes */
}
/* Define a symbol for the top of each memory region */
__top_MFlash128 = 0x0 + 0x20000;
__top_RamLoc16 = 0x10000000 + 0x4000;
__top_RamAHB16 = 0x2007c000 + 0x4000;
/*
* AFC_IPM.c
* openMMC -- Open Source modular IPM Controller firmware
*
* AFCIPMI --
*
* Copyright (C) 2015 Henrique Silva <henrique.silva@lnls.br>
* Copyright (C) 2015 Henrique Silva <henrique.silva@lnls.br>
* Copyright (C) 2015 Piotr Miedzik <P.Miedzik@gsi.de>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
......@@ -17,6 +16,8 @@
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
* @license GPL-3.0+ <http://spdx.org/licenses/GPL-3.0+>
*/
/* Kernel includes. */
......@@ -28,9 +29,7 @@
/* Project includes */
#include "chip.h"
#include "pin_mapping.h"
#include "i2c.h"
#include "led.h"
#include "ipmb.h"
#include "ipmi.h"
#include "sdr.h"
#include "payload.h"
......@@ -38,51 +37,62 @@
#include "fru.h"
#include "jtag.h"
#include "fpga_spi.h"
#include "watchdog.h"
//#define HEAP_TEST
//#define STOP_TEST
/* LED pins initialization */
static void prvHardwareInit( void );
TickType_t getTickDifference(TickType_t current_time, TickType_t start_time);
void heap_test ( void* param);
TaskHandle_t heap_handle;
/*-----------------------------------------------------------*/
uint8_t ipmb_addr = 0xFF;
int main(void)
{
/* Update clock register value - LPC specific */
SystemCoreClockUpdate();
/* Configure LED pins */
prvHardwareInit();
#if (configGENERATE_RUN_TIME_STATS == 1)
vConfigureTimerForRunTimeStats();
#endif
//#define STOP_TEST
#ifdef STOP_TEST
int test = 0;
while (test == 0)
{}
#endif
#ifdef MODULE_WATCHDOG
watchdog_init();
#endif
LED_init();
#ifdef MODULE_FRU
fru_init();
portENABLE_INTERRUPTS();
#endif
afc_board_i2c_init();
afc_board_discover();
portENABLE_INTERRUPTS();
board_i2c_init();
board_discover();
portDISABLE_INTERRUPTS();
ipmb_addr = get_ipmb_addr( );
sdr_init(ipmb_addr);
ipmb_addr = get_ipmb_addr();
#ifdef MODULE_SDR
sdr_init();
#endif
#ifdef MODULE_SENSORS
sensor_init();
#endif
#ifdef MODULE_PAYLOAD
payload_init();
do_quiesced_init();
#endif
#ifdef MODULE_JTAG_SWITCH
init_scansta();
#endif
#ifdef MODULE_FPGA_SPI
init_fpga_spi();
#endif
/* Init IPMI interface */
/* NOTE: ipmb_init() is called inside this function */
ipmi_init();
......@@ -99,19 +109,13 @@ int main(void)
}
/*-----------------------------------------------------------*/
TickType_t getTickDifference(TickType_t current_time, TickType_t start_time)
{
TickType_t result = 0;
if (current_time < start_time) {
result = start_time - current_time;
result = portMAX_DELAY - result;
} else {
result = current_time - start_time;
}
return result;
/* Put the MCU in sleep state when no task is running */
void vApplicationIdleHook (void) {
pm_sleep();
}
/*-----------------------------------------------------------*/
/* System Debug funtions */
#ifdef HEAP_TEST
static char stats[500];
void heap_test ( void* param)
......@@ -121,58 +125,13 @@ void heap_test ( void* param)
for (;;) {
ulTaskNotifyTake(pdTRUE, portMAX_DELAY);
water_mark = uxTaskGetStackHighWaterMark(NULL);
used_heap = configTOTAL_HEAP_SIZE - xPortGetFreeHeapSize();
vTaskGetRunTimeStats(stats);
water_mark = uxTaskGetStackHighWaterMark(NULL);
used_heap = configTOTAL_HEAP_SIZE - xPortGetFreeHeapSize();
vTaskGetRunTimeStats(stats);
}
}
#endif
void prvToggleLED( LED_id led )
{
unsigned long ulLEDState;
unsigned long ulLEDport;
unsigned long ulLEDpin;
switch( led ){
case LED_BLUE:
ulLEDport = LEDBLUE_PORT;
ulLEDpin = LEDBLUE_PIN;
break;
case LED_GREEN:
ulLEDport = LEDGREEN_PORT;
ulLEDpin = LEDGREEN_PIN;
break;
case LED_RED:
ulLEDport = LEDRED_PORT;
ulLEDpin = LEDRED_PIN;
break;
default:
break;
}
/* Obtain the current P0 state. */
ulLEDState = Chip_GPIO_GetPinState(LPC_GPIO, ulLEDport, ulLEDpin);
/* Turn the LED off if it was on, and on if it was off. */
Chip_GPIO_SetPinState(LPC_GPIO, ulLEDport, ulLEDpin, !ulLEDState);
}
/*-----------------------------------------------------------*/
static void prvHardwareInit ( void )
{
/* Init LED Pin */
Chip_GPIO_Init(LPC_GPIO);
/* Set pin as output */
Chip_GPIO_SetPinDIR(LPC_GPIO, LEDBLUE_PORT, LEDBLUE_PIN, true);
Chip_GPIO_SetPinDIR(LPC_GPIO, LEDGREEN_PORT, LEDGREEN_PIN, true);
Chip_GPIO_SetPinDIR(LPC_GPIO, LEDRED_PORT, LEDRED_PIN, true);
/* Init GAddr test pin as output */
Chip_GPIO_SetPinDIR(LPC_GPIO, GA_TEST_PORT, GA_TEST_PIN, true);
}
/*-----------------------------------------------------------*/
/* FreeRTOS Debug Functions */
......@@ -183,14 +142,12 @@ void vApplicationStackOverflowHook ( TaskHandle_t pxTask, signed char * pcTaskNa
taskDISABLE_INTERRUPTS();
/* Place a breakpoint here, so we know when there's a stack overflow */
for ( ; ; ) {
uint32_t watermark = uxTaskGetStackHighWaterMark(pxTask);
uxTaskGetStackHighWaterMark(pxTask);
}
}
#endif
#if (configGENERATE_RUN_TIME_STATS == 1)
void vConfigureTimerForRunTimeStats( void )
{
const unsigned long CTCR_CTM_TIMER = 0x00, TCR_COUNT_ENABLE = 0x01;
......@@ -213,7 +170,6 @@ void vConfigureTimerForRunTimeStats( void )
void vAssertCalled( char* file, uint32_t line) {
taskDISABLE_INTERRUPTS();
prvToggleLED(LED_RED);
for( ;; );
}
......@@ -222,8 +178,3 @@ void vApplicationMallocFailedHook( void ) {
}
#endif
void vApplicationIdleHook (void) {
}
set(MODULE_PATH ${CMAKE_CURRENT_SOURCE_DIR})
set(PROJ_HDRS ${PROJ_HDRS} ${MODULE_PATH} )
set(PROJ_SRCS ${PROJ_SRCS} ${MODULE_PATH}/utils.c)
set(PROJ_SRCS ${PROJ_SRCS} ${MODULE_PATH}/board_version.c)
set(PROJ_SRCS ${PROJ_SRCS} ${MODULE_PATH}/led.c)
set(PROJ_SRCS ${PROJ_SRCS} ${MODULE_PATH}/ipmb.c ${MODULE_PATH}/ipmi.c)
message(STATUS "Selected modules to compile: ${TARGET_MODULES}")
if (";${TARGET_MODULES};" MATCHES ";FRU;")
set(PROJ_SRCS ${PROJ_SRCS} ${MODULE_PATH}/fru.c )
set(MODULES_FLAGS "${MODULES_FLAGS} -DMODULE_FRU")
endif()
if (";${TARGET_MODULES};" MATCHES ";PAYLOAD;")
set(PROJ_SRCS ${PROJ_SRCS} ${MODULE_PATH}/payload.c)
set(MODULES_FLAGS "${MODULES_FLAGS} -DMODULE_PAYLOAD")
endif()
if (";${TARGET_MODULES};" MATCHES ";SDR;")
set(PROJ_SRCS ${PROJ_SRCS} ${MODULE_PATH}/sdr.c )
set(MODULES_FLAGS "${MODULES_FLAGS} -DMODULE_SDR")
endif()
if (";${TARGET_MODULES};" MATCHES ";WATCHDOG;")
set(PROJ_SRCS ${PROJ_SRCS} ${MODULE_PATH}/watchdog.c )
set(MODULES_FLAGS "${MODULES_FLAGS} -DMODULE_WATCHDOG")
endif()
if (";${TARGET_MODULES};" MATCHES ";HPM;")
set(PROJ_SRCS ${PROJ_SRCS} ${MODULE_PATH}/hpm.c )
set(MODULES_FLAGS "${MODULES_FLAGS} -DMODULE_HPM")
if (";${TARGET_MODULES};" MATCHES ";PAYLOAD;")
set(PROJ_SRCS ${PROJ_SRCS} ${MODULE_PATH}/flash_spi.c )
set(MODULES_FLAGS "${MODULES_FLAGS} -DMODULE_FLASH_SPI")
endif()
endif()
if (";${TARGET_MODULES};" MATCHES "SENSOR")
set(MODULES_FLAGS "${MODULES_FLAGS} -DMODULE_SENSORS")
add_subdirectory(sensors)
endif()
#Modules dependencies check
if(${TARGET_BOARD_NAME} MATCHES "^(AFC)")
if (("${MODULES_FLAGS}" MATCHES "-DMODULE_PAYLOAD") AND NOT ("${MODULES_FLAGS}" MATCHES "-DMODULE_DAC_AD84XX"))
message(WARNING "${Red}[AFC] Payload module is being used but the DAC_AD84XX was not included in this build. The VADJ reference will not be configured! ${ColourReset}")
endif()
endif()
if(NOT ("${MODULES_FLAGS}" MATCHES "-DMODULE_HOTSWAP"))
message(FATAL_ERROR "${Red}[ERROR] Mandatory Hotswap sensor module not included!${ColourReset}")
endif()
set(PROJ_SRCS ${PROJ_SRCS} PARENT_SCOPE)
set(PROJ_HDRS ${PROJ_HDRS} PARENT_SCOPE)
set(MODULES_FLAGS ${MODULES_FLAGS} PARENT_SCOPE)
/*
* board_version.h
* openMMC -- Open Source modular IPM Controller firmware
*
* AFCIPMI --
*
* Copyright (C) 2015 Piotr Miedzik <P.Miedzik@gsi.de>
* Copyright (C) 2015 Piotr Miedzik <P.Miedzik@gsi.de>
* Copyright (C) 2015-2016 Henrique Silva <henrique.silva@lnls.br>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
......@@ -17,6 +16,8 @@
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
* @license GPL-3.0+ <http://spdx.org/licenses/GPL-3.0+>
*/
#ifndef AFC_BOARD_VERSION_H_
......@@ -27,20 +28,19 @@
#include "semphr.h"
#include "port.h"
#define CARRIER_TYPE_UNKNOWN 0xFF
#define CARRIER_TYPE_AFC 0x01
#define CARRIER_TYPE_AFCK 0x02
#define CARRIER_TYPE_UNKNOWN 0xFF
#define CARRIER_TYPE_AFC 0x01
#define CARRIER_TYPE_AFCK 0x02
#define BOARD_VERSION_AFC_V1_0 0x00
#define BOARD_VERSION_AFC_V2_0 0x01
#define BOARD_VERSION_AFC_V3_0 0x02
#define BOARD_VERSION_AFC_V3_1 0x03
#define BOARD_VERSION_UNKNOWN 0xFF
#define BOARD_VERSION_AFC_V2_0 0x01
#define BOARD_VERSION_AFC_V3_0 0x02
#define BOARD_VERSION_AFC_V3_1 0x03
#define BOARD_VERSION_UNKNOWN 0xFF
#define I2CMODE_POOLING 1
#define I2CMODE_INTERRUPT 0
#define SPEED_100KHZ 100000
#define I2CMODE_POOLING 1
#define I2CMODE_INTERRUPT 0
#define SPEED_100KHZ 100000
// BUS_ID
// 0 - FMC1
......@@ -48,52 +48,57 @@
// 3 - CPU_ID
//
///////////////////////
#define I2C_BUS_UNKNOWN_ID 0
#define I2C_BUS_FMC1_ID 1
#define I2C_BUS_FMC2_ID 2
#define I2C_BUS_CPU_ID 3
#define I2C_BUS_RTM_ID 4
#define I2C_BUS_CLOCK_ID 5
#define I2C_BUS_FPGA_ID 6
#define CHIP_ID_MUX 0
#define CHIP_ID_LM75AIM_0 1
#define CHIP_ID_LM75AIM_1 2
#define CHIP_ID_LM75AIM_2 3
#define CHIP_ID_LM75AIM_3 4
#define CHIP_ID_MAX6642 5
#define CHIP_ID_RTC 6
#define CHIP_ID_RTC_EEPROM 7
#define CHIP_ID_EEPROM 8
#define CHIP_ID_EEPROM_ID 9
#define CHIP_ID_INA_0 10
#define CHIP_ID_INA_1 11
#define CHIP_ID_INA_2 12
#define CHIP_ID_INA_3 13
#define CHIP_ID_INA_4 14
#define CHIP_ID_INA_5 15
#define CHIP_ID_ADN 16
#define CHIP_ID_SI57x 17
#define CHIP_ID_EEPROM_FMC1 18
#define CHIP_ID_EEPROM_FMC2 19
enum {
I2C_BUS_UNKNOWN_ID = 0x00,
I2C_BUS_FMC1_ID,
I2C_BUS_FMC2_ID,
I2C_BUS_CPU_ID,
I2C_BUS_RTM_ID,
I2C_BUS_CLOCK_ID,
I2C_BUS_FPGA_ID
};
enum {
CHIP_ID_MUX = 0,
CHIP_ID_LM75AIM_0,
CHIP_ID_LM75AIM_1,
CHIP_ID_LM75AIM_2,
CHIP_ID_LM75AIM_3,
CHIP_ID_MAX6642,
CHIP_ID_RTC,
CHIP_ID_RTC_EEPROM,
CHIP_ID_EEPROM,
CHIP_ID_EEPROM_ID,
CHIP_ID_INA_0,
CHIP_ID_INA_1,
CHIP_ID_INA_2,
CHIP_ID_INA_3,
CHIP_ID_INA_4,
CHIP_ID_INA_5,
CHIP_ID_ADN,
CHIP_ID_SI57x,
CHIP_ID_FMC1_EEPROM,
CHIP_ID_FMC1_LM75_1,
CHIP_ID_FMC1_LM75_0,
CHIP_ID_FMC2_EEPROM,
CHIP_ID_FMC2_LM75_1,
CHIP_ID_FMC2_LM75_0
};
typedef struct {
uint8_t carrier_type;
uint8_t board_version;
uint8_t manufacturer[3];
uint8_t manufacturing_day[2];
uint8_t crc;
uint8_t carrier_type;
uint8_t board_version;
uint8_t manufacturer[3];
uint8_t manufacturing_day[2];
uint8_t crc;
} manufacturing_info_raw;
typedef struct {
uint8_t carrier_version;
uint8_t board_version;
uint32_t manufacturer;
uint16_t manufacturing_day;
uint8_t carrier_version;
uint8_t board_version;
uint32_t manufacturer;
uint16_t manufacturing_day;
} manufacturing_info;
typedef struct {
......@@ -102,14 +107,14 @@ typedef struct {
I2C_ID_T i2c_bus;
} I2C_Mutex;
static manufacturing_info_raw afc_board_info;
extern manufacturing_info_raw board_info;
void afc_board_i2c_init( void );
void afc_board_discover( void );
void afc_get_manufacturing_info( manufacturing_info_raw *p_board_info );
void afc_get_board_type( uint8_t *carrier_type, uint8_t *board_version);
Bool afc_i2c_take_by_busid( uint8_t bus_id, I2C_ID_T * i2c_interface, TickType_t max_wait_time );
Bool afc_i2c_take_by_chipid( uint8_t chip_id, uint8_t * i2c_address, I2C_ID_T * i2c_interface, TickType_t max_wait_time );
void afc_i2c_give( I2C_ID_T i2c_interface );
void board_i2c_init( void );
void board_discover( void );
void get_manufacturing_info( manufacturing_info_raw *p_board_info );
void get_board_type( uint8_t *carrier_type, uint8_t *board_version);
Bool i2c_take_by_busid( uint8_t bus_id, I2C_ID_T * i2c_interface, TickType_t max_wait_time );
Bool i2c_take_by_chipid( uint8_t chip_id, uint8_t * i2c_address, I2C_ID_T * i2c_interface, TickType_t max_wait_time );
void i2c_give( I2C_ID_T i2c_interface );
#endif /* AFC_BOARD_VERSION_H_ */
/*
* openMMC -- Open Source modular IPM Controller firmware
*
* Copyright (C) 2015-2016 Henrique Silva <henrique.silva@lnls.br>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program 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 General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
* @license GPL-3.0+ <http://spdx.org/licenses/GPL-3.0+>
*/
/* FreeRTOS Includes */
#include "FreeRTOS.h"
/* Project Includes */
#include "port.h"
#include "flash_spi.h"
#include "pin_mapping.h"
#include <string.h>
void flash_write_enable( void )
{
do {
uint8_t tx_buff[1] = {FLASH_WRITE_ENABLE};
ssp_write( FLASH_SPI, tx_buff, sizeof(tx_buff) );
} while (!(flash_read_status_reg() & 0x2));
}
void flash_write_disable( void )
{
do {
uint8_t tx_buff[1] = {FLASH_WRITE_DISABLE};
ssp_write( FLASH_SPI, tx_buff, sizeof(tx_buff) );
} while (flash_read_status_reg() & 0x2);
}
void flash_read_id( uint8_t * id_buffer, uint8_t buff_size )
{
if ((buff_size < 3)|(id_buffer == NULL)) {
return;
}
uint8_t tx_buff[1] = {FLASH_READ_ID};
/* Size of rx buffer must be the sum of the length of the data expected to receive and the length of the sent data */
uint8_t rx_buff[4] = {0};
ssp_write_read( FLASH_SPI, &tx_buff[0], 1, &rx_buff[0], 3, portMAX_DELAY );
memcpy(id_buffer, &rx_buff[1], 3);
}
uint8_t flash_read_status_reg( void )
{
uint8_t tx_buff[1] = {FLASH_READ_STATUS_REG};
/* Size of rx buffer must be the sum of the length of the data expected to receive and the length of the sent data */
uint8_t rx_buff[2] = {0};
ssp_write_read( FLASH_SPI, &tx_buff[0], 1, &rx_buff[0], 1, portMAX_DELAY );
return rx_buff[1];
}
void flash_write_status_reg( uint8_t data )
{
uint8_t tx_buff[2] = {FLASH_WRITE_STATUS_REG, data};
flash_write_enable();
ssp_write( FLASH_SPI, &tx_buff[0], sizeof(tx_buff) );
}
uint8_t flash_read_lock_reg( uint32_t address )
{
uint8_t tx_buff[4];
tx_buff[0] = FLASH_READ_LOCK_REG;
tx_buff[1] = (address >> 16) & 0xFF;
tx_buff[2] = (address >> 8) & 0xFF;
tx_buff[3] = address & 0xFF;
/* Size of rx buffer must be the sum of the length of the data expected to receive and the length of the sent data */
uint8_t rx_buff[5] = {0};
ssp_write_read( FLASH_SPI, &tx_buff[0], sizeof(tx_buff), &rx_buff[0], sizeof(rx_buff), portMAX_DELAY );
return rx_buff[4];
}
void flash_write_lock_reg( uint32_t address, uint8_t data )
{
uint8_t tx_buff[5];
tx_buff[0] = FLASH_WRITE_LOCK_REG;
tx_buff[1] = (address >> 16) & 0xFF;
tx_buff[2] = (address >> 8) & 0xFF;
tx_buff[3] = address & 0xFF;
tx_buff[4] = data;
flash_write_enable();
ssp_write( FLASH_SPI, &tx_buff[0], sizeof(tx_buff) );
}
uint8_t flash_read_data( uint32_t address )
{
uint8_t tx_buff[4];
tx_buff[0] = FLASH_READ_DATA;
tx_buff[1] = (address >> 16) & 0xFF;
tx_buff[2] = (address >> 8) & 0xFF;
tx_buff[3] = address & 0xFF;
/* Size of rx buffer must be the sum of the length of the data expected to receive and the length of the sent data */
uint8_t rx_buff[5] = {0};
ssp_write_read( FLASH_SPI, &tx_buff[0], 4, &rx_buff[0], 1, portMAX_DELAY );
return rx_buff[4];
}
void flash_fast_read_data( uint32_t start_addr, uint8_t * dst, uint32_t size )
{
/* Size of rx buffer must be the sum of the length of the data expected to receive and the length of the sent data */
/* Use an additional Dumb byte */
uint8_t *rx_buff = pvPortMalloc(size+5);
uint8_t tx_buff[5];
tx_buff[0] = FLASH_FAST_READ_DATA;
tx_buff[1] = (start_addr >> 16) & 0xFF;
tx_buff[2] = (start_addr >> 8) & 0xFF;
tx_buff[3] = start_addr & 0xFF;
tx_buff[4] = 0xFF; /* Dumb Byte */
ssp_write_read( FLASH_SPI, &tx_buff[0], 5, &rx_buff[0], size, portMAX_DELAY );
memcpy(dst, &rx_buff[5], size);
vPortFree(rx_buff);
}
void flash_program_page( uint32_t address, uint8_t * data, uint16_t size )
{
/* The sector MUST be erased before trying to program new data into it */
flash_write_enable();
/* Use malloc to reserve 'size' plus 4 bytes (address and cmd) */
uint8_t *tx_buff = pvPortMalloc(size+4);
tx_buff[0] = FLASH_PROGRAM_PAGE;
tx_buff[1] = (address >> 16) & 0xFF;
tx_buff[2] = (address >> 8) & 0xFF;
tx_buff[3] = address & 0xFF;
memcpy(&tx_buff[4], data, size);
ssp_write( FLASH_SPI, &tx_buff[0], size+4 );
vPortFree(tx_buff);
}
void flash_sector_erase( uint32_t address )
{
uint8_t tx_buff[4];
tx_buff[0] = FLASH_SECTOR_ERASE;
tx_buff[1] = (address >> 16) & 0xFF;
tx_buff[2] = (address >> 8) & 0xFF;
tx_buff[3] = address & 0xFF;
flash_write_enable();
ssp_write( FLASH_SPI, tx_buff, sizeof(tx_buff) );
}
void flash_bulk_erase( void )
{
uint8_t tx_buff[1] = {FLASH_BULK_ERASE};
flash_write_enable();
ssp_write( FLASH_SPI, tx_buff, sizeof(tx_buff) );
}
uint8_t is_flash_busy( void )
{
uint8_t status = flash_read_status_reg();
return (status & 0x01);
}
/*
* openMMC -- Open Source modular IPM Controller firmware
*
* Copyright (C) 2015-2016 Henrique Silva <henrique.silva@lnls.br>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program 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 General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
* @license GPL-3.0+ <http://spdx.org/licenses/GPL-3.0+>
*/
#ifndef FLASH_SPI_H_
#define FLASH_SPI_H_
#define FLASH_SPI_BITRATE 1000000
#define FLASH_SPI_FRAME_SIZE 8
/* M25P128 Flash commands */
#define FLASH_WRITE_ENABLE 0x06
#define FLASH_WRITE_DISABLE 0x04
#define FLASH_READ_ID 0x9F
#define FLASH_READ_STATUS_REG 0x05
#define FLASH_WRITE_STATUS_REG 0x01
#define FLASH_READ_LOCK_REG 0xE8
#define FLASH_WRITE_LOCK_REG 0xE5
#define FLASH_READ_DATA 0x03
#define FLASH_FAST_READ_DATA 0x0B
#define FLASH_PROGRAM_PAGE 0x02
#define FLASH_SECTOR_ERASE 0xD8
#define FLASH_BULK_ERASE 0xC7
void flash_write_enable( void );
void flash_write_disable( void );
void flash_read_id( uint8_t * id_buffer, uint8_t buff_size );
uint8_t flash_read_status_reg( void );
void flash_write_status_reg( uint8_t data );
uint8_t flash_read_data( uint32_t address );
void flash_fast_read_data( uint32_t start_addr, uint8_t * dst, uint32_t size );
void flash_program_page( uint32_t address, uint8_t * data, uint16_t size );
void flash_sector_erase( uint32_t address );
void flash_bulk_erase( void );
uint8_t flash_read_lock_reg( uint32_t address );
void flash_write_lock_reg( uint32_t address, uint8_t data );
uint8_t is_flash_busy( void );
#endif
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
/*
* openMMC -- Open Source modular IPM Controller firmware
*
* Copyright (C) 2015-2016 Henrique Silva <henrique.silva@lnls.br>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program 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 General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
* @license GPL-3.0+ <http://spdx.org/licenses/GPL-3.0+>
*/
#ifndef HPM_H_
#define HPM_H_
#define HPM_SUPPORTED_VERSION 0x00
#define FW_REV_MAJOR 1 /* Binary encoded */
#define FW_REV_MINOR 0 /* BCD encoded */
#define FW_REV_AUX_0 0
#define FW_REV_AUX_1 0
#define FW_REV_AUX_2 0
#define FW_REV_AUX_3 0
#define HPM_UPGRADE_TIMEOUT 10 /* in 5 seconds counts */
#define HPM_SELF_TEST_TIMEOUT 5 /* in 5 seconds counts */
#define HPM_ROLLBACK_TIMEOUT 10 /* in 5 seconds counts */
#define HPM_INACCESSIBILITY_TIMEOUT 10 /* in 5 seconds counts */
#define IPMC_UPDATE_SECTOR_START 0x10
#define IPMC_UPDATE_SECTOR_END 0x11
#define IPMC_UPDATE_ADDRESS_OFFSET (IPMC_UPDATE_SECTOR_START << 12)
#define HPM_BLOCK_SIZE 20
/* Components ID */
enum {
HPM_BOOTLOADER_COMPONENT_ID = 0,
HPM_IPMC_COMPONENT_ID,
HPM_PAYLOAD_COMPONENT_ID,
HPM_MAX_COMPONENTS
};
typedef uint8_t (* t_hpm_upload_block)(uint8_t * block, uint16_t size);
typedef uint8_t (* t_hpm_finish_upload)(uint32_t image_size);
typedef uint8_t (* t_hpm_prepare_comp)(void);
typedef uint8_t (* t_hpm_get_upgrade_status)(void);
typedef uint8_t (* t_hpm_activate_firmware)(void);
typedef union {
struct {
uint8_t upgrade_undesirable:1;
uint8_t automatic_rollback_overridden:1;
uint8_t ipmc_degraded_in_update:1;
uint8_t deferred_activation:1;
uint8_t services_affected:1;
uint8_t manual_rollback:1;
uint8_t automatic_rollback:1;
uint8_t self_test:1;
} flags;
uint8_t byte;
} t_ipmc_capabilities;
typedef union __attribute__ ((__packed__)) {
struct {
uint8_t reserved:2,
cold_reset_required:1,
deferred_activation_supported:1,
comparison_supported:1,
preparation_support:1,
rollback_backup_support:2;
} flags;
uint8_t byte;
} t_comp_properties;
typedef struct {
t_comp_properties properties;
char description[12];
t_hpm_prepare_comp hpm_prepare_comp_f;
t_hpm_upload_block hpm_upload_block_f;
t_hpm_finish_upload hpm_finish_upload_f;
t_hpm_get_upgrade_status hpm_get_upgrade_status_f;
t_hpm_activate_firmware hpm_activate_firmware_f;
} t_component;
#endif
/*
* AFCIPMI --
*
* Copyright (C) 2015 Henrique Silva <henrique.silva@lnls.br>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program 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 General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
/*!
* @file i2c.c
* @author Henrique Silva <henrique.silva@lnls.br>, LNLS
* @date August 2015
*
* @brief Implementation of a generic I2C driver using FreeRTOS features
*/
/* FreeRTOS includes */
#include "FreeRTOS.h"
/* Project includes */
#include "i2c.h"
#include "pin_mapping.h"
#include "port.h"
void vI2CInit( I2C_ID_T i2c_id, uint32_t speed, I2C_Mode mode )
{
/* Enable and configure I2C clock */
vI2CConfig( i2c_id, speed );
if ( mode == I2C_Mode_IPMB ) {
/* Configure Slave Address */
ipmb_addr = get_ipmb_addr( );
vI2CSlaveSetup( i2c_id, ipmb_addr );
}
} /* End of vI2C_Init */
/*
*==============================================================
* MMC ADDRESSING
*==============================================================
*/
/*! @brief Table holding all possible address values in IPMB specification
* @see get_ipmb_addr()
*/
unsigned char IPMBL_TABLE[IPMBL_TABLE_SIZE] = {
0x70, 0x8A, 0x72, 0x8E, 0x92, 0x90, 0x74, 0x8C, 0x76,
0x98, 0x9C, 0x9A, 0xA0, 0xA4, 0x88, 0x9E, 0x86, 0x84,
0x78, 0x94, 0x7A, 0x96, 0x82, 0x80, 0x7C, 0x7E, 0xA2 };
/*! The state of each GA signal is represented by G (grounded), U (unconnected),
* or P (pulled up to Management Power).
*
* The MMC drives P1 low and reads the GA lines. The MMC then drives P1 high and
* reads the GA lines. Any line that changes state between the two reads indicate
* an unconnected (U) pin.
*
* The IPMB-L address of a Module can be calculated as (70h + Site Number x 2). <br>
* G = 0, P = 1, U = 2 <br>
* | Pin | Ternary | Decimal | Address |
* |:---:|:-------:|:-------:|:-------:|
* | GGG | 000 | 0 | 0x70 |
* | GGP | 001 | 1 | 0x8A |
* | GGU | 002 | 2 | 0x72 |
* | GPG | 010 | 3 | 0x8E |
* | GPP | 011 | 4 | 0x92 |
* | GPU | 012 | 5 | 0x90 |
* | GUG | 020 | 6 | 0x74 |
* | GUP | 021 | 7 | 0x8C |
* | GUU | 022 | 8 | 0x76 |
* | PGG | 100 | 9 | 0x98 |
* | PGP | 101 | 10 | 0x9C |
* | PGU | 102 | 11 | 0x9A |
* | PPG | 110 | 12 | 0xA0 |
* | PPP | 111 | 13 | 0xA4 |
* | PPU | 112 | 14 | 0x88 |
* | PUG | 120 | 15 | 0x9E |
* | PUP | 121 | 16 | 0x86 |
* | PUU | 122 | 17 | 0x84 |
* | UGG | 200 | 18 | 0x78 |
* | UGP | 201 | 19 | 0x94 |
* | UGU | 202 | 20 | 0x7A |
* | UPG | 210 | 21 | 0x96 |
* | UPP | 211 | 22 | 0x82 |
* | UPU | 212 | 23 | 0x80 |
* | UUG | 220 | 24 | 0x7C |
* | UUP | 221 | 25 | 0x7E |
* | UUU | 222 | 26 | 0xA2 |
*/
#define GPIO_GA_DELAY 10
uint8_t get_ipmb_addr( void )
{
uint8_t ga0, ga1, ga2;
uint8_t index;
/* Set the test pin and read all GA pins */
Chip_GPIO_SetPinState(LPC_GPIO, GA_TEST_PORT, GA_TEST_PIN, 1);
/* when using NAMC-EXT-RTM at least 11 instruction cycles required
* to have correct GA value after GA_TEST_PIN changes */
{
uint8_t i;
for (i = 0; i < GPIO_GA_DELAY; i++){
__asm volatile ("nop");
}
}
ga0 = Chip_GPIO_GetPinState(LPC_GPIO, GA0_PORT, GA0_PIN);
ga1 = Chip_GPIO_GetPinState(LPC_GPIO, GA1_PORT, GA1_PIN);
ga2 = Chip_GPIO_GetPinState(LPC_GPIO, GA2_PORT, GA2_PIN);
/* Clear the test pin and see if any GA pin has changed is value,
* meaning that it is unconnected */
Chip_GPIO_SetPinState(LPC_GPIO, GA_TEST_PORT, GA_TEST_PIN, 0);
/* when using NAMC-EXT-RTM at least 11 instruction cycles required
* to have correct GA value after GA_TEST_PIN changes */
{
uint8_t i;
for (i = 0; i < GPIO_GA_DELAY; i++)
__asm volatile ("nop");
}
if ( ga0 != Chip_GPIO_GetPinState(LPC_GPIO, GA0_PORT, GA0_PIN) ){
ga0 = UNCONNECTED;
}
if ( ga1 != Chip_GPIO_GetPinState(LPC_GPIO, GA1_PORT, GA1_PIN) ){
ga1 = UNCONNECTED;
}
if ( ga2 != Chip_GPIO_GetPinState(LPC_GPIO, GA2_PORT, GA2_PIN) ){
ga2 = UNCONNECTED;
}
/* Transform the 3-based code in a decimal number */
index = (9 * ga2) + (3 * ga1) + (1 * ga0);
if ( index >= IPMBL_TABLE_SIZE ){
return 0;
}
return IPMBL_TABLE[index];
}
#undef GPIO_GA_DELAY
/*
* AFCIPMI
*
* Copyright (C) 2015 Henrique Silva <henrique.silva@lnls.br>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program 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 General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
/*!
* @file i2c.h
* @author Henrique Silva <henrique.silva@lnls.br>, LNLS
* @date August 2015
*
* @brief Definitions used in I2C Driver
*/
#ifndef I2C_H_
#define I2C_H_
#include "FreeRTOS.h"
#include "task.h"
/*! @brief Max message length (in bits) used in I2C */
#define i2cMAX_MSG_LENGTH 32
/*! @brief Size of #IPMBL_TABLE
*/
#define IPMBL_TABLE_SIZE 27
/*! @brief GA pins definition */
typedef enum {
GROUNDED = 0,
POWERED,
UNCONNECTED
}GA_Pin_state;
/*! @brief I2C Modes definition
* @warning Slave Transmit (Slave write) mode is not implemented
*/
typedef enum {
I2C_Mode_Local_Master = 0, /*!< <b>Master Write</b> and <b>Master Read</b> modes only */
I2C_Mode_IPMB /*!< <b>Master Write</b> and <b>Slave Read</b> modes only */
} I2C_Mode;
/*! @brief I2C driver error enumeration */
typedef enum {
i2c_err_SUCCESS = 0,
i2c_err_FAILURE, /*!< General Failure in I2C driver */
i2c_err_MAX_LENGTH, /*!< Message trying to be sent is higher than I2C buffer limit */
i2c_err_SLA_R_SENT_NACK, /*!< SLA+R address transmitted, but no response has been received.
* @see #I2C_STAT_SLA_R_SENT_NACK */
i2c_err_SLA_DATA_RECV_NACK, /*!< DATA byte has been received, NACK has been returned.
* This usually means that the master will only be reading one
* more byte from the slave.
* @see #I2C_STAT_DATA_RECV_NACK */
i2c_err_SLA_W_SENT_NACK, /*!< SLA+R address transmitted, but no response has been received.
* Slave is either busy or unreachable.
* @see #I2C_STAT_SLA_W_SENT_NACK */
i2c_err_DATA_SENT_NACK /*!< DATA byte has been transmitted, but NACK has returned.
* Slave is either busy or unreachable.
* @see #I2C_STAT_DATA_SENT_NACK */
} i2c_err;
/*! @brief I2C transaction parameter structure */
typedef struct xI2C_msg
{
uint8_t i2c_id; /*!< I2C interface number (0, 1 or 2) */
uint8_t addr; /*!< Slave address of I2C device */
uint8_t tx_data[i2cMAX_MSG_LENGTH]; /*!< Buffer cointaning bytes to transmit, limitted to #i2cMAX_MSG_LENGTH */
uint8_t tx_len; /*!< Number of bytes to transmit */
uint8_t rx_data[i2cMAX_MSG_LENGTH]; /*!< Buffer cointaning received bytes, limitted to #i2cMAX_MSG_LENGTH */
uint8_t rx_len; /*!< Number of bytes to receive */
i2c_err error; /*!< Error value from I2C driver
* @see #i2c_err
*/
} xI2C_msg;
extern uint8_t ipmb_addr;
/***********************/
/* Function Prototypes */
/***********************/
/*! @todo Update i2c function comments */
/*! @brief I2C Interface Initialization
*
* Initialize I2C corresponding pins with the following characteristics:
* - Open Drain
* - Function #3 (If I2C0, it's function #1)
* - No pull-up nor pull-down
*
* Configure and init the I2C interruption, with its priority set to one
* level below the maximum FreeRTOS priority, so the interruption service
* can access the API and manage the semaphore.
* @param i2c_id: Interface ID ( I2C0, I2C1, I2C2 )
* @param mode: Operating mode for the specified I2C interface
*/
void vI2CInit( uint8_t i2c_id, uint32_t speed, I2C_Mode mode );
/*! @todo Document this function */
//void vI2CConfig( I2C_ID_T id, uint32_t speed );
/*! @brief Enter Master Write mode and transmit a buffer
*
* Bytes are transmitted in crescent order, incrementing the buffer index.
*
* @note This function blocks until its completion, in other words, it'll only
* return when the whole buffer has been transmitted or an error occurs in I2C Driver.
*
* Example:
* @code
* uint8_t tx_buffer = { 0xAA, 0x55, 0x00, 0x01 };
* uint8_t slave_address = 0x72;
*
* if( xI2CWrite ( I2C1, slave_address, tx_buffer, sizeof(tx_buffer)/sizeof(tx_buffer[0])) == i2c_err_SUCCESS ) {
*
* // Send next message, for example
*
* } else {
*
* // Retry sending this message or handle error
*
* }
* @endcode
* @param i2c_id: Interface ID ( I2C0, I2C1, I2C2 ).
* @param addr: Destination of the message (7 bit address).
* @param tx_data: Pointer to buffer of bytes to be transmitted.
* @param tx_len: Length of tx_data buffer (must be lower than #i2cMAX_MSG_LENGTH, or an error will return)
* @return I2C Driver error
* @see #xI2CRead
* @see #xI2CSlaveTransfer
*/
//i2c_err xI2CMasterWrite( I2C_ID_T id, uint8_t addr, uint8_t * tx_buff, uint8_t tx_len );
/*! @brief Enter Master Read mode and receive a buffer from slave
*
* @note This function blocks until its completion, in other words, it'll only
* return when the whole buffer has been read or an error occurs in I2C Driver.
*
* @warning @p rx_data must be previously allocated to prevent invalid memory access by functions inside this routine.
*
* Example:
* @code
* uint8_t rx_data[i2cMAX_MSG_LENGTH];
* uint8_t slave_address = 0x72;
* uint8_t bytes_to_receive = 5;
*
* if( xI2CRead ( I2C1, slave_address, rx_data, bytes_to_receive)) == i2c_err_SUCCESS ) {
*
* //Read message and blink a LED
* if ( rx_data[1] == 0x0A ) {
* blink_led(green);
* } else {
* blink_led(red);
* }
*
* } else {
*
* // Retry sending this command or handle error
*
* }
* @endcode
* @param i2c_id: Interface ID ( I2C0, I2C1, I2C2 ).
* @param addr: Destination of the message (7 bit address).
* @param rx_data: Pointer to buffer in which the received bytes will be copied.
* @param rx_len: Number of bytes that will be read from slave
* @return I2C Driver error
* @see #xI2CWrite
* @see #xI2CSlaveTransfer
*/
//i2c_err xI2CMasterRead( I2C_ID_T id, uint8_t addr, uint8_t * rx_buff, uint8_t rx_len );
/*! @todo Document this function */
//i2c_err xI2CMasterWriteRead( I2C_ID_T id, uint8_t addr, uint8_t cmd, uint8_t * rx_buff, uint8_t rx_len );
/*! @brief Enter Slave Receiver mode and waits a data transmission
*
* This function forces the I2C interface switch to Slave Listen (Receiver) mode
* and waits another Master on the bus transmit any data.
* A timeout can be specified for this function, so your functions only block here
* as long as they want.
*
* @warning @p rx_data must be previously allocated to prevent invalid memory access by functions inside this routine.
*
* Example:
* @code
* uint8_t rx_data[i2cMAX_MSG_LENGTH];
* uint32_t timeout = 1000/portTICK_PERIOD_MS; // Specified in ticks ( you can convert to ms dividing the desired value by portTICK_PERIOD_MS macro, defined in portmacro.h file )
* uint8_t data_len;
*
* data_len = xI2CSlaveTransfer( I2C0, rx_data, timeout );
*
* //Read message and blink a LED
* if ( (data_len > 2) && (rx_data[1] == 0x0A) ) {
* blink_led(green);
* } else {
* blink_led(red);
* }
* @endcode
* @param i2c_id: Interface ID ( I2C0, I2C1, I2C2 ).
* @param rx_data: Pointer to buffer in which the received bytes will be copied.
* @param timeout: Amount of time to remain blocked until a message arrives (32-bit value)
* @return Length of message received
* @see #xI2CWrite
* @see #xI2CRead
*/
//uint8_t xI2CSlaveReceive( I2C_ID_T id, uint8_t * rx_buff, uint8_t buff_len, TickType_t timeout );
/*! @todo Document this function */
//void vI2CSlaveSetup ( I2C_ID_T id, uint8_t slave_addr );
/*! @brief Reads own I2C slave address using GA pins
*
* Based on coreipm/coreipm/mmc.c
* @author Gokhan Sozmen
* Reads the GA pins, performing an unconnection checking, to define the device I2C slave address, as specified by MicroTCA documentation.
*
* @return 7-bit Slave Address
*
* @todo Develop a function to discover the Geographic Address once (checking the GA pins)
* and store it into a global variable, since everytime a IPMI message is built
* (request or response) the MMC has to check its own address to fill the rs/rqSA field,
* and it takes some time to go through all this function.
*/
uint8_t get_ipmb_addr( void );
uint8_t ipmb_addr;
#endif /*I2C_H_*/
/*
* ipmb.c
* openMMC -- Open Source modular IPM Controller firmware
*
* AFCIPMI --
*
* Copyright (C) 2015 Henrique Silva <henrique.silva@lnls.br>
* Copyright (C) 2015-2016 Henrique Silva <henrique.silva@lnls.br>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
......@@ -17,6 +15,8 @@
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
* @license GPL-3.0+ <http://spdx.org/licenses/GPL-3.0+>
*/
/* FreeRTOS includes */
......@@ -29,7 +29,7 @@
#include "string.h"
/* Project includes */
#include "i2c.h"
#include "utils.h"
#include "ipmb.h"
#include "ipmi.h"
#include "pin_mapping.h"
......@@ -44,9 +44,6 @@ ipmb_error ipmb_decode ( ipmi_msg * msg, uint8_t * buffer, uint8_t len );
#define I2C_SPEED 100000
/* Macro to check is the message is a response (odd netfn) */
#define IS_RESPONSE(msg) (msg.netfn & 0x01)
/* Local variables */
QueueHandle_t ipmb_txqueue = NULL;
QueueHandle_t client_queue = NULL;
......@@ -66,7 +63,7 @@ void IPMB_TXTask ( void * pvParameters )
/* We're sending a response */
/**********************************/
/* Error checking */
/* Error checking */
/**********************************/
/* See if we've already tried sending this message 3 times */
......@@ -76,7 +73,7 @@ void IPMB_TXTask ( void * pvParameters )
}
/**********************************/
/* Try sending the message */
/* Try sending the message */
/**********************************/
/* Encode the message buffer to the IPMB format */
......@@ -176,9 +173,13 @@ void IPMB_RXTask ( void *pvParameters )
void ipmb_init ( void )
{
vI2CInit( IPMB_I2C, I2C_SPEED, I2C_Mode_IPMB );
vI2CConfig( IPMB_I2C, I2C_SPEED );
ipmb_addr = get_ipmb_addr( );
vI2CSlaveSetup( IPMB_I2C, ipmb_addr );
ipmb_txqueue = xQueueCreate( IPMB_TXQUEUE_LEN, sizeof(ipmi_msg_cfg) );
vQueueAddToRegistry( ipmb_txqueue, "IPMB_TX_QUEUE");
xTaskCreate( IPMB_TXTask, (const char*)"IPMB_TX", 150, ( void * ) NULL, tskIPMB_TX_PRIORITY, ( TaskHandle_t * ) NULL );
xTaskCreate( IPMB_RXTask, (const char*)"IPMB_RX", 300, ( void * ) NULL, tskIPMB_RX_PRIORITY, ( TaskHandle_t * ) NULL );
}
......@@ -279,25 +280,6 @@ ipmb_error ipmb_register_rxqueue ( QueueHandle_t * queue )
}
}
/*! @brief Calculate the IPMB message checksum byte.
* The cheksum byte is calculated by perfoming a simple 8bit 2's complement of the sum of all previous bytes.
* Since we're using a unsigned int to hold the checksum value, we only need to subtract all bytes from it.
* @param buffer Pointer to the message bytes.
* @param range How many bytes will be used in the calculation.
*
* @return Checksum of the specified bytes of the buffer.
*/
uint8_t ipmb_calculate_chksum ( uint8_t * buffer, uint8_t range )
{
configASSERT( buffer != NULL );
uint8_t chksum = 0;
uint8_t i;
for ( i = 0; i < range; i++ ) {
chksum -= buffer[i];
}
return chksum;
}
/*! @brief Asserts the input message checksums by comparing them with our calculated ones.
*
* @param buffer Pointer to the message bytes.
......@@ -313,8 +295,8 @@ ipmb_error ipmb_assert_chksum ( uint8_t * buffer, uint8_t buffer_len )
uint8_t header_chksum = buffer[2];
uint8_t msg_chksum = buffer[buffer_len-1];
uint8_t calc_header_chksum = ipmb_calculate_chksum( buffer, IPMI_HEADER_CHECKSUM_POSITION );
uint8_t calc_msg_chksum = ipmb_calculate_chksum( buffer, buffer_len-1 );
uint8_t calc_header_chksum = calculate_chksum( buffer, IPMI_HEADER_CHECKSUM_POSITION );
uint8_t calc_msg_chksum = calculate_chksum( buffer, buffer_len-1 );
if ( header_chksum == calc_header_chksum ) {
if ( msg_chksum == calc_msg_chksum ) {
return ipmb_error_success;
......@@ -364,7 +346,7 @@ ipmb_error ipmb_encode ( uint8_t * buffer, ipmi_msg * msg )
buffer[i++] = msg->dest_addr;
buffer[i++] = ( ( ( msg->netfn << 2 ) & IPMB_NETFN_MASK ) | ( msg->dest_LUN & IPMB_DEST_LUN_MASK ) );
buffer[i++] = ipmb_calculate_chksum( &buffer[0], IPMI_HEADER_CHECKSUM_POSITION );
buffer[i++] = calculate_chksum( &buffer[0], IPMI_HEADER_CHECKSUM_POSITION );
buffer[i++] = msg->src_addr;
buffer[i++] = ( ( ( msg->seq << 2 ) & IPMB_SEQ_MASK ) | ( msg->src_LUN & IPMB_SRC_LUN_MASK ) );
buffer[i++] = msg->cmd;
......@@ -373,7 +355,7 @@ ipmb_error ipmb_encode ( uint8_t * buffer, ipmi_msg * msg )
}
memcpy (&buffer[i], &msg->data[0], msg->data_len);
i += msg->data_len;
buffer[i] = ipmb_calculate_chksum( &buffer[0], i );
buffer[i] = calculate_chksum( &buffer[0], i );
return ipmb_error_success;
}
......@@ -411,3 +393,116 @@ ipmb_error ipmb_decode ( ipmi_msg * msg, uint8_t * buffer, uint8_t len )
return ipmb_error_success;
}
/*
*==============================================================
* MMC ADDRESSING
*==============================================================
*/
/*! @brief Table holding all possible address values in IPMB specification
* @see get_ipmb_addr()
*/
unsigned char IPMBL_TABLE[IPMBL_TABLE_SIZE] = {
0x70, 0x8A, 0x72, 0x8E, 0x92, 0x90, 0x74, 0x8C, 0x76,
0x98, 0x9C, 0x9A, 0xA0, 0xA4, 0x88, 0x9E, 0x86, 0x84,
0x78, 0x94, 0x7A, 0x96, 0x82, 0x80, 0x7C, 0x7E, 0xA2 };
/*! The state of each GA signal is represented by G (grounded), U (unconnected),
* or P (pulled up to Management Power).
*
* The MMC drives P1 low and reads the GA lines. The MMC then drives P1 high and
* reads the GA lines. Any line that changes state between the two reads indicate
* an unconnected (U) pin.
*
* The IPMB-L address of a Module can be calculated as (70h + Site Number x 2). <br>
* G = 0, P = 1, U = 2 <br>
* | Pin | Ternary | Decimal | Address |
* |:---:|:-------:|:-------:|:-------:|
* | GGG | 000 | 0 | 0x70 |
* | GGP | 001 | 1 | 0x8A |
* | GGU | 002 | 2 | 0x72 |
* | GPG | 010 | 3 | 0x8E |
* | GPP | 011 | 4 | 0x92 |
* | GPU | 012 | 5 | 0x90 |
* | GUG | 020 | 6 | 0x74 |
* | GUP | 021 | 7 | 0x8C |
* | GUU | 022 | 8 | 0x76 |
* | PGG | 100 | 9 | 0x98 |
* | PGP | 101 | 10 | 0x9C |
* | PGU | 102 | 11 | 0x9A |
* | PPG | 110 | 12 | 0xA0 |
* | PPP | 111 | 13 | 0xA4 |
* | PPU | 112 | 14 | 0x88 |
* | PUG | 120 | 15 | 0x9E |
* | PUP | 121 | 16 | 0x86 |
* | PUU | 122 | 17 | 0x84 |
* | UGG | 200 | 18 | 0x78 |
* | UGP | 201 | 19 | 0x94 |
* | UGU | 202 | 20 | 0x7A |
* | UPG | 210 | 21 | 0x96 |
* | UPP | 211 | 22 | 0x82 |
* | UPU | 212 | 23 | 0x80 |
* | UUG | 220 | 24 | 0x7C |
* | UUP | 221 | 25 | 0x7E |
* | UUU | 222 | 26 | 0xA2 |
*/
#define GPIO_GA_DELAY 10
uint8_t get_ipmb_addr( void )
{
uint8_t ga0, ga1, ga2;
uint8_t index;
/* Set the test pin and read all GA pins */
gpio_set_pin_dir(GA_TEST_PORT, GA_TEST_PIN, OUTPUT);
gpio_set_pin_state(GA_TEST_PORT, GA_TEST_PIN, HIGH);
/* when using NAMC-EXT-RTM at least 11 instruction cycles required
* to have correct GA value after GA_TEST_PIN changes */
{
uint8_t i;
for (i = 0; i < GPIO_GA_DELAY; i++){
__asm volatile ("nop");
}
}
ga0 = gpio_read_pin(GA0_PORT, GA0_PIN);
ga1 = gpio_read_pin(GA1_PORT, GA1_PIN);
ga2 = gpio_read_pin(GA2_PORT, GA2_PIN);
/* Clear the test pin and see if any GA pin has changed is value,
* meaning that it is unconnected */
gpio_set_pin_state(GA_TEST_PORT, GA_TEST_PIN, LOW);
/* when using NAMC-EXT-RTM at least 11 instruction cycles required
* to have correct GA value after GA_TEST_PIN changes */
{
uint8_t i;
for (i = 0; i < GPIO_GA_DELAY; i++)
__asm volatile ("nop");
}
if ( ga0 != gpio_read_pin(GA0_PORT, GA0_PIN) ){
ga0 = UNCONNECTED;
}
if ( ga1 != gpio_read_pin(GA1_PORT, GA1_PIN) ){
ga1 = UNCONNECTED;
}
if ( ga2 != gpio_read_pin(GA2_PORT, GA2_PIN) ){
ga2 = UNCONNECTED;
}
/* Transform the 3-based code in a decimal number */
index = (9 * ga2) + (3 * ga1) + (1 * ga0);
if ( index >= IPMBL_TABLE_SIZE ){
return 0;
}
return IPMBL_TABLE[index];
}
#undef GPIO_GA_DELAY
/*
* AFCIPMI --
* openMMC -- Open Source modular IPM Controller firmware
*
* Copyright (C) 2015 Henrique Silva <henrique.silva@lnls.br>
* Copyright (C) 2015-2016 Henrique Silva <henrique.silva@lnls.br>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
......@@ -15,6 +15,8 @@
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
* @license GPL-3.0+ <http://spdx.org/licenses/GPL-3.0+>
*/
/*!
......@@ -87,7 +89,6 @@
*/
#define IPMB_RESP_HEADER_LENGTH 7
#define IPMB_NETFN_MASK 0xFC
#define IPMB_DEST_LUN_MASK 0x3
#define IPMB_SEQ_MASK 0xFC
......@@ -96,6 +97,19 @@
/*! @brief MicroTCA's MCH slave address */
#define MCH_ADDRESS 0x20
/* @brief Macro to check is the message is a response (odd netfn) */
#define IS_RESPONSE(msg) (msg.netfn & 0x01)
/*! @brief Size of #IPMBL_TABLE
*/
#define IPMBL_TABLE_SIZE 27
/*! @brief GA pins definition */
typedef enum {
GROUNDED = 0,
POWERED,
UNCONNECTED
}GA_Pin_state;
/*! @brief IPMI message struct */
typedef struct ipmi_msg {
......@@ -141,6 +155,8 @@ typedef enum ipmb_error {
ipmb_error_queue_creation /*!< Client queue couldn't be created. Invalid pointer to handler was given */
} ipmb_error;
extern uint8_t ipmb_addr;
/* Function Prototypes */
/*! @brief IPMB Transmitter Task
......@@ -201,6 +217,20 @@ ipmb_error ipmb_send_response ( ipmi_msg * req, ipmi_msg * resp );
ipmb_error ipmb_register_rxqueue ( QueueHandle_t * queue );
ipmb_error ipmb_assert_chksum ( uint8_t * buffer, uint8_t buffer_len );
uint8_t ipmb_calculate_chksum ( uint8_t * buffer, uint8_t range );
/*! @brief Reads own I2C slave address using GA pins
*
* Based on coreipm/coreipm/mmc.c
* @author Gokhan Sozmen
* Reads the GA pins, performing an unconnection checking, to define the device I2C slave address, as specified by MicroTCA documentation.
*
* @return 7-bit Slave Address
*
* @todo Develop a function to discover the Geographic Address once (checking the GA pins)
* and store it into a global variable, since everytime a IPMI message is built
* (request or response) the MMC has to check its own address to fill the rs/rqSA field,
* and it takes some time to go through all this function.
*/
uint8_t get_ipmb_addr( void );
#endif
This diff is collapsed.
/*
* ipmi.h
* openMMC -- Open Source modular IPM Controller firmware
*
* AFCIPMI --
*
* Copyright (C) 2015 Henrique Silva <henrique.silva@lnls.br>
* Copyright (C) 2015-2016 Henrique Silva <henrique.silva@lnls.br>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
......@@ -17,21 +15,22 @@
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
* @license GPL-3.0+ <http://spdx.org/licenses/GPL-3.0+>
*/
#ifndef IPMI_H_
#define IPMI_H_
#include "ipmb.h"
#include "sdr.h"
#define IPMI_MAX_DATA_LEN 24
#define IPMI_EXTENSION_VERSION 0x23
#define MAX_FRU_ID 0x01
#define IPMI_EXTENSION_VERSION 0x14
#define MAX_FRU_ID 0x00
#define FRU_DEVICE_ID 0x00
#define MAX_HANDLERS 20
/* Known NetFn codes (even request codes only) */
#define NETFN_CHASSIS 0x00
#define NETFN_BRIDGE 0x02
......@@ -258,6 +257,20 @@
#define IPMI_PICMG_CMD_GET_SHELF_MANAGER_IP_ADDRESSES 0x21
#define IPMI_PICMG_CMD_SHELF_POWER_ALLOCATION 0x22
#define IPMI_PICMG_CMD_GET_TELCO_ALARM_CAPABILITY 0x29
/* HPM Commands */
#define IPMI_PICMG_CMD_HPM_GET_UPGRADE_CAPABILITIES 0x2E
#define IPMI_PICMG_CMD_HPM_GET_COMPONENT_PROPERTIES 0x2F
#define IPMI_PICMG_CMD_HPM_ABORT_FIRMWARE_UPGRADE 0x30
#define IPMI_PICMG_CMD_HPM_INITIATE_UPGRADE_ACTION 0x31
#define IPMI_PICMG_CMD_HPM_UPLOAD_FIRMWARE_BLOCK 0x32
#define IPMI_PICMG_CMD_HPM_FINISH_FIRMWARE_UPLOAD 0x33
#define IPMI_PICMG_CMD_HPM_GET_UPGRADE_STATUS 0x34
#define IPMI_PICMG_CMD_HPM_ACTIVATE_FIRMWARE 0x35
#define IPMI_PICMG_CMD_HPM_QUERY_SELF_RESULTS 0x36
#define IPMI_PICMG_CMD_HPM_QUERY_ROLLBACK_STATUS 0x37
#define IPMI_PICMG_CMD_HPM_INITIATE_MANUAL_ROLLBACK 0x38
#define IPMI_EVENT_MESSAGE_REV 0x04
/* Completion Codes */
#define IPMI_CC_OK 0x00
......@@ -284,6 +297,7 @@
#define IPMI_CC_INSUFFICIENT_PRIVILEGES 0xd4
#define IPMI_CC_NOT_SUPPORTED_PRESENT_STATE 0xd5
#define IPMI_CC_ILLEGAL_COMMAND_DISABLED 0xd6
#define IPMI_CC_COMMAND_IN_PROGRESS 0x80
#define IPMI_CC_UNSPECIFIED_ERROR 0xff
typedef void (* t_req_handler)(ipmi_msg * req, ipmi_msg * resp);
......@@ -292,19 +306,33 @@ typedef struct{
uint8_t netfn;
uint8_t cmd;
t_req_handler req_handler;
}t_req_handler_record;
} t_req_handler_record;
/*
* WARNING!!! Using IPMI_HANDLER_ALIAS and IPMI_HANDLER required to have .ipmi_handlers section in linker script
* .ipmi_handlers : ALIGN(4)
* {
* _ipmi_handlers = .;
* KEEP(*(.ipmi_handlers))
* _eipmi_handlers = .;
* } >FLASHAREA
*/
extern const t_req_handler_record *_ipmi_handlers;
extern const t_req_handler_record *_eipmi_handlers;
#define IPMI_HANDLER_ALIAS(handler_fn, netfn_id, cmd_id) \
const t_req_handler_record __attribute__ ((section (".ipmi_handlers"))) ipmi_handler_##netfn_id##__##cmd_id##_s = { .req_handler = handler_fn , .netfn = netfn_id, .cmd = cmd_id }
#define IPMI_HANDLER(name, netfn_id, cmd_id, args...) \
void ipmi_handler_##netfn_id##__##cmd_id##_f(args); \
const t_req_handler_record __attribute__ ((section (".ipmi_handlers"))) ipmi_handler_##netfn_id##__##cmd_id##_s = { .req_handler = ipmi_handler_##netfn_id##__##cmd_id##_f , .netfn = netfn_id, .cmd = cmd_id }; \
void ipmi_handler_##netfn_id##__##cmd_id##_f(args)
/* Function Prototypes */
void IPMITask ( void *pvParameters );
void ipmi_init ( void );
void IPMI_handler_task( void * pvParameters);
t_req_handler ipmi_retrieve_handler(uint8_t netfn, uint8_t cmd);
/* Handler functions */
void ipmi_app_get_device_id ( ipmi_msg *req, ipmi_msg *rsp );
void ipmi_picmg_set_led ( ipmi_msg *req, ipmi_msg *rsp );
void ipmi_picmg_get_properties ( ipmi_msg *req, ipmi_msg *rsp );
ipmb_error ipmi_event_send( sensor_t * sensor, uint8_t assert_deassert, uint8_t *evData, uint8_t length);
#endif
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment