Commit e5eb92fe authored by Henrique Silva's avatar Henrique Silva

Create task to communicate with FPGA via SPI

This task will periodically send board diagnostic data via SPI,
including sensor reading, slot id and ipmb addr
parent b013a716
#include "FreeRTOS.h"
#include "task.h"
#include "port.h"
#include "fpga_spi.h"
#include "pin_mapping.h"
#include "task_priorities.h"
#include "i2c.h"
#include "string.h"
#include "led.h"
/* Write one byte on the specified address on the FPGA RAM */
static void write_fpga_byte( uint32_t data, uint32_t address )
{
uint8_t tx_buff[7];
tx_buff[0] = WR_COMMAND;
tx_buff[1] = 0x00;
tx_buff[2] = address;
tx_buff[3] = ( ( data >> 24) & 0xff );
tx_buff[4] = ( ( data >> 16) & 0xff );
tx_buff[5] = ( ( data >> 8) & 0xff );
tx_buff[6] = ( data & 0xff );
ssp_write( FPGA_SPI, tx_buff, sizeof(tx_buff)/sizeof(tx_buff[0]) );
}
/* Read one byte from the specified address on the FPGA RAM */
static uint32_t read_fpga_byte( uint32_t address )
{
uint8_t tx_buff[3];
uint8_t rx_buff[7];
tx_buff[0] = RD_COMMAND;
tx_buff[1] = 0x00;
tx_buff[2] = address;
ssp_write_read( FPGA_SPI, tx_buff, sizeof(tx_buff), rx_buff, sizeof(rx_buff)-sizeof(tx_buff) );
return ( (uint32_t) ( (rx_buff[3] << 24) | (rx_buff[4] << 16) | (rx_buff[5] << 8) | rx_buff[6] ) );
}
static void write_fpga_buffer( t_board_diagnostic diag )
{
uint16_t i;
/* Send all bytes sequentially, except the last, whose address is different (0xFF) */
for( i = 0; i < (sizeof(diag.buffer)/sizeof(diag.buffer[0])- 1); i++) {
write_fpga_byte( diag.buffer[i], i );
}
write_fpga_byte( diag.buffer[i+1] , 0xFF );
}
/* Send board data to the FPGA RAM via SPI periodically */
void vTaskFPGA_COMM( void * Parameters )
{
t_board_diagnostic diag_struct;
board_diagnostic * diag = &(diag_struct.info);
uint32_t rx_trace[FPGA_MEM_ADDR_MAX+1] = {0};
uint32_t data;
/* Zero fill the diag struct */
memset( &(diag_struct.buffer[0]), 0, sizeof(diag_struct.buffer));
/* Initialize diagnostic struct with known data */
init_diag_struct( diag );
for ( ;; ) {
/* Check if the FPGA has finished programming itself from the FLASH */
while (!gpio_read_pin( GPIO_DONE_B_PORT, GPIO_DONE_B_PIN)) {
vTaskDelay(FPGA_UPDATE_RATE);
}
/* Update diagnostic struct information */
/* Data Valid byte - indicates that LPC is transferring data */
diag->data_valid = 0x55555555;
/* Update Sensors Readings */
for (uint8_t i = 0, j = 0; i <= NUM_SENSOR; i++) {
if (sensor_array[i].diag_devID != NO_DIAG) {
diag->sensor[j].dev_id = sensor_array[i].diag_devID;
diag->sensor[j].measure = sensor_array[i].data->readout_value;
j++;
}
}
diag->fmc_slot.fmc2_pg_c2m = gpio_read_pin( 1, 19 );
diag->fmc_slot.fmc1_pg_c2m = gpio_read_pin( 1, 18 );
diag->fmc_slot.fmc2_pg_m2c = gpio_read_pin( 1, 17 );
diag->fmc_slot.fmc1_pg_m2c = gpio_read_pin( 1, 16 );
diag->fmc_slot.fmc2_prsnt_m2c_n = gpio_read_pin( 1, 15 );
diag->fmc_slot.fmc2_prsnt_m2c_n = gpio_read_pin( 1, 14 );
write_fpga_buffer( diag_struct );
/* Read the buffer from the FPGA to check eventual corruptions */
for( uint32_t addressFPGAram = 0; addressFPGAram < FPGA_MEM_ADDR_MAX; addressFPGAram++ ) {
rx_trace[addressFPGAram] = read_fpga_byte(addressFPGAram);
}
if( !cmpBuffs( &(diag_struct.buffer[0]), sizeof(diag_struct.buffer)/sizeof(diag_struct.buffer[0]), &rx_trace[0], sizeof(rx_trace)/sizeof(rx_trace[0]) ) ) {
data = 0xAAAAAAAA;
extern const LED_activity_desc_t LED_2Hz_Blink_Activity;
LED_update(LED_RED, &LED_2Hz_Blink_Activity);
} else {
data = 0x55555555;
extern const LED_activity_desc_t LED_Off_Activity;
LED_update(LED_RED, &LED_Off_Activity);
}
write_fpga_byte( data, 0x05 );
vTaskDelay(FPGA_UPDATE_RATE);
}
}
void init_fpga_spi( void )
{
ssp_config( FPGA_SPI, FPGA_BITRATE, 8, true, false );
xTaskCreate(vTaskFPGA_COMM, "FPGA_COMM", configMINIMAL_STACK_SIZE*5, NULL, tskFPGA_COMM_PRIORITY, (TaskHandle_t *) NULL);
}
void init_diag_struct( board_diagnostic * diag )
{
uint8_t i,j;
/* Card ID */
diag->cardID[0] = 0;
diag->cardID[1] = 0;
diag->cardID[2] = 0;
diag->cardID[3] = 0;
/* AMC IPMI address */
diag->ipmi_addr = ipmb_addr;
/* AMC Slot Number */
diag->slot_id = (ipmb_addr-0x70)/2;
/* Data Valid */
/* Indicates that LPC is transfering data */
diag->data_valid = 0x55555555;
/* Sensors Readings */
for (i = 0, j = 0; i <= NUM_SENSOR; i++) {
if (sensor_array[i].diag_devID != NO_DIAG) {
diag->sensor[j].dev_id = sensor_array[i].diag_devID;
diag->sensor[j].measure = sensor_array[i].data->readout_value;
j++;
}
}
diag->fmc_slot.fmc2_pg_c2m = gpio_read_pin( 1, 19 );
diag->fmc_slot.fmc1_pg_c2m = gpio_read_pin( 1, 18 );
diag->fmc_slot.fmc2_pg_m2c = gpio_read_pin( 1, 17 );
diag->fmc_slot.fmc1_pg_m2c = gpio_read_pin( 1, 16 );
diag->fmc_slot.fmc2_prsnt_m2c_n = gpio_read_pin( 1, 15 );
diag->fmc_slot.fmc2_prsnt_m2c_n = gpio_read_pin( 1, 14 );
}
/* Compare two buffers' size and data
* Returns 0 if equal, 0xFF if different */
uint8_t cmpBuffs( uint32_t *bufa, uint32_t len_a, uint32_t *bufb, uint32_t len_b )
{
uint16_t i;
if (len_a != len_b) {
return 0xFF;
}
for( i = 0; i<len_a; i++ ) {
if( *bufa != *bufb ) {
return (0xFF);
}
bufa++;
bufb++;
}
return (0);
}
#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
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