Skip to content
Open
2 changes: 1 addition & 1 deletion common/log.c
Original file line number Diff line number Diff line change
Expand Up @@ -190,7 +190,7 @@ void ApolloLog(log_Event *ev)
// note to self: before you change the size of this buffer
// willy-nilly remember that this has to be accomodated on the stack of every
// FreeRTOS task that calls any of the log_ functions.
#define SZ 128
#define SZ 192
char tmp[SZ];
int r = 0;
#ifdef LOG_USE_COLOR
Expand Down
5 changes: 3 additions & 2 deletions projects/cm_mcu/CommandLineTask.c
Original file line number Diff line number Diff line change
Expand Up @@ -244,10 +244,11 @@ static struct command_t commands[] = {
#if defined(REV2) || defined(REV3)
{"clearclk", clearclk_ctl,
"Reset clk sticky bits\r\n", 0},
{"clk_freq_fpga", clk_freq_fpga_cmd, "read out special FPGA i2c regs\r\n", 1}, // need to call with which fpga you are checking
{"clk_freq_fpga", clk_freq_fpga_cmd, "read out special FPGA i2c regs\r\n", 2}, // need to call with which fpga you are checking
{"clkmon", clkmon_ctl, "CLK chips' status, id:0-4\r\n", 1},
{"clkname", clk_prog_name, "CLK chip program, id:0-4\r\n", 1},
{"clkprog", init_load_clock_ctl, "args: <id> <reset>\r\nLoad clock chip program, id:0-4\r\n", 2},
{"clkreset", clk_reset, "Reset clock chip, id:0-4\r\n", 1},
#endif // REV2
{"eeprom_info", eeprom_info, "Prints information about the EEPROM\r\n", 0},
{"eeprom_read", eeprom_read,
Expand All @@ -265,7 +266,7 @@ static struct command_t commands[] = {
"Prints information about the eeprom error logger\r\n", 0},
{"errorlog_reset", errbuff_reset,
"Resets the eeprom error logger\r\n", 0},
{"first_mcu", first_mcu_ctl, "args: <board #> <revision #>\r\n Detect first-time setup of MCU and prompt loading internal EEPROM configuration\r\n", 4},
{"first_mcu", set_mcu_id, "args: <board #> <revision #>\r\n Detect first-time setup of MCU and prompt loading internal EEPROM configuration\r\n", 4},
#if defined(REV2) || defined(REV3)
{"fpga_flash", fpga_flash, "args # (1|2): Program FPGA 1(2) via a programmed flash\r\n",
1},
Expand Down
14 changes: 3 additions & 11 deletions projects/cm_mcu/MonitorTask.c
Original file line number Diff line number Diff line change
Expand Up @@ -34,14 +34,6 @@
// the PAGE command is an SMBUS standard at register 0
#define PAGE_COMMAND 0x0

// break out of loop, releasing semaphore if we have it
#define release_break() \
{ \
if (xSemaphoreGetMutexHolder(args->xSem) == xTaskGetCurrentTaskHandle()) \
xSemaphoreGive(args->xSem); \
break; \
}

void MonitorTask(void *parameters)
{
// initialize to the current tick time
Expand Down Expand Up @@ -78,7 +70,7 @@ void MonitorTask(void *parameters)
log_info(LOG_MON, "%s: PWR off. Disabling I2C monitoring.\r\n", args->name);
isFullyPowered = false;
}
release_break(); // skip this iteration
break; // skip this iteration
}
else { // if the power state is fully on
if (!isFullyPowered) { // was previously off
Expand Down Expand Up @@ -109,7 +101,7 @@ void MonitorTask(void *parameters)
if (*args->smbus_status != SMBUS_OK) {
log_trace(LOG_MON, "%s:Mux w error %d, break (ps=%d)\r\n", args->name, *args->smbus_status,
ps);
release_break();
break;
}

// loop over pages on the supply
Expand Down Expand Up @@ -158,7 +150,7 @@ void MonitorTask(void *parameters)
args->pm_values[index] = __builtin_nanf("");
if (log)
errbuffer_put(EBUF_I2C, (uint16_t)args->name[0]);
release_break(); // BUG: THIS IS NOT GOING TO WORK -- WE ARE STILL ACTING AS IF WE HAVE THE SEMAPHORE IN THE OUTER LOOP
break;
}
float val;
if (args->commands[c].type == PM_LINEAR11) {
Expand Down
107 changes: 106 additions & 1 deletion projects/cm_mcu/clocksynth.c
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
#include <string.h>

#include "MonitorTaskI2C.h"
#include "common/log.h"
#include "common/smbus_helper.h"
#include "clocksynth.h"
#include "I2CCommunication.h"
Expand Down Expand Up @@ -126,4 +127,108 @@ void getClockProgram(int device, char progname_clkdesgid[CLOCK_PROGNAME_REG_NAME
memcpy(progname_clkdesgid, data, CLOCK_PROGNAME_REG_COUNT);
}
}
#endif // REV2

// Reset the clock synthesizer by toggling the reset pin, which is active low
// the reset pins are connected to the I/O expanders. The schematic names
// are of the form /SYN_RXX_RESET, where XX is the R[01][ABC] clock name.
// must grab and release the semaphore in a larger scope when calling this function.
// return 0 on success, error code otherwise
int resetClockSynth(int device)
{
// extract info about device
// device must be in range 0-4
if (device < 0 || device > 4) {
log_error(LOG_I2C, "Invalid device %d\r\n", device);
return 1;
}
// Devices are
// 0: R0A
// 1: R0B
// 2: R1A
// 3: R1B
// 4: R1C
// Rev3: See page 4.03 of the schematic. R0A and R0B reset are on one expander at address 0x20,
// and R1A, R1B, and R1C reset are on another expander at address 0x21.
// The first I/O expander is on channel 6 of the Mux. The second I/O expander is on channel 7 of the Mux.

// the reset bits are as follows for the TCA9555 I/O expanders.
// R0A: bit P07 --> read reg 0, write reg 2, bit 7
// R0B: bit P10 --> read reg 1, write reg 3, bit 0
// R1A: bit P07 --> read reg 0, write reg 2, bit 7
// R1B: bit P10 --> read reg 1, write reg 3, bit 0
// R1C: bit P11 --> read reg 1, write reg 3, bit 1
int channel = (device < 2) ? 6 : 7;
uint8_t mux_addr = CLOCK_SWITCH_I2C_ADDRESS;
uint8_t expander_addr = (device < 2) ? CLOCK_R0_EXPANDER_I2C_ADDRESS : CLOCK_R1_EXPANDER_I2C_ADDRESS;
// set the mux
int res = apollo_i2c_ctl_w(CLOCK_I2C_DEV, mux_addr, 1, 1 << channel);
if (res != 0) {
log_warn(LOG_SERVICE, "Mux error %s, break (instance=%s)\r\n", SMBUS_get_error(res),
clk_moni2c_addrs[device].name);
return res;
}
int read_reg, write_reg, bit_pos;
switch (device) {
case 0: // R0A
read_reg = CLOCK_EXPANDER_INPUT_PORT_0;
write_reg = CLOCK_EXPANDER_OUTPUT_PORT_0;
bit_pos = 7;
break;
case 1: // R0B
read_reg = CLOCK_EXPANDER_INPUT_PORT_1;
write_reg = CLOCK_EXPANDER_OUTPUT_PORT_1;
bit_pos = 0;
break;
case 2: // R1A
read_reg = CLOCK_EXPANDER_INPUT_PORT_0;
write_reg = CLOCK_EXPANDER_OUTPUT_PORT_0;
bit_pos = 7;
break;
case 3: // R1B
read_reg = CLOCK_EXPANDER_INPUT_PORT_1;
write_reg = CLOCK_EXPANDER_OUTPUT_PORT_1;
bit_pos = 0;
break;
case 4: // R1C
read_reg = CLOCK_EXPANDER_INPUT_PORT_1;
write_reg = CLOCK_EXPANDER_OUTPUT_PORT_1;
bit_pos = 1;
break;
default:
log_error(LOG_I2C, "Invalid device %d\r\n", device);
return 1;
}

// read/modify/write to assert reset (active low)
// read current port value
uint32_t output_port;
res = apollo_i2c_ctl_reg_r(CLOCK_I2C_DEV, expander_addr, 1,
read_reg, 1, &output_port);
if (res != 0) {
log_warn(LOG_SERVICE, "Expander read error %s, break (instance=%s)\r\n", SMBUS_get_error(res),
clk_moni2c_addrs[device].name);
return res;
}
// clear the bit corresponding to the reset pin to assert reset (active low)
output_port &= ~(1 << bit_pos);
res = apollo_i2c_ctl_reg_w(CLOCK_I2C_DEV, expander_addr, 1,
write_reg, 1, output_port);
if (res != 0) {
log_warn(LOG_SERVICE, "Expander write error %s, break (instance=%s)\r\n", SMBUS_get_error(res),
clk_moni2c_addrs[device].name);
return res;
}
vTaskDelay(pdMS_TO_TICKS(10)); // hold reset low for 10 ms
// set the bit corresponding to the reset pin to de-assert reset
output_port |= (1 << bit_pos);
res = apollo_i2c_ctl_reg_w(CLOCK_I2C_DEV, expander_addr, 1,
write_reg, 1, output_port);
if (res != 0) {
log_warn(LOG_SERVICE, "Expander write error %s, break (instance=%s)\r\n", SMBUS_get_error(res),
clk_moni2c_addrs[device].name);
return res;
}

return 0;
}
#endif // REV2 || REV3
12 changes: 9 additions & 3 deletions projects/cm_mcu/clocksynth.h
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@
* Created on: Jul 30, 2020
* Author: rzou
*/
#include "common/utils.h"

#ifndef PROJECTS_CM_MCU_CLOCKSYNTH_H_
#define PROJECTS_CM_MCU_CLOCKSYNTH_H_
Expand All @@ -19,8 +18,8 @@ int load_clock(void);
#define CLOCK_SYNTH_STICKY_FLAG_REGISTER 0x11 // sticky flags for internal status register
#define CLOCK_SWITCH_I2C_ADDRESS 0x70 // TCA9548A
#define CLOCK_SWITCH_ENABLEMAP 0xc1
#define CLOCK_WRITE_EXPANDER_I2C_ADDRESS 0x20 // TCA9555, I2C expander to write to clock synth chip
#define CLOCK_READ_EXPANDER_I2C_ADDREASS 0x21 // TCA9555, I2C expander to read from clcok synth chip
#define CLOCK_R0_EXPANDER_I2C_ADDRESS 0x20 // TCA9555, I2C expander for R0A/R0B clock synth chips
#define CLOCK_R1_EXPANDER_I2C_ADDRESS 0x21 // TCA9555, I2C expander for R1A/R1B/R1C clock synth chips
#define CLOCK_EXPANDER_CONFIGURATION_PORT_1 0x07
#define CLOCK_EXPANDER_CONFIGURATION_PORT_SETASINPUT 1
#define CLOCK_EXPANDER_CONFIGURATION_PORT_SETASOUTPUT 0
Expand All @@ -42,4 +41,11 @@ int load_clock(void);

void getClockProgram(int device, char progname_clkdesgid[CLOCK_PROGNAME_REG_NAME], char progname_eeprom[CLOCK_EEPROM_PROGNAME_REG_NAME]);

// Reset the clock synthesizer by toggling the reset pin, which is active low
// the reset pins are connected to the I/O expanders. The schematic names
// are of the form /SYN_RXX_RESET, where XX is the R[01][ABC] clock name.
// must grab and release the semaphore in a larger scope when calling this function.
// return 0 on success, error code otherwise
int resetClockSynth(int device);

#endif /* PROJECTS_CM_MCU_CLOCKSYNTH_H_ */
64 changes: 34 additions & 30 deletions projects/cm_mcu/commands/BoardCommands.c
Original file line number Diff line number Diff line change
Expand Up @@ -99,46 +99,50 @@ BaseType_t board_id_info(int argc, char **argv, char *m)
return pdFALSE;
}

BaseType_t first_mcu_ctl(int argc, char **argv, char *m)
// set the board ID, revision, firefly USER mask and power supply ignore mask
BaseType_t set_mcu_id(int argc, char **argv, char *m)
{
uint32_t board_id, rev, ps_mask, data;
char *c;
board_id = strtoul(argv[1], &c, 10);
// make sure board_id is sensible and strtoul worked
if (*c != '\0' || c == argv[1] || board_id == 0 || board_id > 0xFFFFU) {
snprintf(m, SCRATCH_SIZE, "Invalid board ID %s\r\n", argv[1]);
return pdFALSE;
}

if (read_eeprom_single(EEPROM_ID_SN_ADDR) == 0xffffffff) {
uint32_t board_id, rev, ps_mask, data;
board_id = strtoul(argv[1], NULL, 10);
rev = strtoul(argv[2], NULL, 10);
ff_USER_mask = strtoul(argv[3], NULL, 16);
ps_mask = strtoul(argv[4], NULL, 16);
snprintf(m, SCRATCH_SIZE, "Registering board_id %lx revision %lx, USER ff mask %lx and PS ignore mask %lx \r\n", board_id, rev, ff_USER_mask, ps_mask);
rev = strtoul(argv[2], &c, 10);
// make sure rev is sensible and strtoul worked
if (*c != '\0' || c == argv[2] || rev == 0 || rev > 3) { // only rev 1-3 supported
snprintf(m, SCRATCH_SIZE, "Invalid revision %s\r\n", argv[2]);
return pdFALSE;
}
// we assume the ff_USER_mask and ps_mask are in hex and that the conversion is ok here
ff_USER_mask = strtoul(argv[3], NULL, 16);
ps_mask = strtoul(argv[4], NULL, 16);
snprintf(m, SCRATCH_SIZE, "Registering board_id %lx revision %lx, USER ff mask %lx and PS ignore mask %lx \r\n", board_id, rev, ff_USER_mask, ps_mask);

data = (board_id << 16) + rev;
uint64_t block = EEPROMBlockFromAddr(ADDR_ID);
data = (board_id << 16) + rev;
uint64_t block = EEPROMBlockFromAddr(ADDR_ID);

uint64_t unlock = EPRMMessage((uint64_t)EPRM_UNLOCK_BLOCK, block, PASS);
xQueueSendToBack(xEPRMQueue_in, &unlock, portMAX_DELAY);
uint64_t unlock = EPRMMessage((uint64_t)EPRM_UNLOCK_BLOCK, block, PASS);
xQueueSendToBack(xEPRMQueue_in, &unlock, portMAX_DELAY);

uint64_t message = EPRMMessage((uint64_t)EPRM_WRITE_SINGLE, ADDR_ID, data);
xQueueSendToBack(xEPRMQueue_in, &message, portMAX_DELAY);

data = ff_USER_mask;
uint64_t message = EPRMMessage((uint64_t)EPRM_WRITE_SINGLE, ADDR_ID, data);
xQueueSendToBack(xEPRMQueue_in, &message, portMAX_DELAY);

message = EPRMMessage((uint64_t)EPRM_WRITE_SINGLE, ADDR_FF, data);
xQueueSendToBack(xEPRMQueue_in, &message, portMAX_DELAY);
data = ff_USER_mask;

data = ps_mask;
message = EPRMMessage((uint64_t)EPRM_WRITE_SINGLE, ADDR_FF, data);
xQueueSendToBack(xEPRMQueue_in, &message, portMAX_DELAY);

message = EPRMMessage((uint64_t)EPRM_WRITE_SINGLE, ADDR_PS, data);
xQueueSendToBack(xEPRMQueue_in, &message, portMAX_DELAY);
data = ps_mask;

uint64_t lock = EPRMMessage((uint64_t)EPRM_LOCK_BLOCK, block << 32, 0);
xQueueSendToBack(xEPRMQueue_in, &lock, portMAX_DELAY);
}
else {
uint32_t sn = read_eeprom_single(EEPROM_ID_SN_ADDR);
message = EPRMMessage((uint64_t)EPRM_WRITE_SINGLE, ADDR_PS, data);
xQueueSendToBack(xEPRMQueue_in, &message, portMAX_DELAY);

uint32_t num = (uint32_t)sn >> 16;
uint32_t rev = ((uint32_t)sn) & 0xff;
snprintf(m, SCRATCH_SIZE, "This is not the first-time loading MCU FW to board #%lx (rev %lx) \r\n", num, rev);
}
uint64_t lock = EPRMMessage((uint64_t)EPRM_LOCK_BLOCK, block << 32, 0);
xQueueSendToBack(xEPRMQueue_in, &lock, portMAX_DELAY);

return pdFALSE;
}
Expand Down
2 changes: 1 addition & 1 deletion projects/cm_mcu/commands/BoardCommands.h
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ BaseType_t restart_mcu(int argc, char **argv, char *m);
BaseType_t set_board_id(int argc, char **argv, char *m);
BaseType_t set_board_id_password(int argc, char **argv, char *m);
BaseType_t board_id_info(int argc, char **argv, char *m);
BaseType_t first_mcu_ctl(int argc, char **argv, char *m);
BaseType_t set_mcu_id(int argc, char **argv, char *m);
BaseType_t jtag_sm_ctl(int argc, char **argv, char *m);
BaseType_t time_ctl(int argc, char **argv, char *m);
BaseType_t gpio_ctl(int argc, char **argv, char *m);
Expand Down
Loading