void system_config_init(void) { struct nvm_device_serial device_serial; nvm_read_device_serial(&device_serial); for(uint8_t x = 0; x < sizeof(device_serial); x++) sprintf((char *) serial_number + (2 * x), "%02X", device_serial.byte[x]); nvm_eeprom_read_buffer((eeprom_addr_t) &EEPROM_PDICLOCK, &(systemconfig.pdiclock), sizeof(EEPROM_PDICLOCK)); nvm_eeprom_read_buffer((eeprom_addr_t) &EEPROM_TPICLOCK, &(systemconfig.tpiclock), sizeof(EEPROM_TPICLOCK)); nvm_eeprom_read_buffer((eeprom_addr_t) &EEPROM_VERSION, &(systemconfig.version), sizeof(EEPROM_VERSION)); nvm_eeprom_read_buffer((eeprom_addr_t) &EEPROM_DRIVER, &(systemconfig.driver), sizeof(EEPROM_DRIVER)); system_config_check(); }
/** * \brief Test device serial number readout * * This test reads out the \e LOTNUMn, \e WAFNUM, \e COORDXn and \e COORDYn * values from the device signature row and checks that they are not all 0xFF. * * \param test Current test case. */ static void run_device_serial_test(const struct test_case *test) { struct nvm_device_serial dev_sn; bool serial_is_set; uint8_t byte_index; nvm_read_device_serial(&dev_sn); serial_is_set = false; for (byte_index = 0; byte_index < sizeof(dev_sn.byte); byte_index++) { if (dev_sn.byte[byte_index] != 0xff) { serial_is_set = true; break; } } test_assert_true(test, serial_is_set, "Read device serial as all 0xFF"); }
int main(void) { // Configure CPU and peripherals clock xmega_set_cpu_clock_to_32MHz(); // Enable interrupts PMIC.CTRL = PMIC_LOLVLEN_bm | PMIC_MEDLVLEN_bm | PMIC_HILVLEN_bm; // Power management - configure sleep mode to IDLE set_sleep_mode(SLEEP_SMODE_IDLE_gc); // Enable sleep mode sleep_enable(); #ifdef MMSN_DEBUG // Initialize serial communication terminal //usartCommTerminalInit(); // Configure and initialize communication bus usart xmega_usart_configure(); /* RS-485 PHYSICAL DEVICE CONFIGURATION */ // Initialize GPIO related to RS-485 interface rs485_driver_gpio_initialize(); // Initially go LOW to enable receiver and start listening rs485_driver_enable(); /* USART INTERRUPTS CONFIGURATION - RECEIVING */ // Turn on USART RXC interrupt xmega_set_usart_rx_interrupt_level(&USART_COMMUNICATION_BUS, USART_RXCINTLVL_HI_gc); // Turn off TXC and DRE interrupts xmega_set_usart_tx_interrupt_level(&USART_COMMUNICATION_BUS, USART_TXCINTLVL_OFF_gc); xmega_set_usart_dre_interrupt_level(&USART_COMMUNICATION_BUS, USART_DREINTLVL_OFF_gc); // Redirect stream to standard output stdout = &mystdout; /* Print out welcome message */ //static const char WelcomeMessage[] PROGMEM = "Multi-Master Serial Network Manager ver 1.0"; //printf("%S\n", WelcomeMessage); printf_P(PSTR("\nMulti-Master Serial Network Manager ver 1.0\n")); //printf("Multi-Master Serial Network Manager ver 1.0\n"); #endif // Calculate CRC-16 value based on the random Internal SRAM memory content. // Move by 0x400 from the beginning to omit memory area related to global variables section. // Take 20 consecutive SRAM bytes for CRC-16 calculation. uint16_t u16RandomValue = xmega_calculate_checksum_crc16((uint8_t *)(INTERNAL_SRAM_START + 1200), 20); // Pseudo-random number generator seeding with previously obtain value srand(u16RandomValue); #ifdef MMSN_DEBUG printf("rnd = %u\n", u16RandomValue); #endif // Read XMEGA device serial number nvm_read_device_serial(&xmegaSerialNumber); // Read configuration data from EEPROM xmega_read_configuration_data(); // Check if logical address was already assigned if (true == _isLogicalNetworkAddrAssigned(&ConfigurationData.u8LogicalNetworkAddr)) { // Logical Network Address was already assigned. g_DeviceConfigStatus = eLogicalAddrAssigned; // Calculate Collision Avoidance (back-off/busy line) timer period value. g_u16CollisionAvoidancePeriod = (ConfigurationData.u8LogicalNetworkAddr * TIMER_COLLISION_AVOIDANCE_520us_VALUE) + TIMER_COLLISION_AVOIDANCE_32us_VALUE; #ifdef MMSN_DEBUG printf("LNA_CA = %d\n", g_u16CollisionAvoidancePeriod); #endif } else { // Logical Network Address was NOT assigned. g_DeviceConfigStatus = eLogicalAddrNotAssigned; // Calculate Collision Avoidance (back-off/busy line) timer period using random value. g_u16CollisionAvoidancePeriod = (xmega_generate_random_logical_network_address() * TIMER_COLLISION_AVOIDANCE_520us_VALUE) + TIMER_COLLISION_AVOIDANCE_32us_VALUE; #ifdef MMSN_DEBUG printf("RND_CA = %d\n", g_u16CollisionAvoidancePeriod); #endif } /************************************************************************/ /* TIMERS CONFIGURATION */ /************************************************************************/ // No response timer - configure but do not run xmega_timer_config(&TIMER_NO_RESPONSE, TC_CLKSEL_OFF_gc, TIMER_NO_RESPONSE_PERIOD); // Collision Avoidance timer - configure but do not run xmega_timer_config(&TIMER_COLLISION_AVOIDANCE, TC_CLKSEL_OFF_gc, g_u16CollisionAvoidancePeriod); // Heartbeat timer - configure but do not run xmega_timer_config(&TIMER_HEARTBEAT, TC_CLKSEL_OFF_gc, TIMER_HEARTBEAT_PERIOD); // Force the state of the SREG register on exit, disabling the Global Interrupt Status flag bit. /* ATOMIC_BLOCK(NONATOMIC_FORCEOFF) { // Clear busy line timeout event FLAG_CLEAR(gSystemEvents, EVENT_IRQ_COLLISION_AVOIDANCE_TIMEOUT_bm); } // Turn busy line timer off xmega_tc_select_clock_source(&TIMER_COLLISION_AVOIDANCE, TC_CLKSEL_OFF_gc); */ /* Initialize event queue */ fifo_init(&eventQueue_desc, &EventQueue[0], EVENT_FIFO_BUFFER_SIZE); /************************************************************************/ /* Initialize Multi-Master Serial Network State Machine */ /************************************************************************/ // SM_stateTable[eSM_Initialize](); //mmsn_InitializeStateMachine(&mmsnFSM); // Initialize global storage for data sending _sendData_FrameBuffer_Init(&gStorage_SendData); // Start heartbeat timer xmega_tc_select_clock_source(&TIMER_HEARTBEAT, TC_CLKSEL_DIV64_gc); xmega_set_usart_rx_interrupt_level(&USART_COMMUNICATION_BUS, USART_RXCINTLVL_HI_gc); // Turn on global interrupts sei(); /************************************************************************/ /* Start infinite main loop, go to sleep and wait for interruption */ /************************************************************************/ for(;;) { // Force the state of the SREG register on exit, enabling the Global Interrupt Status flag bit. ATOMIC_BLOCK(ATOMIC_FORCEON) { // Atomic interrupt safe read of global variable storing event flags u16EventFlags = gSystemEvents; }; while (u16EventFlags) { // Note: Each handler will clear the relevant bit in global variable gSystemEvents // Corresponding event flag will be cleared in FSM handler // Heartbeat timer interrupt fired up if (u16EventFlags & SYSEV_HEARTBEAT_TIMEOUT_bm) { if (gHeartBeatCounter > 5000) { // create a message gStorage_SendData.u8DataSize = 7; gStorage_SendData.u8IsResponseNeeded = true; gStorage_SendData.u8SendDataBuffer[0] = 1; gStorage_SendData.u8SendDataBuffer[1] = 3; gStorage_SendData.u8SendDataBuffer[2] = 5; gStorage_SendData.u8SendDataBuffer[3] = 7; gStorage_SendData.u8SendDataBuffer[4] = 9; gStorage_SendData.u8SendDataBuffer[5] = 11; gStorage_SendData.u8SendDataBuffer[6] = 33; // add event to queue ADD_EVENT_TO_QUEUE(&eventQueue_desc, MMSN_SEND_DATA_EVENT); // reset counter gHeartBeatCounter = 0; // Stop heartbeat timer xmega_tc_select_clock_source(&TIMER_HEARTBEAT, TC_CLKSEL_OFF_gc); } sys_HeartbeatTimeout_Handler(); }; // Collision Avoidance timer interrupt fired up if (u16EventFlags & SYSEV_COLLISION_AVOIDANCE_TIMEOUT_bm) { sysev_CollisionAvoidanceTimeout_Handler(); }; // No response timer interrupt fired up if (u16EventFlags & SYSEV_NO_RESPONSE_TIMEOUT_bm) { sysev_NoResponseTimeout_Handler(); }; // Receive Complete (RXC) interrupt fired up if (u16EventFlags & SYSEV_RECEIVE_COMPLETE_bm) { sysev_ReceiveComplete_Handler(); }; // Data Register Empty (DRE) interrupt fired up if (u16EventFlags & SYSEV_DATA_REGISTER_EMPTY_bm) { sysev_DataRegisterEmpty_Handler(); }; // Transmit Complete (TXC) interrupt fired up if (u16EventFlags & SYSEV_TRANSMIT_COMPLETE_bm) { sysev_TransmitComplete_Handler(); }; // Dispatch events from the MMSN FSM queue while(!fifo_is_empty(&eventQueue_desc)) { // Get event from the queue uint8_t currEvent = fifo_pull_uint8_nocheck(&eventQueue_desc); // Call corresponding FSM event handler if (mmsnFSMActionTable[mmsnFSM.CurrentState][currEvent]) { mmsnFSMActionTable[mmsnFSM.CurrentState][currEvent](&mmsnFSM, currEvent, &g_u8GlobalArgument); } }; // Read the system event flag again after handlers return ATOMIC_BLOCK(ATOMIC_FORCEON) { // Atomic interrupt safe read of global variable storing event flags u16EventFlags = gSystemEvents; } } // while(...) // Read the event register again without allowing any new interrupts cli(); if (0 == gSystemEvents) { sei(); // Go to sleep, everything is handled by interrupts. // An interrupt will cause a wake up and run the while loop sleep_cpu(); }; // Set Global Interrupt Status flag sei(); }; };