Patched version of the PowerControl library that handles (re)starting clocks such that (ETH) power can be brought up and down repeatedly without stalling the mbed.

Dependents:   AutonomousDAQ AutonomousDAQ

Committer:
uci1
Date:
Sat Oct 05 04:31:08 2013 +0000
Revision:
4:e5a50000fcfb
Parent:
2:143913e0e922
allow optional use of the rtos wait

Who changed what in which revision?

UserRevisionLine numberNew contents of line
uci1 0:334c4560cd83 1 #include "EthernetPowerControl.h"
uci1 0:334c4560cd83 2
uci1 4:e5a50000fcfb 3 //#define USE_RTOS
uci1 4:e5a50000fcfb 4
uci1 2:143913e0e922 5 void write_PHY (unsigned int PhyReg, unsigned short Value) {
uci1 0:334c4560cd83 6 /* Write a data 'Value' to PHY register 'PhyReg'. */
uci1 0:334c4560cd83 7 unsigned int tout;
uci1 0:334c4560cd83 8 /* Hardware MII Management for LPC176x devices. */
uci1 0:334c4560cd83 9 LPC_EMAC->MADR = DP83848C_DEF_ADR | PhyReg;
uci1 0:334c4560cd83 10 LPC_EMAC->MWTD = Value;
uci1 0:334c4560cd83 11
uci1 0:334c4560cd83 12 /* Wait utill operation completed */
uci1 0:334c4560cd83 13 for (tout = 0; tout < MII_WR_TOUT; tout++) {
uci1 0:334c4560cd83 14 if ((LPC_EMAC->MIND & MIND_BUSY) == 0) {
uci1 0:334c4560cd83 15 break;
uci1 0:334c4560cd83 16 }
uci1 0:334c4560cd83 17 }
uci1 0:334c4560cd83 18 }
uci1 0:334c4560cd83 19
uci1 2:143913e0e922 20 unsigned short read_PHY (unsigned int PhyReg) {
uci1 0:334c4560cd83 21 /* Read a PHY register 'PhyReg'. */
uci1 0:334c4560cd83 22 unsigned int tout, val;
uci1 0:334c4560cd83 23
uci1 0:334c4560cd83 24 LPC_EMAC->MADR = DP83848C_DEF_ADR | PhyReg;
uci1 0:334c4560cd83 25 LPC_EMAC->MCMD = MCMD_READ;
uci1 0:334c4560cd83 26
uci1 0:334c4560cd83 27 /* Wait until operation completed */
uci1 0:334c4560cd83 28 for (tout = 0; tout < MII_RD_TOUT; tout++) {
uci1 0:334c4560cd83 29 if ((LPC_EMAC->MIND & MIND_BUSY) == 0) {
uci1 0:334c4560cd83 30 break;
uci1 0:334c4560cd83 31 }
uci1 0:334c4560cd83 32 }
uci1 0:334c4560cd83 33 LPC_EMAC->MCMD = 0;
uci1 0:334c4560cd83 34 val = LPC_EMAC->MRDD;
uci1 0:334c4560cd83 35
uci1 0:334c4560cd83 36 return (val);
uci1 0:334c4560cd83 37 }
uci1 0:334c4560cd83 38
uci1 0:334c4560cd83 39 void EMAC_Init()
uci1 0:334c4560cd83 40 {
uci1 0:334c4560cd83 41 unsigned int tout,regv;
uci1 0:334c4560cd83 42 /* Power Up the EMAC controller. */
uci1 0:334c4560cd83 43 Peripheral_PowerUp(LPC1768_PCONP_PCENET);
uci1 0:334c4560cd83 44
uci1 0:334c4560cd83 45 LPC_PINCON->PINSEL2 = 0x50150105;
uci1 0:334c4560cd83 46 LPC_PINCON->PINSEL3 &= ~0x0000000F;
uci1 0:334c4560cd83 47 LPC_PINCON->PINSEL3 |= 0x00000005;
uci1 0:334c4560cd83 48
uci1 0:334c4560cd83 49 /* Reset all EMAC internal modules. */
uci1 0:334c4560cd83 50 LPC_EMAC->MAC1 = MAC1_RES_TX | MAC1_RES_MCS_TX | MAC1_RES_RX | MAC1_RES_MCS_RX |
uci1 0:334c4560cd83 51 MAC1_SIM_RES | MAC1_SOFT_RES;
uci1 0:334c4560cd83 52 LPC_EMAC->Command = CR_REG_RES | CR_TX_RES | CR_RX_RES;
uci1 0:334c4560cd83 53
uci1 0:334c4560cd83 54 /* A short delay after reset. */
uci1 0:334c4560cd83 55 for (tout = 100; tout; tout--);
uci1 0:334c4560cd83 56
uci1 0:334c4560cd83 57 /* Initialize MAC control registers. */
uci1 0:334c4560cd83 58 LPC_EMAC->MAC1 = MAC1_PASS_ALL;
uci1 0:334c4560cd83 59 LPC_EMAC->MAC2 = MAC2_CRC_EN | MAC2_PAD_EN;
uci1 0:334c4560cd83 60 LPC_EMAC->MAXF = ETH_MAX_FLEN;
uci1 0:334c4560cd83 61 LPC_EMAC->CLRT = CLRT_DEF;
uci1 0:334c4560cd83 62 LPC_EMAC->IPGR = IPGR_DEF;
uci1 0:334c4560cd83 63
uci1 0:334c4560cd83 64 /* Enable Reduced MII interface. */
uci1 0:334c4560cd83 65 LPC_EMAC->Command = CR_RMII | CR_PASS_RUNT_FRM;
uci1 0:334c4560cd83 66
uci1 0:334c4560cd83 67 /* Reset Reduced MII Logic. */
uci1 0:334c4560cd83 68 LPC_EMAC->SUPP = SUPP_RES_RMII;
uci1 0:334c4560cd83 69 for (tout = 100; tout; tout--);
uci1 0:334c4560cd83 70 LPC_EMAC->SUPP = 0;
uci1 0:334c4560cd83 71
uci1 0:334c4560cd83 72 /* Put the DP83848C in reset mode */
uci1 0:334c4560cd83 73 write_PHY (PHY_REG_BMCR, 0x8000);
uci1 0:334c4560cd83 74
uci1 0:334c4560cd83 75 /* Wait for hardware reset to end. */
uci1 0:334c4560cd83 76 for (tout = 0; tout < 0x100000; tout++) {
uci1 0:334c4560cd83 77 regv = read_PHY (PHY_REG_BMCR);
uci1 0:334c4560cd83 78 if (!(regv & 0x8000)) {
uci1 0:334c4560cd83 79 /* Reset complete */
uci1 0:334c4560cd83 80 break;
uci1 0:334c4560cd83 81 }
uci1 0:334c4560cd83 82 }
uci1 0:334c4560cd83 83 }
uci1 0:334c4560cd83 84
uci1 0:334c4560cd83 85
uci1 0:334c4560cd83 86 void PHY_PowerDown()
uci1 0:334c4560cd83 87 {
uci1 1:0827478161be 88 if (!Peripheral_GetStatus(LPC1768_PCONP_PCENET)) {
uci1 1:0827478161be 89 if ( (LPC_GPIO1->FIOPIN & 0x8000000)==0 ) {
uci1 1:0827478161be 90 // CJR 2012-10-10: Start the clock BEFORE a potential call to EMAC_Init.
uci1 1:0827478161be 91 // Otherwise the LPC_EMAC->MAC1 assignment there may
uci1 1:0827478161be 92 // hang forever as it waits for a clock signal.
uci1 1:0827478161be 93 LPC_GPIO1->FIODIR |= 0x8000000;
uci1 1:0827478161be 94 LPC_GPIO1->FIOSET = 0x8000000;
uci1 1:0827478161be 95
uci1 1:0827478161be 96 //wait for osc to be stable
uci1 1:0827478161be 97 wait_ms(200);
uci1 1:0827478161be 98 }
uci1 0:334c4560cd83 99 EMAC_Init(); //init EMAC if it is not already init'd
uci1 1:0827478161be 100 }
uci1 0:334c4560cd83 101
uci1 0:334c4560cd83 102 unsigned int regv;
uci1 0:334c4560cd83 103 regv = read_PHY(PHY_REG_BMCR);
uci1 0:334c4560cd83 104 write_PHY(PHY_REG_BMCR, regv | (1 << PHY_REG_BMCR_POWERDOWN));
uci1 0:334c4560cd83 105 regv = read_PHY(PHY_REG_BMCR);
uci1 0:334c4560cd83 106
uci1 0:334c4560cd83 107 //shouldn't need the EMAC now.
uci1 0:334c4560cd83 108 Peripheral_PowerDown(LPC1768_PCONP_PCENET);
uci1 0:334c4560cd83 109
uci1 0:334c4560cd83 110 //and turn off the PHY OSC
uci1 0:334c4560cd83 111 LPC_GPIO1->FIODIR |= 0x8000000;
uci1 0:334c4560cd83 112 LPC_GPIO1->FIOCLR = 0x8000000;
uci1 0:334c4560cd83 113 }
uci1 0:334c4560cd83 114
uci1 0:334c4560cd83 115 void PHY_PowerUp()
uci1 0:334c4560cd83 116 {
uci1 0:334c4560cd83 117 // CJR 2012-10-05: Start the clock BEFORE a potential call to EMAC_Init.
uci1 0:334c4560cd83 118 // Otherwise the LPC_EMAC->MAC1 assignment there may
uci1 0:334c4560cd83 119 // hang forever as it waits for a clock signal.
uci1 0:334c4560cd83 120 LPC_GPIO1->FIODIR |= 0x8000000;
uci1 0:334c4560cd83 121 LPC_GPIO1->FIOSET = 0x8000000;
uci1 0:334c4560cd83 122
uci1 0:334c4560cd83 123 //wait for osc to be stable
uci1 4:e5a50000fcfb 124 #ifdef USE_RTOS
uci1 4:e5a50000fcfb 125 Thread::wait(200);
uci1 4:e5a50000fcfb 126 #else
uci1 0:334c4560cd83 127 wait_ms(200);
uci1 4:e5a50000fcfb 128 #endif
uci1 0:334c4560cd83 129
uci1 0:334c4560cd83 130 if (!Peripheral_GetStatus(LPC1768_PCONP_PCENET))
uci1 0:334c4560cd83 131 EMAC_Init(); //init EMAC if it is not already init'd
uci1 0:334c4560cd83 132
uci1 0:334c4560cd83 133 unsigned int regv;
uci1 0:334c4560cd83 134 regv = read_PHY(PHY_REG_BMCR);
uci1 0:334c4560cd83 135 write_PHY(PHY_REG_BMCR, regv & ~(1 << PHY_REG_BMCR_POWERDOWN));
uci1 0:334c4560cd83 136 regv = read_PHY(PHY_REG_BMCR);
uci1 0:334c4560cd83 137 }
uci1 0:334c4560cd83 138
uci1 0:334c4560cd83 139 void PHY_EnergyDetect_Enable()
uci1 0:334c4560cd83 140 {
uci1 0:334c4560cd83 141 if (!Peripheral_GetStatus(LPC1768_PCONP_PCENET))
uci1 0:334c4560cd83 142 EMAC_Init(); //init EMAC if it is not already init'd
uci1 0:334c4560cd83 143
uci1 0:334c4560cd83 144 unsigned int regv;
uci1 0:334c4560cd83 145 regv = read_PHY(PHY_REG_EDCR);
uci1 0:334c4560cd83 146 write_PHY(PHY_REG_BMCR, regv | (1 << PHY_REG_EDCR_ENABLE));
uci1 0:334c4560cd83 147 regv = read_PHY(PHY_REG_EDCR);
uci1 0:334c4560cd83 148 }
uci1 0:334c4560cd83 149
uci1 0:334c4560cd83 150 void PHY_EnergyDetect_Disable()
uci1 0:334c4560cd83 151 {
uci1 0:334c4560cd83 152 if (!Peripheral_GetStatus(LPC1768_PCONP_PCENET))
uci1 0:334c4560cd83 153 EMAC_Init(); //init EMAC if it is not already init'd
uci1 0:334c4560cd83 154 unsigned int regv;
uci1 0:334c4560cd83 155 regv = read_PHY(PHY_REG_EDCR);
uci1 0:334c4560cd83 156 write_PHY(PHY_REG_BMCR, regv & ~(1 << PHY_REG_EDCR_ENABLE));
uci1 0:334c4560cd83 157 regv = read_PHY(PHY_REG_EDCR);
uci1 0:334c4560cd83 158 }